Use for-of instead of forEach (#3583)
Co-authored-by: syuilo <syuilotan@yahoo.co.jp> Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
This commit is contained in:
		
							parent
							
								
									30c53e9ee0
								
							
						
					
					
						commit
						125849673a
					
				
					 84 changed files with 345 additions and 283 deletions
				
			
		| 
						 | 
					@ -74,14 +74,14 @@ export default abstract class Chart<T> {
 | 
				
			||||||
		const query: Obj = {};
 | 
							const query: Obj = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const dive = (x: Obj, path: string) => {
 | 
							const dive = (x: Obj, path: string) => {
 | 
				
			||||||
			Object.entries(x).forEach(([k, v]) => {
 | 
								for (const [k, v] of Object.entries(x)) {
 | 
				
			||||||
				const p = path ? `${path}.${k}` : k;
 | 
									const p = path ? `${path}.${k}` : k;
 | 
				
			||||||
				if (typeof v === 'number') {
 | 
									if (typeof v === 'number') {
 | 
				
			||||||
					query[p] = v;
 | 
										query[p] = v;
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					dive(v, p);
 | 
										dive(v, p);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dive(x, path);
 | 
							dive(x, path);
 | 
				
			||||||
| 
						 | 
					@ -334,14 +334,14 @@ export default abstract class Chart<T> {
 | 
				
			||||||
		 * にする
 | 
							 * にする
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		const dive = (x: Obj, path?: string) => {
 | 
							const dive = (x: Obj, path?: string) => {
 | 
				
			||||||
			Object.entries(x).forEach(([k, v]) => {
 | 
								for (const [k, v] of Object.entries(x)) {
 | 
				
			||||||
				const p = path ? `${path}.${k}` : k;
 | 
									const p = path ? `${path}.${k}` : k;
 | 
				
			||||||
				if (typeof v == 'object') {
 | 
									if (typeof v == 'object') {
 | 
				
			||||||
					dive(v, p);
 | 
										dive(v, p);
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					nestedProperty.set(res, p, chart.map(s => nestedProperty.get(s, p)));
 | 
										nestedProperty.set(res, p, chart.map(s => nestedProperty.get(s, p)));
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dive(chart[0]);
 | 
							dive(chart[0]);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,9 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onLogs(logs) {
 | 
							onLogs(logs) {
 | 
				
			||||||
			logs.reverse().forEach(log => this.onLog(log));
 | 
								for (const log of logs.reverse()) {
 | 
				
			||||||
 | 
									this.onLog(log)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,7 +132,9 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onStatsLog(statsLog) {
 | 
							onStatsLog(statsLog) {
 | 
				
			||||||
			statsLog.reverse().forEach(stats => this.onStats(stats));
 | 
								for (const stats of statsLog.reverse()) {
 | 
				
			||||||
 | 
									this.onStats(stats);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -127,12 +127,12 @@ export default Vue.extend({
 | 
				
			||||||
		this.$root.api('instances', {
 | 
							this.$root.api('instances', {
 | 
				
			||||||
			sort: '+notes'
 | 
								sort: '+notes'
 | 
				
			||||||
		}).then(instances => {
 | 
							}).then(instances => {
 | 
				
			||||||
			instances.forEach(i => {
 | 
								for (const i of instances) {
 | 
				
			||||||
				i.bg = randomColor({
 | 
									i.bg = randomColor({
 | 
				
			||||||
					seed: i.host,
 | 
										seed: i.host,
 | 
				
			||||||
					luminosity: 'dark'
 | 
										luminosity: 'dark'
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
			this.instances = instances;
 | 
								this.instances = instances;
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,7 +91,9 @@ export default Vue.extend({
 | 
				
			||||||
		fetchEmojis() {
 | 
							fetchEmojis() {
 | 
				
			||||||
			this.$root.api('admin/emoji/list').then(emojis => {
 | 
								this.$root.api('admin/emoji/list').then(emojis => {
 | 
				
			||||||
				emojis.reverse();
 | 
									emojis.reverse();
 | 
				
			||||||
				emojis.forEach(e => e.aliases = (e.aliases || []).join(' '));
 | 
									for (const e of emojis) {
 | 
				
			||||||
 | 
										e.aliases = (e.aliases || []).join(' ');
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.emojis = emojis;
 | 
									this.emojis = emojis;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,9 +17,9 @@
 | 
				
			||||||
	//#region Apply theme
 | 
						//#region Apply theme
 | 
				
			||||||
	const theme = localStorage.getItem('theme');
 | 
						const theme = localStorage.getItem('theme');
 | 
				
			||||||
	if (theme) {
 | 
						if (theme) {
 | 
				
			||||||
		Object.entries(JSON.parse(theme)).forEach(([k, v]) => {
 | 
							for (const [k, v] of Object.entries(JSON.parse(theme))) {
 | 
				
			||||||
			document.documentElement.style.setProperty(`--${k}`, v.toString());
 | 
								document.documentElement.style.setProperty(`--${k}`, v.toString());
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	//#endregion
 | 
						//#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -160,7 +160,7 @@
 | 
				
			||||||
			navigator.serviceWorker.controller.postMessage('clear');
 | 
								navigator.serviceWorker.controller.postMessage('clear');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			navigator.serviceWorker.getRegistrations().then(registrations => {
 | 
								navigator.serviceWorker.getRegistrations().then(registrations => {
 | 
				
			||||||
				registrations.forEach(registration => registration.unregister());
 | 
									for (const registration of registrations) registration.unregister();
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		} catch (e) {
 | 
							} catch (e) {
 | 
				
			||||||
			console.error(e);
 | 
								console.error(e);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
import Vue from 'vue';
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function<T extends object>(data: {
 | 
					export default function <T extends object>(data: {
 | 
				
			||||||
	name: string;
 | 
						name: string;
 | 
				
			||||||
	props?: () => T;
 | 
						props?: () => T;
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
| 
						 | 
					@ -53,11 +53,10 @@ export default function<T extends object>(data: {
 | 
				
			||||||
			mergeProps() {
 | 
								mergeProps() {
 | 
				
			||||||
				if (data.props) {
 | 
									if (data.props) {
 | 
				
			||||||
					const defaultProps = data.props();
 | 
										const defaultProps = data.props();
 | 
				
			||||||
					Object.keys(defaultProps).forEach(prop => {
 | 
										for (const prop of Object.keys(defaultProps)) {
 | 
				
			||||||
						if (!this.props.hasOwnProperty(prop)) {
 | 
											if (this.props.hasOwnProperty(prop)) continue;
 | 
				
			||||||
							Vue.set(this.props, prop, defaultProps[prop]);
 | 
											Vue.set(this.props, prop, defaultProps[prop]);
 | 
				
			||||||
						}
 | 
										}
 | 
				
			||||||
					});
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,15 +28,15 @@ const getKeyMap = keymap => Object.entries(keymap).map(([patterns, callback]): a
 | 
				
			||||||
			shift: false
 | 
								shift: false
 | 
				
			||||||
		} as pattern;
 | 
							} as pattern;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		part.trim().split('+').forEach(key => {
 | 
							const keys = part.trim().split('+').map(x => x.trim().toLowerCase());
 | 
				
			||||||
			key = key.trim().toLowerCase();
 | 
							for (const key of keys) {
 | 
				
			||||||
			switch (key) {
 | 
								switch (key) {
 | 
				
			||||||
				case 'ctrl': pattern.ctrl = true; break;
 | 
									case 'ctrl': pattern.ctrl = true; break;
 | 
				
			||||||
				case 'alt': pattern.alt = true; break;
 | 
									case 'alt': pattern.alt = true; break;
 | 
				
			||||||
				case 'shift': pattern.shift = true; break;
 | 
									case 'shift': pattern.shift = true; break;
 | 
				
			||||||
				default: pattern.which = keyCode(key).map(k => k.toLowerCase());
 | 
									default: pattern.which = keyCode(key).map(k => k.toLowerCase());
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return pattern;
 | 
							return pattern;
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,9 +14,10 @@ export default async function($root: any, force = false, silent = false) {
 | 
				
			||||||
				navigator.serviceWorker.controller.postMessage('clear');
 | 
									navigator.serviceWorker.controller.postMessage('clear');
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			navigator.serviceWorker.getRegistrations().then(registrations => {
 | 
								const registrations = await navigator.serviceWorker.getRegistrations();
 | 
				
			||||||
				registrations.forEach(registration => registration.unregister());
 | 
								for (const registration of registrations) {
 | 
				
			||||||
			});
 | 
									registration.unregister();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		} catch (e) {
 | 
							} catch (e) {
 | 
				
			||||||
			console.error(e);
 | 
								console.error(e);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -111,9 +111,9 @@ export default class Stream extends EventEmitter {
 | 
				
			||||||
				connections = [this.nonSharedConnections.find(c => c.id === id)];
 | 
									connections = [this.nonSharedConnections.find(c => c.id === id)];
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			connections.filter(c => c != null).forEach(c => {
 | 
								for (const c of connections.filter(c => c != null)) {
 | 
				
			||||||
				c.emit(body.type, body.body);
 | 
									c.emit(body.type, body.body);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			this.emit(type, body);
 | 
								this.emit(type, body);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,18 +57,18 @@ const emjdb: EmojiDef[] = lib.map((x: any) => ({
 | 
				
			||||||
	url: `https://twemoji.maxcdn.com/2/svg/${char2file(x[1].char)}.svg`
 | 
						url: `https://twemoji.maxcdn.com/2/svg/${char2file(x[1].char)}.svg`
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lib.forEach((x: any) => {
 | 
					for (const x of lib as any) {
 | 
				
			||||||
	if (x[1].keywords) {
 | 
						if (x[1].keywords) {
 | 
				
			||||||
		x[1].keywords.forEach(k => {
 | 
							for (const k of x[1].keywords) {
 | 
				
			||||||
			emjdb.push({
 | 
								emjdb.push({
 | 
				
			||||||
				emoji: x[1].char,
 | 
									emoji: x[1].char,
 | 
				
			||||||
				name: k,
 | 
									name: k,
 | 
				
			||||||
				aliasOf: x[0],
 | 
									aliasOf: x[0],
 | 
				
			||||||
				url: `https://twemoji.maxcdn.com/2/svg/${char2file(x[1].char)}.svg`
 | 
									url: `https://twemoji.maxcdn.com/2/svg/${char2file(x[1].char)}.svg`
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
emjdb.sort((a, b) => a.name.length - b.name.length);
 | 
					emjdb.sort((a, b) => a.name.length - b.name.length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,7 +120,7 @@ export default Vue.extend({
 | 
				
			||||||
		const customEmojis = (this.$root.getMetaSync() || { emojis: [] }).emojis || [];
 | 
							const customEmojis = (this.$root.getMetaSync() || { emojis: [] }).emojis || [];
 | 
				
			||||||
		const emojiDefinitions: EmojiDef[] = [];
 | 
							const emojiDefinitions: EmojiDef[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		customEmojis.forEach(x => {
 | 
							for (const x of customEmojis) {
 | 
				
			||||||
			emojiDefinitions.push({
 | 
								emojiDefinitions.push({
 | 
				
			||||||
				name: x.name,
 | 
									name: x.name,
 | 
				
			||||||
				emoji: `:${x.name}:`,
 | 
									emoji: `:${x.name}:`,
 | 
				
			||||||
| 
						 | 
					@ -129,7 +129,7 @@ export default Vue.extend({
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (x.aliases) {
 | 
								if (x.aliases) {
 | 
				
			||||||
				x.aliases.forEach(alias => {
 | 
									for (const alias of x.aliases) {
 | 
				
			||||||
					emojiDefinitions.push({
 | 
										emojiDefinitions.push({
 | 
				
			||||||
						name: alias,
 | 
											name: alias,
 | 
				
			||||||
						aliasOf: x.name,
 | 
											aliasOf: x.name,
 | 
				
			||||||
| 
						 | 
					@ -137,9 +137,9 @@ export default Vue.extend({
 | 
				
			||||||
						url: x.url,
 | 
											url: x.url,
 | 
				
			||||||
						isCustomEmoji: true
 | 
											isCustomEmoji: true
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
				});
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		emojiDefinitions.sort((a, b) => a.name.length - b.name.length);
 | 
							emojiDefinitions.sort((a, b) => a.name.length - b.name.length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,9 +148,9 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.textarea.addEventListener('keydown', this.onKeydown);
 | 
							this.textarea.addEventListener('keydown', this.onKeydown);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
							for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
			el.addEventListener('mousedown', this.onMousedown);
 | 
								el.addEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.$nextTick(() => {
 | 
							this.$nextTick(() => {
 | 
				
			||||||
			this.exec();
 | 
								this.exec();
 | 
				
			||||||
| 
						 | 
					@ -166,18 +166,18 @@ export default Vue.extend({
 | 
				
			||||||
	beforeDestroy() {
 | 
						beforeDestroy() {
 | 
				
			||||||
		this.textarea.removeEventListener('keydown', this.onKeydown);
 | 
							this.textarea.removeEventListener('keydown', this.onKeydown);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
							for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
			el.removeEventListener('mousedown', this.onMousedown);
 | 
								el.removeEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		exec() {
 | 
							exec() {
 | 
				
			||||||
			this.select = -1;
 | 
								this.select = -1;
 | 
				
			||||||
			if (this.$refs.suggests) {
 | 
								if (this.$refs.suggests) {
 | 
				
			||||||
				Array.from(this.items).forEach(el => {
 | 
									for (const el of Array.from(this.items)) {
 | 
				
			||||||
					el.removeAttribute('data-selected');
 | 
										el.removeAttribute('data-selected');
 | 
				
			||||||
				});
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (this.type == 'user') {
 | 
								if (this.type == 'user') {
 | 
				
			||||||
| 
						 | 
					@ -316,9 +316,9 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		applySelect() {
 | 
							applySelect() {
 | 
				
			||||||
			Array.from(this.items).forEach(el => {
 | 
								for (const el of Array.from(this.items)) {
 | 
				
			||||||
				el.removeAttribute('data-selected');
 | 
									el.removeAttribute('data-selected');
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.items[this.select].setAttribute('data-selected', 'true');
 | 
								this.items[this.select].setAttribute('data-selected', 'true');
 | 
				
			||||||
			(this.items[this.select] as any).focus();
 | 
								(this.items[this.select] as any).focus();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,11 +114,11 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onScroll(e) {
 | 
							onScroll(e) {
 | 
				
			||||||
			const section = this.categories.forEach(x => {
 | 
								for (const x of this.categories) {
 | 
				
			||||||
				const top = e.target.scrollTop;
 | 
									const top = e.target.scrollTop;
 | 
				
			||||||
				const el = this.$refs[x.ref][0];
 | 
									const el = this.$refs[x.ref][0];
 | 
				
			||||||
				x.isActive = el.offsetTop <= top && el.offsetTop + el.offsetHeight > top;
 | 
									x.isActive = el.offsetTop <= top && el.offsetTop + el.offsetHeight > top;
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		chosen(emoji) {
 | 
							chosen(emoji) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -185,9 +185,9 @@ export default Vue.extend({
 | 
				
			||||||
			loopedBoard: this.game.settings.loopedBoard
 | 
								loopedBoard: this.game.settings.loopedBoard
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.game.logs.forEach(log => {
 | 
							for (const log of this.game.logs) {
 | 
				
			||||||
			this.o.put(log.color, log.pos);
 | 
								this.o.put(log.color, log.pos);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.logs = this.game.logs;
 | 
							this.logs = this.game.logs;
 | 
				
			||||||
		this.logPos = this.logs.length;
 | 
							this.logPos = this.logs.length;
 | 
				
			||||||
| 
						 | 
					@ -287,9 +287,9 @@ export default Vue.extend({
 | 
				
			||||||
				loopedBoard: this.game.settings.loopedBoard
 | 
									loopedBoard: this.game.settings.loopedBoard
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.game.logs.forEach(log => {
 | 
								for (const log of this.game.logs) {
 | 
				
			||||||
				this.o.put(log.color, log.pos, true);
 | 
									this.o.put(log.color, log.pos, true);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.logs = this.game.logs;
 | 
								this.logs = this.game.logs;
 | 
				
			||||||
			this.logPos = this.logs.length;
 | 
								this.logPos = this.logs.length;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -196,12 +196,12 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onRead(ids) {
 | 
							onRead(ids) {
 | 
				
			||||||
			if (!Array.isArray(ids)) ids = [ids];
 | 
								if (!Array.isArray(ids)) ids = [ids];
 | 
				
			||||||
			ids.forEach(id => {
 | 
								for (const id of ids) {
 | 
				
			||||||
				if (this.messages.some(x => x.id == id)) {
 | 
									if (this.messages.some(x => x.id == id)) {
 | 
				
			||||||
					const exist = this.messages.map(x => x.id).indexOf(id);
 | 
										const exist = this.messages.map(x => x.id).indexOf(id);
 | 
				
			||||||
					this.messages[exist].isRead = true;
 | 
										this.messages[exist].isRead = true;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		isBottom() {
 | 
							isBottom() {
 | 
				
			||||||
| 
						 | 
					@ -248,13 +248,13 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onVisibilitychange() {
 | 
							onVisibilitychange() {
 | 
				
			||||||
			if (document.hidden) return;
 | 
								if (document.hidden) return;
 | 
				
			||||||
			this.messages.forEach(message => {
 | 
								for (const message of this.messages) {
 | 
				
			||||||
				if (message.userId !== this.$store.state.i.id && !message.isRead) {
 | 
									if (message.userId !== this.$store.state.i.id && !message.isRead) {
 | 
				
			||||||
					this.connection.send('read', {
 | 
										this.connection.send('read', {
 | 
				
			||||||
						id: message.id
 | 
											id: message.id
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,10 +103,10 @@ export default Vue.extend({
 | 
				
			||||||
			this.messages.unshift(message);
 | 
								this.messages.unshift(message);
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onRead(ids) {
 | 
							onRead(ids) {
 | 
				
			||||||
			ids.forEach(id => {
 | 
								for (const id of ids) {
 | 
				
			||||||
				const found = this.messages.find(m => m.id == id);
 | 
									const found = this.messages.find(m => m.id == id);
 | 
				
			||||||
				if (found) found.isRead = true;
 | 
									if (found) found.isRead = true;
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		search() {
 | 
							search() {
 | 
				
			||||||
			if (this.q == '') {
 | 
								if (this.q == '') {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,12 +55,12 @@ export default Vue.extend({
 | 
				
			||||||
				noteId: this.note.id,
 | 
									noteId: this.note.id,
 | 
				
			||||||
				choice: id
 | 
									choice: id
 | 
				
			||||||
			}).then(() => {
 | 
								}).then(() => {
 | 
				
			||||||
				this.poll.choices.forEach(c => {
 | 
									for (const c of this.poll.choices) {
 | 
				
			||||||
					if (c.id == id) {
 | 
										if (c.id == id) {
 | 
				
			||||||
						c.votes++;
 | 
											c.votes++;
 | 
				
			||||||
						Vue.set(c, 'isVoted', true);
 | 
											Vue.set(c, 'isVoted', true);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				});
 | 
									}
 | 
				
			||||||
				this.showResult = true;
 | 
									this.showResult = true;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -164,7 +164,7 @@ export default define({
 | 
				
			||||||
			this.draw();
 | 
								this.draw();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onStatsLog(statsLog) {
 | 
							onStatsLog(statsLog) {
 | 
				
			||||||
			statsLog.forEach(stats => this.onStats(stats));
 | 
								for (const stats of statsLog) this.onStats(stats);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,7 +121,7 @@ export default Vue.extend({
 | 
				
			||||||
			this.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
 | 
								this.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onStatsLog(statsLog) {
 | 
							onStatsLog(statsLog) {
 | 
				
			||||||
			statsLog.reverse().forEach(stats => this.onStats(stats));
 | 
								for (const stats of statsLog.reverse()) this.onStats(stats);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,9 @@ import Vue from 'vue';
 | 
				
			||||||
export default Vue.extend({
 | 
					export default Vue.extend({
 | 
				
			||||||
	props: ['data'],
 | 
						props: ['data'],
 | 
				
			||||||
	created() {
 | 
						created() {
 | 
				
			||||||
		this.data.forEach(d => d.total = d.notes + d.replies + d.renotes);
 | 
							for (const d of this.data) {
 | 
				
			||||||
 | 
								d.total = d.notes + d.replies + d.renotes;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		const peak = Math.max.apply(null, this.data.map(d => d.total));
 | 
							const peak = Math.max.apply(null, this.data.map(d => d.total));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const now = new Date();
 | 
							const now = new Date();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,10 @@ export default Vue.extend({
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	created() {
 | 
						created() {
 | 
				
			||||||
		this.data.forEach(d => d.total = d.notes + d.replies + d.renotes);
 | 
							for (const d of this.data) {
 | 
				
			||||||
 | 
								d.total = d.notes + d.replies + d.renotes;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.render();
 | 
							this.render();
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,9 +34,9 @@ export default Vue.extend({
 | 
				
			||||||
			this.$el.style.left = x + 'px';
 | 
								this.$el.style.left = x + 'px';
 | 
				
			||||||
			this.$el.style.top = y + 'px';
 | 
								this.$el.style.top = y + 'px';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
								for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
				el.addEventListener('mousedown', this.onMousedown);
 | 
									el.addEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.$el.style.display = 'block';
 | 
								this.$el.style.display = 'block';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,9 +59,9 @@ export default Vue.extend({
 | 
				
			||||||
			this.close();
 | 
								this.close();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		close() {
 | 
							close() {
 | 
				
			||||||
			Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
								for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
				el.removeEventListener('mousedown', this.onMousedown);
 | 
									el.removeEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.$emit('closed');
 | 
								this.$emit('closed');
 | 
				
			||||||
			this.destroyDom();
 | 
								this.destroyDom();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,9 +120,9 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// ファイルだったら
 | 
								// ファイルだったら
 | 
				
			||||||
			if (e.dataTransfer.files.length > 0) {
 | 
								if (e.dataTransfer.files.length > 0) {
 | 
				
			||||||
				Array.from(e.dataTransfer.files).forEach(file => {
 | 
									for (const file of Array.from(e.dataTransfer.files)) {
 | 
				
			||||||
					this.browser.upload(file, this.folder);
 | 
										this.browser.upload(file, this.folder);
 | 
				
			||||||
				});
 | 
									}
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,9 +68,9 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// ファイルだったら
 | 
								// ファイルだったら
 | 
				
			||||||
			if (e.dataTransfer.files.length > 0) {
 | 
								if (e.dataTransfer.files.length > 0) {
 | 
				
			||||||
				Array.from(e.dataTransfer.files).forEach(file => {
 | 
									for (const file of Array.from(e.dataTransfer.files)) {
 | 
				
			||||||
					this.browser.upload(file, this.folder);
 | 
										this.browser.upload(file, this.folder);
 | 
				
			||||||
				});
 | 
									}
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -277,9 +277,9 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// ドロップされてきたものがファイルだったら
 | 
								// ドロップされてきたものがファイルだったら
 | 
				
			||||||
			if (e.dataTransfer.files.length > 0) {
 | 
								if (e.dataTransfer.files.length > 0) {
 | 
				
			||||||
				Array.from(e.dataTransfer.files).forEach(file => {
 | 
									for (const file of Array.from(e.dataTransfer.files)) {
 | 
				
			||||||
					this.upload(file, this.folder);
 | 
										this.upload(file, this.folder);
 | 
				
			||||||
				});
 | 
									}
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -368,9 +368,9 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onChangeFileInput() {
 | 
							onChangeFileInput() {
 | 
				
			||||||
			Array.from((this.$refs.fileInput as any).files).forEach(file => {
 | 
								for (const file of Array.from((this.$refs.fileInput as any).files)) {
 | 
				
			||||||
				this.upload(file, this.folder);
 | 
									this.upload(file, this.folder);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		upload(file, folder) {
 | 
							upload(file, folder) {
 | 
				
			||||||
| 
						 | 
					@ -549,8 +549,8 @@ export default Vue.extend({
 | 
				
			||||||
			let flag = false;
 | 
								let flag = false;
 | 
				
			||||||
			const complete = () => {
 | 
								const complete = () => {
 | 
				
			||||||
				if (flag) {
 | 
									if (flag) {
 | 
				
			||||||
					fetchedFolders.forEach(this.appendFolder);
 | 
										for (const x of fetchedFolders) this.appendFolder(x);
 | 
				
			||||||
					fetchedFiles.forEach(this.appendFile);
 | 
										for (const x of fetchedFiles) this.appendFile(x);
 | 
				
			||||||
					this.fetching = false;
 | 
										this.fetching = false;
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					flag = true;
 | 
										flag = true;
 | 
				
			||||||
| 
						 | 
					@ -575,7 +575,7 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.moreFiles = false;
 | 
										this.moreFiles = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				files.forEach(this.appendFile);
 | 
									for (const x of files) this.appendFile(x);
 | 
				
			||||||
				this.fetching = false;
 | 
									this.fetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,9 +43,9 @@ export default Vue.extend({
 | 
				
			||||||
			this.$el.style.left = x + 'px';
 | 
								this.$el.style.left = x + 'px';
 | 
				
			||||||
			this.$el.style.top = y + 'px';
 | 
								this.$el.style.top = y + 'px';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
								for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
				el.addEventListener('mousedown', this.onMousedown);
 | 
									el.addEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,9 +62,9 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		close() {
 | 
							close() {
 | 
				
			||||||
			Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
								for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
				el.removeEventListener('mousedown', this.onMousedown);
 | 
									el.removeEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.$emit('closed');
 | 
								this.$emit('closed');
 | 
				
			||||||
			this.destroyDom();
 | 
								this.destroyDom();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,23 +102,23 @@ const defaultDesktopHomeWidgets = {
 | 
				
			||||||
//#region Construct home data
 | 
					//#region Construct home data
 | 
				
			||||||
const _defaultDesktopHomeWidgets = [];
 | 
					const _defaultDesktopHomeWidgets = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defaultDesktopHomeWidgets.left.forEach(widget => {
 | 
					for (const widget of defaultDesktopHomeWidgets.left) {
 | 
				
			||||||
	_defaultDesktopHomeWidgets.push({
 | 
						_defaultDesktopHomeWidgets.push({
 | 
				
			||||||
		name: widget,
 | 
							name: widget,
 | 
				
			||||||
		id: uuid(),
 | 
							id: uuid(),
 | 
				
			||||||
		place: 'left',
 | 
							place: 'left',
 | 
				
			||||||
		data: {}
 | 
							data: {}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
});
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defaultDesktopHomeWidgets.right.forEach(widget => {
 | 
					for (const widget of defaultDesktopHomeWidgets.right) {
 | 
				
			||||||
	_defaultDesktopHomeWidgets.push({
 | 
						_defaultDesktopHomeWidgets.push({
 | 
				
			||||||
		name: widget,
 | 
							name: widget,
 | 
				
			||||||
		id: uuid(),
 | 
							id: uuid(),
 | 
				
			||||||
		place: 'right',
 | 
							place: 'right',
 | 
				
			||||||
		data: {}
 | 
							data: {}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
});
 | 
					}
 | 
				
			||||||
//#endregion
 | 
					//#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Vue.extend({
 | 
					export default Vue.extend({
 | 
				
			||||||
| 
						 | 
					@ -220,8 +220,8 @@ export default Vue.extend({
 | 
				
			||||||
			const left = this.widgets.left;
 | 
								const left = this.widgets.left;
 | 
				
			||||||
			const right = this.widgets.right;
 | 
								const right = this.widgets.right;
 | 
				
			||||||
			this.$store.commit('settings/setHome', left.concat(right));
 | 
								this.$store.commit('settings/setHome', left.concat(right));
 | 
				
			||||||
			left.forEach(w => w.place = 'left');
 | 
								for (const w of left) w.place = 'left';
 | 
				
			||||||
			right.forEach(w => w.place = 'right');
 | 
								for (const w of right) w.place = 'right';
 | 
				
			||||||
			this.$root.api('i/update_home', {
 | 
								this.$root.api('i/update_home', {
 | 
				
			||||||
				home: this.home
 | 
									home: this.home
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -156,7 +156,9 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		releaseQueue() {
 | 
							releaseQueue() {
 | 
				
			||||||
			this.queue.forEach(n => this.prepend(n, true));
 | 
								for (const n of this.queue) {
 | 
				
			||||||
 | 
									this.prepend(n, true);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			this.queue = [];
 | 
								this.queue = [];
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,7 +184,8 @@ export default Vue.extend({
 | 
				
			||||||
		if (this.reply && this.reply.text != null) {
 | 
							if (this.reply && this.reply.text != null) {
 | 
				
			||||||
			const ast = parse(this.reply.text);
 | 
								const ast = parse(this.reply.text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ast.filter(t => t.type == 'mention').forEach(x => {
 | 
								// TODO: 新しいMFMパーサに対応
 | 
				
			||||||
 | 
								for (const x of ast.filter(t => t.type == 'mention')) {
 | 
				
			||||||
				const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`;
 | 
									const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// 自分は除外
 | 
									// 自分は除外
 | 
				
			||||||
| 
						 | 
					@ -195,7 +196,7 @@ export default Vue.extend({
 | 
				
			||||||
				if (this.text.indexOf(`${mention} `) != -1) return;
 | 
									if (this.text.indexOf(`${mention} `) != -1) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				this.text += `${mention} `;
 | 
									this.text += `${mention} `;
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// デフォルト公開範囲
 | 
							// デフォルト公開範囲
 | 
				
			||||||
| 
						 | 
					@ -261,7 +262,7 @@ export default Vue.extend({
 | 
				
			||||||
			this.$chooseDriveFile({
 | 
								this.$chooseDriveFile({
 | 
				
			||||||
				multiple: true
 | 
									multiple: true
 | 
				
			||||||
			}).then(files => {
 | 
								}).then(files => {
 | 
				
			||||||
				files.forEach(this.attachMedia);
 | 
									for (const x of files) this.attachMedia(x);
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -276,7 +277,7 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onChangeFile() {
 | 
							onChangeFile() {
 | 
				
			||||||
			Array.from((this.$refs.file as any).files).forEach(this.upload);
 | 
								for (const x of Array.from((this.$refs.file as any).files)) this.upload(x);
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onPollUpdate() {
 | 
							onPollUpdate() {
 | 
				
			||||||
| 
						 | 
					@ -304,11 +305,11 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onPaste(e) {
 | 
							onPaste(e) {
 | 
				
			||||||
			Array.from(e.clipboardData.items).forEach((item: any) => {
 | 
								for (const item of Array.from(e.clipboardData.items)) {
 | 
				
			||||||
				if (item.kind == 'file') {
 | 
									if (item.kind == 'file') {
 | 
				
			||||||
					this.upload(item.getAsFile());
 | 
										this.upload(item.getAsFile());
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onDragover(e) {
 | 
							onDragover(e) {
 | 
				
			||||||
| 
						 | 
					@ -335,7 +336,7 @@ export default Vue.extend({
 | 
				
			||||||
			// ファイルだったら
 | 
								// ファイルだったら
 | 
				
			||||||
			if (e.dataTransfer.files.length > 0) {
 | 
								if (e.dataTransfer.files.length > 0) {
 | 
				
			||||||
				e.preventDefault();
 | 
									e.preventDefault();
 | 
				
			||||||
				Array.from(e.dataTransfer.files).forEach(this.upload);
 | 
									for (const x of Array.from(e.dataTransfer.files)) this.upload(x);
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,15 +120,15 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		open() {
 | 
							open() {
 | 
				
			||||||
			this.isOpen = true;
 | 
								this.isOpen = true;
 | 
				
			||||||
			Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
								for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
				el.addEventListener('mousedown', this.onMousedown);
 | 
									el.addEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		close() {
 | 
							close() {
 | 
				
			||||||
			this.isOpen = false;
 | 
								this.isOpen = false;
 | 
				
			||||||
			Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
								for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
				el.removeEventListener('mousedown', this.onMousedown);
 | 
									el.removeEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onMousedown(e) {
 | 
							onMousedown(e) {
 | 
				
			||||||
			e.preventDefault();
 | 
								e.preventDefault();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,16 +42,16 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		open() {
 | 
							open() {
 | 
				
			||||||
			this.isOpen = true;
 | 
								this.isOpen = true;
 | 
				
			||||||
			Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
								for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
				el.addEventListener('mousedown', this.onMousedown);
 | 
									el.addEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		close() {
 | 
							close() {
 | 
				
			||||||
			this.isOpen = false;
 | 
								this.isOpen = false;
 | 
				
			||||||
			Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
								for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
				el.removeEventListener('mousedown', this.onMousedown);
 | 
									el.removeEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onMousedown(e) {
 | 
							onMousedown(e) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,16 +171,16 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		openNotifications() {
 | 
							openNotifications() {
 | 
				
			||||||
			this.showNotifications = true;
 | 
								this.showNotifications = true;
 | 
				
			||||||
			Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
								for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
				el.addEventListener('mousedown', this.onMousedown);
 | 
									el.addEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		closeNotifications() {
 | 
							closeNotifications() {
 | 
				
			||||||
			this.showNotifications = false;
 | 
								this.showNotifications = false;
 | 
				
			||||||
			Array.from(document.querySelectorAll('body *')).forEach(el => {
 | 
								for (const el of Array.from(document.querySelectorAll('body *'))) {
 | 
				
			||||||
				el.removeEventListener('mousedown', this.onMousedown);
 | 
									el.removeEventListener('mousedown', this.onMousedown);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onMousedown(e) {
 | 
							onMousedown(e) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) (this.$refs.timeline as any).append(n);
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -234,12 +234,12 @@ export default Vue.extend({
 | 
				
			||||||
		top() {
 | 
							top() {
 | 
				
			||||||
			let z = 0;
 | 
								let z = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.$root.os.windows.getAll().forEach(w => {
 | 
								const ws = this.$root.os.windows.getAll().filter(w => w != this);
 | 
				
			||||||
				if (w == this) return;
 | 
								for (const w of ws) {
 | 
				
			||||||
				const m = w.$refs.main;
 | 
									const m = w.$refs.main;
 | 
				
			||||||
				const mz = Number(document.defaultView.getComputedStyle(m, null).zIndex);
 | 
									const mz = Number(document.defaultView.getComputedStyle(m, null).zIndex);
 | 
				
			||||||
				if (mz > z) z = mz;
 | 
									if (mz > z) z = mz;
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (z > 0) {
 | 
								if (z > 0) {
 | 
				
			||||||
				(this.$refs.main as any).style.zIndex = z + 1;
 | 
									(this.$refs.main as any).style.zIndex = z + 1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -224,7 +224,9 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (this.menu) {
 | 
								if (this.menu) {
 | 
				
			||||||
				items.unshift(null);
 | 
									items.unshift(null);
 | 
				
			||||||
				this.menu.reverse().forEach(i => items.unshift(i));
 | 
									for (const i of this.menu.reverse()) {
 | 
				
			||||||
 | 
										items.unshift(i);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return items;
 | 
								return items;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,7 +102,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,7 +104,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -164,7 +164,9 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		releaseQueue() {
 | 
							releaseQueue() {
 | 
				
			||||||
			this.queue.forEach(n => this.prepend(n, true));
 | 
								for (const n of this.queue) {
 | 
				
			||||||
 | 
									this.prepend(n, true);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			this.queue = [];
 | 
								this.queue = [];
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,7 +142,9 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		releaseQueue() {
 | 
							releaseQueue() {
 | 
				
			||||||
			this.queue.forEach(n => this.prepend(n));
 | 
								for (const n of this.queue) {
 | 
				
			||||||
 | 
									this.prepend(n);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			this.queue = [];
 | 
								this.queue = [];
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,7 +123,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -167,11 +167,11 @@ export default Vue.extend({
 | 
				
			||||||
				limit: 9,
 | 
									limit: 9,
 | 
				
			||||||
				untilDate: new Date().getTime() + 1000 * 86400 * 365
 | 
									untilDate: new Date().getTime() + 1000 * 86400 * 365
 | 
				
			||||||
			}).then(notes => {
 | 
								}).then(notes => {
 | 
				
			||||||
				notes.forEach(note => {
 | 
									for (const note of notes) {
 | 
				
			||||||
					note.files.forEach(file => {
 | 
										for (const file of note.files) {
 | 
				
			||||||
						file._note = note;
 | 
											file._note = note;
 | 
				
			||||||
					});
 | 
										}
 | 
				
			||||||
				});
 | 
									}
 | 
				
			||||||
				const files = concat(notes.map((n: any): any[] => n.files));
 | 
									const files = concat(notes.map((n: any): any[] => n.files));
 | 
				
			||||||
				this.images = files.filter(f => image.includes(f.type)).slice(0, 9);
 | 
									this.images = files.filter(f => image.includes(f.type)).slice(0, 9);
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
| 
						 | 
					@ -298,7 +298,7 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) (this.$refs.timeline as any).append(n);
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,7 +94,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,11 +30,11 @@ export default Vue.extend({
 | 
				
			||||||
			limit: 9,
 | 
								limit: 9,
 | 
				
			||||||
			untilDate: new Date().getTime() + 1000 * 86400 * 365
 | 
								untilDate: new Date().getTime() + 1000 * 86400 * 365
 | 
				
			||||||
		}).then(notes => {
 | 
							}).then(notes => {
 | 
				
			||||||
			notes.forEach(note => {
 | 
								for (const note of notes) {
 | 
				
			||||||
				note.files.forEach(file => {
 | 
									for (const file of note.files) {
 | 
				
			||||||
					if (this.images.length < 9) this.images.push(file);
 | 
										if (this.images.length < 9) this.images.push(file);
 | 
				
			||||||
				});
 | 
									}
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
			this.fetching = false;
 | 
								this.fetching = false;
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,7 @@ export default define({
 | 
				
			||||||
			this.$chooseDriveFile({
 | 
								this.$chooseDriveFile({
 | 
				
			||||||
				multiple: true
 | 
									multiple: true
 | 
				
			||||||
			}).then(files => {
 | 
								}).then(files => {
 | 
				
			||||||
				files.forEach(this.attachMedia);
 | 
									for (const x of files) this.attachMedia(x);
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,15 +118,15 @@ export default define({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onPaste(e) {
 | 
							onPaste(e) {
 | 
				
			||||||
			Array.from(e.clipboardData.items).forEach((item: any) => {
 | 
								for (const item of Array.from(e.clipboardData.items)) {
 | 
				
			||||||
				if (item.kind == 'file') {
 | 
									if (item.kind == 'file') {
 | 
				
			||||||
					this.upload(item.getAsFile());
 | 
										this.upload(item.getAsFile());
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onChangeFile() {
 | 
							onChangeFile() {
 | 
				
			||||||
			Array.from((this.$refs.file as any).files).forEach(this.upload);
 | 
								for (const x of Array.from((this.$refs.file as any).files)) this.upload(x);
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		upload(file) {
 | 
							upload(file) {
 | 
				
			||||||
| 
						 | 
					@ -146,7 +146,7 @@ export default define({
 | 
				
			||||||
			// ファイルだったら
 | 
								// ファイルだったら
 | 
				
			||||||
			if (e.dataTransfer.files.length > 0) {
 | 
								if (e.dataTransfer.files.length > 0) {
 | 
				
			||||||
				e.preventDefault();
 | 
									e.preventDefault();
 | 
				
			||||||
				Array.from(e.dataTransfer.files).forEach(this.upload);
 | 
									for (const x of Array.from(e.dataTransfer.files)) this.upload(x);
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -297,8 +297,8 @@ export default Vue.extend({
 | 
				
			||||||
			let flag = false;
 | 
								let flag = false;
 | 
				
			||||||
			const complete = () => {
 | 
								const complete = () => {
 | 
				
			||||||
				if (flag) {
 | 
									if (flag) {
 | 
				
			||||||
					fetchedFolders.forEach(this.appendFolder);
 | 
										for (const x of fetchedFolders) this.appendFolder(x);
 | 
				
			||||||
					fetchedFiles.forEach(this.appendFile);
 | 
										for (const x of fetchedFiles) this.appendFile(x);
 | 
				
			||||||
					this.fetching = false;
 | 
										this.fetching = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					// 一連の読み込みが完了したイベントを発行
 | 
										// 一連の読み込みが完了したイベントを発行
 | 
				
			||||||
| 
						 | 
					@ -336,7 +336,7 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.moreFiles = false;
 | 
										this.moreFiles = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				files.forEach(this.appendFile);
 | 
									for (const x of files) this.appendFile(x);
 | 
				
			||||||
				this.fetching = false;
 | 
									this.fetching = false;
 | 
				
			||||||
				this.fetchingMoreFiles = false;
 | 
									this.fetchingMoreFiles = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
| 
						 | 
					@ -460,8 +460,9 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onChangeLocalFile() {
 | 
							onChangeLocalFile() {
 | 
				
			||||||
			Array.from((this.$refs.file as any).files)
 | 
								for (const f of Array.from((this.$refs.file as any).files)) {
 | 
				
			||||||
				.forEach(f => (this.$refs.uploader as any).upload(f, this.folder));
 | 
									(this.$refs.uploader as any).upload(f, this.folder);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,9 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		releaseQueue() {
 | 
							releaseQueue() {
 | 
				
			||||||
			this.queue.forEach(n => this.prepend(n, true));
 | 
								for (const n of this.queue) {
 | 
				
			||||||
 | 
									this.prepend(n, true);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			this.queue = [];
 | 
								this.queue = [];
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -174,7 +174,7 @@ export default Vue.extend({
 | 
				
			||||||
		if (this.reply && this.reply.text != null) {
 | 
							if (this.reply && this.reply.text != null) {
 | 
				
			||||||
			const ast = parse(this.reply.text);
 | 
								const ast = parse(this.reply.text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ast.filter(t => t.type == 'mention').forEach(x => {
 | 
								for (const x of ast.filter(t => t.type == 'mention')) {
 | 
				
			||||||
				const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`;
 | 
									const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// 自分は除外
 | 
									// 自分は除外
 | 
				
			||||||
| 
						 | 
					@ -185,7 +185,7 @@ export default Vue.extend({
 | 
				
			||||||
				if (this.text.indexOf(`${mention} `) != -1) return;
 | 
									if (this.text.indexOf(`${mention} `) != -1) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				this.text += `${mention} `;
 | 
									this.text += `${mention} `;
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// デフォルト公開範囲
 | 
							// デフォルト公開範囲
 | 
				
			||||||
| 
						 | 
					@ -241,7 +241,7 @@ export default Vue.extend({
 | 
				
			||||||
			this.$chooseDriveFile({
 | 
								this.$chooseDriveFile({
 | 
				
			||||||
				multiple: true
 | 
									multiple: true
 | 
				
			||||||
			}).then(files => {
 | 
								}).then(files => {
 | 
				
			||||||
				files.forEach(this.attachMedia);
 | 
									for (const x of files) this.attachMedia(x);
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -256,7 +256,7 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onChangeFile() {
 | 
							onChangeFile() {
 | 
				
			||||||
			Array.from((this.$refs.file as any).files).forEach(this.upload);
 | 
								for (const x of Array.from((this.$refs.file as any).files)) this.upload(x);
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onPollUpdate() {
 | 
							onPollUpdate() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,7 +94,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,7 +76,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -150,7 +150,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,9 @@ export default Vue.extend({
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					this.existMore = false;
 | 
										this.existMore = false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				notes.forEach(n => (this.$refs.timeline as any).append(n));
 | 
									for (const n of notes) {
 | 
				
			||||||
 | 
										(this.$refs.timeline as any).append(n);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				this.moreFetching = false;
 | 
									this.moreFetching = false;
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,14 +32,16 @@ export default Vue.extend({
 | 
				
			||||||
			limit: 6,
 | 
								limit: 6,
 | 
				
			||||||
			untilDate: new Date().getTime() + 1000 * 86400 * 365
 | 
								untilDate: new Date().getTime() + 1000 * 86400 * 365
 | 
				
			||||||
		}).then(notes => {
 | 
							}).then(notes => {
 | 
				
			||||||
			notes.forEach(note => {
 | 
								for (const note of notes) {
 | 
				
			||||||
				note.media.forEach(media => {
 | 
									for (const media of note.media) {
 | 
				
			||||||
					if (this.images.length < 9) this.images.push({
 | 
										if (this.images.length < 9) {
 | 
				
			||||||
						note,
 | 
											this.images.push({
 | 
				
			||||||
						media
 | 
												note,
 | 
				
			||||||
					});
 | 
												media
 | 
				
			||||||
				});
 | 
											});
 | 
				
			||||||
			});
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			this.fetching = false;
 | 
								this.fetching = false;
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,9 +136,9 @@ export default (os: MiOS) => new Vuex.Store({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mergeMe(ctx, me) {
 | 
							mergeMe(ctx, me) {
 | 
				
			||||||
			Object.entries(me).forEach(([key, value]) => {
 | 
								for (const [key, value] of Object.entries(me)) {
 | 
				
			||||||
				ctx.commit('updateIKeyValue', { key, value });
 | 
									ctx.commit('updateIKeyValue', { key, value });
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (me.clientSettings) {
 | 
								if (me.clientSettings) {
 | 
				
			||||||
				ctx.dispatch('settings/merge', me.clientSettings);
 | 
									ctx.dispatch('settings/merge', me.clientSettings);
 | 
				
			||||||
| 
						 | 
					@ -215,11 +215,11 @@ export default (os: MiOS) => new Vuex.Store({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					//#region Deck
 | 
										//#region Deck
 | 
				
			||||||
					if (state.deck && state.deck.columns) {
 | 
										if (state.deck && state.deck.columns) {
 | 
				
			||||||
						state.deck.columns.filter(c => c.type == 'widgets').forEach(c => {
 | 
											for (const c of state.deck.columns.filter(c => c.type == 'widgets')) {
 | 
				
			||||||
							c.widgets.forEach(w => {
 | 
												for (const w of c.widgets.filter(w => w.id == x.id)) {
 | 
				
			||||||
								if (w.id == x.id) w.data = x.data;
 | 
													w.data = x.data;
 | 
				
			||||||
							});
 | 
												}
 | 
				
			||||||
						});
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					//#endregion
 | 
										//#endregion
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
| 
						 | 
					@ -345,9 +345,9 @@ export default (os: MiOS) => new Vuex.Store({
 | 
				
			||||||
			actions: {
 | 
								actions: {
 | 
				
			||||||
				merge(ctx, settings) {
 | 
									merge(ctx, settings) {
 | 
				
			||||||
					if (settings == null) return;
 | 
										if (settings == null) return;
 | 
				
			||||||
					Object.entries(settings).forEach(([key, value]) => {
 | 
										for (const [key, value] of Object.entries(settings)) {
 | 
				
			||||||
						ctx.commit('set', { key, value });
 | 
											ctx.commit('set', { key, value });
 | 
				
			||||||
					});
 | 
										}
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				set(ctx, x) {
 | 
									set(ctx, x) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,6 +62,8 @@ self.addEventListener('push', ev => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
self.addEventListener('message', ev => {
 | 
					self.addEventListener('message', ev => {
 | 
				
			||||||
	if (ev.data == 'clear') {
 | 
						if (ev.data == 'clear') {
 | 
				
			||||||
		caches.keys().then(keys => keys.forEach(key => caches.delete(key)));
 | 
							caches.keys().then(keys => {
 | 
				
			||||||
 | 
								for (const key of keys) caches.delete(key);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,9 +36,9 @@ export function applyTheme(theme: Theme, persisted = true) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const props = compile(_theme);
 | 
						const props = compile(_theme);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Object.entries(props).forEach(([k, v]) => {
 | 
						for (const [k, v] of Object.entries(props)) {
 | 
				
			||||||
		document.documentElement.style.setProperty(`--${k}`, v.toString());
 | 
							document.documentElement.style.setProperty(`--${k}`, v.toString());
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (persisted) {
 | 
						if (persisted) {
 | 
				
			||||||
		localStorage.setItem('theme', JSON.stringify(props));
 | 
							localStorage.setItem('theme', JSON.stringify(props));
 | 
				
			||||||
| 
						 | 
					@ -74,10 +74,9 @@ function compile(theme: Theme): { [key: string]: string } {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const props = {};
 | 
						const props = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Object.entries(theme.props).forEach(([k, v]) => {
 | 
						for (const [k, v] of Object.entries(theme.props)) {
 | 
				
			||||||
		const c = getColor(v);
 | 
							props[k] = genValue(getColor(v));
 | 
				
			||||||
		props[k] = genValue(c);
 | 
						}
 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const primary = getColor(props['primary']);
 | 
						const primary = getColor(props['primary']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,9 @@ export default function(html: string): string {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let text = '';
 | 
						let text = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dom.childNodes.forEach((n: any) => analyze(n));
 | 
						for (const n of dom.childNodes) {
 | 
				
			||||||
 | 
							analyze(n);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return text.trim();
 | 
						return text.trim();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,13 +63,17 @@ export default function(html: string): string {
 | 
				
			||||||
			case 'p':
 | 
								case 'p':
 | 
				
			||||||
				text += '\n\n';
 | 
									text += '\n\n';
 | 
				
			||||||
				if (node.childNodes) {
 | 
									if (node.childNodes) {
 | 
				
			||||||
					node.childNodes.forEach((n: any) => analyze(n));
 | 
										for (const n of node.childNodes) {
 | 
				
			||||||
 | 
											analyze(n);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				if (node.childNodes) {
 | 
									if (node.childNodes) {
 | 
				
			||||||
					node.childNodes.forEach((n: any) => analyze(n));
 | 
										for (const n of node.childNodes) {
 | 
				
			||||||
 | 
											analyze(n);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,21 +17,20 @@ export default (source: string, plainText = false): Node[] => {
 | 
				
			||||||
			es[0].name === 'text' ? [combineText(es)] : es
 | 
								es[0].name === 'text' ? [combineText(es)] : es
 | 
				
			||||||
		));
 | 
							));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const concatTextRecursive = (es: Node[]): void =>
 | 
						const concatTextRecursive = (es: Node[]): void => {
 | 
				
			||||||
		es.filter(x => x.children).forEach(x => {
 | 
							for (const x of es.filter(x => x.children)) {
 | 
				
			||||||
			x.children = concatText(x.children);
 | 
								x.children = concatText(x.children);
 | 
				
			||||||
			concatTextRecursive(x.children);
 | 
								concatTextRecursive(x.children);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nodes = concatText(nodes);
 | 
						nodes = concatText(nodes);
 | 
				
			||||||
	concatTextRecursive(nodes);
 | 
						concatTextRecursive(nodes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const removeEmptyTextNodes = (nodes: Node[]) => {
 | 
						const removeEmptyTextNodes = (nodes: Node[]) => {
 | 
				
			||||||
		nodes.forEach(n => {
 | 
							for (const n of nodes.filter(n => n.children)) {
 | 
				
			||||||
			if (n.children) {
 | 
								n.children = removeEmptyTextNodes(n.children);
 | 
				
			||||||
				n.children = removeEmptyTextNodes(n.children);
 | 
							}
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		return nodes.filter(n => !(n.name == 'text' && n.props.text == ''));
 | 
							return nodes.filter(n => !(n.name == 'text' && n.props.text == ''));
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,10 @@ export function sum(xs: number[]): number {
 | 
				
			||||||
	return xs.reduce((a, b) => a + b, 0);
 | 
						return xs.reduce((a, b) => a + b, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function maximum(xs: number[]): number {
 | 
				
			||||||
 | 
						return Math.max(...xs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function groupBy<T>(f: (x: T, y: T) => boolean, xs: T[]): T[][] {
 | 
					export function groupBy<T>(f: (x: T, y: T) => boolean, xs: T[]): T[][] {
 | 
				
			||||||
	const groups = [] as T[][];
 | 
						const groups = [] as T[][];
 | 
				
			||||||
	for (const x of xs) {
 | 
						for (const x of xs) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ export default async function(userId: mongo.ObjectID | string, type: string, bod
 | 
				
			||||||
		userId: userId
 | 
							userId: userId
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	subscriptions.forEach(subscription => {
 | 
						for (const subscription of subscriptions) {
 | 
				
			||||||
		const pushSubscription = {
 | 
							const pushSubscription = {
 | 
				
			||||||
			endpoint: subscription.endpoint,
 | 
								endpoint: subscription.endpoint,
 | 
				
			||||||
			keys: {
 | 
								keys: {
 | 
				
			||||||
| 
						 | 
					@ -48,5 +48,5 @@ export default async function(userId: mongo.ObjectID | string, type: string, bod
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,10 +47,7 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
 | 
				
			||||||
	}> = [];
 | 
						}> = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// カウント
 | 
						// カウント
 | 
				
			||||||
	data.map(x => x._id).forEach(x => {
 | 
						for (const x of data.map(x => x._id).filter(x => !hidedTags.includes(x.tag))) {
 | 
				
			||||||
		// ブラックリストに登録されているタグなら弾く
 | 
					 | 
				
			||||||
		if (hidedTags.includes(x.tag)) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		const i = tags.findIndex(tag => tag.name == x.tag);
 | 
							const i = tags.findIndex(tag => tag.name == x.tag);
 | 
				
			||||||
		if (i != -1) {
 | 
							if (i != -1) {
 | 
				
			||||||
			tags[i].count++;
 | 
								tags[i].count++;
 | 
				
			||||||
| 
						 | 
					@ -60,7 +57,7 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
 | 
				
			||||||
				count: 1
 | 
									count: 1
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// タグを人気順に並べ替え
 | 
						// タグを人気順に並べ替え
 | 
				
			||||||
	tags.sort((a, b) => b.count - a.count);
 | 
						tags.sort((a, b) => b.count - a.count);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,14 +100,14 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 | 
				
			||||||
	Note.find({
 | 
						Note.find({
 | 
				
			||||||
		'_files._id': file._id
 | 
							'_files._id': file._id
 | 
				
			||||||
	}).then(notes => {
 | 
						}).then(notes => {
 | 
				
			||||||
		notes.forEach(note => {
 | 
							for (const note of notes) {
 | 
				
			||||||
			note._files[note._files.findIndex(f => f._id.equals(file._id))] = file;
 | 
								note._files[note._files.findIndex(f => f._id.equals(file._id))] = file;
 | 
				
			||||||
			Note.update({ _id: note._id }, {
 | 
								Note.update({ _id: note._id }, {
 | 
				
			||||||
				$set: {
 | 
									$set: {
 | 
				
			||||||
					_files: note._files
 | 
										_files: note._files
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Serialize
 | 
						// Serialize
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,9 +25,8 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 | 
				
			||||||
		loopedBoard: game.settings.loopedBoard
 | 
							loopedBoard: game.settings.loopedBoard
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	game.logs.forEach(log => {
 | 
						for (const log of game.logs)
 | 
				
			||||||
		o.put(log.color, log.pos);
 | 
							o.put(log.color, log.pos);
 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const packed = await pack(game, user);
 | 
						const packed = await pack(game, user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,10 +58,7 @@ export default define(meta, () => new Promise(async (res, rej) => {
 | 
				
			||||||
	}> = [];
 | 
						}> = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// カウント
 | 
						// カウント
 | 
				
			||||||
	data.map(x => x._id).forEach(x => {
 | 
						for (const x of data.map(x => x._id).filter(x => !hidedTags.includes(x.tag))) {
 | 
				
			||||||
		// ブラックリストに登録されているタグなら弾く
 | 
					 | 
				
			||||||
		if (hidedTags.includes(x.tag)) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		const i = tags.findIndex(tag => tag.name == x.tag);
 | 
							const i = tags.findIndex(tag => tag.name == x.tag);
 | 
				
			||||||
		if (i != -1) {
 | 
							if (i != -1) {
 | 
				
			||||||
			tags[i].count++;
 | 
								tags[i].count++;
 | 
				
			||||||
| 
						 | 
					@ -71,7 +68,7 @@ export default define(meta, () => new Promise(async (res, rej) => {
 | 
				
			||||||
				count: 1
 | 
									count: 1
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 最低要求投稿者数を下回るならカットする
 | 
						// 最低要求投稿者数を下回るならカットする
 | 
				
			||||||
	const limitedTags = tags.filter(tag => tag.count >= requiredUsers);
 | 
						const limitedTags = tags.filter(tag => tag.count >= requiredUsers);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,11 +59,11 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 | 
				
			||||||
	//#region Deck
 | 
						//#region Deck
 | 
				
			||||||
	if (widget == null && user.clientSettings.deck && user.clientSettings.deck.columns) {
 | 
						if (widget == null && user.clientSettings.deck && user.clientSettings.deck.columns) {
 | 
				
			||||||
		const deck = user.clientSettings.deck;
 | 
							const deck = user.clientSettings.deck;
 | 
				
			||||||
		deck.columns.filter((c: any) => c.type == 'widgets').forEach((c: any) => {
 | 
							for (const c of deck.columns.filter((c: any) => c.type == 'widgets')) {
 | 
				
			||||||
			c.widgets.forEach((w: any) => {
 | 
								for (const w of c.widgets.filter((w: any) => w.id == ps.id)) {
 | 
				
			||||||
				if (w.id == ps.id) widget = w;
 | 
									widget = w;
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
		if (widget) {
 | 
							if (widget) {
 | 
				
			||||||
				widget.data = ps.data;
 | 
									widget.data = ps.data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,5 +91,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	res(await packMany(mentions, user));
 | 
						res(await packMany(mentions, user));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mentions.forEach(note => read(user._id, note._id));
 | 
						for (const note of mentions) {
 | 
				
			||||||
 | 
							read(user._id, note._id);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,12 +102,12 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		.then(watchers => {
 | 
							.then(watchers => {
 | 
				
			||||||
			watchers.forEach(watcher => {
 | 
								for (const watcher of watchers) {
 | 
				
			||||||
				notify(watcher.userId, user._id, 'poll_vote', {
 | 
									notify(watcher.userId, user._id, 'poll_vote', {
 | 
				
			||||||
					noteId: note._id,
 | 
										noteId: note._id,
 | 
				
			||||||
					choice: ps.choice
 | 
										choice: ps.choice
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// この投稿をWatchする
 | 
						// この投稿をWatchする
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id';
 | 
				
			||||||
import Note from '../../../../models/note';
 | 
					import Note from '../../../../models/note';
 | 
				
			||||||
import User, { pack } from '../../../../models/user';
 | 
					import User, { pack } from '../../../../models/user';
 | 
				
			||||||
import define from '../../define';
 | 
					import define from '../../define';
 | 
				
			||||||
 | 
					import { maximum } from '../../../../prelude/array';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const meta = {
 | 
					export const meta = {
 | 
				
			||||||
	requireCredential: false,
 | 
						requireCredential: false,
 | 
				
			||||||
| 
						 | 
					@ -77,20 +78,16 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
 | 
				
			||||||
	const repliedUsers: any = {};
 | 
						const repliedUsers: any = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Extract replies from recent notes
 | 
						// Extract replies from recent notes
 | 
				
			||||||
	replyTargetNotes.forEach(note => {
 | 
						for (const userId of replyTargetNotes.map(x => x.userId.toString())) {
 | 
				
			||||||
		const userId = note.userId.toString();
 | 
					 | 
				
			||||||
		if (repliedUsers[userId]) {
 | 
							if (repliedUsers[userId]) {
 | 
				
			||||||
			repliedUsers[userId]++;
 | 
								repliedUsers[userId]++;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			repliedUsers[userId] = 1;
 | 
								repliedUsers[userId] = 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Calc peak
 | 
						// Calc peak
 | 
				
			||||||
	let peak = 0;
 | 
						const peak = maximum(Object.values(repliedUsers));
 | 
				
			||||||
	Object.keys(repliedUsers).forEach(user => {
 | 
					 | 
				
			||||||
		if (repliedUsers[user] > peak) peak = repliedUsers[user];
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Sort replies by frequency
 | 
						// Sort replies by frequency
 | 
				
			||||||
	const repliedUsersSorted = Object.keys(repliedUsers).sort((a, b) => repliedUsers[b] - repliedUsers[a]);
 | 
						const repliedUsersSorted = Object.keys(repliedUsers).sort((a, b) => repliedUsers[b] - repliedUsers[a]);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,10 +41,13 @@ const router = new Router();
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Register endpoint handlers
 | 
					 * Register endpoint handlers
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
endpoints.forEach(endpoint => endpoint.meta.requireFile
 | 
					for (const endpoint of endpoints) {
 | 
				
			||||||
	? router.post(`/${endpoint.name}`, upload.single('file'), handler.bind(null, endpoint))
 | 
						if (endpoint.meta.requireFile) {
 | 
				
			||||||
	: router.post(`/${endpoint.name}`, handler.bind(null, endpoint))
 | 
							router.post(`/${endpoint.name}`, upload.single('file'), handler.bind(null, endpoint));
 | 
				
			||||||
);
 | 
						} else {
 | 
				
			||||||
 | 
							router.post(`/${endpoint.name}`, handler.bind(null, endpoint));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
router.post('/signup', require('./private/signup').default);
 | 
					router.post('/signup', require('./private/signup').default);
 | 
				
			||||||
router.post('/signin', require('./private/signin').default);
 | 
					router.post('/signin', require('./private/signin').default);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -242,9 +242,9 @@ export default class extends Channel {
 | 
				
			||||||
			loopedBoard: game.settings.loopedBoard
 | 
								loopedBoard: game.settings.loopedBoard
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		game.logs.forEach(log => {
 | 
							for (const log of game.logs) {
 | 
				
			||||||
			o.put(log.color, log.pos);
 | 
								o.put(log.color, log.pos);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const myColor =
 | 
							const myColor =
 | 
				
			||||||
			(game.user1Id.equals(this.user._id) && game.black == 1) || (game.user2Id.equals(this.user._id) && game.black == 2)
 | 
								(game.user1Id.equals(this.user._id) && game.black == 1) || (game.user2Id.equals(this.user._id) && game.black == 2)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -213,8 +213,8 @@ export default class Connection {
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	@autobind
 | 
						@autobind
 | 
				
			||||||
	public dispose() {
 | 
						public dispose() {
 | 
				
			||||||
		this.channels.forEach(c => {
 | 
							for (const c of this.channels.filter(c => c.dispose)) {
 | 
				
			||||||
			if (c.dispose) c.dispose();
 | 
								c.dispose();
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,9 +91,9 @@ app.use(mount(require('./web')));
 | 
				
			||||||
function createServer() {
 | 
					function createServer() {
 | 
				
			||||||
	if (config.https) {
 | 
						if (config.https) {
 | 
				
			||||||
		const certs: any = {};
 | 
							const certs: any = {};
 | 
				
			||||||
		Object.keys(config.https).forEach(k => {
 | 
							for (const k of Object.keys(config.https)) {
 | 
				
			||||||
			certs[k] = fs.readFileSync(config.https[k]);
 | 
								certs[k] = fs.readFileSync(config.https[k]);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
		certs['allowHTTP1'] = true;
 | 
							certs['allowHTTP1'] = true;
 | 
				
			||||||
		return http2.createSecureServer(certs, app.callback());
 | 
							return http2.createSecureServer(certs, app.callback());
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ async function genVars(lang: string): Promise<{ [key: string]: any }> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const docs = glob.sync(`src/docs/**/*.${lang}.md`, { cwd });
 | 
						const docs = glob.sync(`src/docs/**/*.${lang}.md`, { cwd });
 | 
				
			||||||
	vars['docs'] = {};
 | 
						vars['docs'] = {};
 | 
				
			||||||
	docs.forEach(x => {
 | 
						for (const x of docs) {
 | 
				
			||||||
		const [, name] = x.match(/docs\/(.+?)\.(.+?)\.md$/);
 | 
							const [, name] = x.match(/docs\/(.+?)\.(.+?)\.md$/);
 | 
				
			||||||
		if (vars['docs'][name] == null) {
 | 
							if (vars['docs'][name] == null) {
 | 
				
			||||||
			vars['docs'][name] = {
 | 
								vars['docs'][name] = {
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@ async function genVars(lang: string): Promise<{ [key: string]: any }> {
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		vars['docs'][name]['title'][lang] = fs.readFileSync(cwd + x, 'utf-8').match(/^# (.+?)\r?\n/)[1];
 | 
							vars['docs'][name]['title'][lang] = fs.readFileSync(cwd + x, 'utf-8').match(/^# (.+?)\r?\n/)[1];
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vars['kebab'] = (string: string) => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase();
 | 
						vars['kebab'] = (string: string) => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,7 +121,7 @@ const sortParams = (params: Array<{ name: string }>) => {
 | 
				
			||||||
const extractParamDefRef = (params: Context[]) => {
 | 
					const extractParamDefRef = (params: Context[]) => {
 | 
				
			||||||
	let defs: any[] = [];
 | 
						let defs: any[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params.forEach(param => {
 | 
						for (const param of params) {
 | 
				
			||||||
		if (param.data && param.data.ref) {
 | 
							if (param.data && param.data.ref) {
 | 
				
			||||||
			const props = (param as ObjectContext<any>).props;
 | 
								const props = (param as ObjectContext<any>).props;
 | 
				
			||||||
			defs.push({
 | 
								defs.push({
 | 
				
			||||||
| 
						 | 
					@ -133,7 +133,7 @@ const extractParamDefRef = (params: Context[]) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			defs = defs.concat(childDefs);
 | 
								defs = defs.concat(childDefs);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return sortParams(defs);
 | 
						return sortParams(defs);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -141,7 +141,7 @@ const extractParamDefRef = (params: Context[]) => {
 | 
				
			||||||
const extractPropDefRef = (props: any[]) => {
 | 
					const extractPropDefRef = (props: any[]) => {
 | 
				
			||||||
	let defs: any[] = [];
 | 
						let defs: any[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Object.entries(props).forEach(([k, v]) => {
 | 
						for (const [k, v] of Object.entries(props)) {
 | 
				
			||||||
		if (v.props) {
 | 
							if (v.props) {
 | 
				
			||||||
			defs.push({
 | 
								defs.push({
 | 
				
			||||||
				name: k,
 | 
									name: k,
 | 
				
			||||||
| 
						 | 
					@ -152,7 +152,7 @@ const extractPropDefRef = (props: any[]) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			defs = defs.concat(childDefs);
 | 
								defs = defs.concat(childDefs);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return sortParams(defs);
 | 
						return sortParams(defs);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,10 +11,10 @@ export default async function(user: IUser) {
 | 
				
			||||||
		followeeId: user._id
 | 
							followeeId: user._id
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	requests.forEach(async request => {
 | 
						for (const request of requests) {
 | 
				
			||||||
		const follower = await User.findOne({ _id: request.followerId });
 | 
							const follower = await User.findOne({ _id: request.followerId });
 | 
				
			||||||
		accept(user, follower);
 | 
							accept(user, follower);
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	User.update({ _id: user._id }, {
 | 
						User.update({ _id: user._id }, {
 | 
				
			||||||
		$set: {
 | 
							$set: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,9 +101,9 @@ export async function deliverPinnedChange(userId: mongo.ObjectID, noteId: mongo.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const item = `${config.url}/notes/${noteId}`;
 | 
						const item = `${config.url}/notes/${noteId}`;
 | 
				
			||||||
	const content = packAp(isAddition ? renderAdd(user, target, item) : renderRemove(user, target, item));
 | 
						const content = packAp(isAddition ? renderAdd(user, target, item) : renderRemove(user, target, item));
 | 
				
			||||||
	queue.forEach(inbox => {
 | 
						for (const inbox of queue) {
 | 
				
			||||||
		deliver(user, content, inbox);
 | 
							deliver(user, content, inbox);
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,9 +30,9 @@ export async function publishToFollowers(userId: mongo.ObjectID) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (queue.length > 0) {
 | 
							if (queue.length > 0) {
 | 
				
			||||||
			const content = packAp(renderUpdate(await renderPerson(user), user));
 | 
								const content = packAp(renderUpdate(await renderPerson(user), user));
 | 
				
			||||||
			queue.forEach(inbox => {
 | 
								for (const inbox of queue) {
 | 
				
			||||||
				deliver(user, content, inbox);
 | 
									deliver(user, content, inbox);
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,8 +65,8 @@ class NotificationManager {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public deliver() {
 | 
						public async deliver() {
 | 
				
			||||||
		this.queue.forEach(async x => {
 | 
							for (const x of this.queue) {
 | 
				
			||||||
			// ミュート情報を取得
 | 
								// ミュート情報を取得
 | 
				
			||||||
			const mentioneeMutes = await Mute.find({
 | 
								const mentioneeMutes = await Mute.find({
 | 
				
			||||||
				muterId: x.target
 | 
									muterId: x.target
 | 
				
			||||||
| 
						 | 
					@ -80,7 +80,7 @@ class NotificationManager {
 | 
				
			||||||
					noteId: this.note._id
 | 
										noteId: this.note._id
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -175,11 +175,11 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (data.visibility == 'specified') {
 | 
						if (data.visibility == 'specified') {
 | 
				
			||||||
		data.visibleUsers.forEach(u => {
 | 
							for (const u of data.visibleUsers) {
 | 
				
			||||||
			if (!mentionedUsers.some(x => x._id.equals(u._id))) {
 | 
								if (!mentionedUsers.some(x => x._id.equals(u._id))) {
 | 
				
			||||||
				mentionedUsers.push(u);
 | 
									mentionedUsers.push(u);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const note = await insertNote(user, data, tags, emojis, mentionedUsers);
 | 
						const note = await insertNote(user, data, tags, emojis, mentionedUsers);
 | 
				
			||||||
| 
						 | 
					@ -213,13 +213,13 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ファイルが添付されていた場合ドライブのファイルの「このファイルが添付された投稿一覧」プロパティにこの投稿を追加
 | 
						// ファイルが添付されていた場合ドライブのファイルの「このファイルが添付された投稿一覧」プロパティにこの投稿を追加
 | 
				
			||||||
	if (data.files) {
 | 
						if (data.files) {
 | 
				
			||||||
		data.files.forEach(file => {
 | 
							for (const file of data.files) {
 | 
				
			||||||
			DriveFile.update({ _id: file._id }, {
 | 
								DriveFile.update({ _id: file._id }, {
 | 
				
			||||||
				$push: {
 | 
									$push: {
 | 
				
			||||||
					'metadata.attachedNoteIds': note._id
 | 
										'metadata.attachedNoteIds': note._id
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Increment notes count
 | 
						// Increment notes count
 | 
				
			||||||
| 
						 | 
					@ -230,13 +230,13 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 未読通知を作成
 | 
						// 未読通知を作成
 | 
				
			||||||
	if (data.visibility == 'specified') {
 | 
						if (data.visibility == 'specified') {
 | 
				
			||||||
		data.visibleUsers.forEach(u => {
 | 
							for (const u of data.visibleUsers) {
 | 
				
			||||||
			insertNoteUnread(u, note, true);
 | 
								insertNoteUnread(u, note, true);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		mentionedUsers.forEach(u => {
 | 
							for (const u of mentionedUsers) {
 | 
				
			||||||
			insertNoteUnread(u, note, false);
 | 
								insertNoteUnread(u, note, false);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (data.reply) {
 | 
						if (data.reply) {
 | 
				
			||||||
| 
						 | 
					@ -469,12 +469,12 @@ function extractHashtags(tokens: ReturnType<typeof parse>): string[] {
 | 
				
			||||||
	const hashtags: string[] = [];
 | 
						const hashtags: string[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const extract = (tokens: Node[]) => {
 | 
						const extract = (tokens: Node[]) => {
 | 
				
			||||||
		tokens.filter(x => x.name === 'hashtag').forEach(x => {
 | 
							for (const x of tokens.filter(x => x.name === 'hashtag')) {
 | 
				
			||||||
			hashtags.push(x.props.hashtag);
 | 
								hashtags.push(x.props.hashtag);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
		tokens.filter(x => x.children).forEach(x => {
 | 
							for (const x of tokens.filter(x => x.children)) {
 | 
				
			||||||
			extract(x.children);
 | 
								extract(x.children);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Extract hashtags
 | 
						// Extract hashtags
 | 
				
			||||||
| 
						 | 
					@ -487,14 +487,14 @@ export function extractEmojis(tokens: ReturnType<typeof parse>): string[] {
 | 
				
			||||||
	const emojis: string[] = [];
 | 
						const emojis: string[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const extract = (tokens: Node[]) => {
 | 
						const extract = (tokens: Node[]) => {
 | 
				
			||||||
		tokens.filter(x => x.name === 'emoji').forEach(x => {
 | 
							for (const x of tokens.filter(x => x.name === 'emoji')) {
 | 
				
			||||||
			if (x.props.name && x.props.name.length <= 100) {
 | 
								if (x.props.name && x.props.name.length <= 100) {
 | 
				
			||||||
				emojis.push(x.props.name);
 | 
									emojis.push(x.props.name);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
		tokens.filter(x => x.children).forEach(x => {
 | 
							for (const x of tokens.filter(x => x.children)) {
 | 
				
			||||||
			extract(x.children);
 | 
								extract(x.children);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Extract emojis
 | 
						// Extract emojis
 | 
				
			||||||
| 
						 | 
					@ -526,9 +526,9 @@ async function notifyToWatchersOfRenotee(renote: INote, user: IUser, nm: Notific
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	watchers.forEach(watcher => {
 | 
						for (const watcher of watchers) {
 | 
				
			||||||
		nm.push(watcher.userId, type);
 | 
							nm.push(watcher.userId, type);
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function notifyToWatchersOfReplyee(reply: INote, user: IUser, nm: NotificationManager) {
 | 
					async function notifyToWatchersOfReplyee(reply: INote, user: IUser, nm: NotificationManager) {
 | 
				
			||||||
| 
						 | 
					@ -541,9 +541,9 @@ async function notifyToWatchersOfReplyee(reply: INote, user: IUser, nm: Notifica
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	watchers.forEach(watcher => {
 | 
						for (const watcher of watchers) {
 | 
				
			||||||
		nm.push(watcher.userId, 'reply');
 | 
							nm.push(watcher.userId, 'reply');
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function publishToUserLists(note: INote, noteObj: any) {
 | 
					async function publishToUserLists(note: INote, noteObj: any) {
 | 
				
			||||||
| 
						 | 
					@ -551,9 +551,9 @@ async function publishToUserLists(note: INote, noteObj: any) {
 | 
				
			||||||
		userIds: note.userId
 | 
							userIds: note.userId
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lists.forEach(list => {
 | 
						for (const list of lists) {
 | 
				
			||||||
		publishUserListStream(list._id, 'note', noteObj);
 | 
							publishUserListStream(list._id, 'note', noteObj);
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function publishToFollowers(note: INote, user: IUser, noteActivity: any) {
 | 
					async function publishToFollowers(note: INote, user: IUser, noteActivity: any) {
 | 
				
			||||||
| 
						 | 
					@ -594,19 +594,19 @@ async function publishToFollowers(note: INote, user: IUser, noteActivity: any) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	queue.forEach(inbox => {
 | 
						for (const inbox of queue) {
 | 
				
			||||||
		deliver(user as any, noteActivity, inbox);
 | 
							deliver(user as any, noteActivity, inbox);
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function deliverNoteToMentionedRemoteUsers(mentionedUsers: IUser[], user: ILocalUser, noteActivity: any) {
 | 
					function deliverNoteToMentionedRemoteUsers(mentionedUsers: IUser[], user: ILocalUser, noteActivity: any) {
 | 
				
			||||||
	mentionedUsers.filter(u => isRemoteUser(u)).forEach(async (u) => {
 | 
						for (const u of mentionedUsers.filter(u => isRemoteUser(u))) {
 | 
				
			||||||
		deliver(user, noteActivity, (u as IRemoteUser).inbox);
 | 
							deliver(user, noteActivity, (u as IRemoteUser).inbox);
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function createMentionedEvents(mentionedUsers: IUser[], note: INote, nm: NotificationManager) {
 | 
					async function createMentionedEvents(mentionedUsers: IUser[], note: INote, nm: NotificationManager) {
 | 
				
			||||||
	mentionedUsers.filter(u => isLocalUser(u)).forEach(async (u) => {
 | 
						for (const u of mentionedUsers.filter(u => isLocalUser(u))) {
 | 
				
			||||||
		const detailPackedNote = await pack(note, u, {
 | 
							const detailPackedNote = await pack(note, u, {
 | 
				
			||||||
			detail: true
 | 
								detail: true
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
| 
						 | 
					@ -615,7 +615,7 @@ function createMentionedEvents(mentionedUsers: IUser[], note: INote, nm: Notific
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Create notification
 | 
							// Create notification
 | 
				
			||||||
		nm.push(u._id, 'mention');
 | 
							nm.push(u._id, 'mention');
 | 
				
			||||||
	});
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function saveQuote(renote: INote, note: INote) {
 | 
					function saveQuote(renote: INote, note: INote) {
 | 
				
			||||||
| 
						 | 
					@ -668,12 +668,12 @@ async function extractMentionedUsers(user: IUser, tokens: ReturnType<typeof pars
 | 
				
			||||||
	const mentions: any[] = [];
 | 
						const mentions: any[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const extract = (tokens: Node[]) => {
 | 
						const extract = (tokens: Node[]) => {
 | 
				
			||||||
		tokens.filter(x => x.name === 'mention').forEach(x => {
 | 
							for (const x of tokens.filter(x => x.name === 'mention')) {
 | 
				
			||||||
			mentions.push(x.props);
 | 
								mentions.push(x.props);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
		tokens.filter(x => x.children).forEach(x => {
 | 
							for (const x of tokens.filter(x => x.children)) {
 | 
				
			||||||
			extract(x.children);
 | 
								extract(x.children);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Extract hashtags
 | 
						// Extract hashtags
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,20 +44,20 @@ export default async function(user: IUser, note: INote) {
 | 
				
			||||||
	NoteUnread.find({
 | 
						NoteUnread.find({
 | 
				
			||||||
		noteId: note._id
 | 
							noteId: note._id
 | 
				
			||||||
	}).then(unreads => {
 | 
						}).then(unreads => {
 | 
				
			||||||
		unreads.forEach(unread => {
 | 
							for (const unread of unreads) {
 | 
				
			||||||
			read(unread.userId, unread.noteId);
 | 
								read(unread.userId, unread.noteId);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ファイルが添付されていた場合ドライブのファイルの「このファイルが添付された投稿一覧」プロパティからこの投稿を削除
 | 
						// ファイルが添付されていた場合ドライブのファイルの「このファイルが添付された投稿一覧」プロパティからこの投稿を削除
 | 
				
			||||||
	if (note.fileIds) {
 | 
						if (note.fileIds) {
 | 
				
			||||||
		note.fileIds.forEach(fileId => {
 | 
							for (const fileId of note.fileIds) {
 | 
				
			||||||
			DriveFile.update({ _id: fileId }, {
 | 
								DriveFile.update({ _id: fileId }, {
 | 
				
			||||||
				$pull: {
 | 
									$pull: {
 | 
				
			||||||
					'metadata.attachedNoteIds': note._id
 | 
										'metadata.attachedNoteIds': note._id
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//#region ローカルの投稿なら削除アクティビティを配送
 | 
						//#region ローカルの投稿なら削除アクティビティを配送
 | 
				
			||||||
| 
						 | 
					@ -69,9 +69,9 @@ export default async function(user: IUser, note: INote) {
 | 
				
			||||||
			'_follower.host': { $ne: null }
 | 
								'_follower.host': { $ne: null }
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		followings.forEach(following => {
 | 
							for (const following of followings) {
 | 
				
			||||||
			deliver(user, content, following._follower.inbox);
 | 
								deliver(user, content, following._follower.inbox);
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	//#endregion
 | 
						//#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,12 +70,12 @@ export default async (user: IUser, note: INote, reaction: string) => new Promise
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		.then(watchers => {
 | 
							.then(watchers => {
 | 
				
			||||||
			watchers.forEach(watcher => {
 | 
								for (const watcher of watchers) {
 | 
				
			||||||
				notify(watcher.userId, user._id, 'reaction', {
 | 
									notify(watcher.userId, user._id, 'reaction', {
 | 
				
			||||||
					noteId: note._id,
 | 
										noteId: note._id,
 | 
				
			||||||
					reaction: reaction
 | 
										reaction: reaction
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			});
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ユーザーがローカルユーザーかつ自動ウォッチ設定がオンならばこの投稿をWatchする
 | 
						// ユーザーがローカルユーザーかつ自動ウォッチ設定がオンならばこの投稿をWatchする
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,10 @@
 | 
				
			||||||
		"member-ordering": [false],
 | 
							"member-ordering": [false],
 | 
				
			||||||
		"ban-types": [
 | 
							"ban-types": [
 | 
				
			||||||
			"Object"
 | 
								"Object"
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
 | 
							"ban": [
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
								{"name": ["*", "forEach"], "message": "Use for-of loop instead."}
 | 
				
			||||||
		]
 | 
							]
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"rulesDirectory": []
 | 
						"rulesDirectory": []
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue