リファクタリングなど
This commit is contained in:
		
							parent
							
								
									1625b37b44
								
							
						
					
					
						commit
						372bfaceda
					
				
					 64 changed files with 521 additions and 570 deletions
				
			
		| 
						 | 
					@ -18,61 +18,65 @@ export default function<T extends object>(data: {
 | 
				
			||||||
				default: false
 | 
									default: false
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		computed: {
 | 
							computed: {
 | 
				
			||||||
			id(): string {
 | 
								id(): string {
 | 
				
			||||||
				return this.widget.id;
 | 
									return this.widget.id;
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								props(): T {
 | 
				
			||||||
 | 
									return this.widget.data;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		data() {
 | 
							data() {
 | 
				
			||||||
			return {
 | 
								return {
 | 
				
			||||||
				props: data.props ? data.props() : {} as T,
 | 
									bakedOldProps: null
 | 
				
			||||||
				bakedOldProps: null,
 | 
					 | 
				
			||||||
				preventSave: false
 | 
					 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		created() {
 | 
							created() {
 | 
				
			||||||
			if (this.props) {
 | 
								this.mergeProps();
 | 
				
			||||||
				Object.keys(this.props).forEach(prop => {
 | 
					
 | 
				
			||||||
					if (this.widget.data.hasOwnProperty(prop)) {
 | 
								this.$watch('props', () => {
 | 
				
			||||||
						this.props[prop] = this.widget.data[prop];
 | 
									this.mergeProps();
 | 
				
			||||||
					}
 | 
								});
 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.bakeProps();
 | 
								this.bakeProps();
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.$watch('props', newProps => {
 | 
							methods: {
 | 
				
			||||||
				if (this.preventSave) {
 | 
								bakeProps() {
 | 
				
			||||||
					this.preventSave = false;
 | 
									this.bakedOldProps = JSON.stringify(this.props);
 | 
				
			||||||
					this.bakeProps();
 | 
								},
 | 
				
			||||||
					return;
 | 
					
 | 
				
			||||||
 | 
								mergeProps() {
 | 
				
			||||||
 | 
									if (data.props) {
 | 
				
			||||||
 | 
										const defaultProps = data.props();
 | 
				
			||||||
 | 
										Object.keys(defaultProps).forEach(prop => {
 | 
				
			||||||
 | 
											if (!this.props.hasOwnProperty(prop)) {
 | 
				
			||||||
 | 
												Vue.set(this.props, prop, defaultProps[prop]);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (this.bakedOldProps == JSON.stringify(newProps)) return;
 | 
								},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								save() {
 | 
				
			||||||
 | 
									if (this.bakedOldProps == JSON.stringify(this.props)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				this.bakeProps();
 | 
									this.bakeProps();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (this.isMobile) {
 | 
									if (this.isMobile) {
 | 
				
			||||||
					(this as any).api('i/update_mobile_home', {
 | 
										(this as any).api('i/update_mobile_home', {
 | 
				
			||||||
						id: this.id,
 | 
											id: this.id,
 | 
				
			||||||
						data: newProps
 | 
											data: this.props
 | 
				
			||||||
					}).then(() => {
 | 
					 | 
				
			||||||
						(this as any).os.i.clientSettings.mobileHome.find(w => w.id == this.id).data = newProps;
 | 
					 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					(this as any).api('i/update_home', {
 | 
										(this as any).api('i/update_home', {
 | 
				
			||||||
						id: this.id,
 | 
											id: this.id,
 | 
				
			||||||
						data: newProps
 | 
											data: this.props
 | 
				
			||||||
					}).then(() => {
 | 
					 | 
				
			||||||
						(this as any).os.i.clientSettings.home.find(w => w.id == this.id).data = newProps;
 | 
					 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}, {
 | 
					 | 
				
			||||||
				deep: true
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		methods: {
 | 
					 | 
				
			||||||
			bakeProps() {
 | 
					 | 
				
			||||||
				this.bakedOldProps = JSON.stringify(this.props);
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ import { EventEmitter } from 'eventemitter3';
 | 
				
			||||||
import * as merge from 'object-assign-deep';
 | 
					import * as merge from 'object-assign-deep';
 | 
				
			||||||
import * as uuid from 'uuid';
 | 
					import * as uuid from 'uuid';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import initStore from '../store';
 | 
				
			||||||
import { hostname, apiUrl, swPublickey, version, lang, googleMapsApiKey } from '../config';
 | 
					import { hostname, apiUrl, swPublickey, version, lang, googleMapsApiKey } from '../config';
 | 
				
			||||||
import Progress from './scripts/loading';
 | 
					import Progress from './scripts/loading';
 | 
				
			||||||
import Connection from './scripts/streaming/stream';
 | 
					import Connection from './scripts/streaming/stream';
 | 
				
			||||||
| 
						 | 
					@ -16,16 +17,6 @@ import Err from '../common/views/components/connect-failed.vue';
 | 
				
			||||||
import { LocalTimelineStreamManager } from './scripts/streaming/local-timeline';
 | 
					import { LocalTimelineStreamManager } from './scripts/streaming/local-timeline';
 | 
				
			||||||
import { GlobalTimelineStreamManager } from './scripts/streaming/global-timeline';
 | 
					import { GlobalTimelineStreamManager } from './scripts/streaming/global-timeline';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const defaultSettings = {
 | 
					 | 
				
			||||||
	fetchOnScroll: true,
 | 
					 | 
				
			||||||
	showMaps: true,
 | 
					 | 
				
			||||||
	showPostFormOnTopOfTl: false,
 | 
					 | 
				
			||||||
	gradientWindowHeader: false,
 | 
					 | 
				
			||||||
	showReplyTarget: true,
 | 
					 | 
				
			||||||
	showMyRenotes: true,
 | 
					 | 
				
			||||||
	showRenotedMyNotes: true
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//#region api requests
 | 
					//#region api requests
 | 
				
			||||||
let spinner = null;
 | 
					let spinner = null;
 | 
				
			||||||
let pending = 0;
 | 
					let pending = 0;
 | 
				
			||||||
| 
						 | 
					@ -117,6 +108,8 @@ export default class MiOS extends EventEmitter {
 | 
				
			||||||
		return localStorage.getItem('enableSounds') == 'true';
 | 
							return localStorage.getItem('enableSounds') == 'true';
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public store: ReturnType<typeof initStore>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public apis: API;
 | 
						public apis: API;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
| 
						 | 
					@ -232,6 +225,11 @@ export default class MiOS extends EventEmitter {
 | 
				
			||||||
		console.error.apply(null, args);
 | 
							console.error.apply(null, args);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public bakeMe() {
 | 
				
			||||||
 | 
							// ローカルストレージにキャッシュ
 | 
				
			||||||
 | 
							localStorage.setItem('me', JSON.stringify(this.i));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public signout() {
 | 
						public signout() {
 | 
				
			||||||
		localStorage.removeItem('me');
 | 
							localStorage.removeItem('me');
 | 
				
			||||||
		document.cookie = `i=; domain=${hostname}; expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
 | 
							document.cookie = `i=; domain=${hostname}; expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
 | 
				
			||||||
| 
						 | 
					@ -243,6 +241,8 @@ export default class MiOS extends EventEmitter {
 | 
				
			||||||
	 * @param callback A function that call when initialized
 | 
						 * @param callback A function that call when initialized
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public async init(callback) {
 | 
						public async init(callback) {
 | 
				
			||||||
 | 
							this.store = initStore(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//#region Init stream managers
 | 
							//#region Init stream managers
 | 
				
			||||||
		this.streams.serverStream = new ServerStreamManager(this);
 | 
							this.streams.serverStream = new ServerStreamManager(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -307,16 +307,11 @@ export default class MiOS extends EventEmitter {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// フェッチが完了したとき
 | 
							// フェッチが完了したとき
 | 
				
			||||||
		const fetched = me => {
 | 
							const fetched = me => {
 | 
				
			||||||
			if (me) {
 | 
					 | 
				
			||||||
				// デフォルトの設定をマージ
 | 
					 | 
				
			||||||
				me.clientSettings = Object.assign(defaultSettings, me.clientSettings);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				// ローカルストレージにキャッシュ
 | 
					 | 
				
			||||||
				localStorage.setItem('me', JSON.stringify(me));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			this.i = me;
 | 
								this.i = me;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// ローカルストレージにキャッシュ
 | 
				
			||||||
 | 
								this.bakeMe();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.emit('signedin');
 | 
								this.emit('signedin');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Finish init
 | 
								// Finish init
 | 
				
			||||||
| 
						 | 
					@ -333,6 +328,14 @@ export default class MiOS extends EventEmitter {
 | 
				
			||||||
		// Get cached account data
 | 
							// Get cached account data
 | 
				
			||||||
		const cachedMe = JSON.parse(localStorage.getItem('me'));
 | 
							const cachedMe = JSON.parse(localStorage.getItem('me'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//#region キャッシュされた設定を復元
 | 
				
			||||||
 | 
							const cachedSettings = JSON.parse(localStorage.getItem('settings'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (cachedSettings) {
 | 
				
			||||||
 | 
								this.store.commit('settings/init', cachedSettings);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							//#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// キャッシュがあったとき
 | 
							// キャッシュがあったとき
 | 
				
			||||||
		if (cachedMe) {
 | 
							if (cachedMe) {
 | 
				
			||||||
			if (cachedMe.token == null) {
 | 
								if (cachedMe.token == null) {
 | 
				
			||||||
| 
						 | 
					@ -346,12 +349,25 @@ export default class MiOS extends EventEmitter {
 | 
				
			||||||
			// 後から新鮮なデータをフェッチ
 | 
								// 後から新鮮なデータをフェッチ
 | 
				
			||||||
			fetchme(cachedMe.token, freshData => {
 | 
								fetchme(cachedMe.token, freshData => {
 | 
				
			||||||
				merge(cachedMe, freshData);
 | 
									merge(cachedMe, freshData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									this.store.commit('settings/init', freshData.clientSettings);
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			// Get token from cookie
 | 
								// Get token from cookie
 | 
				
			||||||
			const i = (document.cookie.match(/i=(!\w+)/) || [null, null])[1];
 | 
								const i = (document.cookie.match(/i=(!\w+)/) || [null, null])[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			fetchme(i, fetched);
 | 
								fetchme(i, me => {
 | 
				
			||||||
 | 
									if (me) {
 | 
				
			||||||
 | 
										Object.entries(me.clientSettings).forEach(([key, value]) => {
 | 
				
			||||||
 | 
											this.store.commit('settings/set', { key, value });
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										fetched(me);
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										// Finish init
 | 
				
			||||||
 | 
										callback();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -456,7 +472,7 @@ export default class MiOS extends EventEmitter {
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const promise = new Promise((resolve, reject) => {
 | 
							const promise = new Promise((resolve, reject) => {
 | 
				
			||||||
			const viaStream = this.stream.hasConnection &&
 | 
								const viaStream = this.stream && this.stream.hasConnection &&
 | 
				
			||||||
				(localStorage.getItem('apiViaStream') ? localStorage.getItem('apiViaStream') == 'true' : true);
 | 
									(localStorage.getItem('apiViaStream') ? localStorage.getItem('apiViaStream') == 'true' : true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (viaStream) {
 | 
								if (viaStream) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,10 +25,31 @@ export class HomeStream extends Stream {
 | 
				
			||||||
				console.log('I updated:', i);
 | 
									console.log('I updated:', i);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			merge(me, i);
 | 
								merge(me, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// キャッシュ更新
 | 
				
			||||||
 | 
								os.bakeMe();
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('clientSettingUpdated', x => {
 | 
				
			||||||
 | 
								os.store.commit('settings/set', {
 | 
				
			||||||
 | 
									key: x.key,
 | 
				
			||||||
 | 
									value: x.value
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('home_updated', x => {
 | 
				
			||||||
 | 
								if (x.home) {
 | 
				
			||||||
 | 
									os.store.commit('settings/setHome', x.home);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									os.store.commit('settings/setHomeWidget', {
 | 
				
			||||||
 | 
										id: x.id,
 | 
				
			||||||
 | 
										data: x.data
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// トークンが再生成されたとき
 | 
							// トークンが再生成されたとき
 | 
				
			||||||
		// このままではAPIが利用できないので強制的にサインアウトさせる
 | 
							// このままではMisskeyが利用できないので強制的にサインアウトさせる
 | 
				
			||||||
		this.on('my_token_regenerated', () => {
 | 
							this.on('my_token_regenerated', () => {
 | 
				
			||||||
			alert('%i18n:!common.my-token-regenerated%');
 | 
								alert('%i18n:!common.my-token-regenerated%');
 | 
				
			||||||
			os.signout();
 | 
								os.signout();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										38
									
								
								src/client/app/common/views/components/avatar.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/client/app/common/views/components/avatar.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,38 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<router-link class="mk-avatar" :to="user | userPage" :title="user | acct" :target="target" :style="{ borderRadius: clientSettings.circleIcons ? '100%' : null }">
 | 
				
			||||||
 | 
							<img v-if="disablePreview" :src="`${user.avatarUrl}?thumbnail&size=128`" alt=""/>
 | 
				
			||||||
 | 
							<img v-else :src="`${user.avatarUrl}?thumbnail&size=128`" alt="" v-user-preview="user.id"/>
 | 
				
			||||||
 | 
						</router-link>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					export default Vue.extend({
 | 
				
			||||||
 | 
						props: {
 | 
				
			||||||
 | 
							user: {
 | 
				
			||||||
 | 
								required: true
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							target: {
 | 
				
			||||||
 | 
								required: false,
 | 
				
			||||||
 | 
								default: null
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							disablePreview: {
 | 
				
			||||||
 | 
								required: false,
 | 
				
			||||||
 | 
								default: false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="stylus" scoped>
 | 
				
			||||||
 | 
					.mk-avatar
 | 
				
			||||||
 | 
						display block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						> img
 | 
				
			||||||
 | 
							display inline-block
 | 
				
			||||||
 | 
							width 100%
 | 
				
			||||||
 | 
							height 100%
 | 
				
			||||||
 | 
							margin 0
 | 
				
			||||||
 | 
							border-radius inherit
 | 
				
			||||||
 | 
							vertical-align bottom
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ import Vue from 'vue';
 | 
				
			||||||
import signin from './signin.vue';
 | 
					import signin from './signin.vue';
 | 
				
			||||||
import signup from './signup.vue';
 | 
					import signup from './signup.vue';
 | 
				
			||||||
import forkit from './forkit.vue';
 | 
					import forkit from './forkit.vue';
 | 
				
			||||||
 | 
					import avatar from './avatar.vue';
 | 
				
			||||||
import nav from './nav.vue';
 | 
					import nav from './nav.vue';
 | 
				
			||||||
import noteHtml from './note-html';
 | 
					import noteHtml from './note-html';
 | 
				
			||||||
import poll from './poll.vue';
 | 
					import poll from './poll.vue';
 | 
				
			||||||
| 
						 | 
					@ -28,6 +29,7 @@ import welcomeTimeline from './welcome-timeline.vue';
 | 
				
			||||||
Vue.component('mk-signin', signin);
 | 
					Vue.component('mk-signin', signin);
 | 
				
			||||||
Vue.component('mk-signup', signup);
 | 
					Vue.component('mk-signup', signup);
 | 
				
			||||||
Vue.component('mk-forkit', forkit);
 | 
					Vue.component('mk-forkit', forkit);
 | 
				
			||||||
 | 
					Vue.component('mk-avatar', avatar);
 | 
				
			||||||
Vue.component('mk-nav', nav);
 | 
					Vue.component('mk-nav', nav);
 | 
				
			||||||
Vue.component('mk-note-html', noteHtml);
 | 
					Vue.component('mk-note-html', noteHtml);
 | 
				
			||||||
Vue.component('mk-poll', poll);
 | 
					Vue.component('mk-poll', poll);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="message" :data-is-me="isMe">
 | 
					<div class="message" :data-is-me="isMe">
 | 
				
			||||||
	<router-link class="avatar-anchor" :to="message.user | userPage" :title="message.user | acct" target="_blank">
 | 
						<mk-avatar class="avatar" :user="message.user" target="_blank"/>
 | 
				
			||||||
		<img class="avatar" :src="`${message.user.avatarUrl}?thumbnail&size=80`" alt=""/>
 | 
					 | 
				
			||||||
	</router-link>
 | 
					 | 
				
			||||||
	<div class="content">
 | 
						<div class="content">
 | 
				
			||||||
		<div class="balloon" :data-no-text="message.text == null">
 | 
							<div class="balloon" :data-no-text="message.text == null">
 | 
				
			||||||
			<p class="read" v-if="isMe && message.isRead">%i18n:@is-read%</p>
 | 
								<p class="read" v-if="isMe && message.isRead">%i18n:@is-read%</p>
 | 
				
			||||||
| 
						 | 
					@ -67,20 +65,14 @@ export default Vue.extend({
 | 
				
			||||||
	padding 10px 12px 10px 12px
 | 
						padding 10px 12px 10px 12px
 | 
				
			||||||
	background-color transparent
 | 
						background-color transparent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .avatar-anchor
 | 
						> .avatar
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		position absolute
 | 
							position absolute
 | 
				
			||||||
		top 10px
 | 
							top 10px
 | 
				
			||||||
 | 
							width 54px
 | 
				
			||||||
		> .avatar
 | 
							height 54px
 | 
				
			||||||
			display block
 | 
							border-radius 8px
 | 
				
			||||||
			min-width 54px
 | 
							transition all 0.1s ease
 | 
				
			||||||
			min-height 54px
 | 
					 | 
				
			||||||
			max-width 54px
 | 
					 | 
				
			||||||
			max-height 54px
 | 
					 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			border-radius 8px
 | 
					 | 
				
			||||||
			transition all 0.1s ease
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .content
 | 
						> .content
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -201,7 +193,7 @@ export default Vue.extend({
 | 
				
			||||||
				margin-left 4px
 | 
									margin-left 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	&:not([data-is-me])
 | 
						&:not([data-is-me])
 | 
				
			||||||
		> .avatar-anchor
 | 
							> .avatar
 | 
				
			||||||
			left 12px
 | 
								left 12px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .content
 | 
							> .content
 | 
				
			||||||
| 
						 | 
					@ -225,7 +217,7 @@ export default Vue.extend({
 | 
				
			||||||
				text-align left
 | 
									text-align left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	&[data-is-me]
 | 
						&[data-is-me]
 | 
				
			||||||
		> .avatar-anchor
 | 
							> .avatar
 | 
				
			||||||
			right 12px
 | 
								right 12px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .content
 | 
							> .content
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@
 | 
				
			||||||
					@click="navigate(user)"
 | 
										@click="navigate(user)"
 | 
				
			||||||
					tabindex="-1"
 | 
										tabindex="-1"
 | 
				
			||||||
				>
 | 
									>
 | 
				
			||||||
					<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=32`" alt=""/>
 | 
										<mk-avatar class="avatar" :user="user"/>
 | 
				
			||||||
					<span class="name">{{ user | userName }}</span>
 | 
										<span class="name">{{ user | userName }}</span>
 | 
				
			||||||
					<span class="username">@{{ user | acct }}</span>
 | 
										<span class="username">@{{ user | acct }}</span>
 | 
				
			||||||
				</li>
 | 
									</li>
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@
 | 
				
			||||||
				:key="message.id"
 | 
									:key="message.id"
 | 
				
			||||||
			>
 | 
								>
 | 
				
			||||||
				<div>
 | 
									<div>
 | 
				
			||||||
					<img class="avatar" :src="`${isMe(message) ? message.recipient.avatarUrl : message.user.avatarUrl}?thumbnail&size=64`" alt=""/>
 | 
										<mk-avatar class="avatar" :user="isMe(message) ? message.recipient : message.user"/>
 | 
				
			||||||
					<header>
 | 
										<header>
 | 
				
			||||||
						<span class="name">{{ isMe(message) ? message.recipient : message.user | userName }}</span>
 | 
											<span class="name">{{ isMe(message) ? message.recipient : message.user | userName }}</span>
 | 
				
			||||||
						<span class="username">@{{ isMe(message) ? message.recipient : message.user | acct }}</span>
 | 
											<span class="username">@{{ isMe(message) ? message.recipient : message.user | acct }}</span>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,7 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="mk-welcome-timeline">
 | 
					<div class="mk-welcome-timeline">
 | 
				
			||||||
	<div v-for="note in notes">
 | 
						<div v-for="note in notes">
 | 
				
			||||||
		<router-link class="avatar-anchor" :to="note.user | userPage" v-user-preview="note.user.id">
 | 
							<mk-avatar class="avatar" :user="note.user" target="_blank"/>
 | 
				
			||||||
			<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=96`" alt="avatar"/>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		<div class="body">
 | 
							<div class="body">
 | 
				
			||||||
			<header>
 | 
								<header>
 | 
				
			||||||
				<router-link class="name" :to="note.user | userPage" v-user-preview="note.user.id">{{ note.user | userName }}</router-link>
 | 
									<router-link class="name" :to="note.user | userPage" v-user-preview="note.user.id">{{ note.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -69,18 +67,15 @@ export default Vue.extend({
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
			clear both
 | 
								clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .avatar-anchor
 | 
							> .avatar
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
			float left
 | 
								float left
 | 
				
			||||||
			position -webkit-sticky
 | 
								position -webkit-sticky
 | 
				
			||||||
			position sticky
 | 
								position sticky
 | 
				
			||||||
			top 16px
 | 
								top 16px
 | 
				
			||||||
 | 
								width 42px
 | 
				
			||||||
			> img
 | 
								height 42px
 | 
				
			||||||
				display block
 | 
								border-radius 6px
 | 
				
			||||||
				width 42px
 | 
					 | 
				
			||||||
				height 42px
 | 
					 | 
				
			||||||
				border-radius 6px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .body
 | 
							> .body
 | 
				
			||||||
			float right
 | 
								float right
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,6 +61,7 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.design++;
 | 
									this.props.design++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,7 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.design++;
 | 
									this.props.design++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,6 +73,7 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.design++;
 | 
									this.props.design++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		tick() {
 | 
							tick() {
 | 
				
			||||||
			const now = new Date();
 | 
								const now = new Date();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,6 +59,8 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.design++;
 | 
									this.props.design++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,6 +40,7 @@ export default define({
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		func() {
 | 
							func() {
 | 
				
			||||||
			this.props.compact = !this.props.compact;
 | 
								this.props.compact = !this.props.compact;
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		fetch() {
 | 
							fetch() {
 | 
				
			||||||
			fetch(`https://api.rss2json.com/v1/api.json?rss_url=${this.url}`, {
 | 
								fetch(`https://api.rss2json.com/v1/api.json?rss_url=${this.url}`, {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,7 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.view++;
 | 
									this.props.view++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		func() {
 | 
							func() {
 | 
				
			||||||
			if (this.props.design == 2) {
 | 
								if (this.props.design == 2) {
 | 
				
			||||||
| 
						 | 
					@ -75,6 +76,7 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.design++;
 | 
									this.props.design++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,6 +64,7 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.size++;
 | 
									this.props.size++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.applySize();
 | 
								this.applySize();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
| 
						 | 
					@ -111,6 +112,7 @@ export default define({
 | 
				
			||||||
		choose() {
 | 
							choose() {
 | 
				
			||||||
			(this as any).apis.chooseDriveFolder().then(folder => {
 | 
								(this as any).apis.chooseDriveFolder().then(folder => {
 | 
				
			||||||
				this.props.folder = folder ? folder.id : null;
 | 
									this.props.folder = folder ? folder.id : null;
 | 
				
			||||||
 | 
									this.save();
 | 
				
			||||||
				this.fetch();
 | 
									this.fetch();
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,9 +3,7 @@
 | 
				
			||||||
	<p class="title">気になるユーザーをフォロー:</p>
 | 
						<p class="title">気になるユーザーをフォロー:</p>
 | 
				
			||||||
	<div class="users" v-if="!fetching && users.length > 0">
 | 
						<div class="users" v-if="!fetching && users.length > 0">
 | 
				
			||||||
		<div class="user" v-for="user in users" :key="user.id">
 | 
							<div class="user" v-for="user in users" :key="user.id">
 | 
				
			||||||
			<router-link class="avatar-anchor" :to="user | userPage">
 | 
								<mk-avatar class="avatar" :user="user" target="_blank"/>
 | 
				
			||||||
				<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=42`" alt="" v-user-preview="user.id"/>
 | 
					 | 
				
			||||||
			</router-link>
 | 
					 | 
				
			||||||
			<div class="body">
 | 
								<div class="body">
 | 
				
			||||||
				<router-link class="name" :to="user | userPage" v-user-preview="user.id">{{ user | userName }}</router-link>
 | 
									<router-link class="name" :to="user | userPage" v-user-preview="user.id">{{ user | userName }}</router-link>
 | 
				
			||||||
				<p class="username">@{{ user | acct }}</p>
 | 
									<p class="username">@{{ user | acct }}</p>
 | 
				
			||||||
| 
						 | 
					@ -86,18 +84,13 @@ export default Vue.extend({
 | 
				
			||||||
				display block
 | 
									display block
 | 
				
			||||||
				clear both
 | 
									clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> .avatar-anchor
 | 
								> .avatar
 | 
				
			||||||
				display block
 | 
									display block
 | 
				
			||||||
				float left
 | 
									float left
 | 
				
			||||||
				margin 0 12px 0 0
 | 
									margin 0 12px 0 0
 | 
				
			||||||
 | 
									width 42px
 | 
				
			||||||
				> .avatar
 | 
									height 42px
 | 
				
			||||||
					display block
 | 
									border-radius 8px
 | 
				
			||||||
					width 42px
 | 
					 | 
				
			||||||
					height 42px
 | 
					 | 
				
			||||||
					margin 0
 | 
					 | 
				
			||||||
					border-radius 8px
 | 
					 | 
				
			||||||
					vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> .body
 | 
								> .body
 | 
				
			||||||
				float left
 | 
									float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,7 @@
 | 
				
			||||||
			<div class="main">
 | 
								<div class="main">
 | 
				
			||||||
				<a @click="hint">カスタマイズのヒント</a>
 | 
									<a @click="hint">カスタマイズのヒント</a>
 | 
				
			||||||
				<div>
 | 
									<div>
 | 
				
			||||||
					<mk-post-form v-if="os.i.clientSettings.showPostFormOnTopOfTl"/>
 | 
										<mk-post-form v-if="clientSettings.showPostFormOnTopOfTl"/>
 | 
				
			||||||
					<mk-timeline ref="tl" @loaded="onTlLoaded"/>
 | 
										<mk-timeline ref="tl" @loaded="onTlLoaded"/>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@
 | 
				
			||||||
				<component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" @chosen="warp"/>
 | 
									<component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" @chosen="warp"/>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
			<div class="main">
 | 
								<div class="main">
 | 
				
			||||||
				<mk-post-form v-if="os.i.clientSettings.showPostFormOnTopOfTl"/>
 | 
									<mk-post-form v-if="clientSettings.showPostFormOnTopOfTl"/>
 | 
				
			||||||
				<mk-timeline ref="tl" @loaded="onTlLoaded" v-if="mode == 'timeline'"/>
 | 
									<mk-timeline ref="tl" @loaded="onTlLoaded" v-if="mode == 'timeline'"/>
 | 
				
			||||||
				<mk-mentions @loaded="onTlLoaded" v-if="mode == 'mentions'"/>
 | 
									<mk-mentions @loaded="onTlLoaded" v-if="mode == 'mentions'"/>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,7 @@ export default Vue.extend({
 | 
				
			||||||
	components: {
 | 
						components: {
 | 
				
			||||||
		XDraggable
 | 
							XDraggable
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	props: {
 | 
						props: {
 | 
				
			||||||
		customize: {
 | 
							customize: {
 | 
				
			||||||
			type: Boolean,
 | 
								type: Boolean,
 | 
				
			||||||
| 
						 | 
					@ -91,61 +92,43 @@ export default Vue.extend({
 | 
				
			||||||
			default: 'timeline'
 | 
								default: 'timeline'
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data() {
 | 
						data() {
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			connection: null,
 | 
								connection: null,
 | 
				
			||||||
			connectionId: null,
 | 
								connectionId: null,
 | 
				
			||||||
			widgetAdderSelected: null,
 | 
								widgetAdderSelected: null,
 | 
				
			||||||
			trash: [],
 | 
								trash: []
 | 
				
			||||||
			widgets: {
 | 
					 | 
				
			||||||
				left: [],
 | 
					 | 
				
			||||||
				right: []
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	computed: {
 | 
						computed: {
 | 
				
			||||||
		home: {
 | 
							home(): any[] {
 | 
				
			||||||
			get(): any[] {
 | 
								return this.$store.state.settings.data.home;
 | 
				
			||||||
				//#region 互換性のため
 | 
					 | 
				
			||||||
				(this as any).os.i.clientSettings.home.forEach(w => {
 | 
					 | 
				
			||||||
					if (w.name == 'rss-reader') w.name = 'rss';
 | 
					 | 
				
			||||||
					if (w.name == 'user-recommendation') w.name = 'users';
 | 
					 | 
				
			||||||
					if (w.name == 'recommended-polls') w.name = 'polls';
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
				//#endregion
 | 
					 | 
				
			||||||
				return (this as any).os.i.clientSettings.home;
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			set(value) {
 | 
					 | 
				
			||||||
				(this as any).os.i.clientSettings.home = value;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		left(): any[] {
 | 
							left(): any[] {
 | 
				
			||||||
			return this.home.filter(w => w.place == 'left');
 | 
								return this.home.filter(w => w.place == 'left');
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		right(): any[] {
 | 
							right(): any[] {
 | 
				
			||||||
			return this.home.filter(w => w.place == 'right');
 | 
								return this.home.filter(w => w.place == 'right');
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							widgets(): any {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									left: this.left,
 | 
				
			||||||
 | 
									right: this.right
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	created() {
 | 
					
 | 
				
			||||||
		this.widgets.left = this.left;
 | 
					 | 
				
			||||||
		this.widgets.right = this.right;
 | 
					 | 
				
			||||||
		this.$watch('os.i.clientSettings', i => {
 | 
					 | 
				
			||||||
			this.widgets.left = this.left;
 | 
					 | 
				
			||||||
			this.widgets.right = this.right;
 | 
					 | 
				
			||||||
		}, {
 | 
					 | 
				
			||||||
			deep: true
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	mounted() {
 | 
						mounted() {
 | 
				
			||||||
		this.connection = (this as any).os.stream.getConnection();
 | 
							this.connection = (this as any).os.stream.getConnection();
 | 
				
			||||||
		this.connectionId = (this as any).os.stream.use();
 | 
							this.connectionId = (this as any).os.stream.use();
 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.connection.on('home_updated', this.onHomeUpdated);
 | 
					 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	beforeDestroy() {
 | 
						beforeDestroy() {
 | 
				
			||||||
		this.connection.off('home_updated', this.onHomeUpdated);
 | 
					 | 
				
			||||||
		(this as any).os.stream.dispose(this.connectionId);
 | 
							(this as any).os.stream.dispose(this.connectionId);
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		hint() {
 | 
							hint() {
 | 
				
			||||||
			(this as any).apis.dialog({
 | 
								(this as any).apis.dialog({
 | 
				
			||||||
| 
						 | 
					@ -159,56 +142,44 @@ export default Vue.extend({
 | 
				
			||||||
				}]
 | 
									}]
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onTlLoaded() {
 | 
							onTlLoaded() {
 | 
				
			||||||
			this.$emit('loaded');
 | 
								this.$emit('loaded');
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onHomeUpdated(data) {
 | 
					
 | 
				
			||||||
			if (data.home) {
 | 
					 | 
				
			||||||
				(this as any).os.i.clientSettings.home = data.home;
 | 
					 | 
				
			||||||
				this.widgets.left = data.home.filter(w => w.place == 'left');
 | 
					 | 
				
			||||||
				this.widgets.right = data.home.filter(w => w.place == 'right');
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				const w = (this as any).os.i.clientSettings.home.find(w => w.id == data.id);
 | 
					 | 
				
			||||||
				if (w != null) {
 | 
					 | 
				
			||||||
					w.data = data.data;
 | 
					 | 
				
			||||||
					this.$refs[w.id][0].preventSave = true;
 | 
					 | 
				
			||||||
					this.$refs[w.id][0].props = w.data;
 | 
					 | 
				
			||||||
					this.widgets.left = (this as any).os.i.clientSettings.home.filter(w => w.place == 'left');
 | 
					 | 
				
			||||||
					this.widgets.right = (this as any).os.i.clientSettings.home.filter(w => w.place == 'right');
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		onWidgetContextmenu(widgetId) {
 | 
							onWidgetContextmenu(widgetId) {
 | 
				
			||||||
			const w = (this.$refs[widgetId] as any)[0];
 | 
								const w = (this.$refs[widgetId] as any)[0];
 | 
				
			||||||
			if (w.func) w.func();
 | 
								if (w.func) w.func();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onWidgetSort() {
 | 
							onWidgetSort() {
 | 
				
			||||||
			this.saveHome();
 | 
								this.saveHome();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		onTrash(evt) {
 | 
							onTrash(evt) {
 | 
				
			||||||
			this.saveHome();
 | 
								this.saveHome();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		addWidget() {
 | 
							addWidget() {
 | 
				
			||||||
			const widget = {
 | 
								this.$store.dispatch('settings/addHomeWidget', {
 | 
				
			||||||
				name: this.widgetAdderSelected,
 | 
									name: this.widgetAdderSelected,
 | 
				
			||||||
				id: uuid(),
 | 
									id: uuid(),
 | 
				
			||||||
				place: 'left',
 | 
									place: 'left',
 | 
				
			||||||
				data: {}
 | 
									data: {}
 | 
				
			||||||
			};
 | 
								});
 | 
				
			||||||
 | 
					 | 
				
			||||||
			this.widgets.left.unshift(widget);
 | 
					 | 
				
			||||||
			this.saveHome();
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		saveHome() {
 | 
							saveHome() {
 | 
				
			||||||
			const left = this.widgets.left;
 | 
								const left = this.widgets.left;
 | 
				
			||||||
			const right = this.widgets.right;
 | 
								const right = this.widgets.right;
 | 
				
			||||||
			this.home = left.concat(right);
 | 
								this.$store.commit('settings/setHome', left.concat(right));
 | 
				
			||||||
			left.forEach(w => w.place = 'left');
 | 
								left.forEach(w => w.place = 'left');
 | 
				
			||||||
			right.forEach(w => w.place = 'right');
 | 
								right.forEach(w => w.place = 'right');
 | 
				
			||||||
			(this as any).api('i/update_home', {
 | 
								(this as any).api('i/update_home', {
 | 
				
			||||||
				home: this.home
 | 
									home: this.home
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		warp(date) {
 | 
							warp(date) {
 | 
				
			||||||
			(this.$refs.tl as any).warp(date);
 | 
								(this.$refs.tl as any).warp(date);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="sub" :title="title">
 | 
					<div class="sub" :title="title">
 | 
				
			||||||
	<router-link class="avatar-anchor" :to="note.user | userPage">
 | 
						<mk-avatar class="avatar" :user="note.user"/>
 | 
				
			||||||
		<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=64`" alt="avatar" v-user-preview="note.userId"/>
 | 
					 | 
				
			||||||
	</router-link>
 | 
					 | 
				
			||||||
	<div class="main">
 | 
						<div class="main">
 | 
				
			||||||
		<header>
 | 
							<header>
 | 
				
			||||||
			<div class="left">
 | 
								<div class="left">
 | 
				
			||||||
| 
						 | 
					@ -57,18 +55,13 @@ root(isDark)
 | 
				
			||||||
		> .main > footer > button
 | 
							> .main > footer > button
 | 
				
			||||||
			color #888
 | 
								color #888
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .avatar-anchor
 | 
						> .avatar
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
		margin 0 16px 0 0
 | 
							margin 0 16px 0 0
 | 
				
			||||||
 | 
							width 44px
 | 
				
			||||||
		> .avatar
 | 
							height 44px
 | 
				
			||||||
			display block
 | 
							border-radius 4px
 | 
				
			||||||
			width 44px
 | 
					 | 
				
			||||||
			height 44px
 | 
					 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			border-radius 4px
 | 
					 | 
				
			||||||
			vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .main
 | 
						> .main
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,18 +18,14 @@
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<div class="renote" v-if="isRenote">
 | 
						<div class="renote" v-if="isRenote">
 | 
				
			||||||
		<p>
 | 
							<p>
 | 
				
			||||||
			<router-link class="avatar-anchor" :to="note.user | userPage" v-user-preview="note.userId">
 | 
								<mk-avatar class="avatar" :user="note.user"/>
 | 
				
			||||||
				<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=32`" alt="avatar"/>
 | 
					 | 
				
			||||||
			</router-link>
 | 
					 | 
				
			||||||
			%fa:retweet%
 | 
								%fa:retweet%
 | 
				
			||||||
			<router-link class="name" :href="note.user | userPage">{{ note.user | userName }}</router-link>
 | 
								<router-link class="name" :href="note.user | userPage">{{ note.user | userName }}</router-link>
 | 
				
			||||||
			がRenote
 | 
								がRenote
 | 
				
			||||||
		</p>
 | 
							</p>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<article>
 | 
						<article>
 | 
				
			||||||
		<router-link class="avatar-anchor" :to="p.user | userPage">
 | 
							<mk-avatar class="avatar" :user="p.user"/>
 | 
				
			||||||
			<img class="avatar" :src="`${p.user.avatarUrl}?thumbnail&size=64`" alt="avatar" v-user-preview="p.user.id"/>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		<header>
 | 
							<header>
 | 
				
			||||||
			<router-link class="name" :to="p.user | userPage" v-user-preview="p.user.id">{{ p.user | userName }}</router-link>
 | 
								<router-link class="name" :to="p.user | userPage" v-user-preview="p.user.id">{{ p.user | userName }}</router-link>
 | 
				
			||||||
			<span class="username">@{{ p.user | acct }}</span>
 | 
								<span class="username">@{{ p.user | acct }}</span>
 | 
				
			||||||
| 
						 | 
					@ -159,7 +155,7 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Draw map
 | 
							// Draw map
 | 
				
			||||||
		if (this.p.geo) {
 | 
							if (this.p.geo) {
 | 
				
			||||||
			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.clientSettings.showMaps : true;
 | 
								const shouldShowMap = (this as any).os.isSignedIn ? (this as any).clientSettings.showMaps : true;
 | 
				
			||||||
			if (shouldShowMap) {
 | 
								if (shouldShowMap) {
 | 
				
			||||||
				(this as any).os.getGoogleMaps().then(maps => {
 | 
									(this as any).os.getGoogleMaps().then(maps => {
 | 
				
			||||||
					const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
 | 
										const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
 | 
				
			||||||
| 
						 | 
					@ -262,17 +258,12 @@ root(isDark)
 | 
				
			||||||
			margin 0
 | 
								margin 0
 | 
				
			||||||
			padding 16px 32px
 | 
								padding 16px 32px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			.avatar-anchor
 | 
								.avatar
 | 
				
			||||||
				display inline-block
 | 
									display inline-block
 | 
				
			||||||
 | 
									width 28px
 | 
				
			||||||
				.avatar
 | 
									height 28px
 | 
				
			||||||
					vertical-align bottom
 | 
									margin 0 8px 0 0
 | 
				
			||||||
					min-width 28px
 | 
									border-radius 6px
 | 
				
			||||||
					min-height 28px
 | 
					 | 
				
			||||||
					max-width 28px
 | 
					 | 
				
			||||||
					max-height 28px
 | 
					 | 
				
			||||||
					margin 0 8px 0 0
 | 
					 | 
				
			||||||
					border-radius 6px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			[data-fa]
 | 
								[data-fa]
 | 
				
			||||||
				margin-right 4px
 | 
									margin-right 4px
 | 
				
			||||||
| 
						 | 
					@ -298,18 +289,10 @@ root(isDark)
 | 
				
			||||||
			> footer > button
 | 
								> footer > button
 | 
				
			||||||
				color isDark ? #707b97 : #888
 | 
									color isDark ? #707b97 : #888
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .avatar-anchor
 | 
							> .avatar
 | 
				
			||||||
			display block
 | 
					 | 
				
			||||||
			width 60px
 | 
								width 60px
 | 
				
			||||||
			height 60px
 | 
								height 60px
 | 
				
			||||||
 | 
								border-radius 8px
 | 
				
			||||||
			> .avatar
 | 
					 | 
				
			||||||
				display block
 | 
					 | 
				
			||||||
				width 60px
 | 
					 | 
				
			||||||
				height 60px
 | 
					 | 
				
			||||||
				margin 0
 | 
					 | 
				
			||||||
				border-radius 8px
 | 
					 | 
				
			||||||
				vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> header
 | 
							> header
 | 
				
			||||||
			position absolute
 | 
								position absolute
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="mk-note-preview" :title="title">
 | 
					<div class="mk-note-preview" :title="title">
 | 
				
			||||||
	<router-link class="avatar-anchor" :to="note.user | userPage">
 | 
						<mk-avatar class="avatar" :user="note.user"/>
 | 
				
			||||||
		<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=64`" alt="avatar" v-user-preview="note.userId"/>
 | 
					 | 
				
			||||||
	</router-link>
 | 
					 | 
				
			||||||
	<div class="main">
 | 
						<div class="main">
 | 
				
			||||||
		<header>
 | 
							<header>
 | 
				
			||||||
			<router-link class="name" :to="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</router-link>
 | 
								<router-link class="name" :to="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -41,18 +39,13 @@ root(isDark)
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		clear both
 | 
							clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .avatar-anchor
 | 
						> .avatar
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
		margin 0 16px 0 0
 | 
							margin 0 16px 0 0
 | 
				
			||||||
 | 
							width 52px
 | 
				
			||||||
		> .avatar
 | 
							height 52px
 | 
				
			||||||
			display block
 | 
							border-radius 8px
 | 
				
			||||||
			width 52px
 | 
					 | 
				
			||||||
			height 52px
 | 
					 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			border-radius 8px
 | 
					 | 
				
			||||||
			vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .main
 | 
						> .main
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="sub" :title="title">
 | 
					<div class="sub" :title="title">
 | 
				
			||||||
	<router-link class="avatar-anchor" :to="note.user | userPage">
 | 
						<mk-avatar class="avatar" :user="note.user"/>
 | 
				
			||||||
		<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=64`" alt="avatar" v-user-preview="note.userId"/>
 | 
					 | 
				
			||||||
	</router-link>
 | 
					 | 
				
			||||||
	<div class="main">
 | 
						<div class="main">
 | 
				
			||||||
		<header>
 | 
							<header>
 | 
				
			||||||
			<router-link class="name" :to="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</router-link>
 | 
								<router-link class="name" :to="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -53,18 +51,13 @@ root(isDark)
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		clear both
 | 
							clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .avatar-anchor
 | 
						> .avatar
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
		margin 0 14px 0 0
 | 
							margin 0 14px 0 0
 | 
				
			||||||
 | 
							width 52px
 | 
				
			||||||
		> .avatar
 | 
							height 52px
 | 
				
			||||||
			display block
 | 
							border-radius 8px
 | 
				
			||||||
			width 52px
 | 
					 | 
				
			||||||
			height 52px
 | 
					 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			border-radius 8px
 | 
					 | 
				
			||||||
			vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .main
 | 
						> .main
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,10 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="note" tabindex="-1" :title="title" @keydown="onKeydown">
 | 
					<div class="note" tabindex="-1" :title="title" @keydown="onKeydown">
 | 
				
			||||||
	<div class="reply-to" v-if="p.reply && (!os.isSignedIn || os.i.clientSettings.showReplyTarget)">
 | 
						<div class="reply-to" v-if="p.reply && (!os.isSignedIn || clientSettings.showReplyTarget)">
 | 
				
			||||||
		<x-sub :note="p.reply"/>
 | 
							<x-sub :note="p.reply"/>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<div class="renote" v-if="isRenote">
 | 
						<div class="renote" v-if="isRenote">
 | 
				
			||||||
		<router-link class="avatar-anchor" :to="note.user | userPage" v-user-preview="note.userId">
 | 
							<mk-avatar class="avatar" :user="note.user"/>
 | 
				
			||||||
			<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=32`" alt="avatar"/>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		%fa:retweet%
 | 
							%fa:retweet%
 | 
				
			||||||
		<span>{{ '%i18n:!@reposted-by%'.substr(0, '%i18n:!@reposted-by%'.indexOf('{')) }}</span>
 | 
							<span>{{ '%i18n:!@reposted-by%'.substr(0, '%i18n:!@reposted-by%'.indexOf('{')) }}</span>
 | 
				
			||||||
		<a class="name" :href="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</a>
 | 
							<a class="name" :href="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</a>
 | 
				
			||||||
| 
						 | 
					@ -14,9 +12,7 @@
 | 
				
			||||||
		<mk-time :time="note.createdAt"/>
 | 
							<mk-time :time="note.createdAt"/>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<article>
 | 
						<article>
 | 
				
			||||||
		<router-link class="avatar-anchor" :to="p.user | userPage">
 | 
							<mk-avatar class="avatar" :user="p.user"/>
 | 
				
			||||||
			<img class="avatar" :src="`${p.user.avatarUrl}?thumbnail&size=64`" alt="avatar" v-user-preview="p.user.id"/>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		<div class="main">
 | 
							<div class="main">
 | 
				
			||||||
			<header>
 | 
								<header>
 | 
				
			||||||
				<router-link class="name" :to="p.user | userPage" v-user-preview="p.user.id">{{ p.user | userName }}</router-link>
 | 
									<router-link class="name" :to="p.user | userPage" v-user-preview="p.user.id">{{ p.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -182,7 +178,7 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Draw map
 | 
							// Draw map
 | 
				
			||||||
		if (this.p.geo) {
 | 
							if (this.p.geo) {
 | 
				
			||||||
			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.clientSettings.showMaps : true;
 | 
								const shouldShowMap = (this as any).os.isSignedIn ? (this as any).clientSettings.showMaps : true;
 | 
				
			||||||
			if (shouldShowMap) {
 | 
								if (shouldShowMap) {
 | 
				
			||||||
				(this as any).os.getGoogleMaps().then(maps => {
 | 
									(this as any).os.getGoogleMaps().then(maps => {
 | 
				
			||||||
					const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
 | 
										const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
 | 
				
			||||||
| 
						 | 
					@ -343,15 +339,12 @@ root(isDark)
 | 
				
			||||||
		color #9dbb00
 | 
							color #9dbb00
 | 
				
			||||||
		background isDark ? linear-gradient(to bottom, #314027 0%, #282c37 100%) : linear-gradient(to bottom, #edfde2 0%, #fff 100%)
 | 
							background isDark ? linear-gradient(to bottom, #314027 0%, #282c37 100%) : linear-gradient(to bottom, #edfde2 0%, #fff 100%)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		.avatar-anchor
 | 
							.avatar
 | 
				
			||||||
			display inline-block
 | 
								display inline-block
 | 
				
			||||||
 | 
								width 28px
 | 
				
			||||||
			.avatar
 | 
								height 28px
 | 
				
			||||||
				vertical-align bottom
 | 
								margin 0 8px 0 0
 | 
				
			||||||
				width 28px
 | 
								border-radius 6px
 | 
				
			||||||
				height 28px
 | 
					 | 
				
			||||||
				margin 0 8px 0 0
 | 
					 | 
				
			||||||
				border-radius 6px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[data-fa]
 | 
							[data-fa]
 | 
				
			||||||
			margin-right 4px
 | 
								margin-right 4px
 | 
				
			||||||
| 
						 | 
					@ -390,22 +383,17 @@ root(isDark)
 | 
				
			||||||
			> .main > footer > button
 | 
								> .main > footer > button
 | 
				
			||||||
				color isDark ? #707b97 : #888
 | 
									color isDark ? #707b97 : #888
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .avatar-anchor
 | 
							> .avatar
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
			float left
 | 
								float left
 | 
				
			||||||
			margin 0 16px 10px 0
 | 
								margin 0 16px 10px 0
 | 
				
			||||||
 | 
								width 58px
 | 
				
			||||||
 | 
								height 58px
 | 
				
			||||||
 | 
								border-radius 8px
 | 
				
			||||||
			//position -webkit-sticky
 | 
								//position -webkit-sticky
 | 
				
			||||||
			//position sticky
 | 
								//position sticky
 | 
				
			||||||
			//top 74px
 | 
								//top 74px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> .avatar
 | 
					 | 
				
			||||||
				display block
 | 
					 | 
				
			||||||
				width 58px
 | 
					 | 
				
			||||||
				height 58px
 | 
					 | 
				
			||||||
				margin 0
 | 
					 | 
				
			||||||
				border-radius 8px
 | 
					 | 
				
			||||||
				vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		> .main
 | 
							> .main
 | 
				
			||||||
			float left
 | 
								float left
 | 
				
			||||||
			width calc(100% - 74px)
 | 
								width calc(100% - 74px)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,13 +121,13 @@ export default Vue.extend({
 | 
				
			||||||
			const isMyNote = note.userId == (this as any).os.i.id;
 | 
								const isMyNote = note.userId == (this as any).os.i.id;
 | 
				
			||||||
			const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null;
 | 
								const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ((this as any).os.i.clientSettings.showMyRenotes === false) {
 | 
								if ((this as any).clientSettings.showMyRenotes === false) {
 | 
				
			||||||
				if (isMyNote && isPureRenote) {
 | 
									if (isMyNote && isPureRenote) {
 | 
				
			||||||
					return;
 | 
										return;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ((this as any).os.i.clientSettings.showRenotedMyNotes === false) {
 | 
								if ((this as any).clientSettings.showRenotedMyNotes === false) {
 | 
				
			||||||
				if (isPureRenote && (note.renote.userId == (this as any).os.i.id)) {
 | 
									if (isPureRenote && (note.renote.userId == (this as any).os.i.id)) {
 | 
				
			||||||
					return;
 | 
										return;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -199,7 +199,7 @@ export default Vue.extend({
 | 
				
			||||||
				this.clearNotification();
 | 
									this.clearNotification();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ((this as any).os.i.clientSettings.fetchOnScroll !== false) {
 | 
								if ((this as any).clientSettings.fetchOnScroll !== false) {
 | 
				
			||||||
				const current = window.scrollY + window.innerHeight;
 | 
									const current = window.scrollY + window.innerHeight;
 | 
				
			||||||
				if (current > document.body.offsetHeight - 8) this.loadMore();
 | 
									if (current > document.body.offsetHeight - 8) this.loadMore();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,9 +6,7 @@
 | 
				
			||||||
				<div class="notification" :class="notification.type" :key="notification.id">
 | 
									<div class="notification" :class="notification.type" :key="notification.id">
 | 
				
			||||||
					<mk-time :time="notification.createdAt"/>
 | 
										<mk-time :time="notification.createdAt"/>
 | 
				
			||||||
					<template v-if="notification.type == 'reaction'">
 | 
										<template v-if="notification.type == 'reaction'">
 | 
				
			||||||
						<router-link class="avatar-anchor" :to="notification.user | userPage" v-user-preview="notification.user.id">
 | 
											<mk-avatar class="avatar" :user="notification.user"/>
 | 
				
			||||||
							<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 | 
					 | 
				
			||||||
						</router-link>
 | 
					 | 
				
			||||||
						<div class="text">
 | 
											<div class="text">
 | 
				
			||||||
							<p>
 | 
												<p>
 | 
				
			||||||
								<mk-reaction-icon :reaction="notification.reaction"/>
 | 
													<mk-reaction-icon :reaction="notification.reaction"/>
 | 
				
			||||||
| 
						 | 
					@ -20,9 +18,7 @@
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
					</template>
 | 
										</template>
 | 
				
			||||||
					<template v-if="notification.type == 'renote'">
 | 
										<template v-if="notification.type == 'renote'">
 | 
				
			||||||
						<router-link class="avatar-anchor" :to="notification.note.user | userPage" v-user-preview="notification.note.userId">
 | 
											<mk-avatar class="avatar" :user="notification.note.user"/>
 | 
				
			||||||
							<img class="avatar" :src="`${notification.note.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 | 
					 | 
				
			||||||
						</router-link>
 | 
					 | 
				
			||||||
						<div class="text">
 | 
											<div class="text">
 | 
				
			||||||
							<p>%fa:retweet%
 | 
												<p>%fa:retweet%
 | 
				
			||||||
								<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
 | 
													<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -33,9 +29,7 @@
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
					</template>
 | 
										</template>
 | 
				
			||||||
					<template v-if="notification.type == 'quote'">
 | 
										<template v-if="notification.type == 'quote'">
 | 
				
			||||||
						<router-link class="avatar-anchor" :to="notification.note.user | userPage" v-user-preview="notification.note.userId">
 | 
											<mk-avatar class="avatar" :user="notification.note.user"/>
 | 
				
			||||||
							<img class="avatar" :src="`${notification.note.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 | 
					 | 
				
			||||||
						</router-link>
 | 
					 | 
				
			||||||
						<div class="text">
 | 
											<div class="text">
 | 
				
			||||||
							<p>%fa:quote-left%
 | 
												<p>%fa:quote-left%
 | 
				
			||||||
								<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
 | 
													<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -44,9 +38,7 @@
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
					</template>
 | 
										</template>
 | 
				
			||||||
					<template v-if="notification.type == 'follow'">
 | 
										<template v-if="notification.type == 'follow'">
 | 
				
			||||||
						<router-link class="avatar-anchor" :to="notification.user | userPage" v-user-preview="notification.user.id">
 | 
											<mk-avatar class="avatar" :user="notification.user"/>
 | 
				
			||||||
							<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 | 
					 | 
				
			||||||
						</router-link>
 | 
					 | 
				
			||||||
						<div class="text">
 | 
											<div class="text">
 | 
				
			||||||
							<p>%fa:user-plus%
 | 
												<p>%fa:user-plus%
 | 
				
			||||||
								<router-link :to="notification.user | userPage" v-user-preview="notification.user.id">{{ notification.user | userName }}</router-link>
 | 
													<router-link :to="notification.user | userPage" v-user-preview="notification.user.id">{{ notification.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -54,9 +46,7 @@
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
					</template>
 | 
										</template>
 | 
				
			||||||
					<template v-if="notification.type == 'reply'">
 | 
										<template v-if="notification.type == 'reply'">
 | 
				
			||||||
						<router-link class="avatar-anchor" :to="notification.note.user | userPage" v-user-preview="notification.note.userId">
 | 
											<mk-avatar class="avatar" :user="notification.note.user"/>
 | 
				
			||||||
							<img class="avatar" :src="`${notification.note.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 | 
					 | 
				
			||||||
						</router-link>
 | 
					 | 
				
			||||||
						<div class="text">
 | 
											<div class="text">
 | 
				
			||||||
							<p>%fa:reply%
 | 
												<p>%fa:reply%
 | 
				
			||||||
								<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
 | 
													<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -65,9 +55,7 @@
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
					</template>
 | 
										</template>
 | 
				
			||||||
					<template v-if="notification.type == 'mention'">
 | 
										<template v-if="notification.type == 'mention'">
 | 
				
			||||||
						<router-link class="avatar-anchor" :to="notification.note.user | userPage" v-user-preview="notification.note.userId">
 | 
											<mk-avatar class="avatar" :user="notification.note.user"/>
 | 
				
			||||||
							<img class="avatar" :src="`${notification.note.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 | 
					 | 
				
			||||||
						</router-link>
 | 
					 | 
				
			||||||
						<div class="text">
 | 
											<div class="text">
 | 
				
			||||||
							<p>%fa:at%
 | 
												<p>%fa:at%
 | 
				
			||||||
								<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
 | 
													<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -76,9 +64,7 @@
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
					</template>
 | 
										</template>
 | 
				
			||||||
					<template v-if="notification.type == 'poll_vote'">
 | 
										<template v-if="notification.type == 'poll_vote'">
 | 
				
			||||||
						<router-link class="avatar-anchor" :to="notification.user | userPage" v-user-preview="notification.user.id">
 | 
											<mk-avatar class="avatar" :user="notification.user"/>
 | 
				
			||||||
							<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=48`" alt="avatar"/>
 | 
					 | 
				
			||||||
						</router-link>
 | 
					 | 
				
			||||||
						<div class="text">
 | 
											<div class="text">
 | 
				
			||||||
							<p>%fa:chart-pie%<a :href="notification.user | userPage" v-user-preview="notification.user.id">{{ notification.user | userName }}</a></p>
 | 
												<p>%fa:chart-pie%<a :href="notification.user | userPage" v-user-preview="notification.user.id">{{ notification.user | userName }}</a></p>
 | 
				
			||||||
							<router-link class="note-ref" :to="notification.note | notePage">
 | 
												<router-link class="note-ref" :to="notification.note | notePage">
 | 
				
			||||||
| 
						 | 
					@ -223,20 +209,15 @@ root(isDark)
 | 
				
			||||||
					display block
 | 
										display block
 | 
				
			||||||
					clear both
 | 
										clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				> .avatar-anchor
 | 
									> .avatar
 | 
				
			||||||
					display block
 | 
										display block
 | 
				
			||||||
					float left
 | 
										float left
 | 
				
			||||||
					position -webkit-sticky
 | 
										position -webkit-sticky
 | 
				
			||||||
					position sticky
 | 
										position sticky
 | 
				
			||||||
					top 16px
 | 
										top 16px
 | 
				
			||||||
 | 
										width 36px
 | 
				
			||||||
					> img
 | 
										height 36px
 | 
				
			||||||
						display block
 | 
										border-radius 6px
 | 
				
			||||||
						min-width 36px
 | 
					 | 
				
			||||||
						min-height 36px
 | 
					 | 
				
			||||||
						max-width 36px
 | 
					 | 
				
			||||||
						max-height 36px
 | 
					 | 
				
			||||||
						border-radius 6px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				> .text
 | 
									> .text
 | 
				
			||||||
					float right
 | 
										float right
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<section class="web" v-show="page == 'web'">
 | 
							<section class="web" v-show="page == 'web'">
 | 
				
			||||||
			<h1>動作</h1>
 | 
								<h1>動作</h1>
 | 
				
			||||||
			<mk-switch v-model="os.i.clientSettings.fetchOnScroll" @change="onChangeFetchOnScroll" text="スクロールで自動読み込み">
 | 
								<mk-switch v-model="clientSettings.fetchOnScroll" @change="onChangeFetchOnScroll" text="スクロールで自動読み込み">
 | 
				
			||||||
				<span>ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。</span>
 | 
									<span>ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。</span>
 | 
				
			||||||
			</mk-switch>
 | 
								</mk-switch>
 | 
				
			||||||
			<mk-switch v-model="autoPopout" text="ウィンドウの自動ポップアウト">
 | 
								<mk-switch v-model="autoPopout" text="ウィンドウの自動ポップアウト">
 | 
				
			||||||
| 
						 | 
					@ -41,13 +41,14 @@
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
			<div class="div">
 | 
								<div class="div">
 | 
				
			||||||
				<mk-switch v-model="darkmode" text="ダークモード"/>
 | 
									<mk-switch v-model="darkmode" text="ダークモード"/>
 | 
				
			||||||
				<mk-switch v-model="os.i.clientSettings.gradientWindowHeader" @change="onChangeGradientWindowHeader" text="ウィンドウのタイトルバーにグラデーションを使用"/>
 | 
									<mk-switch v-model="clientSettings.circleIcons" @change="onChangeCircleIcons" text="丸いアイコンを使用"/>
 | 
				
			||||||
 | 
									<mk-switch v-model="clientSettings.gradientWindowHeader" @change="onChangeGradientWindowHeader" text="ウィンドウのタイトルバーにグラデーションを使用"/>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
			<mk-switch v-model="os.i.clientSettings.showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" text="タイムライン上部に投稿フォームを表示する"/>
 | 
								<mk-switch v-model="clientSettings.showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" text="タイムライン上部に投稿フォームを表示する"/>
 | 
				
			||||||
			<mk-switch v-model="os.i.clientSettings.showReplyTarget" @change="onChangeShowReplyTarget" text="リプライ先を表示する"/>
 | 
								<mk-switch v-model="clientSettings.showReplyTarget" @change="onChangeShowReplyTarget" text="リプライ先を表示する"/>
 | 
				
			||||||
			<mk-switch v-model="os.i.clientSettings.showMyRenotes" @change="onChangeShowMyRenotes" text="自分の行ったRenoteをタイムラインに表示する"/>
 | 
								<mk-switch v-model="clientSettings.showMyRenotes" @change="onChangeShowMyRenotes" text="自分の行ったRenoteをタイムラインに表示する"/>
 | 
				
			||||||
			<mk-switch v-model="os.i.clientSettings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes" text="Renoteされた自分の投稿をタイムラインに表示する"/>
 | 
								<mk-switch v-model="clientSettings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes" text="Renoteされた自分の投稿をタイムラインに表示する"/>
 | 
				
			||||||
			<mk-switch v-model="os.i.clientSettings.showMaps" @change="onChangeShowMaps" text="マップの自動展開">
 | 
								<mk-switch v-model="clientSettings.showMaps" @change="onChangeShowMaps" text="マップの自動展開">
 | 
				
			||||||
				<span>位置情報が添付された投稿のマップを自動的に展開します。</span>
 | 
									<span>位置情報が添付された投稿のマップを自動的に展開します。</span>
 | 
				
			||||||
			</mk-switch>
 | 
								</mk-switch>
 | 
				
			||||||
		</section>
 | 
							</section>
 | 
				
			||||||
| 
						 | 
					@ -69,7 +70,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<section class="web" v-show="page == 'web'">
 | 
							<section class="web" v-show="page == 'web'">
 | 
				
			||||||
			<h1>モバイル</h1>
 | 
								<h1>モバイル</h1>
 | 
				
			||||||
			<mk-switch v-model="os.i.clientSettings.disableViaMobile" @change="onChangeDisableViaMobile" text="「モバイルからの投稿」フラグを付けない"/>
 | 
								<mk-switch v-model="clientSettings.disableViaMobile" @change="onChangeDisableViaMobile" text="「モバイルからの投稿」フラグを付けない"/>
 | 
				
			||||||
		</section>
 | 
							</section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<section class="web" v-show="page == 'web'">
 | 
							<section class="web" v-show="page == 'web'">
 | 
				
			||||||
| 
						 | 
					@ -297,8 +298,8 @@ export default Vue.extend({
 | 
				
			||||||
			this.$emit('done');
 | 
								this.$emit('done');
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onChangeFetchOnScroll(v) {
 | 
							onChangeFetchOnScroll(v) {
 | 
				
			||||||
			(this as any).api('i/update_client_setting', {
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
				name: 'fetchOnScroll',
 | 
									key: 'fetchOnScroll',
 | 
				
			||||||
				value: v
 | 
									value: v
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
| 
						 | 
					@ -308,50 +309,56 @@ export default Vue.extend({
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onChangeDark(v) {
 | 
							onChangeDark(v) {
 | 
				
			||||||
			(this as any).api('i/update_client_setting', {
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
				name: 'dark',
 | 
									key: 'dark',
 | 
				
			||||||
				value: v
 | 
									value: v
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onChangeShowPostFormOnTopOfTl(v) {
 | 
							onChangeShowPostFormOnTopOfTl(v) {
 | 
				
			||||||
			(this as any).api('i/update_client_setting', {
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
				name: 'showPostFormOnTopOfTl',
 | 
									key: 'showPostFormOnTopOfTl',
 | 
				
			||||||
				value: v
 | 
									value: v
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onChangeShowReplyTarget(v) {
 | 
							onChangeShowReplyTarget(v) {
 | 
				
			||||||
			(this as any).api('i/update_client_setting', {
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
				name: 'showReplyTarget',
 | 
									key: 'showReplyTarget',
 | 
				
			||||||
				value: v
 | 
									value: v
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onChangeShowMyRenotes(v) {
 | 
							onChangeShowMyRenotes(v) {
 | 
				
			||||||
			(this as any).api('i/update_client_setting', {
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
				name: 'showMyRenotes',
 | 
									key: 'showMyRenotes',
 | 
				
			||||||
				value: v
 | 
									value: v
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onChangeShowRenotedMyNotes(v) {
 | 
							onChangeShowRenotedMyNotes(v) {
 | 
				
			||||||
			(this as any).api('i/update_client_setting', {
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
				name: 'showRenotedMyNotes',
 | 
									key: 'showRenotedMyNotes',
 | 
				
			||||||
				value: v
 | 
									value: v
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onChangeShowMaps(v) {
 | 
							onChangeShowMaps(v) {
 | 
				
			||||||
			(this as any).api('i/update_client_setting', {
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
				name: 'showMaps',
 | 
									key: 'showMaps',
 | 
				
			||||||
 | 
									value: v
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							onChangeCircleIcons(v) {
 | 
				
			||||||
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
 | 
									key: 'circleIcons',
 | 
				
			||||||
				value: v
 | 
									value: v
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onChangeGradientWindowHeader(v) {
 | 
							onChangeGradientWindowHeader(v) {
 | 
				
			||||||
			(this as any).api('i/update_client_setting', {
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
				name: 'gradientWindowHeader',
 | 
									key: 'gradientWindowHeader',
 | 
				
			||||||
				value: v
 | 
									value: v
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onChangeDisableViaMobile(v) {
 | 
							onChangeDisableViaMobile(v) {
 | 
				
			||||||
			(this as any).api('i/update_client_setting', {
 | 
								this.$store.dispatch('settings/set', {
 | 
				
			||||||
				name: 'disableViaMobile',
 | 
									key: 'disableViaMobile',
 | 
				
			||||||
				value: v
 | 
									value: v
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,8 +101,8 @@ export default Vue.extend({
 | 
				
			||||||
				(this as any).api(this.endpoint, {
 | 
									(this as any).api(this.endpoint, {
 | 
				
			||||||
					limit: fetchLimit + 1,
 | 
										limit: fetchLimit + 1,
 | 
				
			||||||
					untilDate: this.date ? this.date.getTime() : undefined,
 | 
										untilDate: this.date ? this.date.getTime() : undefined,
 | 
				
			||||||
					includeMyRenotes: (this as any).os.i.clientSettings.showMyRenotes,
 | 
										includeMyRenotes: (this as any).clientSettings.showMyRenotes,
 | 
				
			||||||
					includeRenotedMyNotes: (this as any).os.i.clientSettings.showRenotedMyNotes
 | 
										includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
 | 
				
			||||||
				}).then(notes => {
 | 
									}).then(notes => {
 | 
				
			||||||
					if (notes.length == fetchLimit + 1) {
 | 
										if (notes.length == fetchLimit + 1) {
 | 
				
			||||||
						notes.pop();
 | 
											notes.pop();
 | 
				
			||||||
| 
						 | 
					@ -123,8 +123,8 @@ export default Vue.extend({
 | 
				
			||||||
			(this as any).api(this.endpoint, {
 | 
								(this as any).api(this.endpoint, {
 | 
				
			||||||
				limit: fetchLimit + 1,
 | 
									limit: fetchLimit + 1,
 | 
				
			||||||
				untilId: (this.$refs.timeline as any).tail().id,
 | 
									untilId: (this.$refs.timeline as any).tail().id,
 | 
				
			||||||
				includeMyRenotes: (this as any).os.i.clientSettings.showMyRenotes,
 | 
									includeMyRenotes: (this as any).clientSettings.showMyRenotes,
 | 
				
			||||||
				includeRenotedMyNotes: (this as any).os.i.clientSettings.showRenotedMyNotes
 | 
									includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
 | 
				
			||||||
			}).then(notes => {
 | 
								}).then(notes => {
 | 
				
			||||||
				if (notes.length == fetchLimit + 1) {
 | 
									if (notes.length == fetchLimit + 1) {
 | 
				
			||||||
					notes.pop();
 | 
										notes.pop();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
<div class="account">
 | 
					<div class="account">
 | 
				
			||||||
	<button class="header" :data-active="isOpen" @click="toggle">
 | 
						<button class="header" :data-active="isOpen" @click="toggle">
 | 
				
			||||||
		<span class="username">{{ os.i.username }}<template v-if="!isOpen">%fa:angle-down%</template><template v-if="isOpen">%fa:angle-up%</template></span>
 | 
							<span class="username">{{ os.i.username }}<template v-if="!isOpen">%fa:angle-down%</template><template v-if="isOpen">%fa:angle-up%</template></span>
 | 
				
			||||||
		<img class="avatar" :src="`${ os.i.avatarUrl }?thumbnail&size=64`" alt="avatar"/>
 | 
							<mk-avatar class="avatar" :user="os.i"/>
 | 
				
			||||||
	</button>
 | 
						</button>
 | 
				
			||||||
	<transition name="zoom-in-top">
 | 
						<transition name="zoom-in-top">
 | 
				
			||||||
		<div class="menu" v-if="isOpen">
 | 
							<div class="menu" v-if="isOpen">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,8 +46,8 @@ export default Vue.extend({
 | 
				
			||||||
				(this as any).api('notes/user-list-timeline', {
 | 
									(this as any).api('notes/user-list-timeline', {
 | 
				
			||||||
					listId: this.list.id,
 | 
										listId: this.list.id,
 | 
				
			||||||
					limit: fetchLimit + 1,
 | 
										limit: fetchLimit + 1,
 | 
				
			||||||
					includeMyRenotes: (this as any).os.i.clientSettings.showMyRenotes,
 | 
										includeMyRenotes: (this as any).clientSettings.showMyRenotes,
 | 
				
			||||||
					includeRenotedMyNotes: (this as any).os.i.clientSettings.showRenotedMyNotes
 | 
										includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
 | 
				
			||||||
				}).then(notes => {
 | 
									}).then(notes => {
 | 
				
			||||||
					if (notes.length == fetchLimit + 1) {
 | 
										if (notes.length == fetchLimit + 1) {
 | 
				
			||||||
						notes.pop();
 | 
											notes.pop();
 | 
				
			||||||
| 
						 | 
					@ -66,8 +66,8 @@ export default Vue.extend({
 | 
				
			||||||
				listId: this.list.id,
 | 
									listId: this.list.id,
 | 
				
			||||||
				limit: fetchLimit + 1,
 | 
									limit: fetchLimit + 1,
 | 
				
			||||||
				untilId: (this.$refs.timeline as any).tail().id,
 | 
									untilId: (this.$refs.timeline as any).tail().id,
 | 
				
			||||||
				includeMyRenotes: (this as any).os.i.clientSettings.showMyRenotes,
 | 
									includeMyRenotes: (this as any).clientSettings.showMyRenotes,
 | 
				
			||||||
				includeRenotedMyNotes: (this as any).os.i.clientSettings.showRenotedMyNotes
 | 
									includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
 | 
				
			||||||
			}).then(notes => {
 | 
								}).then(notes => {
 | 
				
			||||||
				if (notes.length == fetchLimit + 1) {
 | 
									if (notes.length == fetchLimit + 1) {
 | 
				
			||||||
					notes.pop();
 | 
										notes.pop();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,9 +2,7 @@
 | 
				
			||||||
<div class="mk-user-preview">
 | 
					<div class="mk-user-preview">
 | 
				
			||||||
	<template v-if="u != null">
 | 
						<template v-if="u != null">
 | 
				
			||||||
		<div class="banner" :style="u.bannerUrl ? `background-image: url(${u.bannerUrl}?thumbnail&size=512)` : ''"></div>
 | 
							<div class="banner" :style="u.bannerUrl ? `background-image: url(${u.bannerUrl}?thumbnail&size=512)` : ''"></div>
 | 
				
			||||||
		<router-link class="avatar" :to="u | userPage">
 | 
							<mk-avatar class="avatar" :user="u" :disable-preview="true"/>
 | 
				
			||||||
			<img :src="`${u.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		<div class="title">
 | 
							<div class="title">
 | 
				
			||||||
			<router-link class="name" :to="u | userPage">{{ u | userName }}</router-link>
 | 
								<router-link class="name" :to="u | userPage">{{ u | userName }}</router-link>
 | 
				
			||||||
			<p class="username">@{{ u | acct }}</p>
 | 
								<p class="username">@{{ u | acct }}</p>
 | 
				
			||||||
| 
						 | 
					@ -111,14 +109,10 @@ root(isDark)
 | 
				
			||||||
		top 62px
 | 
							top 62px
 | 
				
			||||||
		left 13px
 | 
							left 13px
 | 
				
			||||||
		z-index 2
 | 
							z-index 2
 | 
				
			||||||
 | 
							width 58px
 | 
				
			||||||
		> img
 | 
							height 58px
 | 
				
			||||||
			display block
 | 
							border solid 3px isDark ? #282c37 : #fff
 | 
				
			||||||
			width 58px
 | 
							border-radius 8px
 | 
				
			||||||
			height 58px
 | 
					 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			border solid 3px isDark ? #282c37 : #fff
 | 
					 | 
				
			||||||
			border-radius 8px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .title
 | 
						> .title
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="root item">
 | 
					<div class="root item">
 | 
				
			||||||
	<router-link class="avatar-anchor" :to="user | userPage" v-user-preview="user.id">
 | 
						<mk-avatar class="avatar" :user="user"/>
 | 
				
			||||||
		<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
	</router-link>
 | 
					 | 
				
			||||||
	<div class="main">
 | 
						<div class="main">
 | 
				
			||||||
		<header>
 | 
							<header>
 | 
				
			||||||
			<router-link class="name" :to="user | userPage" v-user-preview="user.id">{{ user | userName }}</router-link>
 | 
								<router-link class="name" :to="user | userPage" v-user-preview="user.id">{{ user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -35,18 +33,13 @@ export default Vue.extend({
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		clear both
 | 
							clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .avatar-anchor
 | 
						> .avatar
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
		margin 0 16px 0 0
 | 
							margin 0 16px 0 0
 | 
				
			||||||
 | 
							width 58px
 | 
				
			||||||
		> .avatar
 | 
							height 58px
 | 
				
			||||||
			display block
 | 
							border-radius 8px
 | 
				
			||||||
			width 58px
 | 
					 | 
				
			||||||
			height 58px
 | 
					 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			border-radius 8px
 | 
					 | 
				
			||||||
			vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .main
 | 
						> .main
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,8 +24,8 @@ export default Vue.extend({
 | 
				
			||||||
	computed: {
 | 
						computed: {
 | 
				
			||||||
		withGradient(): boolean {
 | 
							withGradient(): boolean {
 | 
				
			||||||
			return (this as any).os.isSignedIn
 | 
								return (this as any).os.isSignedIn
 | 
				
			||||||
				? (this as any).os.i.clientSettings.gradientWindowHeader != null
 | 
									? (this as any).clientSettings.gradientWindowHeader != null
 | 
				
			||||||
					? (this as any).os.i.clientSettings.gradientWindowHeader
 | 
										? (this as any).clientSettings.gradientWindowHeader
 | 
				
			||||||
					: false
 | 
										: false
 | 
				
			||||||
				: false;
 | 
									: false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,8 +94,8 @@ export default Vue.extend({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		withGradient(): boolean {
 | 
							withGradient(): boolean {
 | 
				
			||||||
			return (this as any).os.isSignedIn
 | 
								return (this as any).os.isSignedIn
 | 
				
			||||||
				? (this as any).os.i.clientSettings.gradientWindowHeader != null
 | 
									? (this as any).clientSettings.gradientWindowHeader != null
 | 
				
			||||||
					? (this as any).os.i.clientSettings.gradientWindowHeader
 | 
										? (this as any).clientSettings.gradientWindowHeader
 | 
				
			||||||
					: false
 | 
										: false
 | 
				
			||||||
				: false;
 | 
									: false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,9 +8,7 @@
 | 
				
			||||||
			<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw% %i18n:common.loading%<mk-ellipsis/></p>
 | 
								<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw% %i18n:common.loading%<mk-ellipsis/></p>
 | 
				
			||||||
			<template v-else-if="users.length != 0">
 | 
								<template v-else-if="users.length != 0">
 | 
				
			||||||
				<div class="user" v-for="_user in users">
 | 
									<div class="user" v-for="_user in users">
 | 
				
			||||||
					<router-link class="avatar-anchor" :to="_user | userPage">
 | 
										<mk-avatar class="avatar" :user="_user"/>
 | 
				
			||||||
						<img class="avatar" :src="`${_user.avatarUrl}?thumbnail&size=42`" alt="" v-user-preview="_user.id"/>
 | 
					 | 
				
			||||||
					</router-link>
 | 
					 | 
				
			||||||
					<div class="body">
 | 
										<div class="body">
 | 
				
			||||||
						<router-link class="name" :to="_user | userPage" v-user-preview="_user.id">{{ _user | userName }}</router-link>
 | 
											<router-link class="name" :to="_user | userPage" v-user-preview="_user.id">{{ _user | userName }}</router-link>
 | 
				
			||||||
						<p class="username">@{{ _user | acct }}</p>
 | 
											<p class="username">@{{ _user | acct }}</p>
 | 
				
			||||||
| 
						 | 
					@ -80,18 +78,13 @@ root(isDark)
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
			clear both
 | 
								clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .avatar-anchor
 | 
							> .avatar
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
			float left
 | 
								float left
 | 
				
			||||||
			margin 0 12px 0 0
 | 
								margin 0 12px 0 0
 | 
				
			||||||
 | 
								width 42px
 | 
				
			||||||
			> .avatar
 | 
								height 42px
 | 
				
			||||||
				display block
 | 
								border-radius 8px
 | 
				
			||||||
				width 42px
 | 
					 | 
				
			||||||
				height 42px
 | 
					 | 
				
			||||||
				margin 0
 | 
					 | 
				
			||||||
				border-radius 8px
 | 
					 | 
				
			||||||
				vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .body
 | 
							> .body
 | 
				
			||||||
			float left
 | 
								float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,9 +4,7 @@
 | 
				
			||||||
	<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:@loading%<mk-ellipsis/></p>
 | 
						<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:@loading%<mk-ellipsis/></p>
 | 
				
			||||||
	<template v-if="!fetching && users.length != 0">
 | 
						<template v-if="!fetching && users.length != 0">
 | 
				
			||||||
		<div class="user" v-for="friend in users">
 | 
							<div class="user" v-for="friend in users">
 | 
				
			||||||
			<router-link class="avatar-anchor" :to="friend | userPage">
 | 
								<mk-avatar class="avatar" :user="friend"/>
 | 
				
			||||||
				<img class="avatar" :src="`${friend.avatarUrl}?thumbnail&size=42`" alt="" v-user-preview="friend.id"/>
 | 
					 | 
				
			||||||
			</router-link>
 | 
					 | 
				
			||||||
			<div class="body">
 | 
								<div class="body">
 | 
				
			||||||
				<router-link class="name" :to="friend | userPage" v-user-preview="friend.id">{{ friend.name }}</router-link>
 | 
									<router-link class="name" :to="friend | userPage" v-user-preview="friend.id">{{ friend.name }}</router-link>
 | 
				
			||||||
				<p class="username">@{{ friend | acct }}</p>
 | 
									<p class="username">@{{ friend | acct }}</p>
 | 
				
			||||||
| 
						 | 
					@ -82,18 +80,13 @@ export default Vue.extend({
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
			clear both
 | 
								clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .avatar-anchor
 | 
							> .avatar
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
			float left
 | 
								float left
 | 
				
			||||||
			margin 0 12px 0 0
 | 
								margin 0 12px 0 0
 | 
				
			||||||
 | 
								width 42px
 | 
				
			||||||
			> .avatar
 | 
								height 42px
 | 
				
			||||||
				display block
 | 
								border-radius 8px
 | 
				
			||||||
				width 42px
 | 
					 | 
				
			||||||
				height 42px
 | 
					 | 
				
			||||||
				margin 0
 | 
					 | 
				
			||||||
				border-radius 8px
 | 
					 | 
				
			||||||
				vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .body
 | 
							> .body
 | 
				
			||||||
			float left
 | 
								float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@
 | 
				
			||||||
		<div class="fade"></div>
 | 
							<div class="fade"></div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<div class="container">
 | 
						<div class="container">
 | 
				
			||||||
		<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=150`" alt="avatar"/>
 | 
							<mk-avatar class="avatar" :user="user" :disable-preview="true"/>
 | 
				
			||||||
		<div class="title">
 | 
							<div class="title">
 | 
				
			||||||
			<p class="name">{{ user | userName }}</p>
 | 
								<p class="name">{{ user | userName }}</p>
 | 
				
			||||||
			<p class="username">@{{ user | acct }}</p>
 | 
								<p class="username">@{{ user | acct }}</p>
 | 
				
			||||||
| 
						 | 
					@ -139,7 +139,6 @@ export default Vue.extend({
 | 
				
			||||||
			z-index 2
 | 
								z-index 2
 | 
				
			||||||
			width 160px
 | 
								width 160px
 | 
				
			||||||
			height 160px
 | 
								height 160px
 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			border solid 3px #fff
 | 
								border solid 3px #fff
 | 
				
			||||||
			border-radius 8px
 | 
								border-radius 8px
 | 
				
			||||||
			box-shadow 1px 1px 3px rgba(#000, 0.2)
 | 
								box-shadow 1px 1px 3px rgba(#000, 0.2)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,9 +8,7 @@
 | 
				
			||||||
					<p>ようこそ! <b>Misskey</b>はTwitter風ミニブログSNSです。思ったことや皆と共有したいことを投稿しましょう。タイムラインを見れば、皆の関心事をすぐにチェックすることもできます。<a :href="aboutUrl">詳しく...</a></p>
 | 
										<p>ようこそ! <b>Misskey</b>はTwitter風ミニブログSNSです。思ったことや皆と共有したいことを投稿しましょう。タイムラインを見れば、皆の関心事をすぐにチェックすることもできます。<a :href="aboutUrl">詳しく...</a></p>
 | 
				
			||||||
					<p><button class="signup" @click="signup">はじめる</button><button class="signin" @click="signin">ログイン</button></p>
 | 
										<p><button class="signup" @click="signup">はじめる</button><button class="signin" @click="signin">ログイン</button></p>
 | 
				
			||||||
					<div class="users">
 | 
										<div class="users">
 | 
				
			||||||
						<router-link v-for="user in users" :key="user.id" class="avatar-anchor" :to="user | userPage" v-user-preview="user.id">
 | 
											<mk-avatar class="avatar" :key="user.id" :user="user"/>
 | 
				
			||||||
							<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
						</router-link>
 | 
					 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
				<div>
 | 
									<div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,9 +22,11 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.design++;
 | 
									this.props.design++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		viewChanged(view) {
 | 
							viewChanged(view) {
 | 
				
			||||||
			this.props.view = view;
 | 
								this.props.view = view;
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,7 @@ export default define({
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		func() {
 | 
							func() {
 | 
				
			||||||
			this.props.compact = !this.props.compact;
 | 
								this.props.compact = !this.props.compact;
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		settings() {
 | 
							settings() {
 | 
				
			||||||
			const id = window.prompt('チャンネルID');
 | 
								const id = window.prompt('チャンネルID');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,7 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.design++;
 | 
									this.props.design++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ export default define({
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		func() {
 | 
							func() {
 | 
				
			||||||
			this.props.compact = !this.props.compact;
 | 
								this.props.compact = !this.props.compact;
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,7 @@ export default define({
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		func() {
 | 
							func() {
 | 
				
			||||||
			this.props.compact = !this.props.compact;
 | 
								this.props.compact = !this.props.compact;
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		fetch() {
 | 
							fetch() {
 | 
				
			||||||
			this.fetching = true;
 | 
								this.fetching = true;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,7 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.design++;
 | 
									this.props.design++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		onKeydown(e) {
 | 
							onKeydown(e) {
 | 
				
			||||||
			if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey)) this.post();
 | 
								if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey)) this.post();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,7 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.design++;
 | 
									this.props.design++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@ export default define({
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				this.props.design++;
 | 
									this.props.design++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,7 @@ export default define({
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		func() {
 | 
							func() {
 | 
				
			||||||
			this.props.compact = !this.props.compact;
 | 
								this.props.compact = !this.props.compact;
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		fetch() {
 | 
							fetch() {
 | 
				
			||||||
			this.fetching = true;
 | 
								this.fetching = true;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,9 +8,7 @@
 | 
				
			||||||
			<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
 | 
								<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
 | 
				
			||||||
			<template v-else-if="users.length != 0">
 | 
								<template v-else-if="users.length != 0">
 | 
				
			||||||
				<div class="user" v-for="_user in users">
 | 
									<div class="user" v-for="_user in users">
 | 
				
			||||||
					<router-link class="avatar-anchor" :to="_user | userPage">
 | 
										<mk-avatar class="avatar" :user="_user"/>
 | 
				
			||||||
						<img class="avatar" :src="`${_user.avatarUrl}?thumbnail&size=42`" alt="" v-user-preview="_user.id"/>
 | 
					 | 
				
			||||||
					</router-link>
 | 
					 | 
				
			||||||
					<div class="body">
 | 
										<div class="body">
 | 
				
			||||||
						<router-link class="name" :to="_user | userPage" v-user-preview="_user.id">{{ _user | userName }}</router-link>
 | 
											<router-link class="name" :to="_user | userPage" v-user-preview="_user.id">{{ _user | userName }}</router-link>
 | 
				
			||||||
						<p class="username">@{{ _user | acct }}</p>
 | 
											<p class="username">@{{ _user | acct }}</p>
 | 
				
			||||||
| 
						 | 
					@ -48,6 +46,7 @@ export default define({
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		func() {
 | 
							func() {
 | 
				
			||||||
			this.props.compact = !this.props.compact;
 | 
								this.props.compact = !this.props.compact;
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		fetch() {
 | 
							fetch() {
 | 
				
			||||||
			this.fetching = true;
 | 
								this.fetching = true;
 | 
				
			||||||
| 
						 | 
					@ -88,18 +87,13 @@ root(isDark)
 | 
				
			||||||
				display block
 | 
									display block
 | 
				
			||||||
				clear both
 | 
									clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> .avatar-anchor
 | 
								> .avatar
 | 
				
			||||||
				display block
 | 
									display block
 | 
				
			||||||
				float left
 | 
									float left
 | 
				
			||||||
				margin 0 12px 0 0
 | 
									margin 0 12px 0 0
 | 
				
			||||||
 | 
									width 42px
 | 
				
			||||||
				> .avatar
 | 
									height 42px
 | 
				
			||||||
					display block
 | 
									border-radius 8px
 | 
				
			||||||
					width 42px
 | 
					 | 
				
			||||||
					height 42px
 | 
					 | 
				
			||||||
					margin 0
 | 
					 | 
				
			||||||
					border-radius 8px
 | 
					 | 
				
			||||||
					vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> .body
 | 
								> .body
 | 
				
			||||||
				float left
 | 
									float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Vue from 'vue';
 | 
					import Vue from 'vue';
 | 
				
			||||||
import Vuex from 'vuex';
 | 
					import Vuex, { mapState } from 'vuex';
 | 
				
			||||||
import VueRouter from 'vue-router';
 | 
					import VueRouter from 'vue-router';
 | 
				
			||||||
import VModal from 'vue-js-modal';
 | 
					import VModal from 'vue-js-modal';
 | 
				
			||||||
import * as TreeView from 'vue-json-tree-view';
 | 
					import * as TreeView from 'vue-json-tree-view';
 | 
				
			||||||
| 
						 | 
					@ -41,17 +41,6 @@ require('./common/views/widgets');
 | 
				
			||||||
// Register global filters
 | 
					// Register global filters
 | 
				
			||||||
require('./common/views/filters');
 | 
					require('./common/views/filters');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const store = new Vuex.Store({
 | 
					 | 
				
			||||||
	state: {
 | 
					 | 
				
			||||||
		uiHeaderHeight: 0
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	mutations: {
 | 
					 | 
				
			||||||
		setUiHeaderHeight(state, height) {
 | 
					 | 
				
			||||||
			state.uiHeaderHeight = height;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Vue.mixin({
 | 
					Vue.mixin({
 | 
				
			||||||
	destroyed(this: any) {
 | 
						destroyed(this: any) {
 | 
				
			||||||
		if (this.$el.parentNode) {
 | 
							if (this.$el.parentNode) {
 | 
				
			||||||
| 
						 | 
					@ -159,20 +148,15 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
 | 
				
			||||||
						api: os.api,
 | 
											api: os.api,
 | 
				
			||||||
						apis: os.apis
 | 
											apis: os.apis
 | 
				
			||||||
					};
 | 
										};
 | 
				
			||||||
				}
 | 
									},
 | 
				
			||||||
 | 
									computed: mapState({
 | 
				
			||||||
 | 
										clientSettings: state => state.settings.data
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const app = new Vue({
 | 
								const app = new Vue({
 | 
				
			||||||
				store,
 | 
									store: os.store,
 | 
				
			||||||
				router,
 | 
									router,
 | 
				
			||||||
				created() {
 | 
					 | 
				
			||||||
					this.$watch('os.i', i => {
 | 
					 | 
				
			||||||
						// キャッシュ更新
 | 
					 | 
				
			||||||
						localStorage.setItem('me', JSON.stringify(i));
 | 
					 | 
				
			||||||
					}, {
 | 
					 | 
				
			||||||
						deep: true
 | 
					 | 
				
			||||||
					});
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				render: createEl => createEl(App)
 | 
									render: createEl => createEl(App)
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="root sub">
 | 
					<div class="root sub">
 | 
				
			||||||
	<router-link class="avatar-anchor" :to="note.user | userPage">
 | 
						<mk-avatar class="avatar" :user="note.user"/>
 | 
				
			||||||
		<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
	</router-link>
 | 
					 | 
				
			||||||
	<div class="main">
 | 
						<div class="main">
 | 
				
			||||||
		<header>
 | 
							<header>
 | 
				
			||||||
			<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
 | 
								<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -43,18 +41,13 @@ root(isDark)
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		clear both
 | 
							clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .avatar-anchor
 | 
						> .avatar
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
		margin 0 12px 0 0
 | 
							margin 0 12px 0 0
 | 
				
			||||||
 | 
							width 48px
 | 
				
			||||||
		> .avatar
 | 
							height 48px
 | 
				
			||||||
			display block
 | 
							border-radius 8px
 | 
				
			||||||
			width 48px
 | 
					 | 
				
			||||||
			height 48px
 | 
					 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			border-radius 8px
 | 
					 | 
				
			||||||
			vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .main
 | 
						> .main
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,17 +17,12 @@
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<div class="renote" v-if="isRenote">
 | 
						<div class="renote" v-if="isRenote">
 | 
				
			||||||
		<p>
 | 
							<p>
 | 
				
			||||||
			<router-link class="avatar-anchor" :to="note.user | userPage">
 | 
								<mk-avatar class="avatar" :user="note.user"/>%fa:retweet%<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>がRenote
 | 
				
			||||||
				<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=32`" alt="avatar"/>
 | 
					 | 
				
			||||||
			</router-link>
 | 
					 | 
				
			||||||
			%fa:retweet%<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>がRenote
 | 
					 | 
				
			||||||
		</p>
 | 
							</p>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<article>
 | 
						<article>
 | 
				
			||||||
		<header>
 | 
							<header>
 | 
				
			||||||
			<router-link class="avatar-anchor" :to="p.user | userPage">
 | 
								<mk-avatar class="avatar" :user="p.user"/>
 | 
				
			||||||
				<img class="avatar" :src="`${p.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
			</router-link>
 | 
					 | 
				
			||||||
			<div>
 | 
								<div>
 | 
				
			||||||
				<router-link class="name" :to="p.user | userPage">{{ p.user | userName }}</router-link>
 | 
									<router-link class="name" :to="p.user | userPage">{{ p.user | userName }}</router-link>
 | 
				
			||||||
				<span class="username">@{{ p.user | acct }}</span>
 | 
									<span class="username">@{{ p.user | acct }}</span>
 | 
				
			||||||
| 
						 | 
					@ -152,7 +147,7 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Draw map
 | 
							// Draw map
 | 
				
			||||||
		if (this.p.geo) {
 | 
							if (this.p.geo) {
 | 
				
			||||||
			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.clientSettings.showMaps : true;
 | 
								const shouldShowMap = (this as any).os.isSignedIn ? (this as any).clientSettings.showMaps : true;
 | 
				
			||||||
			if (shouldShowMap) {
 | 
								if (shouldShowMap) {
 | 
				
			||||||
				(this as any).os.getGoogleMaps().then(maps => {
 | 
									(this as any).os.getGoogleMaps().then(maps => {
 | 
				
			||||||
					const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
 | 
										const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
 | 
				
			||||||
| 
						 | 
					@ -262,17 +257,12 @@ root(isDark)
 | 
				
			||||||
			margin 0
 | 
								margin 0
 | 
				
			||||||
			padding 16px 32px
 | 
								padding 16px 32px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			.avatar-anchor
 | 
								.avatar
 | 
				
			||||||
				display inline-block
 | 
									display inline-block
 | 
				
			||||||
 | 
									width 28px
 | 
				
			||||||
				.avatar
 | 
									height 28px
 | 
				
			||||||
					vertical-align bottom
 | 
									margin 0 8px 0 0
 | 
				
			||||||
					min-width 28px
 | 
									border-radius 6px
 | 
				
			||||||
					min-height 28px
 | 
					 | 
				
			||||||
					max-width 28px
 | 
					 | 
				
			||||||
					max-height 28px
 | 
					 | 
				
			||||||
					margin 0 8px 0 0
 | 
					 | 
				
			||||||
					border-radius 6px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			[data-fa]
 | 
								[data-fa]
 | 
				
			||||||
				margin-right 4px
 | 
									margin-right 4px
 | 
				
			||||||
| 
						 | 
					@ -301,21 +291,16 @@ root(isDark)
 | 
				
			||||||
			display flex
 | 
								display flex
 | 
				
			||||||
			line-height 1.1em
 | 
								line-height 1.1em
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> .avatar-anchor
 | 
								> .avatar
 | 
				
			||||||
				display block
 | 
									display block
 | 
				
			||||||
				padding 0 12px 0 0
 | 
									margin 0 12px 0 0
 | 
				
			||||||
 | 
									width 54px
 | 
				
			||||||
 | 
									height 54px
 | 
				
			||||||
 | 
									border-radius 8px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				> .avatar
 | 
									@media (min-width 500px)
 | 
				
			||||||
					display block
 | 
										width 60px
 | 
				
			||||||
					width 54px
 | 
										height 60px
 | 
				
			||||||
					height 54px
 | 
					 | 
				
			||||||
					margin 0
 | 
					 | 
				
			||||||
					border-radius 8px
 | 
					 | 
				
			||||||
					vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					@media (min-width 500px)
 | 
					 | 
				
			||||||
						width 60px
 | 
					 | 
				
			||||||
						height 60px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> div
 | 
								> div
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="mk-note-preview">
 | 
					<div class="mk-note-preview">
 | 
				
			||||||
	<router-link class="avatar-anchor" :to="note.user | userPage">
 | 
						<mk-avatar class="avatar" :user="note.user"/>
 | 
				
			||||||
		<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
	</router-link>
 | 
					 | 
				
			||||||
	<div class="main">
 | 
						<div class="main">
 | 
				
			||||||
		<header>
 | 
							<header>
 | 
				
			||||||
			<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
 | 
								<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -37,18 +35,13 @@ root(isDark)
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		clear both
 | 
							clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .avatar-anchor
 | 
						> .avatar
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
		margin 0 12px 0 0
 | 
							margin 0 12px 0 0
 | 
				
			||||||
 | 
							width 48px
 | 
				
			||||||
		> .avatar
 | 
							height 48px
 | 
				
			||||||
			display block
 | 
							border-radius 8px
 | 
				
			||||||
			width 48px
 | 
					 | 
				
			||||||
			height 48px
 | 
					 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			border-radius 8px
 | 
					 | 
				
			||||||
			vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .main
 | 
						> .main
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="sub">
 | 
					<div class="sub">
 | 
				
			||||||
	<router-link class="avatar-anchor" :to="note.user | userPage">
 | 
						<mk-avatar class="avatar" :user="note.user"/>
 | 
				
			||||||
		<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=96`" alt="avatar"/>
 | 
					 | 
				
			||||||
	</router-link>
 | 
					 | 
				
			||||||
	<div class="main">
 | 
						<div class="main">
 | 
				
			||||||
		<header>
 | 
							<header>
 | 
				
			||||||
			<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
 | 
								<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -49,25 +47,18 @@ root(isDark)
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		clear both
 | 
							clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .avatar-anchor
 | 
						> .avatar
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
		margin 0 10px 0 0
 | 
							margin 0 10px 0 0
 | 
				
			||||||
 | 
							width 44px
 | 
				
			||||||
 | 
							height 44px
 | 
				
			||||||
 | 
							border-radius 8px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@media (min-width 500px)
 | 
							@media (min-width 500px)
 | 
				
			||||||
			margin-right 16px
 | 
								margin-right 16px
 | 
				
			||||||
 | 
								width 52px
 | 
				
			||||||
		> .avatar
 | 
								height 52px
 | 
				
			||||||
			display block
 | 
					 | 
				
			||||||
			width 44px
 | 
					 | 
				
			||||||
			height 44px
 | 
					 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			border-radius 8px
 | 
					 | 
				
			||||||
			vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			@media (min-width 500px)
 | 
					 | 
				
			||||||
				width 52px
 | 
					 | 
				
			||||||
				height 52px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .main
 | 
						> .main
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,10 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="note" :class="{ renote: isRenote }">
 | 
					<div class="note" :class="{ renote: isRenote }">
 | 
				
			||||||
	<div class="reply-to" v-if="p.reply && (!os.isSignedIn || os.i.clientSettings.showReplyTarget)">
 | 
						<div class="reply-to" v-if="p.reply && (!os.isSignedIn || clientSettings.showReplyTarget)">
 | 
				
			||||||
		<x-sub :note="p.reply"/>
 | 
							<x-sub :note="p.reply"/>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<div class="renote" v-if="isRenote">
 | 
						<div class="renote" v-if="isRenote">
 | 
				
			||||||
		<router-link class="avatar-anchor" :to="note.user | userPage">
 | 
							<mk-avatar class="avatar" :user="note.user"/>
 | 
				
			||||||
			<img class="avatar" :src="`${note.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		%fa:retweet%
 | 
							%fa:retweet%
 | 
				
			||||||
		<span>{{ '%i18n:!@reposted-by%'.substr(0, '%i18n:!@reposted-by%'.indexOf('{')) }}</span>
 | 
							<span>{{ '%i18n:!@reposted-by%'.substr(0, '%i18n:!@reposted-by%'.indexOf('{')) }}</span>
 | 
				
			||||||
		<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
 | 
							<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -14,9 +12,7 @@
 | 
				
			||||||
		<mk-time :time="note.createdAt"/>
 | 
							<mk-time :time="note.createdAt"/>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<article>
 | 
						<article>
 | 
				
			||||||
		<router-link class="avatar-anchor" :to="p.user | userPage">
 | 
							<mk-avatar class="avatar" :user="p.user"/>
 | 
				
			||||||
			<img class="avatar" :src="`${p.user.avatarUrl}?thumbnail&size=96`" alt="avatar"/>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		<div class="main">
 | 
							<div class="main">
 | 
				
			||||||
			<header>
 | 
								<header>
 | 
				
			||||||
				<router-link class="name" :to="p.user | userPage">{{ p.user | userName }}</router-link>
 | 
									<router-link class="name" :to="p.user | userPage">{{ p.user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -154,7 +150,7 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Draw map
 | 
							// Draw map
 | 
				
			||||||
		if (this.p.geo) {
 | 
							if (this.p.geo) {
 | 
				
			||||||
			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.clientSettings.showMaps : true;
 | 
								const shouldShowMap = (this as any).os.isSignedIn ? (this as any).clientSettings.showMaps : true;
 | 
				
			||||||
			if (shouldShowMap) {
 | 
								if (shouldShowMap) {
 | 
				
			||||||
				(this as any).os.getGoogleMaps().then(maps => {
 | 
									(this as any).os.getGoogleMaps().then(maps => {
 | 
				
			||||||
					const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
 | 
										const uluru = new maps.LatLng(this.p.geo.coordinates[1], this.p.geo.coordinates[0]);
 | 
				
			||||||
| 
						 | 
					@ -268,15 +264,12 @@ root(isDark)
 | 
				
			||||||
		@media (min-width 600px)
 | 
							@media (min-width 600px)
 | 
				
			||||||
			padding 16px 32px
 | 
								padding 16px 32px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		.avatar-anchor
 | 
							.avatar
 | 
				
			||||||
			display inline-block
 | 
								display inline-block
 | 
				
			||||||
 | 
								width 28px
 | 
				
			||||||
			.avatar
 | 
								height 28px
 | 
				
			||||||
				vertical-align bottom
 | 
								margin 0 8px 0 0
 | 
				
			||||||
				width 28px
 | 
								border-radius 6px
 | 
				
			||||||
				height 28px
 | 
					 | 
				
			||||||
				margin 0 8px 0 0
 | 
					 | 
				
			||||||
				border-radius 6px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[data-fa]
 | 
							[data-fa]
 | 
				
			||||||
			margin-right 4px
 | 
								margin-right 4px
 | 
				
			||||||
| 
						 | 
					@ -314,29 +307,22 @@ root(isDark)
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
			clear both
 | 
								clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .avatar-anchor
 | 
							> .avatar
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
			float left
 | 
								float left
 | 
				
			||||||
			margin 0 10px 8px 0
 | 
								margin 0 10px 8px 0
 | 
				
			||||||
 | 
								width 48px
 | 
				
			||||||
 | 
								height 48px
 | 
				
			||||||
 | 
								border-radius 6px
 | 
				
			||||||
			//position -webkit-sticky
 | 
								//position -webkit-sticky
 | 
				
			||||||
			//position sticky
 | 
								//position sticky
 | 
				
			||||||
			//top 62px
 | 
								//top 62px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			@media (min-width 500px)
 | 
								@media (min-width 500px)
 | 
				
			||||||
				margin-right 16px
 | 
									margin-right 16px
 | 
				
			||||||
 | 
									width 58px
 | 
				
			||||||
			> .avatar
 | 
									height 58px
 | 
				
			||||||
				display block
 | 
									border-radius 8px
 | 
				
			||||||
				width 48px
 | 
					 | 
				
			||||||
				height 48px
 | 
					 | 
				
			||||||
				margin 0
 | 
					 | 
				
			||||||
				border-radius 6px
 | 
					 | 
				
			||||||
				vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				@media (min-width 500px)
 | 
					 | 
				
			||||||
					width 58px
 | 
					 | 
				
			||||||
					height 58px
 | 
					 | 
				
			||||||
					border-radius 8px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .main
 | 
							> .main
 | 
				
			||||||
			float left
 | 
								float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,13 +116,13 @@ export default Vue.extend({
 | 
				
			||||||
			const isMyNote = note.userId == (this as any).os.i.id;
 | 
								const isMyNote = note.userId == (this as any).os.i.id;
 | 
				
			||||||
			const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null;
 | 
								const isPureRenote = note.renoteId != null && note.text == null && note.mediaIds.length == 0 && note.poll == null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ((this as any).os.i.clientSettings.showMyRenotes === false) {
 | 
								if ((this as any).clientSettings.showMyRenotes === false) {
 | 
				
			||||||
				if (isMyNote && isPureRenote) {
 | 
									if (isMyNote && isPureRenote) {
 | 
				
			||||||
					return;
 | 
										return;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ((this as any).os.i.clientSettings.showRenotedMyNotes === false) {
 | 
								if ((this as any).clientSettings.showRenotedMyNotes === false) {
 | 
				
			||||||
				if (isPureRenote && (note.renote.userId == (this as any).os.i.id)) {
 | 
									if (isPureRenote && (note.renote.userId == (this as any).os.i.id)) {
 | 
				
			||||||
					return;
 | 
										return;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -187,7 +187,7 @@ export default Vue.extend({
 | 
				
			||||||
				this.clearNotification();
 | 
									this.clearNotification();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ((this as any).os.i.clientSettings.fetchOnScroll !== false) {
 | 
								if ((this as any).clientSettings.fetchOnScroll !== false) {
 | 
				
			||||||
				const current = window.scrollY + window.innerHeight;
 | 
									const current = window.scrollY + window.innerHeight;
 | 
				
			||||||
				if (current > document.body.offsetHeight - 8) this.loadMore();
 | 
									if (current > document.body.offsetHeight - 8) this.loadMore();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,7 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="mk-notification">
 | 
					<div class="mk-notification">
 | 
				
			||||||
	<div class="notification reaction" v-if="notification.type == 'reaction'">
 | 
						<div class="notification reaction" v-if="notification.type == 'reaction'">
 | 
				
			||||||
		<router-link class="avatar-anchor" :to="notification.user | userPage">
 | 
							<mk-avatar class="avatar" :user="notification.user"/>
 | 
				
			||||||
			<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		<div>
 | 
							<div>
 | 
				
			||||||
			<header>
 | 
								<header>
 | 
				
			||||||
				<mk-reaction-icon :reaction="notification.reaction"/>
 | 
									<mk-reaction-icon :reaction="notification.reaction"/>
 | 
				
			||||||
| 
						 | 
					@ -18,9 +16,7 @@
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<div class="notification renote" v-if="notification.type == 'renote'">
 | 
						<div class="notification renote" v-if="notification.type == 'renote'">
 | 
				
			||||||
		<router-link class="avatar-anchor" :to="notification.user | userPage">
 | 
							<mk-avatar class="avatar" :user="notification.user"/>
 | 
				
			||||||
			<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		<div>
 | 
							<div>
 | 
				
			||||||
			<header>
 | 
								<header>
 | 
				
			||||||
				%fa:retweet%
 | 
									%fa:retweet%
 | 
				
			||||||
| 
						 | 
					@ -34,9 +30,7 @@
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<div class="notification follow" v-if="notification.type == 'follow'">
 | 
						<div class="notification follow" v-if="notification.type == 'follow'">
 | 
				
			||||||
		<router-link class="avatar-anchor" :to="notification.user | userPage">
 | 
							<mk-avatar class="avatar" :user="notification.user"/>
 | 
				
			||||||
			<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		<div>
 | 
							<div>
 | 
				
			||||||
			<header>
 | 
								<header>
 | 
				
			||||||
				%fa:user-plus%
 | 
									%fa:user-plus%
 | 
				
			||||||
| 
						 | 
					@ -47,9 +41,7 @@
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<div class="notification poll_vote" v-if="notification.type == 'poll_vote'">
 | 
						<div class="notification poll_vote" v-if="notification.type == 'poll_vote'">
 | 
				
			||||||
		<router-link class="avatar-anchor" :to="notification.user | userPage">
 | 
							<mk-avatar class="avatar" :user="notification.user"/>
 | 
				
			||||||
			<img class="avatar" :src="`${notification.user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		<div>
 | 
							<div>
 | 
				
			||||||
			<header>
 | 
								<header>
 | 
				
			||||||
				%fa:chart-pie%
 | 
									%fa:chart-pie%
 | 
				
			||||||
| 
						 | 
					@ -111,18 +103,16 @@ root(isDark)
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
			clear both
 | 
								clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> .avatar-anchor
 | 
							> .avatar
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
			float left
 | 
								float left
 | 
				
			||||||
 | 
								width 36px
 | 
				
			||||||
 | 
								height 36px
 | 
				
			||||||
 | 
								border-radius 6px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			img
 | 
								@media (min-width 500px)
 | 
				
			||||||
				width 36px
 | 
									width 42px
 | 
				
			||||||
				height 36px
 | 
									height 42px
 | 
				
			||||||
				border-radius 6px
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				@media (min-width 500px)
 | 
					 | 
				
			||||||
					width 42px
 | 
					 | 
				
			||||||
					height 42px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		> div
 | 
							> div
 | 
				
			||||||
			float right
 | 
								float right
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -166,7 +166,7 @@ export default Vue.extend({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		post() {
 | 
							post() {
 | 
				
			||||||
			this.posting = true;
 | 
								this.posting = true;
 | 
				
			||||||
			const viaMobile = (this as any).os.i.clientSettings.disableViaMobile !== true;
 | 
								const viaMobile = (this as any).clientSettings.disableViaMobile !== true;
 | 
				
			||||||
			(this as any).api('notes/create', {
 | 
								(this as any).api('notes/create', {
 | 
				
			||||||
				text: this.text == '' ? undefined : this.text,
 | 
									text: this.text == '' ? undefined : this.text,
 | 
				
			||||||
				mediaIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
 | 
									mediaIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,8 +46,8 @@ export default Vue.extend({
 | 
				
			||||||
				(this as any).api('notes/user-list-timeline', {
 | 
									(this as any).api('notes/user-list-timeline', {
 | 
				
			||||||
					listId: this.list.id,
 | 
										listId: this.list.id,
 | 
				
			||||||
					limit: fetchLimit + 1,
 | 
										limit: fetchLimit + 1,
 | 
				
			||||||
					includeMyRenotes: (this as any).os.i.clientSettings.showMyRenotes,
 | 
										includeMyRenotes: (this as any).clientSettings.showMyRenotes,
 | 
				
			||||||
					includeRenotedMyNotes: (this as any).os.i.clientSettings.showRenotedMyNotes
 | 
										includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
 | 
				
			||||||
				}).then(notes => {
 | 
									}).then(notes => {
 | 
				
			||||||
					if (notes.length == fetchLimit + 1) {
 | 
										if (notes.length == fetchLimit + 1) {
 | 
				
			||||||
						notes.pop();
 | 
											notes.pop();
 | 
				
			||||||
| 
						 | 
					@ -66,8 +66,8 @@ export default Vue.extend({
 | 
				
			||||||
				listId: this.list.id,
 | 
									listId: this.list.id,
 | 
				
			||||||
				limit: fetchLimit + 1,
 | 
									limit: fetchLimit + 1,
 | 
				
			||||||
				untilId: (this.$refs.timeline as any).tail().id,
 | 
									untilId: (this.$refs.timeline as any).tail().id,
 | 
				
			||||||
				includeMyRenotes: (this as any).os.i.clientSettings.showMyRenotes,
 | 
									includeMyRenotes: (this as any).clientSettings.showMyRenotes,
 | 
				
			||||||
				includeRenotedMyNotes: (this as any).os.i.clientSettings.showRenotedMyNotes
 | 
									includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
 | 
				
			||||||
			}).then(notes => {
 | 
								}).then(notes => {
 | 
				
			||||||
				if (notes.length == fetchLimit + 1) {
 | 
									if (notes.length == fetchLimit + 1) {
 | 
				
			||||||
					notes.pop();
 | 
										notes.pop();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="mk-user-preview">
 | 
					<div class="mk-user-preview">
 | 
				
			||||||
	<router-link class="avatar-anchor" :to="user | userPage">
 | 
						<mk-avatar class="avatar" :user="user"/>
 | 
				
			||||||
		<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
	</router-link>
 | 
					 | 
				
			||||||
	<div class="main">
 | 
						<div class="main">
 | 
				
			||||||
		<header>
 | 
							<header>
 | 
				
			||||||
			<router-link class="name" :to="user | userPage">{{ user | userName }}</router-link>
 | 
								<router-link class="name" :to="user | userPage">{{ user | userName }}</router-link>
 | 
				
			||||||
| 
						 | 
					@ -40,26 +38,19 @@ export default Vue.extend({
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		clear both
 | 
							clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .avatar-anchor
 | 
						> .avatar
 | 
				
			||||||
		display block
 | 
							display block
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
		margin 0 10px 0 0
 | 
							margin 0 10px 0 0
 | 
				
			||||||
 | 
							width 48px
 | 
				
			||||||
 | 
							height 48px
 | 
				
			||||||
 | 
							border-radius 6px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@media (min-width 500px)
 | 
							@media (min-width 500px)
 | 
				
			||||||
			margin-right 16px
 | 
								margin-right 16px
 | 
				
			||||||
 | 
								width 58px
 | 
				
			||||||
		> .avatar
 | 
								height 58px
 | 
				
			||||||
			display block
 | 
								border-radius 8px
 | 
				
			||||||
			width 48px
 | 
					 | 
				
			||||||
			height 48px
 | 
					 | 
				
			||||||
			margin 0
 | 
					 | 
				
			||||||
			border-radius 6px
 | 
					 | 
				
			||||||
			vertical-align bottom
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			@media (min-width 500px)
 | 
					 | 
				
			||||||
				width 58px
 | 
					 | 
				
			||||||
				height 58px
 | 
					 | 
				
			||||||
				border-radius 8px
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	> .main
 | 
						> .main
 | 
				
			||||||
		float left
 | 
							float left
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,8 +64,8 @@ export default Vue.extend({
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	created() {
 | 
						created() {
 | 
				
			||||||
		if ((this as any).os.i.clientSettings.mobileHome == null) {
 | 
							if ((this as any).clientSettings.mobileHome == null) {
 | 
				
			||||||
			Vue.set((this as any).os.i.clientSettings, 'mobileHome', [{
 | 
								Vue.set((this as any).clientSettings, 'mobileHome', [{
 | 
				
			||||||
				name: 'calendar',
 | 
									name: 'calendar',
 | 
				
			||||||
				id: 'a', data: {}
 | 
									id: 'a', data: {}
 | 
				
			||||||
			}, {
 | 
								}, {
 | 
				
			||||||
| 
						 | 
					@ -87,14 +87,14 @@ export default Vue.extend({
 | 
				
			||||||
				name: 'version',
 | 
									name: 'version',
 | 
				
			||||||
				id: 'g', data: {}
 | 
									id: 'g', data: {}
 | 
				
			||||||
			}]);
 | 
								}]);
 | 
				
			||||||
			this.widgets = (this as any).os.i.clientSettings.mobileHome;
 | 
								this.widgets = (this as any).clientSettings.mobileHome;
 | 
				
			||||||
			this.saveHome();
 | 
								this.saveHome();
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			this.widgets = (this as any).os.i.clientSettings.mobileHome;
 | 
								this.widgets = (this as any).clientSettings.mobileHome;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.$watch('os.i.clientSettings', i => {
 | 
							this.$watch('clientSettings', i => {
 | 
				
			||||||
			this.widgets = (this as any).os.i.clientSettings.mobileHome;
 | 
								this.widgets = (this as any).clientSettings.mobileHome;
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
			deep: true
 | 
								deep: true
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
| 
						 | 
					@ -107,15 +107,15 @@ export default Vue.extend({
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		onHomeUpdated(data) {
 | 
							onHomeUpdated(data) {
 | 
				
			||||||
			if (data.home) {
 | 
								if (data.home) {
 | 
				
			||||||
				(this as any).os.i.clientSettings.mobileHome = data.home;
 | 
									(this as any).clientSettings.mobileHome = data.home;
 | 
				
			||||||
				this.widgets = data.home;
 | 
									this.widgets = data.home;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				const w = (this as any).os.i.clientSettings.mobileHome.find(w => w.id == data.id);
 | 
									const w = (this as any).clientSettings.mobileHome.find(w => w.id == data.id);
 | 
				
			||||||
				if (w != null) {
 | 
									if (w != null) {
 | 
				
			||||||
					w.data = data.data;
 | 
										w.data = data.data;
 | 
				
			||||||
					this.$refs[w.id][0].preventSave = true;
 | 
										this.$refs[w.id][0].preventSave = true;
 | 
				
			||||||
					this.$refs[w.id][0].props = w.data;
 | 
										this.$refs[w.id][0].props = w.data;
 | 
				
			||||||
					this.widgets = (this as any).os.i.clientSettings.mobileHome;
 | 
										this.widgets = (this as any).clientSettings.mobileHome;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
| 
						 | 
					@ -144,7 +144,7 @@ export default Vue.extend({
 | 
				
			||||||
			this.saveHome();
 | 
								this.saveHome();
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		saveHome() {
 | 
							saveHome() {
 | 
				
			||||||
			(this as any).os.i.clientSettings.mobileHome = this.widgets;
 | 
								(this as any).clientSettings.mobileHome = this.widgets;
 | 
				
			||||||
			(this as any).api('i/update_mobile_home', {
 | 
								(this as any).api('i/update_mobile_home', {
 | 
				
			||||||
				home: this.widgets
 | 
									home: this.widgets
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,8 +92,8 @@ export default Vue.extend({
 | 
				
			||||||
				(this as any).api(this.endpoint, {
 | 
									(this as any).api(this.endpoint, {
 | 
				
			||||||
					limit: fetchLimit + 1,
 | 
										limit: fetchLimit + 1,
 | 
				
			||||||
					untilDate: this.date ? this.date.getTime() : undefined,
 | 
										untilDate: this.date ? this.date.getTime() : undefined,
 | 
				
			||||||
					includeMyRenotes: (this as any).os.i.clientSettings.showMyRenotes,
 | 
										includeMyRenotes: (this as any).clientSettings.showMyRenotes,
 | 
				
			||||||
					includeRenotedMyNotes: (this as any).os.i.clientSettings.showRenotedMyNotes
 | 
										includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
 | 
				
			||||||
				}).then(notes => {
 | 
									}).then(notes => {
 | 
				
			||||||
					if (notes.length == fetchLimit + 1) {
 | 
										if (notes.length == fetchLimit + 1) {
 | 
				
			||||||
						notes.pop();
 | 
											notes.pop();
 | 
				
			||||||
| 
						 | 
					@ -114,8 +114,8 @@ export default Vue.extend({
 | 
				
			||||||
			(this as any).api(this.endpoint, {
 | 
								(this as any).api(this.endpoint, {
 | 
				
			||||||
				limit: fetchLimit + 1,
 | 
									limit: fetchLimit + 1,
 | 
				
			||||||
				untilId: (this.$refs.timeline as any).tail().id,
 | 
									untilId: (this.$refs.timeline as any).tail().id,
 | 
				
			||||||
				includeMyRenotes: (this as any).os.i.clientSettings.showMyRenotes,
 | 
									includeMyRenotes: (this as any).clientSettings.showMyRenotes,
 | 
				
			||||||
				includeRenotedMyNotes: (this as any).os.i.clientSettings.showRenotedMyNotes
 | 
									includeRenotedMyNotes: (this as any).clientSettings.showRenotedMyNotes
 | 
				
			||||||
			}).then(notes => {
 | 
								}).then(notes => {
 | 
				
			||||||
				if (notes.length == fetchLimit + 1) {
 | 
									if (notes.length == fetchLimit + 1) {
 | 
				
			||||||
					notes.pop();
 | 
										notes.pop();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,9 +22,7 @@
 | 
				
			||||||
			<mk-welcome-timeline/>
 | 
								<mk-welcome-timeline/>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		<div class="users">
 | 
							<div class="users">
 | 
				
			||||||
			<router-link v-for="user in users" :key="user.id" class="avatar-anchor" :to="`/@${user.username}`">
 | 
								<mk-avatar class="avatar" :key="user.id" :user="user"/>
 | 
				
			||||||
				<img class="avatar" :src="`${user.avatarUrl}?thumbnail&size=64`" alt="avatar"/>
 | 
					 | 
				
			||||||
			</router-link>
 | 
					 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		<footer>
 | 
							<footer>
 | 
				
			||||||
			<small>{{ copyright }}</small>
 | 
								<small>{{ copyright }}</small>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,7 @@ export default define({
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		func() {
 | 
							func() {
 | 
				
			||||||
			this.props.compact = !this.props.compact;
 | 
								this.props.compact = !this.props.compact;
 | 
				
			||||||
 | 
								this.save();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										90
									
								
								src/client/app/store.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/client/app/store.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,90 @@
 | 
				
			||||||
 | 
					import Vuex from 'vuex';
 | 
				
			||||||
 | 
					import MiOS from './common/mios';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const defaultSettings = {
 | 
				
			||||||
 | 
						home: [],
 | 
				
			||||||
 | 
						fetchOnScroll: true,
 | 
				
			||||||
 | 
						showMaps: true,
 | 
				
			||||||
 | 
						showPostFormOnTopOfTl: false,
 | 
				
			||||||
 | 
						circleIcons: true,
 | 
				
			||||||
 | 
						gradientWindowHeader: false,
 | 
				
			||||||
 | 
						showReplyTarget: true,
 | 
				
			||||||
 | 
						showMyRenotes: true,
 | 
				
			||||||
 | 
						showRenotedMyNotes: true
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default (os: MiOS) => new Vuex.Store({
 | 
				
			||||||
 | 
						plugins: [store => {
 | 
				
			||||||
 | 
							store.subscribe((mutation, state) => {
 | 
				
			||||||
 | 
								if (mutation.type.startsWith('settings/')) {
 | 
				
			||||||
 | 
									localStorage.setItem('settings', JSON.stringify(state.settings.data));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state: {
 | 
				
			||||||
 | 
							uiHeaderHeight: 0
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutations: {
 | 
				
			||||||
 | 
							setUiHeaderHeight(state, height) {
 | 
				
			||||||
 | 
								state.uiHeaderHeight = height;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						modules: {
 | 
				
			||||||
 | 
							settings: {
 | 
				
			||||||
 | 
								namespaced: true,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								state: {
 | 
				
			||||||
 | 
									data: defaultSettings
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								mutations: {
 | 
				
			||||||
 | 
									init(state, settings) {
 | 
				
			||||||
 | 
										state.data = settings;
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									set(state, x: { key: string; value: any }) {
 | 
				
			||||||
 | 
										state.data[x.key] = x.value;
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									setHome(state, data) {
 | 
				
			||||||
 | 
										state.data.home = data;
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									setHomeWidget(state, x) {
 | 
				
			||||||
 | 
										const w = state.data.home.find(w => w.id == x.id);
 | 
				
			||||||
 | 
										if (w) {
 | 
				
			||||||
 | 
											w.data = x.data;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									addHomeWidget(state, widget) {
 | 
				
			||||||
 | 
										state.data.home.unshift(widget);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								actions: {
 | 
				
			||||||
 | 
									set(ctx, x) {
 | 
				
			||||||
 | 
										ctx.commit('set', x);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (os.isSignedIn) {
 | 
				
			||||||
 | 
											os.api('i/update_client_setting', {
 | 
				
			||||||
 | 
												name: x.key,
 | 
				
			||||||
 | 
												value: x.value
 | 
				
			||||||
 | 
											});
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									addHomeWidget(ctx, widget) {
 | 
				
			||||||
 | 
										ctx.commit('addHomeWidget', widget);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										os.api('i/update_home', {
 | 
				
			||||||
 | 
											home: ctx.state.data.home
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -24,16 +24,11 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 | 
				
			||||||
		$set: x
 | 
							$set: x
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Serialize
 | 
						res();
 | 
				
			||||||
	user.clientSettings[name] = value;
 | 
					
 | 
				
			||||||
	const iObj = await pack(user, user, {
 | 
						// Publish event
 | 
				
			||||||
		detail: true,
 | 
						event(user._id, 'clientSettingUpdated', {
 | 
				
			||||||
		includeSecrets: true
 | 
							key: name,
 | 
				
			||||||
 | 
							value
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Send response
 | 
					 | 
				
			||||||
	res(iObj);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Publish i updated event
 | 
					 | 
				
			||||||
	event(user._id, 'i_updated', iObj);
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,9 +26,9 @@ if (process.env.NODE_ENV != 'production') {
 | 
				
			||||||
	app.use(logger());
 | 
						app.use(logger());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Delay
 | 
						// Delay
 | 
				
			||||||
	app.use(slow({
 | 
						//app.use(slow({
 | 
				
			||||||
		delay: 1000
 | 
						//	delay: 1000
 | 
				
			||||||
	}));
 | 
						//}));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Compress response
 | 
					// Compress response
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue