Skip to content
This repository was archived by the owner on Feb 23, 2026. It is now read-only.

Commit cc913ac

Browse files
committed
いい感じに
1 parent 5526713 commit cc913ac

File tree

13 files changed

+1706
-3536
lines changed

13 files changed

+1706
-3536
lines changed

packages/backend/src/models/json-schema/note.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,5 +283,13 @@ export const packedNoteSchema = {
283283
type: 'string',
284284
optional: true, nullable: true,
285285
},
286+
myReactions: {
287+
type: 'array',
288+
optional: true, nullable: false,
289+
items: {
290+
type: 'string',
291+
optional: false, nullable: false,
292+
},
293+
},
286294
},
287295
} as const;

packages/frontend/src/cache.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const rolesCache = new Cache(1000 * 60 * 30, () => misskeyApi('admin/role
1212
export const userListsCache = new Cache<Misskey.entities.UserList[]>(1000 * 60 * 30, () => misskeyApi('users/lists/list'));
1313
export const antennasCache = new Cache<Misskey.entities.Antenna[]>(1000 * 60 * 30, () => misskeyApi('antennas/list'));
1414
export const favoritedChannelsCache = new Cache<Misskey.entities.Channel[]>(1000 * 60 * 30, () => misskeyApi('channels/my-favorites', { limit: 100 }));
15-
export const userFavoriteListsCache = new Cache(1000 * 60 * 30, () => misskeyApi('users/lists/list-favorite'));
15+
// list-favorite endpoint doesn't exist, using empty array for now
16+
export const userFavoriteListsCache = new Cache(1000 * 60 * 30, () => Promise.resolve([]));
1617
export const userChannelsCache = new Cache<Misskey.entities.Channel[]>(1000 * 60 * 30, () => misskeyApi('channels/owned'));
1718
export const userChannelFollowingsCache = new Cache<Misskey.entities.Channel[]>(1000 * 60 * 30, () => misskeyApi('channels/followed'));

packages/frontend/src/components/MkNote.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ SPDX-License-Identifier: AGPL-3.0-only
254254
:reactionEmojis="$appearNote.reactionEmojis"
255255
:myReaction="$appearNote.myReaction"
256256
:noteId="appearNote.id"
257-
:note="appearNote"
257+
:note="$appearNote"
258258
:maxNumber="16"
259259
@mockUpdateMyReaction="emitUpdReaction"
260260
>
@@ -304,15 +304,15 @@ SPDX-License-Identifier: AGPL-3.0-only
304304
<i
305305
v-if="
306306
appearNote.reactionAcceptance === 'likeOnly' &&
307-
appearNote.myReactions?.length >= 4
307+
$appearNote.myReactions?.length >= 4
308308
"
309309
class="ti ti-heart-filled"
310310
style="color: var(--MI_THEME-love)"
311311
></i>
312312
<i
313313
v-else-if="
314-
appearNote.myReactions?.length >= 4 ||
315-
(appearNote.myReaction && appearNote.user.host)
314+
$appearNote.myReactions?.length >= 4 ||
315+
($appearNote.myReaction && appearNote.user.host)
316316
"
317317
class="ti ti-minus"
318318
style="color: var(--MI_THEME-accent)"
@@ -554,7 +554,7 @@ const canRenote = computed(() => ['public', 'home'].includes(appearNote.visibili
554554
const renoteCollapsed = ref(
555555
prefer.s.collapseRenotes && isRenote && (
556556
($i && ($i.id === note.userId || $i.id === appearNote.userId)) || // `||` must be `||`! See https://github.com/misskey-dev/misskey/issues/13131
557-
(appearNote.myReaction != null)
557+
($appearNote.myReaction != null)
558558
),
559559
);
560560
@@ -855,7 +855,7 @@ function toggleReact() {
855855
if ($appearNote.myReaction == null) {
856856
react();
857857
} else {
858-
undoReact($appearNote);
858+
undoReact(appearNote);
859859
}
860860
}
861861

packages/frontend/src/components/MkNoteDetailed.vue

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ SPDX-License-Identifier: AGPL-3.0-only
143143
:reactionEmojis="$appearNote.reactionEmojis"
144144
:myReaction="$appearNote.myReaction"
145145
:noteId="appearNote.id"
146-
:note="appearNote"
146+
:note="$appearNote"
147147
:maxNumber="16"
148148
@mockUpdateMyReaction="emitUpdReaction"
149149
/>
@@ -166,7 +166,7 @@ SPDX-License-Identifier: AGPL-3.0-only
166166
</button>
167167
<button ref="reactButton" :class="$style.noteFooterButton" class="_button" @click="toggleReact()">
168168
<i v-if="appearNote.reactionAcceptance === 'likeOnly' && $appearNote.myReactions?.length >= 4 " class="ti ti-heart-filled" style="color: var(--MI_THEME-love);"></i>
169-
<i v-else-if="$appearNote.myReactions?.length >= 4 || appearNote.myReaction && appearNote.user.host " class="ti ti-minus" style="color: var(--MI_THEME-accent);"></i>
169+
<i v-else-if="$appearNote.myReactions?.length >= 4 || $appearNote.myReaction && appearNote.user.host " class="ti ti-minus" style="color: var(--MI_THEME-accent);"></i>
170170
<i v-else-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
171171
<i v-else class="ti ti-plus"></i>
172172
<p v-if="(appearNote.reactionAcceptance === 'likeOnly' || prefer.s.showReactionsCount) && $appearNote.reactionCount > 0" :class="$style.noteFooterButtonCount">{{ number($appearNote.reactionCount) }}</p>
@@ -370,6 +370,17 @@ const replies = ref<Misskey.entities.Note[]>([]);
370370
const mutedReactions = ref<string[]>(store.s.mutedReactions);
371371
const canRenote = computed(() => appearNote && (['public', 'home'].includes(appearNote.visibility) || appearNote.userId === $i?.id));
372372
373+
// Add missing gaming ref
374+
const gaming = ref<'light' | 'dark' | null>(null);
375+
376+
// Add missing emitUpdReaction function
377+
function emitUpdReaction(newReaction: string) {
378+
// Update the local reaction state
379+
if ($appearNote.myReaction !== newReaction) {
380+
$appearNote.myReaction = newReaction;
381+
}
382+
}
383+
373384
useGlobalEvent('noteDeleted', (noteId) => {
374385
if (noteId === note.id || noteId === appearNote.id) {
375386
isDeleted.value = true;
@@ -570,7 +581,7 @@ function undoReact(targetNote: Misskey.entities.Note): void {
570581
}
571582
572583
function toggleReact() {
573-
if (appearNote.value.myReactions?.length < 4 || appearNote.myReaction && appearNote.value.user.host || !appearNote.value.myReactions ) {
584+
if (!$appearNote.myReactions || $appearNote.myReactions.length < 4 || ($appearNote.myReaction && appearNote.user.host)) {
574585
react();
575586
} else {
576587
undoReact(appearNote);

packages/frontend/src/components/MkReactionsViewer.reaction.vue

Lines changed: 10 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -125,56 +125,31 @@ async function toggleReaction() {
125125
if (!canToggle.value) return;
126126
if (!props.note) return; // Guard against undefined note
127127
128-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
129-
const oldReaction = props.note.myReactions?.includes(props.reaction)
130-
? props.reaction
131-
: null;
132-
if (oldReaction) {
128+
// Check if already reacted using the same logic as isReacted
129+
const alreadyReacted = props.note.myReactions?.includes(props.reaction) ?? false;
130+
131+
if (alreadyReacted) {
133132
const confirm = await os.confirm({
134133
type: 'warning',
135-
text:
136-
oldReaction !== props.reaction
137-
? i18n.ts.changeReactionConfirm
138-
: i18n.ts.cancelReactionConfirm,
134+
text: i18n.ts.cancelReactionConfirm,
139135
});
140136
if (confirm.canceled) return;
141137
142-
// eslint-disable-next-line vue/no-mutating-props
143-
props.note.myReactions.splice(
144-
props.note.myReactions.indexOf(oldReaction),
145-
1,
146-
);
147-
if (oldReaction !== props.reaction) {
148-
sound.playMisskeySfx('reaction');
149-
}
150-
151138
if (mock) {
152139
emit('reactionToggled', props.reaction, props.count - 1);
153140
return;
154141
}
155142
143+
// Note: The myReactions array will be updated by the noteEvents handler in use-note-capture.ts
144+
156145
misskeyApi('notes/reactions/delete', {
157146
noteId: props.noteId,
158-
reaction: oldReaction,
147+
reaction: props.reaction,
159148
}).then(() => {
160149
noteEvents.emit(`unreacted:${props.noteId}`, {
161150
userId: $i!.id,
162-
reaction: oldReaction,
151+
reaction: props.reaction,
163152
});
164-
if (
165-
oldReaction !== props.reaction
166-
) {
167-
misskeyApi('notes/reactions/create', {
168-
noteId: props.noteId,
169-
reaction: props.reaction,
170-
}).then(() => {
171-
noteEvents.emit(`reacted:${props.noteId}`, {
172-
userId: $i!.id,
173-
reaction: props.reaction,
174-
emoji: emoji.value,
175-
});
176-
});
177-
}
178153
});
179154
} else {
180155
if (prefer.s.confirmOnReact) {
@@ -193,6 +168,7 @@ async function toggleReaction() {
193168
return;
194169
}
195170
171+
// Note: The myReactions array will be updated by the noteEvents handler in use-note-capture.ts
196172
misskeyApi('notes/reactions/create', {
197173
noteId: props.noteId,
198174
reaction: props.reaction,

packages/frontend/src/components/XNote.vue

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,15 @@ SPDX-License-Identifier: AGPL-3.0-only
9494
</div>
9595
<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
9696
</div>
97-
<MkReactionsViewer v-if="appearNote.reactionAcceptance !== 'likeOnly'" :note="appearNote" :maxNumber="16" @mockUpdateMyReaction="emitUpdReaction">
97+
<MkReactionsViewer
98+
v-if="appearNote.reactionAcceptance !== 'likeOnly'"
99+
:noteId="appearNote.id"
100+
:reactions="appearNote.reactions"
101+
:reactionEmojis="appearNote.reactionEmojis"
102+
:myReaction="appearNote.myReaction"
103+
:note="appearNote"
104+
:maxNumber="16"
105+
@mockUpdateMyReaction="emitUpdReaction">
98106
<template #more>
99107
<MkA :to="`/notes/${appearNote.id}/reactions`" :class="[$style.reactionOmitted]">{{ i18n.ts.more }}</MkA>
100108
</template>

packages/frontend/src/composables/use-note-capture.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ export type ReactiveNoteData = {
190190
reactionCount: Misskey.entities.Note['reactionCount'];
191191
reactionEmojis: Misskey.entities.Note['reactionEmojis'];
192192
myReaction: Misskey.entities.Note['myReaction'];
193+
myReactions: Misskey.entities.Note['myReactions'];
193194
pollChoices: NonNullable<Misskey.entities.Note['poll']>['choices'];
194195
};
195196

@@ -219,6 +220,7 @@ export function useNoteCapture(props: {
219220
reactionCount: note.reactionCount,
220221
reactionEmojis: note.reactionEmojis,
221222
myReaction: note.myReaction,
223+
myReactions: note.myReactions ?? [],
222224
pollChoices: note.poll?.choices ?? [],
223225
});
224226

@@ -247,6 +249,10 @@ export function useNoteCapture(props: {
247249

248250
if ($i && (ctx.userId === $i.id)) {
249251
$note.myReaction = normalizedName;
252+
// Update myReactions array
253+
if (!$note.myReactions.includes(normalizedName)) {
254+
$note.myReactions.push(normalizedName);
255+
}
250256
}
251257
}
252258

@@ -266,6 +272,11 @@ export function useNoteCapture(props: {
266272

267273
if ($i && (ctx.userId === $i.id)) {
268274
$note.myReaction = null;
275+
// Update myReactions array
276+
const index = $note.myReactions.indexOf(normalizedName);
277+
if (index > -1) {
278+
$note.myReactions.splice(index, 1);
279+
}
269280
}
270281
}
271282

packages/frontend/src/pages/welcome.timeline.note.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
2424
<MkMediaList :mediaList="note.files.slice(0, 4)"/>
2525
</div>
2626
<div v-if="note.reactionCount > 0" :class="$style.reactions">
27-
<MkReactionsViewer :noteId="note.id" :reactions="note.reactions" :reactionEmojis="note.reactionEmojis" :myReaction="note.myReaction" :maxNumber="16"/>
27+
<MkReactionsViewer :noteId="note.id" :reactions="note.reactions" :reactionEmojis="note.reactionEmojis" :myReaction="note.myReaction" :note="note" :maxNumber="16"/>
2828
</div>
2929
</div>
3030
</div>

0 commit comments

Comments
 (0)