Merge remote-tracking branch 'misskey-original/develop' into develop

# Conflicts:
#	package.json
#	packages/backend/src/server/api/endpoints.ts
#	packages/frontend/src/components/MkButton.vue
#	packages/frontend/src/components/MkDrive.vue
#	packages/frontend/src/components/MkEmojiPicker.section.vue
#	packages/frontend/src/components/MkEmojiPicker.vue
#	packages/frontend/src/components/MkFoldableSection.vue
#	packages/frontend/src/components/MkInput.vue
#	packages/frontend/src/components/MkMenu.vue
#	packages/frontend/src/components/MkNote.vue
#	packages/frontend/src/components/MkPostForm.vue
#	packages/frontend/src/components/MkSignupDialog.form.vue
#	packages/frontend/src/components/MkSwitch.button.vue
#	packages/frontend/src/components/MkTab.vue
#	packages/frontend/src/components/MkTimeline.vue
#	packages/frontend/src/components/MkUserSelectDialog.vue
#	packages/frontend/src/components/global/MkCustomEmoji.vue
#	packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts
#	packages/frontend/src/os.ts
#	packages/frontend/src/pages/admin/index.vue
#	packages/frontend/src/pages/user/home.vue
#	packages/frontend/src/ui/universal.vue
This commit is contained in:
mattyatea 2024-01-31 19:51:51 +09:00
commit 942b7f1b3c
250 changed files with 2788 additions and 1788 deletions

View file

