summaryrefslogtreecommitdiff
path: root/packages/frontend/src/scripts/use-note-capture.ts
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2022-12-27 14:36:33 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2022-12-27 14:36:33 +0900
commit9384f5399da39e53855beb8e7f8ded1aa56bf72e (patch)
treece5959571a981b9c4047da3c7b3fd080aa44222c /packages/frontend/src/scripts/use-note-capture.ts
parentwip: retention for dashboard (diff)
downloadsharkey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.tar.gz
sharkey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.tar.bz2
sharkey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.zip
rename: client -> frontend
Diffstat (limited to 'packages/frontend/src/scripts/use-note-capture.ts')
-rw-r--r--packages/frontend/src/scripts/use-note-capture.ts110
1 files changed, 110 insertions, 0 deletions
diff --git a/packages/frontend/src/scripts/use-note-capture.ts b/packages/frontend/src/scripts/use-note-capture.ts
new file mode 100644
index 0000000000..e6bdb345c4
--- /dev/null
+++ b/packages/frontend/src/scripts/use-note-capture.ts
@@ -0,0 +1,110 @@
+import { onUnmounted, Ref } from 'vue';
+import * as misskey from 'misskey-js';
+import { stream } from '@/stream';
+import { $i } from '@/account';
+
+export function useNoteCapture(props: {
+ rootEl: Ref<HTMLElement>;
+ note: Ref<misskey.entities.Note>;
+ isDeletedRef: Ref<boolean>;
+}) {
+ const note = props.note;
+ const connection = $i ? stream : null;
+
+ function onStreamNoteUpdated(noteData): void {
+ const { type, id, body } = noteData;
+
+ if (id !== note.value.id) return;
+
+ switch (type) {
+ case 'reacted': {
+ const reaction = body.reaction;
+
+ if (body.emoji) {
+ const emojis = note.value.emojis || [];
+ if (!emojis.includes(body.emoji)) {
+ note.value.emojis = [...emojis, body.emoji];
+ }
+ }
+
+ // TODO: reactionsプロパティがない場合ってあったっけ? なければ || {} は消せる
+ const currentCount = (note.value.reactions || {})[reaction] || 0;
+
+ note.value.reactions[reaction] = currentCount + 1;
+
+ if ($i && (body.userId === $i.id)) {
+ note.value.myReaction = reaction;
+ }
+ break;
+ }
+
+ case 'unreacted': {
+ const reaction = body.reaction;
+
+ // TODO: reactionsプロパティがない場合ってあったっけ? なければ || {} は消せる
+ const currentCount = (note.value.reactions || {})[reaction] || 0;
+
+ note.value.reactions[reaction] = Math.max(0, currentCount - 1);
+
+ if ($i && (body.userId === $i.id)) {
+ note.value.myReaction = null;
+ }
+ break;
+ }
+
+ case 'pollVoted': {
+ const choice = body.choice;
+
+ const choices = [...note.value.poll.choices];
+ choices[choice] = {
+ ...choices[choice],
+ votes: choices[choice].votes + 1,
+ ...($i && (body.userId === $i.id) ? {
+ isVoted: true,
+ } : {}),
+ };
+
+ note.value.poll.choices = choices;
+ break;
+ }
+
+ case 'deleted': {
+ props.isDeletedRef.value = true;
+ break;
+ }
+ }
+ }
+
+ function capture(withHandler = false): void {
+ if (connection) {
+ // TODO: このノートがストリーミング経由で流れてきた場合のみ sr する
+ connection.send(document.body.contains(props.rootEl.value) ? 'sr' : 's', { id: note.value.id });
+ if (withHandler) connection.on('noteUpdated', onStreamNoteUpdated);
+ }
+ }
+
+ function decapture(withHandler = false): void {
+ if (connection) {
+ connection.send('un', {
+ id: note.value.id,
+ });
+ if (withHandler) connection.off('noteUpdated', onStreamNoteUpdated);
+ }
+ }
+
+ function onStreamConnected() {
+ capture(false);
+ }
+
+ capture(true);
+ if (connection) {
+ connection.on('_connected_', onStreamConnected);
+ }
+
+ onUnmounted(() => {
+ decapture(true);
+ if (connection) {
+ connection.off('_connected_', onStreamConnected);
+ }
+ });
+}