wip
This commit is contained in:
parent
66c3666d0c
commit
5ac2116449
|
@ -92,7 +92,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:noteId="appearNote.id"
|
||||
:multiple="appearNote.poll.multiple"
|
||||
:expiresAt="appearNote.poll.expiresAt"
|
||||
:choices="pollChoices"
|
||||
:choices="$appearNote.pollChoices"
|
||||
:author="appearNote.user"
|
||||
:emojiUrls="appearNote.emojis"
|
||||
:class="$style.poll"
|
||||
|
@ -113,9 +113,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkReactionsViewer
|
||||
v-if="appearNote.reactionAcceptance !== 'likeOnly'"
|
||||
style="margin-top: 6px;"
|
||||
:reactions="reactions"
|
||||
:reactionEmojis="reactionEmojis"
|
||||
:myReaction="myReaction"
|
||||
:reactions="$appearNote.reactions"
|
||||
:reactionEmojis="$appearNote.reactionEmojis"
|
||||
:myReaction="$appearNote.myReaction"
|
||||
:noteId="appearNote.id"
|
||||
:maxNumber="16"
|
||||
@mockUpdateMyReaction="emitUpdReaction"
|
||||
|
@ -143,11 +143,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<i class="ti ti-ban"></i>
|
||||
</button>
|
||||
<button ref="reactButton" :class="$style.footerButton" class="_button" @click="toggleReact()">
|
||||
<i v-if="appearNote.reactionAcceptance === 'likeOnly' && myReaction != null" class="ti ti-heart-filled" style="color: var(--MI_THEME-love);"></i>
|
||||
<i v-else-if="myReaction != null" class="ti ti-minus" style="color: var(--MI_THEME-accent);"></i>
|
||||
<i v-if="appearNote.reactionAcceptance === 'likeOnly' && $appearNote.myReaction != null" class="ti ti-heart-filled" style="color: var(--MI_THEME-love);"></i>
|
||||
<i v-else-if="$appearNote.myReaction != null" class="ti ti-minus" style="color: var(--MI_THEME-accent);"></i>
|
||||
<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
|
||||
<i v-else class="ti ti-plus"></i>
|
||||
<p v-if="(appearNote.reactionAcceptance === 'likeOnly' || prefer.s.showReactionsCount) && reactionCount > 0" :class="$style.footerButtonCount">{{ number(reactionCount) }}</p>
|
||||
<p v-if="(appearNote.reactionAcceptance === 'likeOnly' || prefer.s.showReactionsCount) && $appearNote.reactionCount > 0" :class="$style.footerButtonCount">{{ number($appearNote.reactionCount) }}</p>
|
||||
</button>
|
||||
<button v-if="prefer.s.showClipButtonInNoteFooter" ref="clipButton" :class="$style.footerButton" class="_button" @mousedown.prevent="clip()">
|
||||
<i class="ti ti-paperclip"></i>
|
||||
|
@ -194,7 +194,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, onMounted, ref, useTemplateRef, watch, provide, shallowRef } from 'vue';
|
||||
import { computed, inject, onMounted, ref, useTemplateRef, watch, provide, shallowRef, reactive } from 'vue';
|
||||
import * as mfm from 'mfm-js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { isLink } from '@@/js/is-link.js';
|
||||
|
@ -287,11 +287,13 @@ if (noteViewInterruptors.length > 0) {
|
|||
|
||||
const isRenote = Misskey.note.isPureRenote(note);
|
||||
const appearNote = getAppearNote(note);
|
||||
const reactions = ref(appearNote.reactions);
|
||||
const reactionCount = ref(appearNote.reactionCount);
|
||||
const reactionEmojis = ref(appearNote.reactionEmojis);
|
||||
const myReaction = ref(appearNote.myReaction);
|
||||
const pollChoices = ref(appearNote.poll?.choices);
|
||||
const $appearNote = reactive({
|
||||
reactions: appearNote.reactions,
|
||||
reactionCount: appearNote.reactionCount,
|
||||
reactionEmojis: appearNote.reactionEmojis,
|
||||
myReaction: appearNote.myReaction,
|
||||
pollChoices: appearNote.poll?.choices,
|
||||
});
|
||||
|
||||
const rootEl = useTemplateRef('rootEl');
|
||||
const menuButton = useTemplateRef('menuButton');
|
||||
|
@ -317,7 +319,7 @@ const canRenote = computed(() => ['public', 'home'].includes(appearNote.visibili
|
|||
const renoteCollapsed = ref(
|
||||
prefer.s.collapseRenotes && isRenote && (
|
||||
($i && ($i.id === note.userId || $i.id === appearNote.userId)) || // `||` must be `||`! See https://github.com/misskey-dev/misskey/issues/13131
|
||||
(myReaction.value != null)
|
||||
($appearNote.myReaction != null)
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -421,12 +423,7 @@ if (props.mock) {
|
|||
useNoteCapture({
|
||||
note: appearNote,
|
||||
parentNote: note,
|
||||
reactionsRef: reactions,
|
||||
reactionCountRef: reactionCount,
|
||||
reactionEmojisRef: reactionEmojis,
|
||||
myReactionRef: myReaction,
|
||||
pollChoicesRef: pollChoices,
|
||||
isDeletedRef: isDeleted,
|
||||
$note: $appearNote,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -456,7 +453,7 @@ if (!props.mock) {
|
|||
const reactions = await misskeyApiGet('notes/reactions', {
|
||||
noteId: appearNote.id,
|
||||
limit: 10,
|
||||
_cacheKey_: reactionCount.value,
|
||||
_cacheKey_: $appearNote.reactionCount,
|
||||
});
|
||||
|
||||
const users = reactions.map(x => x.user);
|
||||
|
@ -467,7 +464,7 @@ if (!props.mock) {
|
|||
showing,
|
||||
reaction: '❤️',
|
||||
users,
|
||||
count: reactionCount.value,
|
||||
count: $appearNote.reactionCount,
|
||||
targetElement: reactButton.value!,
|
||||
}, {
|
||||
closed: () => dispose(),
|
||||
|
@ -566,7 +563,7 @@ function react(): void {
|
|||
}
|
||||
|
||||
function undoReact(): void {
|
||||
const oldReaction = myReaction.value;
|
||||
const oldReaction = $appearNote.myReaction;
|
||||
if (!oldReaction) return;
|
||||
|
||||
if (props.mock) {
|
||||
|
@ -580,7 +577,7 @@ function undoReact(): void {
|
|||
}
|
||||
|
||||
function toggleReact() {
|
||||
if (myReaction.value == null) {
|
||||
if ($appearNote.myReaction == null) {
|
||||
react();
|
||||
} else {
|
||||
undoReact();
|
||||
|
|
|
@ -136,9 +136,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkReactionsViewer
|
||||
v-if="appearNote.reactionAcceptance !== 'likeOnly'"
|
||||
style="margin-top: 6px;"
|
||||
:reactions="reactions"
|
||||
:reactionEmojis="reactionEmojis"
|
||||
:myReaction="myReaction"
|
||||
:reactions="$appearNote.reactions"
|
||||
:reactionEmojis="$appearNote.reactionEmojis"
|
||||
:myReaction="$appearNote.myReaction"
|
||||
:noteId="appearNote.id"
|
||||
:maxNumber="16"
|
||||
@mockUpdateMyReaction="emitUpdReaction"
|
||||
|
@ -161,11 +161,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<i class="ti ti-ban"></i>
|
||||
</button>
|
||||
<button ref="reactButton" :class="$style.noteFooterButton" class="_button" @click="toggleReact()">
|
||||
<i v-if="appearNote.reactionAcceptance === 'likeOnly' && myReaction != null" class="ti ti-heart-filled" style="color: var(--MI_THEME-love);"></i>
|
||||
<i v-else-if="myReaction != null" class="ti ti-minus" style="color: var(--MI_THEME-accent);"></i>
|
||||
<i v-if="appearNote.reactionAcceptance === 'likeOnly' && $appearNote.myReaction != null" class="ti ti-heart-filled" style="color: var(--MI_THEME-love);"></i>
|
||||
<i v-else-if="$appearNote.myReaction != null" class="ti ti-minus" style="color: var(--MI_THEME-accent);"></i>
|
||||
<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
|
||||
<i v-else class="ti ti-plus"></i>
|
||||
<p v-if="(appearNote.reactionAcceptance === 'likeOnly' || prefer.s.showReactionsCount) && reactionCount > 0" :class="$style.noteFooterButtonCount">{{ number(reactionCount) }}</p>
|
||||
<p v-if="(appearNote.reactionAcceptance === 'likeOnly' || prefer.s.showReactionsCount) && $appearNote.reactionCount > 0" :class="$style.noteFooterButtonCount">{{ number($appearNote.reactionCount) }}</p>
|
||||
</button>
|
||||
<button v-if="prefer.s.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown.prevent="clip()">
|
||||
<i class="ti ti-paperclip"></i>
|
||||
|
@ -229,7 +229,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, onMounted, provide, ref, useTemplateRef } from 'vue';
|
||||
import { computed, inject, onMounted, provide, reactive, ref, useTemplateRef } from 'vue';
|
||||
import * as mfm from 'mfm-js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { isLink } from '@@/js/is-link.js';
|
||||
|
@ -308,11 +308,13 @@ if (noteViewInterruptors.length > 0) {
|
|||
|
||||
const isRenote = Misskey.note.isPureRenote(note);
|
||||
const appearNote = getAppearNote(note);
|
||||
const reactions = ref(appearNote.reactions);
|
||||
const reactionCount = ref(appearNote.reactionCount);
|
||||
const reactionEmojis = ref(appearNote.reactionEmojis);
|
||||
const myReaction = ref(appearNote.myReaction);
|
||||
const pollChoices = ref(appearNote.poll?.choices);
|
||||
const $appearNote = reactive({
|
||||
reactions: appearNote.reactions,
|
||||
reactionCount: appearNote.reactionCount,
|
||||
reactionEmojis: appearNote.reactionEmojis,
|
||||
myReaction: appearNote.myReaction,
|
||||
pollChoices: appearNote.poll?.choices,
|
||||
});
|
||||
|
||||
const rootEl = useTemplateRef('rootEl');
|
||||
const menuButton = useTemplateRef('menuButton');
|
||||
|
@ -376,7 +378,7 @@ provide(DI.mfmEmojiReactCallback, (reaction) => {
|
|||
const tab = ref(props.initialTab);
|
||||
const reactionTabType = ref<string | null>(null);
|
||||
|
||||
const renotesPagination = computed<Paging>(() => ({
|
||||
const renotesPagination = computed(() => ({
|
||||
endpoint: 'notes/renotes',
|
||||
limit: 10,
|
||||
params: {
|
||||
|
@ -384,7 +386,7 @@ const renotesPagination = computed<Paging>(() => ({
|
|||
},
|
||||
}));
|
||||
|
||||
const reactionsPagination = computed<Paging>(() => ({
|
||||
const reactionsPagination = computed(() => ({
|
||||
endpoint: 'notes/reactions',
|
||||
limit: 10,
|
||||
params: {
|
||||
|
@ -396,12 +398,7 @@ const reactionsPagination = computed<Paging>(() => ({
|
|||
useNoteCapture({
|
||||
note: appearNote,
|
||||
parentNote: note,
|
||||
reactionsRef: reactions,
|
||||
reactionCountRef: reactionCount,
|
||||
reactionEmojisRef: reactionEmojis,
|
||||
myReactionRef: myReaction,
|
||||
pollChoicesRef: pollChoices,
|
||||
isDeletedRef: isDeleted,
|
||||
$note: $appearNote,
|
||||
});
|
||||
|
||||
useTooltip(renoteButton, async (showing) => {
|
||||
|
@ -429,7 +426,7 @@ if (appearNote.reactionAcceptance === 'likeOnly') {
|
|||
const reactions = await misskeyApiGet('notes/reactions', {
|
||||
noteId: appearNote.id,
|
||||
limit: 10,
|
||||
_cacheKey_: reactionCount.value,
|
||||
_cacheKey_: $appearNote.reactionCount,
|
||||
});
|
||||
|
||||
const users = reactions.map(x => x.user);
|
||||
|
@ -440,7 +437,7 @@ if (appearNote.reactionAcceptance === 'likeOnly') {
|
|||
showing,
|
||||
reaction: '❤️',
|
||||
users,
|
||||
count: reactionCount.value,
|
||||
count: $appearNote.reactionCount,
|
||||
targetElement: reactButton.value!,
|
||||
}, {
|
||||
closed: () => dispose(),
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { onUnmounted } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import type { Ref } from 'vue';
|
||||
import type { Reactive, Ref } from 'vue';
|
||||
import { useStream } from '@/stream.js';
|
||||
import { $i } from '@/i.js';
|
||||
import { store } from '@/store.js';
|
||||
|
@ -86,17 +86,14 @@ window.setInterval(() => {
|
|||
|
||||
function pollingSubscribe(props: {
|
||||
note: Pick<Misskey.entities.Note, 'id' | 'createdAt'>;
|
||||
reactionsRef: Ref<Misskey.entities.Note['reactions']>;
|
||||
reactionCountRef: Ref<Misskey.entities.Note['reactionCount']>;
|
||||
reactionEmojisRef: Ref<Misskey.entities.Note['reactionEmojis']>;
|
||||
isDeletedRef: Ref<boolean>;
|
||||
$note: ReactiveNoteData;
|
||||
}) {
|
||||
const { note, reactionsRef, reactionCountRef, reactionEmojisRef } = props;
|
||||
const { note, $note } = props;
|
||||
|
||||
function onFetched(data: Pick<Misskey.entities.Note, 'reactions' | 'reactionEmojis'>): void {
|
||||
reactionsRef.value = data.reactions;
|
||||
reactionCountRef.value = Object.values(data.reactions).reduce((a, b) => a + b, 0);
|
||||
reactionEmojisRef.value = data.reactionEmojis;
|
||||
$note.reactions = data.reactions;
|
||||
$note.reactionCount = Object.values(data.reactions).reduce((a, b) => a + b, 0);
|
||||
$note.reactionEmojis = data.reactionEmojis;
|
||||
}
|
||||
|
||||
pollingEnqueue(note);
|
||||
|
@ -177,17 +174,20 @@ function realtimeSubscribe(props: {
|
|||
});
|
||||
}
|
||||
|
||||
type ReactiveNoteData = Reactive<{
|
||||
reactions: Misskey.entities.Note['reactions'];
|
||||
reactionCount: Misskey.entities.Note['reactionCount'];
|
||||
reactionEmojis: Misskey.entities.Note['reactionEmojis'];
|
||||
myReaction: Misskey.entities.Note['myReaction'];
|
||||
pollChoices: NonNullable<Misskey.entities.Note['poll']>['choices'];
|
||||
}>;
|
||||
|
||||
export function useNoteCapture(props: {
|
||||
note: Pick<Misskey.entities.Note, 'id' | 'createdAt'>;
|
||||
parentNote: Misskey.entities.Note | null;
|
||||
reactionsRef: Ref<Misskey.entities.Note['reactions']>;
|
||||
reactionCountRef: Ref<Misskey.entities.Note['reactionCount']>;
|
||||
reactionEmojisRef: Ref<Misskey.entities.Note['reactionEmojis']>;
|
||||
myReactionRef: Ref<Misskey.entities.Note['myReaction']>;
|
||||
pollChoicesRef: Ref<NonNullable<Misskey.entities.Note['poll']>['choices'] | null>;
|
||||
isDeletedRef: Ref<boolean>;
|
||||
$note: ReactiveNoteData;
|
||||
}) {
|
||||
const { note, parentNote, reactionsRef, reactionCountRef, reactionEmojisRef, myReactionRef, pollChoicesRef } = props;
|
||||
const { note, parentNote, $note } = props;
|
||||
|
||||
noteEvents.on(`reacted:${note.id}`, onReacted);
|
||||
noteEvents.on(`unreacted:${note.id}`, onUnreacted);
|
||||
|
@ -203,17 +203,17 @@ export function useNoteCapture(props: {
|
|||
if (newReactedKey === latestReactedKey) return;
|
||||
latestReactedKey = newReactedKey;
|
||||
|
||||
if (ctx.emoji && !(ctx.emoji.name in reactionEmojisRef.value)) {
|
||||
reactionEmojisRef.value[ctx.emoji.name] = ctx.emoji.url;
|
||||
if (ctx.emoji && !(ctx.emoji.name in $note.reactionEmojis)) {
|
||||
$note.reactionEmojis[ctx.emoji.name] = ctx.emoji.url;
|
||||
}
|
||||
|
||||
const currentCount = reactionsRef.value[ctx.reaction] || 0;
|
||||
const currentCount = $note.reactions[ctx.reaction] || 0;
|
||||
|
||||
reactionsRef.value[ctx.reaction] = currentCount + 1;
|
||||
reactionCountRef.value += 1;
|
||||
$note.reactions[ctx.reaction] = currentCount + 1;
|
||||
$note.reactionCount += 1;
|
||||
|
||||
if ($i && (ctx.userId === $i.id)) {
|
||||
myReactionRef.value = ctx.reaction;
|
||||
$note.myReaction = ctx.reaction;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,14 +222,14 @@ export function useNoteCapture(props: {
|
|||
if (newUnreactedKey === latestUnreactedKey) return;
|
||||
latestUnreactedKey = newUnreactedKey;
|
||||
|
||||
const currentCount = reactionsRef.value[ctx.reaction] || 0;
|
||||
const currentCount = $note.reactions[ctx.reaction] || 0;
|
||||
|
||||
reactionsRef.value[ctx.reaction] = Math.max(0, currentCount - 1);
|
||||
reactionCountRef.value = Math.max(0, reactionCountRef.value - 1);
|
||||
if (reactionsRef.value[ctx.reaction] === 0) delete reactionsRef.value[ctx.reaction];
|
||||
$note.reactions[ctx.reaction] = Math.max(0, currentCount - 1);
|
||||
$note.reactionCount = Math.max(0, $note.reactionCount - 1);
|
||||
if ($note.reactions[ctx.reaction] === 0) delete $note.reactions[ctx.reaction];
|
||||
|
||||
if ($i && (ctx.userId === $i.id)) {
|
||||
myReactionRef.value = null;
|
||||
$note.myReaction = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ export function useNoteCapture(props: {
|
|||
if (newPollVotedKey === latestPollVotedKey) return;
|
||||
latestPollVotedKey = newPollVotedKey;
|
||||
|
||||
const choices = [...pollChoicesRef.value];
|
||||
const choices = [...$note.pollChoices];
|
||||
choices[ctx.choice] = {
|
||||
...choices[ctx.choice],
|
||||
votes: choices[ctx.choice].votes + 1,
|
||||
|
@ -247,11 +247,11 @@ export function useNoteCapture(props: {
|
|||
} : {}),
|
||||
};
|
||||
|
||||
pollChoicesRef.value = choices;
|
||||
$note.pollChoices = choices;
|
||||
}
|
||||
|
||||
function onDeleted(): void {
|
||||
props.isDeletedRef.value = true;
|
||||
$note.isDeleted = true;
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
|
|
Loading…
Reference in New Issue