@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div
v-if="!hardMuted && muted === false"
v-show="!isDeleted"
ref="el"
ref="rootEl"
v-hotkey="keymap"
:class="[$style.root,
{ [$style.showActionsOnlyHover]: defaultStore.state.showNoteActionsOnlyHover } ,
@ -80,16 +80,16 @@ SPDX-License-Identifier: AGPL-3.0-only
/>
<div v-if="translating || translation" :class="$style.translation">
<MkLoading v-if="translating" mini/>
<div v-else>
<div v-else-if="translation">
<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b>
<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis"/>
</div>
</div>
</div>
<div v-if="appearNote.files.length > 0">
<div v-if="appearNote.files && appearNote.files.length > 0">
<MkMediaList :mediaList="appearNote.files"/>
</div>
<MkPoll v-if="appearNote.poll" :note="appearNote" :class="$style.poll"/>
<MkPoll v-if="appearNote.poll" :noteId="appearNote.id" :poll="appearNote.poll" :class="$style.poll"/>
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="false" :class="$style.urlPreview"/>
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
<button v-if="isLong && collapsed" :class="$style.collapsed" class="_button" @click="collapsed = false">
@ -134,7 +134,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" :class="$style.footerButton" class="_button" @mousedown="clip()">
<i class="ti ti-paperclip"></i>
</button>
<button ref="menuButton" :class="$style.footerButton" class="_button" @mousedown="menu()">
<button ref="menuButton" :class="$style.footerButton" class="_button" @mousedown="showMenu()">
<i class="ti ti-dots"></i>
</button>
</footer>
@ -229,7 +229,7 @@ if (noteViewInterruptors.length > 0) {
let result: Misskey.entities.Note | null = deepClone(note.value);
for (const interruptor of noteViewInterruptors) {
try {
result = await interruptor.handler(result);
result = await interruptor.handler(result!) as Misskey.entities.Note | null;
if (result === null) {
isDeleted.value = true;
return;
@ -238,7 +238,7 @@ if (noteViewInterruptors.length > 0) {
console.error(err);
}
}
note.value = result;
note.value = result as Misskey.entities.Note;
});
}
@ -246,11 +246,11 @@ const isRenote = (
note.value.renote != null &&
note.value.text == null &&
note.value.cw == null &&
note.value.fileIds.length === 0 &&
note.value.fileIds && note.value.fileIds.length === 0 &&
note.value.poll == null
);
const el = shallowRef<HTMLElement>();
const rootEl = shallowRef<HTMLElement>();
const menuButton = shallowRef<HTMLElement>();
const renoteButton = shallowRef<HTMLElement>();
const renoteTime = shallowRef<HTMLElement>();
@ -269,8 +269,8 @@ const hardMuted = ref(props.withHardMute && checkMute(appearNote.value, $i?.hard
const translation = ref<Misskey.entities.NotesTranslateResponse | null>(null);
const translating = ref(false);
const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.value.user.instance);
const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || (appearNote.value.visibility === 'followers' && appearNote.value.userId === $i.id));
const renoteCollapsed = ref(defaultStore.state.collapseRenotes && isRenote && (($i && ($i.id === note.value.userId || $i.id === appearNote.value.userId)) || (appearNote.value.myReaction != null)));
const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || (appearNote.value.visibility === 'followers' && appearNote.value.userId === $i?.id));
const renoteCollapsed = ref(defaultStore.state.collapseRenotes && isRenote && (($i && ($i.id === note.value.userId || $i.id === appearNote.value.userId)) ?? (appearNote.value.myReaction != null)));
/* Overload FunctionLint
function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: true): boolean;
@ -292,11 +292,11 @@ function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string
const keymap = {
'r': () => reply(true),
'e|a|plus': () => react(true),
'q': () => renoteButton.value.renote(true),
'q': () => renote(true),
'up|k|shift+tab': focusBefore,
'down|j|tab': focusAfter,
'esc': blur,
'm|o': () => menu(true),
'm|o': () => showMenu(true),
's': () => showContent.value !== showContent.value,
};
@ -313,7 +313,7 @@ if (props.mock) {
}, { deep: true });
} else {
useNoteCapture({
rootEl: el,
rootEl: rootEl,
note: appearNote,
pureNote: note,
isDeletedRef: isDeleted,
@ -359,7 +359,7 @@ function reply(viaKeyboard = false): void {
reply: appearNote.value,
channel: appearNote.value.channel,
animation: !viaKeyboard,
}, () => {
}).then(() => {
focus();
});
}
@ -378,7 +378,7 @@ function react(viaKeyboard = false): void {
noteId: appearNote.value.id,
reaction: '❤️',
});
const el = reactButton.value as HTMLElement | null | undefined;
const el = reactButton.value;
if (el) {
const rect = el.getBoundingClientRect();
const x = rect.left + (el.offsetWidth / 2);
@ -387,7 +387,7 @@ function react(viaKeyboard = false): void {
}
} else {
blur();
reactionPicker.show(reactButton.value, reaction => {
reactionPicker.show(reactButton.value ?? null, reaction => {
sound.playMisskeySfx('reaction');
if (props.mock) {
@ -408,8 +408,8 @@ function react(viaKeyboard = false): void {
}
}
function undoReact(note): void {
const oldReaction = note.myReaction;
function undoReact(targetNote: Misskey.entities.Note): void {
const oldReaction = targetNote.myReaction;
if (!oldReaction) return;
if (props.mock) {
@ -418,7 +418,7 @@ function undoReact(note): void {
}
misskeyApi('notes/reactions/delete', {
noteId: note.id,
noteId: targetNote.id,
});
}
@ -427,16 +427,18 @@ function onContextmenu(ev: MouseEvent): void {
return;
}
const isLink = (el: HTMLElement) => {
const isLink = (el: HTMLElement): boolean => {
if (el.tagName === 'A') return true;
// Audio
if (el.tagName === 'AUDIO') return true;
if (el.parentElement) {
return isLink(el.parentElement);
}
return false;
};
if (isLink(ev.target)) return;
if (window.getSelection().toString() !== '') return;
if (ev.target && isLink(ev.target as HTMLElement)) return;
if (window.getSelection()?.toString() !== '') return;
if (defaultStore.state.useReactionPickerForContextMenu) {
ev.preventDefault();
@ -446,7 +448,7 @@ function onContextmenu(ev: MouseEvent): void {
note: note.value,
translating,
translation,
menuButton,
isDeleted,
currentClip: currentClip?.value
});
@ -454,7 +456,7 @@ function onContextmenu(ev: MouseEvent): void {
}
}
function menu(viaKeyboard = false): void {
function showMenu(viaKeyboard = false): void {
if (props.mock) {
return;
}
@ -463,7 +465,7 @@ function menu(viaKeyboard = false): void {
note: note.value,
translating,
translation,
menuButton,
isDeleted,
currentClip: currentClip?.value
});
@ -517,7 +519,7 @@ function showRenoteMenu(viaKeyboard = false): void {
getCopyNoteLinkMenu(note.value, i18n.ts.copyLinkRenote),
{ type: 'divider' },
getAbuseNoteMenu(note.value, i18n.ts.reportAbuseRenote),
$i.isModerator || $i.isAdmin ? getUnrenote() : undefined,
($i?.isModerator || $i?.isAdmin) ? getUnrenote() : undefined,
], renoteTime.value, {
viaKeyboard: viaKeyboard,
});
@ -525,19 +527,19 @@ function showRenoteMenu(viaKeyboard = false): void {
}
function focus() {
el.value.focus();
rootEl.value?.focus();
}
function blur() {
el.value.blur();
rootEl.value?.blur();
}
function focusBefore() {
focusPrev(el.value);
focusPrev(rootEl.value ?? null);
}
function focusAfter() {
focusNext(el.value);
focusNext(rootEl.value ?? null);
}
function readPromo() {