やった
This commit is contained in:
		
							parent
							
								
									818bc96aab
								
							
						
					
					
						commit
						be9f836b21
					
				
					 13 changed files with 159 additions and 16 deletions
				
			
		|  | @ -87,6 +87,7 @@ common: | |||
|     swap-right: "右に移動" | ||||
|     remove: "カラムを削除" | ||||
|     add-column: "カラムを追加" | ||||
|     rename: "名前を変更" | ||||
| 
 | ||||
| common/views/components/connect-failed.vue: | ||||
|   title: "サーバーに接続できません" | ||||
|  |  | |||
|  | @ -20,6 +20,10 @@ export default Vue.extend({ | |||
| 			type: String, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		name: { | ||||
| 			type: String, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		menu: { | ||||
| 			type: Array, | ||||
| 			required: false | ||||
|  | @ -75,6 +79,17 @@ export default Vue.extend({ | |||
| 
 | ||||
| 		showMenu() { | ||||
| 			const items = [{ | ||||
| 				content: '%fa:pencil-alt% %i18n:common.deck.rename%', | ||||
| 				onClick: () => { | ||||
| 					(this as any).apis.input({ | ||||
| 						title: '%i18n:common.deck.rename%', | ||||
| 						default: this.name, | ||||
| 						allowEmpty: false | ||||
| 					}).then(name => { | ||||
| 						this.$store.dispatch('settings/renameDeckColumn', { id: this.id, name }); | ||||
| 					}); | ||||
| 				} | ||||
| 			}, null, { | ||||
| 				content: '%fa:arrow-left% %i18n:common.deck.swap-left%', | ||||
| 				onClick: () => { | ||||
| 					this.$store.dispatch('settings/swapLeftDeckColumn', this.id); | ||||
|  | @ -84,7 +99,7 @@ export default Vue.extend({ | |||
| 				onClick: () => { | ||||
| 					this.$store.dispatch('settings/swapRightDeckColumn', this.id); | ||||
| 				} | ||||
| 			}, { | ||||
| 			}, null, { | ||||
| 				content: '%fa:trash-alt R% %i18n:common.deck.remove%', | ||||
| 				onClick: () => { | ||||
| 					this.$store.dispatch('settings/removeDeckColumn', this.id); | ||||
|  |  | |||
|  | @ -18,6 +18,11 @@ export default Vue.extend({ | |||
| 		list: { | ||||
| 			type: Object, | ||||
| 			required: true | ||||
| 		}, | ||||
| 		mediaOnly: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -30,6 +35,12 @@ export default Vue.extend({ | |||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	watch: { | ||||
| 		mediaOnly() { | ||||
| 			this.fetch(); | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	mounted() { | ||||
| 		if (this.connection) this.connection.close(); | ||||
| 		this.connection = new UserListStream((this as any).os, this.$store.state.i, this.list.id); | ||||
|  | @ -52,6 +63,7 @@ export default Vue.extend({ | |||
| 				(this as any).api('notes/user-list-timeline', { | ||||
| 					listId: this.list.id, | ||||
| 					limit: fetchLimit + 1, | ||||
| 					mediaOnly: this.mediaOnly, | ||||
| 					includeMyRenotes: this.$store.state.settings.showMyRenotes, | ||||
| 					includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes | ||||
| 				}).then(notes => { | ||||
|  | @ -72,6 +84,7 @@ export default Vue.extend({ | |||
| 				listId: this.list.id, | ||||
| 				limit: fetchLimit + 1, | ||||
| 				untilId: (this.$refs.timeline as any).tail().id, | ||||
| 				mediaOnly: this.mediaOnly, | ||||
| 				includeMyRenotes: this.$store.state.settings.showMyRenotes, | ||||
| 				includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes | ||||
| 			}); | ||||
|  | @ -89,6 +102,8 @@ export default Vue.extend({ | |||
| 			return promise; | ||||
| 		}, | ||||
| 		onNote(note) { | ||||
| 			if (this.mediaOnly && note.media.length == 0) return; | ||||
| 
 | ||||
| 			// Prepend a note | ||||
| 			(this.$refs.timeline as any).prepend(note); | ||||
| 		}, | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div> | ||||
| 	<x-column :id="id"> | ||||
| 		<span slot="header">%fa:bell R%%i18n:common.deck.notifications%</span> | ||||
| 	<x-column :id="column.id" :name="name"> | ||||
| 		<span slot="header">%fa:bell R%{{ name }}</span> | ||||
| 
 | ||||
| 		<x-notifications/> | ||||
| 	</x-column> | ||||
|  | @ -20,10 +20,17 @@ export default Vue.extend({ | |||
| 	}, | ||||
| 
 | ||||
| 	props: { | ||||
| 		id: { | ||||
| 			type: String, | ||||
| 		column: { | ||||
| 			type: Object, | ||||
| 			required: true | ||||
| 		} | ||||
| 	} | ||||
| 	}, | ||||
| 
 | ||||
| 	computed: { | ||||
| 		name(): string { | ||||
| 			if (this.column.name) return this.column.name; | ||||
| 			return '%i18n:common.deck.notifications%'; | ||||
| 		} | ||||
| 	}, | ||||
| }); | ||||
| </script> | ||||
|  |  | |||
|  | @ -1,15 +1,20 @@ | |||
| <template> | ||||
| <div> | ||||
| 	<x-column :id="column.id"> | ||||
| 	<x-column :id="column.id" :menu="menu" :name="name"> | ||||
| 		<span slot="header"> | ||||
| 			<template v-if="column.type == 'home'">%fa:home%%i18n:common.deck.home%</template> | ||||
| 			<template v-if="column.type == 'local'">%fa:R comments%%i18n:common.deck.local%</template> | ||||
| 			<template v-if="column.type == 'global'">%fa:globe%%i18n:common.deck.global%</template> | ||||
| 			<template v-if="column.type == 'list'">%fa:list%{{ column.list.title }}</template> | ||||
| 			<template v-if="column.type == 'home'">%fa:home%</template> | ||||
| 			<template v-if="column.type == 'local'">%fa:R comments%</template> | ||||
| 			<template v-if="column.type == 'global'">%fa:globe%</template> | ||||
| 			<template v-if="column.type == 'list'">%fa:list%</template> | ||||
| 			<span>{{ name }}</span> | ||||
| 		</span> | ||||
| 
 | ||||
| 		<x-list-tl v-if="column.type == 'list'" :list="column.list"/> | ||||
| 		<x-tl v-else :src="column.type"/> | ||||
| 		<div class="editor" v-if="edit"> | ||||
| 			<mk-switch v-model="column.isMediaOnly" @change="onChangeSettings" text="%i18n:@is-media-only%"/> | ||||
| 			<mk-switch v-model="column.isMediaView" @change="onChangeSettings" text="%i18n:@is-media-view%"/> | ||||
| 		</div> | ||||
| 		<x-list-tl v-if="column.type == 'list'" :list="column.list" :media-only="column.isMediaOnly"/> | ||||
| 		<x-tl v-else :src="column.type" :media-only="column.isMediaOnly"/> | ||||
| 	</x-column> | ||||
| </div> | ||||
| </template> | ||||
|  | @ -32,6 +37,37 @@ export default Vue.extend({ | |||
| 			type: Object, | ||||
| 			required: true | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			edit: false, | ||||
| 			menu: [{ | ||||
| 				content: '%fa:cog% %i18n:@edit%', | ||||
| 				onClick: () => { | ||||
| 					this.edit = !this.edit; | ||||
| 				} | ||||
| 			}] | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	computed: { | ||||
| 		name(): string { | ||||
| 			if (this.column.name) return this.column.name; | ||||
| 
 | ||||
| 			switch (this.column.type) { | ||||
| 				case 'home': return '%i18n:common.deck.home%'; | ||||
| 				case 'local': return '%i18n:common.deck.local%'; | ||||
| 				case 'global': return '%i18n:common.deck.global%'; | ||||
| 				case 'list': return this.column.list.title; | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		onChangeSettings(v) { | ||||
| 			this.$store.dispatch('settings/saveDeck'); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
|  |  | |||
|  | @ -18,6 +18,11 @@ export default Vue.extend({ | |||
| 			type: String, | ||||
| 			required: false, | ||||
| 			default: 'home' | ||||
| 		}, | ||||
| 		mediaOnly: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -31,6 +36,12 @@ export default Vue.extend({ | |||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	watch: { | ||||
| 		mediaOnly() { | ||||
| 			this.fetch(); | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	computed: { | ||||
| 		stream(): any { | ||||
| 			return this.src == 'home' | ||||
|  | @ -78,6 +89,7 @@ export default Vue.extend({ | |||
| 			(this.$refs.timeline as any).init(() => new Promise((res, rej) => { | ||||
| 				(this as any).api(this.endpoint, { | ||||
| 					limit: fetchLimit + 1, | ||||
| 					mediaOnly: this.mediaOnly, | ||||
| 					includeMyRenotes: this.$store.state.settings.showMyRenotes, | ||||
| 					includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes | ||||
| 				}).then(notes => { | ||||
|  | @ -97,6 +109,7 @@ export default Vue.extend({ | |||
| 
 | ||||
| 			const promise = (this as any).api(this.endpoint, { | ||||
| 				limit: fetchLimit + 1, | ||||
| 				mediaOnly: this.mediaOnly, | ||||
| 				untilId: (this.$refs.timeline as any).tail().id, | ||||
| 				includeMyRenotes: this.$store.state.settings.showMyRenotes, | ||||
| 				includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes | ||||
|  | @ -116,6 +129,8 @@ export default Vue.extend({ | |||
| 		}, | ||||
| 
 | ||||
| 		onNote(note) { | ||||
| 			if (this.mediaOnly && note.media.length == 0) return; | ||||
| 
 | ||||
| 			// Prepend a note | ||||
| 			(this.$refs.timeline as any).prepend(note); | ||||
| 		}, | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| 	<div class="qlvquzbjribqcaozciifydkngcwtyzje" :data-darkmode="$store.state.device.darkmode"> | ||||
| 		<template v-for="column in columns"> | ||||
| 			<x-widgets-column v-if="column.type == 'widgets'" :key="column.id" :column="column"/> | ||||
| 			<x-notifications-column v-if="column.type == 'notifications'" :key="column.id" :id="column.id"/> | ||||
| 			<x-notifications-column v-if="column.type == 'notifications'" :key="column.id" :column="column"/> | ||||
| 			<x-tl-column v-if="column.type == 'home'" :key="column.id" :column="column"/> | ||||
| 			<x-tl-column v-if="column.type == 'local'" :key="column.id" :column="column"/> | ||||
| 			<x-tl-column v-if="column.type == 'global'" :key="column.id" :column="column"/> | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="wtdtxvecapixsepjtcupubtsmometobz"> | ||||
| 	<x-column :id="column.id" :menu="menu" :naked="true" :narrow="true"> | ||||
| 		<span slot="header">%fa:calculator%%i18n:common.deck.widgets%</span> | ||||
| 	<x-column :id="column.id" :menu="menu" :naked="true" :narrow="true" :name="name"> | ||||
| 		<span slot="header">%fa:calculator%{{ name }}</span> | ||||
| 
 | ||||
| 		<div class="gqpwvtwtprsbmnssnbicggtwqhmylhnq"> | ||||
| 			<template v-if="edit"> | ||||
|  | @ -81,6 +81,13 @@ export default Vue.extend({ | |||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	computed: { | ||||
| 		name(): string { | ||||
| 			if (this.column.name) return this.column.name; | ||||
| 			return '%i18n:common.deck.widgets%'; | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	created() { | ||||
| 		this.menu = [{ | ||||
| 			content: '%fa:cog% %i18n:@edit%', | ||||
|  |  | |||
|  | @ -222,6 +222,12 @@ export default (os: MiOS) => new Vuex.Store({ | |||
| 					const column = state.deck.columns.find(c => c.id == x.id); | ||||
| 					if (column == null) return; | ||||
| 					column.widgets = column.widgets.filter(w => w.id != x.widget.id); | ||||
| 				}, | ||||
| 
 | ||||
| 				renameDeckColumn(state, x) { | ||||
| 					const column = state.deck.columns.find(c => c.id == x.id); | ||||
| 					if (column == null) return; | ||||
| 					column.name = x.name; | ||||
| 				} | ||||
| 			}, | ||||
| 
 | ||||
|  | @ -281,6 +287,11 @@ export default (os: MiOS) => new Vuex.Store({ | |||
| 					ctx.dispatch('saveDeck'); | ||||
| 				}, | ||||
| 
 | ||||
| 				renameDeckColumn(ctx, x) { | ||||
| 					ctx.commit('renameDeckColumn', x); | ||||
| 					ctx.dispatch('saveDeck'); | ||||
| 				}, | ||||
| 
 | ||||
| 				addHomeWidget(ctx, widget) { | ||||
| 					ctx.commit('addHomeWidget', widget); | ||||
| 
 | ||||
|  |  | |||
|  | @ -35,6 +35,10 @@ module.exports = async (params, user) => { | |||
| 		throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; | ||||
| 	} | ||||
| 
 | ||||
| 	// Get 'mediaOnly' parameter
 | ||||
| 	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); | ||||
| 	if (mediaOnlyErr) throw 'invalid mediaOnly param'; | ||||
| 
 | ||||
| 	// ミュートしているユーザーを取得
 | ||||
| 	const mutedUserIds = user ? (await Mute.find({ | ||||
| 		muterId: user._id | ||||
|  | @ -64,6 +68,10 @@ module.exports = async (params, user) => { | |||
| 		}; | ||||
| 	} | ||||
| 
 | ||||
| 	if (mediaOnly) { | ||||
| 		query.mediaIds = { $exists: true, $ne: [] }; | ||||
| 	} | ||||
| 
 | ||||
| 	if (sinceId) { | ||||
| 		sort._id = 1; | ||||
| 		query._id = { | ||||
|  |  | |||
|  | @ -35,6 +35,10 @@ module.exports = async (params, user) => { | |||
| 		throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified'; | ||||
| 	} | ||||
| 
 | ||||
| 	// Get 'mediaOnly' parameter
 | ||||
| 	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); | ||||
| 	if (mediaOnlyErr) throw 'invalid mediaOnly param'; | ||||
| 
 | ||||
| 	// ミュートしているユーザーを取得
 | ||||
| 	const mutedUserIds = user ? (await Mute.find({ | ||||
| 		muterId: user._id | ||||
|  | @ -67,6 +71,10 @@ module.exports = async (params, user) => { | |||
| 		}; | ||||
| 	} | ||||
| 
 | ||||
| 	if (mediaOnly) { | ||||
| 		query.mediaIds = { $exists: true, $ne: [] }; | ||||
| 	} | ||||
| 
 | ||||
| 	if (sinceId) { | ||||
| 		sort._id = 1; | ||||
| 		query._id = { | ||||
|  |  | |||
|  | @ -44,6 +44,10 @@ module.exports = async (params, user, app) => { | |||
| 	const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional().get(params.includeRenotedMyNotes); | ||||
| 	if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param'; | ||||
| 
 | ||||
| 	// Get 'mediaOnly' parameter
 | ||||
| 	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); | ||||
| 	if (mediaOnlyErr) throw 'invalid mediaOnly param'; | ||||
| 
 | ||||
| 	const [followings, mutedUserIds] = await Promise.all([ | ||||
| 		// フォローを取得
 | ||||
| 		// Fetch following
 | ||||
|  | @ -137,6 +141,12 @@ module.exports = async (params, user, app) => { | |||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	if (mediaOnly) { | ||||
| 		query.$and.push({ | ||||
| 			mediaIds: { $exists: true, $ne: [] } | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	if (sinceId) { | ||||
| 		sort._id = 1; | ||||
| 		query._id = { | ||||
|  |  | |||
|  | @ -44,6 +44,10 @@ module.exports = async (params, user, app) => { | |||
| 	const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional().get(params.includeRenotedMyNotes); | ||||
| 	if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param'; | ||||
| 
 | ||||
| 	// Get 'mediaOnly' parameter
 | ||||
| 	const [mediaOnly, mediaOnlyErr] = $.bool.optional().get(params.mediaOnly); | ||||
| 	if (mediaOnlyErr) throw 'invalid mediaOnly param'; | ||||
| 
 | ||||
| 	// Get 'listId' parameter
 | ||||
| 	const [listId, listIdErr] = $.type(ID).get(params.listId); | ||||
| 	if (listIdErr) throw 'invalid listId param'; | ||||
|  | @ -146,6 +150,12 @@ module.exports = async (params, user, app) => { | |||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	if (mediaOnly) { | ||||
| 		query.$and.push({ | ||||
| 			mediaIds: { $exists: true, $ne: [] } | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	if (sinceId) { | ||||
| 		sort._id = 1; | ||||
| 		query._id = { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue