From 3434092a10a6f3488368011efd0cbeac3bd716d8 Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 12:45:57 +0100 Subject: [PATCH] copy from MkNote to SkNote --- packages/frontend/src/components/SkNote.vue | 138 +++++++++++++------- 1 file changed, 91 insertions(+), 47 deletions(-) diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue index 98f250c8b3..ff47170f5d 100644 --- a/packages/frontend/src/components/SkNote.vue +++ b/packages/frontend/src/components/SkNote.vue @@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only ref="rootEl" v-hotkey="keymap" :class="[$style.root, { [$style.showActionsOnlyHover]: defaultStore.state.showNoteActionsOnlyHover }]" - :tabindex="!isDeleted ? '-1' : undefined" + :tabindex="isDeleted ? '-1' : '0'" >
@@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- @@ -94,7 +94,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._animatedMFM.stop }}
- +
@@ -127,7 +127,7 @@ SPDX-License-Identifier: AGPL-3.0-only class="_button" :style="renoted ? 'color: var(--accent) !important;' : ''" @click.stop - @mousedown="renoted ? undoRenote(appearNote) : boostVisibility()" + @mousedown.prevent="renoted ? undoRenote(appearNote) : boostVisibility()" >

{{ number(appearNote.renoteCount) }}

@@ -155,10 +155,10 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ number(appearNote.reactionCount) }}

