misskey/packages/frontend/src/scripts/use-note-capture.ts
riku6460 8d06a6475e
chore: 著作権とライセンスについての情報を各ファイルに追加する (#141)
* chore: 著作権とライセンスについての情報を各ファイルに追加する

* chore: Add the SPDX information to each file

Add copyright and licensing information as defined in version 3.0 of
the REUSE Specification.

* tweak format

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>

* chore: Add SPDX-License-Identifier [skip ci]

* add missing SPDX-License-Identifier

* remove unused file

---------

Co-authored-by: Shun Sakai <sorairolake@protonmail.ch>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Co-authored-by: Chocolate Pie <106949016+chocolate-pie@users.noreply.github.com>
2023-08-15 02:52:38 +09:00

114 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { onUnmounted, Ref } from 'vue';
import * as misskey from 'misskey-js';
import { useStream } 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 ? useStream() : 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 && !(body.emoji.name in note.value.reactionEmojis)) {
note.value.reactionEmojis[body.emoji.name] = body.emoji.url;
}
// 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 (note.value.reactions[reaction] === 0) delete note.value.reactions[reaction];
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);
}
});
}