diff options
Diffstat (limited to 'src/client/app/common/scripts/note-subscriber.ts')
| -rw-r--r-- | src/client/app/common/scripts/note-subscriber.ts | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/client/app/common/scripts/note-subscriber.ts b/src/client/app/common/scripts/note-subscriber.ts new file mode 100644 index 0000000000..5fc82942d5 --- /dev/null +++ b/src/client/app/common/scripts/note-subscriber.ts @@ -0,0 +1,105 @@ +import Vue from 'vue'; + +export default prop => ({ + data() { + return { + connection: null + }; + }, + + computed: { + $_ns_note_(): any { + return this[prop]; + }, + + $_ns_isRenote(): boolean { + return (this.$_ns_note_.renote && + this.$_ns_note_.text == null && + this.$_ns_note_.fileIds.length == 0 && + this.$_ns_note_.poll == null); + }, + + $_ns_target(): any { + return this._ns_isRenote ? this.$_ns_note_.renote : this.$_ns_note_; + }, + }, + + created() { + if (this.$store.getters.isSignedIn) { + this.connection = (this as any).os.stream; + } + }, + + mounted() { + this.capture(true); + + if (this.$store.getters.isSignedIn) { + this.connection.on('_connected_', this.onStreamConnected); + } + }, + + beforeDestroy() { + this.decapture(true); + + if (this.$store.getters.isSignedIn) { + this.connection.off('_connected_', this.onStreamConnected); + } + }, + + methods: { + capture(withHandler = false) { + if (this.$store.getters.isSignedIn) { + const data = { + id: this.$_ns_target.id + } as any; + + if ( + (this.$_ns_target.visibleUserIds || []).includes(this.$store.state.i.id) || + (this.$_ns_target.mentions || []).includes(this.$store.state.i.id) + ) { + data.read = true; + } + + this.connection.send('sn', data); + if (withHandler) this.connection.on('noteUpdated', this.onStreamNoteUpdated); + } + }, + + decapture(withHandler = false) { + if (this.$store.getters.isSignedIn) { + this.connection.send('un', { + id: this.$_ns_target.id + }); + if (withHandler) this.connection.off('noteUpdated', this.onStreamNoteUpdated); + } + }, + + onStreamConnected() { + this.capture(); + }, + + onStreamNoteUpdated(data) { + const { type, id, body } = data; + + if (id !== this.$_ns_target.id) return; + + switch (type) { + case 'reacted': { + const reaction = body.reaction; + if (this.$_ns_target.reactionCounts == null) Vue.set(this.$_ns_target, 'reactionCounts', {}); + this.$_ns_target.reactionCounts[reaction] = (this.$_ns_target.reactionCounts[reaction] || 0) + 1; + break; + } + + case 'pollVoted': { + if (body.userId == this.$store.state.i.id) return; + const choice = body.choice; + this.$_ns_target.poll.choices.find(c => c.id === choice).votes++; + break; + } + } + + this.$emit(`update:${prop}`, this.$_ns_note_); + }, + } +}); |