- - @@ -204,8 +204,7 @@ import MkPoll from '@/components/MkPoll.vue'; import MkUsersTooltip from '@/components/MkUsersTooltip.vue'; import MkUrlPreview from '@/components/MkUrlPreview.vue'; import MkButton from '@/components/MkButton.vue'; -import { pleaseLogin } from '@/scripts/please-login.js'; -import { focusPrev, focusNext } from '@/scripts/focus.js'; +import { pleaseLogin, type OpenOnRemoteOptions } from '@/scripts/please-login.js'; import { checkWordMute } from '@/scripts/check-word-mute.js'; import { userPage } from '@/filters/user.js'; import number from '@/filters/number.js'; @@ -231,7 +230,10 @@ import { showMovedDialog } from '@/scripts/show-moved-dialog.js'; import { shouldCollapsed } from '@/scripts/collapsed.js'; import { useRouter } from '@/router/supplier.js'; import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js'; +import { host } from '@/config.js'; import { isEnabledUrlPreview } from '@/instance.js'; +import { type Keymap } from '@/scripts/hotkey.js'; +import { focusPrev, focusNext } from '@/scripts/focus.js'; const props = withDefaults(defineProps<{ note: Misskey.entities.Note; @@ -302,7 +304,7 @@ const quoteButton = shallowRef(); const clipButton = shallowRef(); const likeButton = shallowRef(); const appearNote = computed(() => isRenote ? note.value.renote as Misskey.entities.Note : note.value); - +const galleryEl = shallowRef>(); const isMyRenote = $i && ($i.id === note.value.userId); const showContent = ref(defaultStore.state.uncollapseCW); const parsed = computed(() => appearNote.value.text ? mfm.parse(appearNote.value.text) : null); @@ -328,6 +330,11 @@ const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state. const animated = computed(() => parsed.value ? checkAnimationFromMfm(parsed.value) : null); const allowAnim = ref(defaultStore.state.advancedMfm && defaultStore.state.animatedMfm ? true : false); +const pleaseLoginContext = computed(() => ({ + type: 'lookup', + url: `https://${host}/notes/${appearNote.value.id}`, +})); + /* Overload FunctionにLintが対応していないのでコメントアウト function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array | undefined | null, checkOnly: true): boolean; function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array | undefined | null, checkOnly: false): boolean | 'sensitiveMute'; @@ -348,15 +355,53 @@ function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array reply(true), - 'e|a|plus': () => react(true), - '(q)': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); }, - 'up|k|shift+tab': focusBefore, - 'down|j|tab': focusAfter, - 'esc': blur, - 'm|o': () => showMenu(true), - 's': () => showContent.value !== showContent.value, -}; + 'r': () => { + if (renoteCollapsed.value) return; + reply(); + }, + 'e|a|plus': () => { + if (renoteCollapsed.value) return; + react(); + }, + 'q': () => { + if (renoteCollapsed.value) return; + if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); + }, + 'm': () => { + if (renoteCollapsed.value) return; + showMenu(); + }, + 'c': () => { + if (renoteCollapsed.value) return; + if (!defaultStore.state.showClipButtonInNoteFooter) return; + clip(); + }, + 'o': () => { + if (renoteCollapsed.value) return; + galleryEl.value?.openGallery(); + }, + 'v|enter': () => { + if (renoteCollapsed.value) { + renoteCollapsed.value = false; + } else if (appearNote.value.cw != null) { + showContent.value = !showContent.value; + } else if (isLong) { + collapsed.value = !collapsed.value; + } + }, + 'esc': { + allowRepeat: true, + callback: () => blur(), + }, + 'up|k|shift+tab': { + allowRepeat: true, + callback: () => focusBefore(), + }, + 'down|j|tab': { + allowRepeat: true, + callback: () => focusAfter(), + }, +} as const satisfies Keymap; provide('react', (reaction: string) => { misskeyApi('notes/reactions/create', { @@ -389,12 +434,14 @@ if (!props.mock) { if (users.length < 1) return; - os.popup(MkUsersTooltip, { + const { dispose } = os.popup(MkUsersTooltip, { showing, users, count: appearNote.value.renoteCount, targetElement: renoteButton.value, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); useTooltip(quoteButton, async (showing) => { @@ -438,13 +485,15 @@ if (!props.mock) { if (users.length < 1) return; - os.popup(MkReactionsViewerDetails, { + const { dispose } = os.popup(MkReactionsViewerDetails, { showing, reaction: '❤️', users, count: appearNote.value.reactionCount, targetElement: reactButton.value!, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); } } @@ -460,7 +509,7 @@ function boostVisibility() { } function renote(visibility: Visibility, localOnly: boolean = false) { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); renoting = true; @@ -506,7 +555,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { } function quote() { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); if (props.mock) { return; @@ -560,22 +609,21 @@ function quote() { } } -function reply(viaKeyboard = false): void { - pleaseLogin(); +function reply(): void { + pleaseLogin(undefined, pleaseLoginContext.value); if (props.mock) { return; } os.post({ reply: appearNote.value, channel: appearNote.value.channel, - animation: !viaKeyboard, }).then(() => { focus(); }); } function like(): void { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); sound.playMisskeySfx('reaction'); if (props.mock) { @@ -595,7 +643,7 @@ function like(): void { } function react(viaKeyboard = false): void { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); if (appearNote.value.reactionAcceptance === 'likeOnly') { sound.playMisskeySfx('reaction'); @@ -613,7 +661,9 @@ function react(viaKeyboard = false): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } else { blur(); @@ -706,15 +756,13 @@ function onContextmenu(ev: MouseEvent): void { } } -function showMenu(viaKeyboard = false): void { +function showMenu(): void { if (props.mock) { return; } const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value }); - os.popupMenu(menu, menuButton.value, { - viaKeyboard, - }).then(focus).finally(cleanup); + os.popupMenu(menu, menuButton.value).then(focus).finally(cleanup); } async function menuVersions(viaKeyboard = false): Promise { @@ -724,7 +772,7 @@ async function menuVersions(viaKeyboard = false): Promise { }).then(focus).finally(cleanup); } -async function clip() { +async function clip(): Promise { if (props.mock) { return; } @@ -732,7 +780,7 @@ async function clip() { os.popupMenu(await getNoteClipMenu({ note: note.value, isDeleted, currentClip: currentClip?.value }), clipButton.value).then(focus); } -function showRenoteMenu(viaKeyboard = false): void { +function showRenoteMenu(): void { if (props.mock) { return; } @@ -752,23 +800,19 @@ function showRenoteMenu(viaKeyboard = false): void { } if (isMyRenote) { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); os.popupMenu([ getCopyNoteLinkMenu(note.value, i18n.ts.copyLinkRenote), { type: 'divider' }, getUnrenote(), - ], renoteTime.value, { - viaKeyboard: viaKeyboard, - }); + ], renoteTime.value); } else { os.popupMenu([ getCopyNoteLinkMenu(note.value, i18n.ts.copyLinkRenote), { type: 'divider' }, getAbuseNoteMenu(note.value, i18n.ts.reportAbuseRenote), ($i?.isModerator || $i?.isAdmin) ? getUnrenote() : undefined, - ], renoteTime.value, { - viaKeyboard: viaKeyboard, - }); + ], renoteTime.value); } } @@ -793,11 +837,11 @@ function blur() { } function focusBefore() { - focusPrev(rootEl.value ?? null); + focusPrev(rootEl.value); } function focusAfter() { - focusNext(rootEl.value ?? null); + focusNext(rootEl.value); } function readPromo() { @@ -835,7 +879,7 @@ function emitUpdReaction(emoji: string, delta: number) { &:focus-visible { outline: none; - &:after { + &::after { content: ""; pointer-events: none; display: block; @@ -848,7 +892,7 @@ function emitUpdReaction(emoji: string, delta: number) { margin: auto; width: calc(100% - 8px); height: calc(100% - 8px); - border: solid 1px var(--focus); + border: solid 2px var(--focus); border-radius: var(--radius); box-sizing: border-box; }