parent
							
								
									b32737cdff
								
							
						
					
					
						commit
						b5a1fdd4c7
					
				
					 5 changed files with 73 additions and 70 deletions
				
			
		|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div | ||||
| 	class="note _panel" | ||||
| 	v-show="!isDeleted && !hideThisNote" | ||||
| 	v-show="!isDeleted" | ||||
| 	:tabindex="!isDeleted ? '-1' : null" | ||||
| 	:class="{ renote: isRenote }" | ||||
| 	v-hotkey="keymap" | ||||
|  | @ -37,16 +37,16 @@ | |||
| 		<mk-avatar class="avatar" :user="appearNote.user" v-once/> | ||||
| 		<div class="main"> | ||||
| 			<x-note-header class="header" :note="appearNote" :mini="true"/> | ||||
| 			<div class="body" v-if="appearNote.deletedAt == null" ref="noteBody"> | ||||
| 			<div class="body" ref="noteBody"> | ||||
| 				<p v-if="appearNote.cw != null" class="cw"> | ||||
| 				<mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis" v-once/> | ||||
| 				<mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$store.state.i" :custom-emojis="emojis" v-once/> | ||||
| 					<x-cw-button v-model="showContent" :note="appearNote"/> | ||||
| 				</p> | ||||
| 				<div class="content" v-show="appearNote.cw == null || showContent"> | ||||
| 					<div class="text"> | ||||
| 						<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ $t('private') }})</span> | ||||
| 						<router-link class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><fa :icon="faReply"/></router-link> | ||||
| 						<mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis" v-once/> | ||||
| 						<mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$store.state.i" :custom-emojis="emojis" v-once/> | ||||
| 						<a class="rp" v-if="appearNote.renote != null">RN:</a> | ||||
| 					</div> | ||||
| 					<div class="files" v-if="appearNote.files.length > 0"> | ||||
|  | @ -57,8 +57,8 @@ | |||
| 					<div class="renote" v-if="appearNote.renote"><x-note-preview :note="appearNote.renote"/></div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			<footer v-if="appearNote.deletedAt == null" class="footer"> | ||||
| 				<x-reactions-viewer :note="appearNote" ref="reactionsViewer"/> | ||||
| 			<footer class="footer"> | ||||
| 				<x-reactions-viewer :note="appearNote" :reactions="reactions" :my-reaction="myReaction" :emojis="emojis" ref="reactionsViewer"/> | ||||
| 				<button @click="reply()" class="button _button"> | ||||
| 					<template v-if="appearNote.reply"><fa :icon="faReplyAll"/></template> | ||||
| 					<template v-else><fa :icon="faReply"/></template> | ||||
|  | @ -70,17 +70,16 @@ | |||
| 				<button v-else class="button _button"> | ||||
| 					<fa :icon="faBan"/> | ||||
| 				</button> | ||||
| 				<button v-if="!isMyNote && appearNote.myReaction == null" class="button _button" @click="react()" ref="reactButton"> | ||||
| 				<button v-if="!isMyNote && myReaction == null" class="button _button" @click="react()" ref="reactButton"> | ||||
| 					<fa :icon="faPlus"/> | ||||
| 				</button> | ||||
| 				<button v-if="!isMyNote && appearNote.myReaction != null" class="button _button reacted" @click="undoReact(appearNote)" ref="reactButton"> | ||||
| 				<button v-if="!isMyNote && myReaction != null" class="button _button reacted" @click="undoReact()" ref="reactButton"> | ||||
| 					<fa :icon="faMinus"/> | ||||
| 				</button> | ||||
| 				<button class="button _button" @click="menu()" ref="menuButton"> | ||||
| 					<fa :icon="faEllipsisH"/> | ||||
| 				</button> | ||||
| 			</footer> | ||||
| 			<div class="deleted" v-if="appearNote.deletedAt != null">{{ $t('deleted') }}</div> | ||||
| 		</div> | ||||
| 	</article> | ||||
| 	<x-sub v-for="note in replies" :key="note.id" :note="note" class="reply" :detail="true"/> | ||||
|  | @ -142,7 +141,10 @@ export default Vue.extend({ | |||
| 			conversation: [], | ||||
| 			replies: [], | ||||
| 			showContent: false, | ||||
| 			hideThisNote: false, | ||||
| 			isDeleted: false, | ||||
| 			myReaction: null, | ||||
| 			reactions: {}, | ||||
| 			emojis: [], | ||||
| 			noteBody: this.$refs.noteBody, | ||||
| 			faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faBiohazard, faPlug | ||||
| 		}; | ||||
|  | @ -186,10 +188,6 @@ export default Vue.extend({ | |||
| 			return this.isRenote ? this.note.renote : this.note; | ||||
| 		}, | ||||
| 
 | ||||
| 		isDeleted(): boolean { | ||||
| 			return this.appearNote.deletedAt != null || this.note.deletedAt != null; | ||||
| 		}, | ||||
| 
 | ||||
| 		isMyNote(): boolean { | ||||
| 			return this.$store.getters.isSignedIn && (this.$store.state.i.id === this.appearNote.userId); | ||||
| 		}, | ||||
|  | @ -203,9 +201,7 @@ export default Vue.extend({ | |||
| 		}, | ||||
| 
 | ||||
| 		reactionsCount(): number { | ||||
| 			return this.appearNote.reactions | ||||
| 				? sum(Object.values(this.appearNote.reactions)) | ||||
| 				: 0; | ||||
| 			return sum(Object.values(this.reactions)); | ||||
| 		}, | ||||
| 
 | ||||
| 		urls(): string[] { | ||||
|  | @ -232,6 +228,10 @@ export default Vue.extend({ | |||
| 	}, | ||||
| 
 | ||||
| 	created() { | ||||
| 		this.emojis = [...this.appearNote.emojis]; | ||||
| 		this.reactions = { ...this.appearNote.reactions }; | ||||
| 		this.myReaction = this.appearNote.myReaction; | ||||
| 
 | ||||
| 		if (this.$store.getters.isSignedIn) { | ||||
| 			this.connection = this.$root.stream; | ||||
| 		} | ||||
|  | @ -261,7 +261,7 @@ export default Vue.extend({ | |||
| 			this.connection.on('_connected_', this.onStreamConnected); | ||||
| 		} | ||||
| 
 | ||||
| 		this.noteBody = this.$refs.noteBody | ||||
| 		this.noteBody = this.$refs.noteBody; | ||||
| 	}, | ||||
| 
 | ||||
| 	beforeDestroy() { | ||||
|  | @ -277,7 +277,7 @@ export default Vue.extend({ | |||
| 			(this as any).$root.api('promo/read', { | ||||
| 				noteId: this.appearNote.id | ||||
| 			}); | ||||
| 			this.hideThisNote = true; | ||||
| 			this.isDeleted = true; | ||||
| 		}, | ||||
| 
 | ||||
| 		capture(withHandler = false) { | ||||
|  | @ -310,26 +310,20 @@ export default Vue.extend({ | |||
| 					const reaction = body.reaction; | ||||
| 
 | ||||
| 					if (body.emoji) { | ||||
| 						const emojis = this.appearNote.emojis || []; | ||||
| 						if (!emojis.includes(body.emoji)) { | ||||
| 							emojis.push(body.emoji); | ||||
| 							Vue.set(this.appearNote, 'emojis', emojis); | ||||
| 						if (!this.emojis.includes(body.emoji)) { | ||||
| 							this.emojis.push(body.emoji); | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					if (this.appearNote.reactions == null) { | ||||
| 						Vue.set(this.appearNote, 'reactions', {}); | ||||
| 					} | ||||
| 
 | ||||
| 					if (this.appearNote.reactions[reaction] == null) { | ||||
| 						Vue.set(this.appearNote.reactions, reaction, 0); | ||||
| 					if (this.reactions[reaction] == null) { | ||||
| 						Vue.set(this.reactions, reaction, 0); | ||||
| 					} | ||||
| 
 | ||||
| 					// Increment the count | ||||
| 					this.appearNote.reactions[reaction]++; | ||||
| 					this.reactions[reaction]++; | ||||
| 
 | ||||
| 					if (body.userId == this.$store.state.i.id) { | ||||
| 						Vue.set(this.appearNote, 'myReaction', reaction); | ||||
| 					if (body.userId === this.$store.state.i.id) { | ||||
| 						this.myReaction = reaction; | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
|  | @ -337,19 +331,15 @@ export default Vue.extend({ | |||
| 				case 'unreacted': { | ||||
| 					const reaction = body.reaction; | ||||
| 
 | ||||
| 					if (this.appearNote.reactions == null) { | ||||
| 						return; | ||||
| 					} | ||||
| 
 | ||||
| 					if (this.appearNote.reactions[reaction] == null) { | ||||
| 					if (this.reactions[reaction] == null) { | ||||
| 						return; | ||||
| 					} | ||||
| 
 | ||||
| 					// Decrement the count | ||||
| 					if (this.appearNote.reactions[reaction] > 0) this.appearNote.reactions[reaction]--; | ||||
| 					if (this.reactions[reaction] > 0) this.reactions[reaction]--; | ||||
| 
 | ||||
| 					if (body.userId == this.$store.state.i.id) { | ||||
| 						Vue.set(this.appearNote, 'myReaction', null); | ||||
| 					if (body.userId === this.$store.state.i.id) { | ||||
| 						this.myReaction = null; | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
|  | @ -357,19 +347,14 @@ export default Vue.extend({ | |||
| 				case 'pollVoted': { | ||||
| 					const choice = body.choice; | ||||
| 					this.appearNote.poll.choices[choice].votes++; | ||||
| 					if (body.userId == this.$store.state.i.id) { | ||||
| 					if (body.userId === this.$store.state.i.id) { | ||||
| 						Vue.set(this.appearNote.poll.choices[choice], 'isVoted', true); | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 
 | ||||
| 				case 'deleted': { | ||||
| 					Vue.set(this.appearNote, 'deletedAt', body.deletedAt); | ||||
| 					Vue.set(this.appearNote, 'renote', null); | ||||
| 					this.appearNote.text = null; | ||||
| 					this.appearNote.fileIds = []; | ||||
| 					this.appearNote.poll = null; | ||||
| 					this.appearNote.cw = null; | ||||
| 					this.isDeleted = true; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
|  | @ -442,11 +427,11 @@ export default Vue.extend({ | |||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		undoReact(note) { | ||||
| 			const oldReaction = note.myReaction; | ||||
| 		undoReact() { | ||||
| 			const oldReaction = this.myReaction; | ||||
| 			if (!oldReaction) return; | ||||
| 			this.$root.api('notes/reactions/delete', { | ||||
| 				noteId: note.id | ||||
| 				noteId: this.appearNote.id | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
|  | @ -638,7 +623,7 @@ export default Vue.extend({ | |||
| 						this.$root.api('notes/delete', { | ||||
| 							noteId: this.note.id | ||||
| 						}); | ||||
| 						Vue.set(this.note, 'deletedAt', new Date()); | ||||
| 						this.isDeleted = true; | ||||
| 					} | ||||
| 				}], | ||||
| 				source: this.$refs.renoteTime, | ||||
|  | @ -925,10 +910,6 @@ export default Vue.extend({ | |||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			> .deleted { | ||||
| 				opacity: 0.7; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <button | ||||
| 	class="hkzvhatu _button" | ||||
| 	:class="{ reacted: note.myReaction == reaction, canToggle }" | ||||
| 	:class="{ reacted: myReaction == reaction, canToggle }" | ||||
| 	@click="toggleReaction(reaction)" | ||||
| 	v-if="count > 0" | ||||
| 	@touchstart="onMouseover" | ||||
|  | @ -11,7 +11,7 @@ | |||
| 	ref="reaction" | ||||
| 	v-particle="canToggle" | ||||
| > | ||||
| 	<x-reaction-icon :reaction="reaction" :custom-emojis="note.emojis" ref="icon"/> | ||||
| 	<x-reaction-icon :reaction="reaction" :custom-emojis="emojis" ref="icon"/> | ||||
| 	<span>{{ count }}</span> | ||||
| </button> | ||||
| </template> | ||||
|  | @ -30,6 +30,14 @@ export default Vue.extend({ | |||
| 			type: String, | ||||
| 			required: true, | ||||
| 		}, | ||||
| 		myReaction: { | ||||
| 			type: String, | ||||
| 			required: false, | ||||
| 		}, | ||||
| 		emojis: { | ||||
| 			type: Array, | ||||
| 			required: true, | ||||
| 		}, | ||||
| 		count: { | ||||
| 			type: Number, | ||||
| 			required: true, | ||||
|  | @ -71,7 +79,7 @@ export default Vue.extend({ | |||
| 		toggleReaction() { | ||||
| 			if (!this.canToggle) return; | ||||
| 
 | ||||
| 			const oldReaction = this.note.myReaction; | ||||
| 			const oldReaction = this.myReaction; | ||||
| 			if (oldReaction) { | ||||
| 				this.$root.api('notes/reactions/delete', { | ||||
| 					noteId: this.note.id | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <div class="tdflqwzn" :class="{ isMe }"> | ||||
| 	<x-reaction v-for="(count, reaction) in note.reactions" :reaction="reaction" :count="count" :is-initial="initialReactions.has(reaction)" :note="note" :key="reaction"/> | ||||
| 	<x-reaction v-for="(count, reaction) in reactions" :reaction="reaction" :count="count" :is-initial="initialReactions.has(reaction)" :note="note" :my-reaction="myReaction" :emojis="emojis" :key="reaction"/> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
|  | @ -12,16 +12,28 @@ export default Vue.extend({ | |||
| 	components: { | ||||
| 		XReaction | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			initialReactions: new Set(Object.keys(this.note.reactions)) | ||||
| 		}; | ||||
| 	}, | ||||
| 	props: { | ||||
| 		note: { | ||||
| 			type: Object, | ||||
| 			required: true | ||||
| 		}, | ||||
| 		reactions: { | ||||
| 			type: Object, | ||||
| 			required: true | ||||
| 		}, | ||||
| 		myReaction: { | ||||
| 			type: String, | ||||
| 			required: false, | ||||
| 		}, | ||||
| 		emojis: { | ||||
| 			type: Array, | ||||
| 			required: true, | ||||
| 		}, | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			initialReactions: new Set(Object.keys(this.note.reactions)) | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
| 		isMe(): boolean { | ||||
|  |  | |||
|  | @ -52,8 +52,8 @@ export default Vue.extend({ | |||
| 		}); | ||||
| 
 | ||||
| 		const prepend = note => { | ||||
| 			const _note = JSON.parse(JSON.stringify(note));	// deepcopy | ||||
| 			(this.$refs.tl as any).prepend(_note); | ||||
| 			Object.freeze(note); | ||||
| 			(this.$refs.tl as any).prepend(note); | ||||
| 
 | ||||
| 			this.$emit('note'); | ||||
| 
 | ||||
|  |  | |||
|  | @ -74,10 +74,6 @@ export default (opts) => ({ | |||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		updateItem(i, item) { | ||||
| 			Vue.set((this as any).items, i, item); | ||||
| 		}, | ||||
| 
 | ||||
| 		reload() { | ||||
| 			this.items = []; | ||||
| 			this.init(); | ||||
|  | @ -94,6 +90,9 @@ export default (opts) => ({ | |||
| 				...params, | ||||
| 				limit: this.pagination.noPaging ? (this.pagination.limit || 10) : (this.pagination.limit || 10) + 1, | ||||
| 			}).then(items => { | ||||
| 				for (const item of items) { | ||||
| 					Object.freeze(item); | ||||
| 				} | ||||
| 				if (!this.pagination.noPaging && (items.length > (this.pagination.limit || 10))) { | ||||
| 					items.pop(); | ||||
| 					this.items = this.pagination.reversed ? [...items].reverse() : items; | ||||
|  | @ -130,6 +129,9 @@ export default (opts) => ({ | |||
| 					untilId: this.items[this.items.length - 1].id, | ||||
| 				}), | ||||
| 			}).then(items => { | ||||
| 				for (const item of items) { | ||||
| 					Object.freeze(item); | ||||
| 				} | ||||
| 				if (items.length > SECOND_FETCH_LIMIT) { | ||||
| 					items.pop(); | ||||
| 					this.items = this.pagination.reversed ? [...items].reverse().concat(this.items) : this.items.concat(items); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue