summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src/components')
-rw-r--r--packages/frontend/src/components/DynamicNote.vue2
-rw-r--r--packages/frontend/src/components/MkDateSeparatedList.vue4
-rw-r--r--packages/frontend/src/components/MkGoogle.vue4
-rw-r--r--packages/frontend/src/components/MkMediaAudio.vue2
-rw-r--r--packages/frontend/src/components/MkMediaImage.vue2
-rw-r--r--packages/frontend/src/components/MkMediaVideo.vue2
-rw-r--r--packages/frontend/src/components/MkNote.vue49
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue33
-rw-r--r--packages/frontend/src/components/MkNoteSimple.vue4
-rw-r--r--packages/frontend/src/components/MkNoteSub.vue125
-rw-r--r--packages/frontend/src/components/MkPostForm.vue4
-rw-r--r--packages/frontend/src/components/MkPostFormAttaches.vue2
-rw-r--r--packages/frontend/src/components/MkSubNoteContent.vue16
-rw-r--r--packages/frontend/src/components/MkUrlPreview.vue3
-rw-r--r--packages/frontend/src/components/MkUrlWarningDialog.vue10
-rw-r--r--packages/frontend/src/components/MkVisibilityPicker.vue3
-rw-r--r--packages/frontend/src/components/SkFetchNote.vue2
-rw-r--r--packages/frontend/src/components/SkFlashPlayer.vue14
-rw-r--r--packages/frontend/src/components/SkModPlayer.vue4
-rw-r--r--packages/frontend/src/components/SkNote.vue63
-rw-r--r--packages/frontend/src/components/SkNoteDetailed.vue34
-rw-r--r--packages/frontend/src/components/SkNoteHeader.vue4
-rw-r--r--packages/frontend/src/components/SkNoteSimple.vue2
-rw-r--r--packages/frontend/src/components/SkNoteSub.vue42
-rw-r--r--packages/frontend/src/components/SkOldNoteWindow.vue8
-rw-r--r--packages/frontend/src/components/global/MkMfm.ts2
26 files changed, 212 insertions, 228 deletions
diff --git a/packages/frontend/src/components/DynamicNote.vue b/packages/frontend/src/components/DynamicNote.vue
index 6703099591..b2133f8836 100644
--- a/packages/frontend/src/components/DynamicNote.vue
+++ b/packages/frontend/src/components/DynamicNote.vue
@@ -21,7 +21,7 @@ import { computed, defineAsyncComponent, shallowRef } from 'vue';
import type { ComponentExposed } from 'vue-component-type-helpers';
import type MkNote from '@/components/MkNote.vue';
import type SkNote from '@/components/SkNote.vue';
-import { defaultStore } from '@/store';
+import { defaultStore } from '@/store.js';
const XNote = computed(() =>
defineAsyncComponent(() =>
diff --git a/packages/frontend/src/components/MkDateSeparatedList.vue b/packages/frontend/src/components/MkDateSeparatedList.vue
index f94f28de41..857b7e3f92 100644
--- a/packages/frontend/src/components/MkDateSeparatedList.vue
+++ b/packages/frontend/src/components/MkDateSeparatedList.vue
@@ -13,7 +13,7 @@ import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
import { instance } from '@/instance.js';
import { prefer } from '@/preferences.js';
-import { $i } from '@/account.js';
+import { $i } from '@/i.js';
export default defineComponent({
props: {
@@ -116,7 +116,7 @@ export default defineComponent({
});
const renderChildren = () => {
- const shouldHideAds = !defaultStore.state.forceShowAds && $i && $i.policies.canHideAds;
+ const shouldHideAds = (!prefer.s.forceShowAds && $i && $i.policies.canHideAds) ?? false;
const children = renderChildrenImpl(shouldHideAds);
if (isDebuggerEnabled(6864)) {
diff --git a/packages/frontend/src/components/MkGoogle.vue b/packages/frontend/src/components/MkGoogle.vue
index 6cdab2479e..e7ee7ffab5 100644
--- a/packages/frontend/src/components/MkGoogle.vue
+++ b/packages/frontend/src/components/MkGoogle.vue
@@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { ref } from 'vue';
import { i18n } from '@/i18n.js';
-import { defaultStore } from '@/store';
+import { prefer } from '@/preferences.js';
const props = defineProps<{
q: string;
@@ -23,7 +23,7 @@ const query = ref(props.q);
const search = () => {
const searchQuery = encodeURIComponent(query.value);
- const searchUrl = defaultStore.state.searchEngine.replace(/{query}|%s\b/g, searchQuery);
+ const searchUrl = prefer.s.searchEngine.replace(/{query}|%s\b/g, searchQuery);
window.open(searchUrl, '_blank', 'noopener');
};
diff --git a/packages/frontend/src/components/MkMediaAudio.vue b/packages/frontend/src/components/MkMediaAudio.vue
index 8ede22db0d..4c78854fad 100644
--- a/packages/frontend/src/components/MkMediaAudio.vue
+++ b/packages/frontend/src/components/MkMediaAudio.vue
@@ -95,7 +95,7 @@ import { useTemplateRef, watch, computed, ref, onDeactivated, onActivated, onMou
import * as Misskey from 'misskey-js';
import type { MenuItem } from '@/types/menu.js';
import type { Keymap } from '@/utility/hotkey.js';
-import { copyToClipboard } from '@/utility/copy-to-clipboard';
+import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
import bytes from '@/filters/bytes.js';
diff --git a/packages/frontend/src/components/MkMediaImage.vue b/packages/frontend/src/components/MkMediaImage.vue
index 0f72da9ce9..2b59ed9f85 100644
--- a/packages/frontend/src/components/MkMediaImage.vue
+++ b/packages/frontend/src/components/MkMediaImage.vue
@@ -55,7 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { watch, ref, computed } from 'vue';
import * as Misskey from 'misskey-js';
import type { MenuItem } from '@/types/menu.js';
-import { copyToClipboard } from '@/utility/copy-to-clipboard';
+import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
import { getStaticImageUrl } from '@/utility/media-proxy.js';
import bytes from '@/filters/bytes.js';
import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue
index 8db3924fbd..041257b06f 100644
--- a/packages/frontend/src/components/MkMediaVideo.vue
+++ b/packages/frontend/src/components/MkMediaVideo.vue
@@ -116,7 +116,7 @@ import { ref, useTemplateRef, computed, watch, onDeactivated, onActivated, onMou
import * as Misskey from 'misskey-js';
import type { MenuItem } from '@/types/menu.js';
import type { Keymap } from '@/utility/hotkey.js';
-import { copyToClipboard } from '@/utility/copy-to-clipboard';
+import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
import bytes from '@/filters/bytes.js';
import { hms } from '@/filters/hms.js';
import { i18n } from '@/i18n.js';
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 5fcb91b338..86792931a9 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -52,7 +52,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<article v-else :class="$style.article" @contextmenu.stop="onContextmenu">
<div v-if="appearNote.channel" :class="$style.colorBar" :style="{ background: appearNote.channel.color }"></div>
<MkAvatar :class="[$style.avatar, prefer.s.useStickyIcons ? $style.useSticky : null]" :user="appearNote.user" :link="!mock" :preview="!mock"/>
- <div :class="[$style.main, { [$style.clickToOpen]: defaultStore.state.clickToOpen }]" @click.stop="defaultStore.state.clickToOpen ? noteclick(appearNote.id) : undefined">
+ <div :class="[$style.main, { [$style.clickToOpen]: prefer.s.clickToOpen }]" @click.stop="prefer.s.clickToOpen ? noteclick(appearNote.id) : undefined">
<MkNoteHeader :note="appearNote" :mini="true" @click.stop/>
<MkInstanceTicker v-if="showTicker" :host="appearNote.user.host" :instance="appearNote.user.instance"/>
<div style="container-type: inline-size;">
@@ -94,7 +94,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
- <MkButton v-else-if="!defaultStore.state.animatedMfm && allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
+ <MkButton v-else-if="!prefer.s.animatedMfm && allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
</div>
<div v-if="appearNote.files && appearNote.files.length > 0">
<MkMediaList ref="galleryEl" :mediaList="appearNote.files" @click.stop/>
@@ -211,11 +211,12 @@ import * as Misskey from 'misskey-js';
import { isLink } from '@@/js/is-link.js';
import { shouldCollapsed } from '@@/js/collapsed.js';
import { host } from '@@/js/config.js';
-import type { Ref } from 'vue';
import { computeMergedCw } from '@@/js/compute-merged-cw.js';
+import type { Ref } from 'vue';
import type { MenuItem } from '@/types/menu.js';
import type { OpenOnRemoteOptions } from '@/utility/please-login.js';
import type { Keymap } from '@/utility/hotkey.js';
+import type { Visibility } from '@/utility/boost-quote.js';
import MkNoteSub from '@/components/MkNoteSub.vue';
import MkNoteHeader from '@/components/MkNoteHeader.vue';
import MkNoteSimple from '@/components/MkNoteSimple.vue';
@@ -250,14 +251,14 @@ import { claimAchievement } from '@/utility/achievements.js';
import { getNoteSummary } from '@/utility/get-note-summary.js';
import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { showMovedDialog } from '@/utility/show-moved-dialog.js';
-import { useRouter } from '@/router/supplier.js';
-import { boostMenuItems, type Visibility, computeRenoteTooltip } from '@/utility/boost-quote.js';
+import { boostMenuItems, computeRenoteTooltip } from '@/utility/boost-quote.js';
import { isEnabledUrlPreview } from '@/instance.js';
import { focusPrev, focusNext } from '@/utility/focus.js';
import { getAppearNote } from '@/utility/get-appear-note.js';
import { prefer } from '@/preferences.js';
import { getPluginHandlers } from '@/plugin.js';
import { DI } from '@/di.js';
+import { useRouter } from '@/router.js';
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
@@ -285,7 +286,7 @@ const currentClip = inject<Ref<Misskey.entities.Clip> | null>('currentClip', nul
const note = ref(deepClone(props.note));
function noteclick(id: string) {
- const selection = document.getSelection();
+ const selection = window.document.getSelection();
if (selection?.toString().length === 0) {
router.push(`/notes/${id}`);
}
@@ -325,11 +326,11 @@ const likeButton = useTemplateRef('likeButton');
const appearNote = computed(() => getAppearNote(note.value));
const galleryEl = useTemplateRef('galleryEl');
const isMyRenote = $i && ($i.id === note.value.userId);
-const showContent = ref(defaultStore.state.uncollapseCW);
+const showContent = ref(prefer.s.uncollapseCW);
const parsed = computed(() => appearNote.value.text ? mfm.parse(appearNote.value.text) : null);
const urls = computed(() => parsed.value ? extractUrlFromMfm(parsed.value).filter((url) => appearNote.value.renote?.url !== url && appearNote.value.renote?.uri !== url) : null);
const isLong = shouldCollapsed(appearNote.value, urls.value ?? []);
-const collapsed = ref(defaultStore.state.expandLongNote && appearNote.value.cw == null && isLong ? false : appearNote.value.cw == null && isLong);
+const collapsed = ref(prefer.s.expandLongNote && appearNote.value.cw == null && isLong ? false : appearNote.value.cw == null && isLong);
const isDeleted = ref(false);
const renoted = ref(false);
const muted = ref(checkMute(appearNote.value, $i?.mutedWords));
@@ -345,10 +346,10 @@ const renoteCollapsed = ref(
(appearNote.value.myReaction != null)
),
);
-const inReplyToCollapsed = ref(defaultStore.state.collapseNotesRepliedTo);
-const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
+const inReplyToCollapsed = ref(prefer.s.collapseNotesRepliedTo);
+const defaultLike = computed(() => prefer.s.like ? prefer.s.like : null);
const animated = computed(() => parsed.value ? checkAnimationFromMfm(parsed.value) : null);
-const allowAnim = ref(defaultStore.state.advancedMfm && defaultStore.state.animatedMfm ? true : false);
+const allowAnim = ref(prefer.s.advancedMfm && prefer.s.animatedMfm);
const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
type: 'lookup',
@@ -397,7 +398,7 @@ const keymap = {
},
'q': () => {
if (renoteCollapsed.value) return;
- if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost);
+ if (canRenote.value && !renoted.value && !renoting) renote(prefer.s.visibilityOnBoost);
},
'm': () => {
if (renoteCollapsed.value) return;
@@ -458,6 +459,8 @@ if (props.mock) {
if (!props.mock) {
useTooltip(renoteButton, async (showing) => {
+ if (!renoteButton.value) return;
+
const renotes = await misskeyApi('notes/renotes', {
noteId: appearNote.value.id,
limit: 11,
@@ -478,6 +481,8 @@ if (!props.mock) {
});
useTooltip(quoteButton, async (showing) => {
+ if (!quoteButton.value) return;
+
const renotes = await misskeyApi('notes/renotes', {
noteId: appearNote.value.id,
limit: 11,
@@ -536,8 +541,8 @@ if (!props.mock) {
function boostVisibility(forceMenu: boolean = false) {
if (renoting) return;
- if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
- renote(defaultStore.state.visibilityOnBoost);
+ if (!prefer.s.showVisibilitySelectorOnBoost && !forceMenu) {
+ renote(prefer.s.visibilityOnBoost);
} else {
os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
}
@@ -799,8 +804,8 @@ function onContextmenu(ev: MouseEvent): void {
ev.preventDefault();
react();
} else {
- const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
- os.contextMenu(menu, ev).then(focus).finally(cleanup);
+ const { popupMenu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
+ os.contextMenu(popupMenu, ev).then(focus).finally(cleanup);
}
}
@@ -809,15 +814,13 @@ function showMenu(): void {
return;
}
- const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
- os.popupMenu(menu, menuButton.value).then(focus).finally(cleanup);
+ const { popupMenu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
+ os.popupMenu(popupMenu, menuButton.value).then(focus).finally(cleanup);
}
-async function menuVersions(viaKeyboard = false): Promise<void> {
- const { menu, cleanup } = await getNoteVersionsMenu({ note: note.value, menuVersionsButton });
- os.popupMenu(menu, menuVersionsButton.value, {
- viaKeyboard,
- }).then(focus).finally(cleanup);
+async function menuVersions(): Promise<void> {
+ const { menu, cleanup } = await getNoteVersionsMenu({ note: note.value, menuButton: menuVersionsButton });
+ os.popupMenu(menu, menuVersionsButton.value).then(focus).finally(cleanup);
}
async function clip(): Promise<void> {
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index fe911a1293..42defb69a8 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -112,7 +112,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
- <MkButton v-else-if="!defaultStore.state.animatedMfm && allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
+ <MkButton v-else-if="!prefer.s.animatedMfm && allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
<div v-if="appearNote.files && appearNote.files.length > 0">
<MkMediaList ref="galleryEl" :mediaList="appearNote.files"/>
</div>
@@ -241,7 +241,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, ref, useTemplateRef, watch } from 'vue';
import * as mfm from '@transfem-org/sfm-js';
import * as Misskey from 'misskey-js';
import { isLink } from '@@/js/is-link.js';
@@ -285,7 +285,8 @@ import MkUserCardMini from '@/components/MkUserCardMini.vue';
import MkPagination from '@/components/MkPagination.vue';
import MkReactionIcon from '@/components/MkReactionIcon.vue';
import MkButton from '@/components/MkButton.vue';
-import { boostMenuItems, type Visibility, computeRenoteTooltip } from '@/utility/boost-quote.js';
+import { boostMenuItems, computeRenoteTooltip } from '@/utility/boost-quote.js';
+import type { Visibility } from '@/utility/boost-quote.js';
import { isEnabledUrlPreview } from '@/instance.js';
import { getAppearNote } from '@/utility/get-appear-note.js';
import { prefer } from '@/preferences.js';
@@ -338,7 +339,7 @@ const likeButton = useTemplateRef('likeButton');
const appearNote = computed(() => getAppearNote(note.value));
const galleryEl = useTemplateRef('galleryEl');
const isMyRenote = $i && ($i.id === note.value.userId);
-const showContent = ref(defaultStore.state.uncollapseCW);
+const showContent = ref(prefer.s.uncollapseCW);
const isDeleted = ref(false);
const renoted = ref(false);
const muted = ref($i ? checkWordMute(appearNote.value, $i, $i.mutedWords) : false);
@@ -353,7 +354,7 @@ const conversation = ref<Misskey.entities.Note[]>([]);
const replies = ref<Misskey.entities.Note[]>([]);
const quotes = ref<Misskey.entities.Note[]>([]);
const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || (appearNote.value.visibility === 'followers' && appearNote.value.userId === $i?.id));
-const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
+const defaultLike = computed(() => prefer.s.like ? prefer.s.like : null);
const mergedCW = computed(() => computeMergedCw(appearNote.value));
@@ -383,7 +384,7 @@ const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
const keymap = {
'r': () => reply(),
'e|a|plus': () => react(),
- 'q': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); },
+ 'q': () => { if (canRenote.value && !renoted.value && !renoting) renote(prefer.s.visibilityOnBoost); },
'm': () => showMenu(),
'c': () => {
if (!prefer.s.showClipButtonInNoteFooter) return;
@@ -494,8 +495,8 @@ useTooltip(quoteButton, async (showing) => {
function boostVisibility(forceMenu: boolean = false) {
if (renoting) return;
- if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
- renote(defaultStore.state.visibilityOnBoost);
+ if (!prefer.s.showVisibilitySelectorOnBoost && !forceMenu) {
+ renote(prefer.s.visibilityOnBoost);
} else {
os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
}
@@ -531,7 +532,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
renoting = true;
- if (appearNote.value.channel) {
+ if (appearNote.value.channel && !appearNote.value.channel.allowRenoteToExternal) {
const el = renoteButton.value as HTMLElement | null | undefined;
if (el) {
const rect = el.getBoundingClientRect();
@@ -549,7 +550,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) {
os.toast(i18n.ts.renoted);
renoted.value = true;
}).finally(() => { renoting = false; });
- } else if (!appearNote.value.channel || appearNote.value.channel.allowRenoteToExternal) {
+ } else {
const el = renoteButton.value as HTMLElement | null | undefined;
if (el) {
const rect = el.getBoundingClientRect();
@@ -748,18 +749,18 @@ function onContextmenu(ev: MouseEvent): void {
ev.preventDefault();
react();
} else {
- const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
- os.contextMenu(menu, ev).then(focus).finally(cleanup);
+ const { popupMenu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
+ os.contextMenu(popupMenu, ev).then(focus).finally(cleanup);
}
}
function showMenu(): void {
- const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
- os.popupMenu(menu, menuButton.value).then(focus).finally(cleanup);
+ const { popupMenu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
+ os.popupMenu(popupMenu, menuButton.value).then(focus).finally(cleanup);
}
async function menuVersions(): Promise<void> {
- const { menu, cleanup } = await getNoteVersionsMenu({ note: note.value, menuVersionsButton });
+ const { menu, cleanup } = await getNoteVersionsMenu({ note: note.value, menuButton: menuVersionsButton });
os.popupMenu(menu, menuVersionsButton.value).then(focus).finally(cleanup);
}
@@ -833,7 +834,7 @@ function loadConversation() {
});
}
-if (appearNote.value.reply && appearNote.value.reply.replyId && defaultStore.state.autoloadConversation) loadConversation();
+if (appearNote.value.reply && appearNote.value.reply.replyId && prefer.s.autoloadConversation) loadConversation();
function animatedMFM() {
if (allowAnim.value) {
diff --git a/packages/frontend/src/components/MkNoteSimple.vue b/packages/frontend/src/components/MkNoteSimple.vue
index 3720aa7493..4df6b1d75c 100644
--- a/packages/frontend/src/components/MkNoteSimple.vue
+++ b/packages/frontend/src/components/MkNoteSimple.vue
@@ -34,8 +34,8 @@ import MkNoteHeader from '@/components/MkNoteHeader.vue';
import MkSubNoteContent from '@/components/MkSubNoteContent.vue';
import MkCwButton from '@/components/MkCwButton.vue';
import MkButton from '@/components/MkButton.vue';
-import { defaultStore } from '@/store.js';
import { i18n } from '@/i18n.js';
+import { prefer } from '@/preferences.js';
const props = defineProps<{
note: Misskey.entities.Note & {
@@ -46,7 +46,7 @@ const props = defineProps<{
hideFiles?: boolean;
}>();
-let showContent = ref(defaultStore.state.uncollapseCW);
+let showContent = ref(prefer.s.uncollapseCW);
const isDeleted = ref(false);
const mergedCW = computed(() => computeMergedCw(props.note));
diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue
index 3d1884b6e4..b796494a51 100644
--- a/packages/frontend/src/components/MkNoteSub.vue
+++ b/packages/frontend/src/components/MkNoteSub.vue
@@ -65,7 +65,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</footer>
</div>
</div>
- <template v-if="depth < numberOfReplies">
+ <template v-if="depth < store.s.numberOfReplies">
<MkNoteSub v-for="reply in replies" :key="reply.id" :note="reply" :class="$style.reply" :detail="true" :depth="depth + 1" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply"/>
</template>
<div v-else :class="$style.more">
@@ -87,6 +87,9 @@ SPDX-License-Identifier: AGPL-3.0-only
import { computed, ref, shallowRef, watch } from 'vue';
import * as Misskey from 'misskey-js';
import { computeMergedCw } from '@@/js/compute-merged-cw.js';
+import { host } from '@@/js/config.js';
+import type { Visibility } from '@/utility/boost-quote.js';
+import type { OpenOnRemoteOptions } from '@/utility/please-login.js';
import MkNoteHeader from '@/components/MkNoteHeader.vue';
import MkReactionsViewer from '@/components/MkReactionsViewer.vue';
import MkSubNoteContent from '@/components/MkSubNoteContent.vue';
@@ -99,16 +102,16 @@ import { i18n } from '@/i18n.js';
import { $i } from '@/i.js';
import { userPage } from '@/filters/user.js';
import { checkWordMute } from '@/utility/check-word-mute.js';
-import { defaultStore } from '@/store.js';
-import { host } from '@@/js/config.js';
-import { pleaseLogin, type OpenOnRemoteOptions } from '@/utility/please-login.js';
+import { pleaseLogin } from '@/utility/please-login.js';
import { showMovedDialog } from '@/utility/show-moved-dialog.js';
import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { reactionPicker } from '@/utility/reaction-picker.js';
import { claimAchievement } from '@/utility/achievements.js';
import { getNoteMenu } from '@/utility/get-note-menu.js';
-import { useNoteCapture } from '@/utility/use-note-capture.js';
-import { boostMenuItems, type Visibility, computeRenoteTooltip } from '@/utility/boost-quote.js';
+import { boostMenuItems, computeRenoteTooltip } from '@/utility/boost-quote.js';
+import { prefer } from '@/preferences.js';
+import { useNoteCapture } from '@/use/use-note-capture.js';
+import { store } from '@/store.js';
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
@@ -120,6 +123,7 @@ const props = withDefaults(defineProps<{
depth?: number;
}>(), {
depth: 1,
+ onDeleteCallback: undefined,
});
const canRenote = computed(() => ['public', 'home'].includes(props.note.visibility) || props.note.userId === $i.id);
@@ -130,17 +134,16 @@ const translation = ref<any>(null);
const translating = ref(false);
const isDeleted = ref(false);
const renoted = ref(false);
-const numberOfReplies = ref(defaultStore.state.numberOfReplies);
const reactButton = shallowRef<HTMLElement>();
const renoteButton = shallowRef<HTMLElement>();
const quoteButton = shallowRef<HTMLElement>();
const menuButton = shallowRef<HTMLElement>();
const likeButton = shallowRef<HTMLElement>();
-const renoteTooltip = computeRenoteTooltip(computed);
+const renoteTooltip = computeRenoteTooltip(renoted);
let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
-const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
+const defaultLike = computed(() => prefer.s.like ? prefer.s.like : null);
const replies = ref<Misskey.entities.Note[]>([]);
const mergedCW = computed(() => computeMergedCw(appearNote.value));
@@ -175,8 +178,8 @@ useNoteCapture({
note: appearNote,
isDeletedRef: isDeleted,
// only update replies if we are, in fact, showing replies
- onReplyCallback: props.detail && props.depth < numberOfReplies.value ? addReplyTo : undefined,
- onDeleteCallback: props.detail && props.depth < numberOfReplies.value ? props.onDeleteCallback : undefined,
+ onReplyCallback: props.detail && props.depth < store.s.numberOfReplies ? addReplyTo : undefined,
+ onDeleteCallback: props.detail && props.depth < store.s.numberOfReplies ? props.onDeleteCallback : undefined,
});
if ($i) {
@@ -190,22 +193,21 @@ if ($i) {
}
function focus() {
- el.value.focus();
+ el.value?.focus();
}
-function reply(viaKeyboard = false): void {
+async function reply(viaKeyboard = false): Promise<void> {
pleaseLogin({ openOnRemote: pleaseLoginContext.value });
showMovedDialog();
- os.post({
+ await os.post({
reply: props.note,
- channel: props.note.channel,
+ channel: props.note.channel ?? undefined,
animation: !viaKeyboard,
- }, () => {
- focus();
});
+ focus();
}
-function react(viaKeyboard = false): void {
+function react(): void {
pleaseLogin({ openOnRemote: pleaseLoginContext.value });
showMovedDialog();
sound.playMisskeySfx('reaction');
@@ -285,15 +287,15 @@ function undoRenote() : void {
}
}
-let showContent = ref(defaultStore.state.uncollapseCW);
+let showContent = ref(prefer.s.uncollapseCW);
watch(() => props.expandAllCws, (expandAllCws) => {
if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
});
function boostVisibility(forceMenu: boolean = false) {
- if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
- renote(defaultStore.state.visibilityOnBoost);
+ if (!prefer.s.showVisibilitySelectorOnBoost && !forceMenu) {
+ renote(prefer.s.visibilityOnBoost);
} else {
os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
}
@@ -347,65 +349,36 @@ function quote() {
pleaseLogin({ openOnRemote: pleaseLoginContext.value });
showMovedDialog();
- if (appearNote.value.channel) {
- os.post({
- renote: appearNote.value,
- channel: appearNote.value.channel,
- }).then((cancelled) => {
- if (cancelled) return;
- misskeyApi('notes/renotes', {
- noteId: props.note.id,
- userId: $i.id,
- limit: 1,
- quote: true,
- }).then((res) => {
- if (!(res.length > 0)) return;
- const el = quoteButton.value as HTMLElement | null | undefined;
- if (el && res.length > 0) {
- const rect = el.getBoundingClientRect();
- const x = rect.left + (el.offsetWidth / 2);
- const y = rect.top + (el.offsetHeight / 2);
- const { dispose } = os.popup(MkRippleEffect, { x, y }, {
- end: () => dispose(),
- });
- }
-
- os.toast(i18n.ts.quoted);
- });
- });
- } else {
- os.post({
- renote: appearNote.value,
- }).then((cancelled) => {
- if (cancelled) return;
- misskeyApi('notes/renotes', {
- noteId: props.note.id,
- userId: $i.id,
- limit: 1,
- quote: true,
- }).then((res) => {
- if (!(res.length > 0)) return;
- const el = quoteButton.value as HTMLElement | null | undefined;
- if (el && res.length > 0) {
- const rect = el.getBoundingClientRect();
- const x = rect.left + (el.offsetWidth / 2);
- const y = rect.top + (el.offsetHeight / 2);
- const { dispose } = os.popup(MkRippleEffect, { x, y }, {
- end: () => dispose(),
- });
- }
+ os.post({
+ renote: appearNote.value,
+ channel: appearNote.value.channel ?? undefined,
+ }).then((cancelled) => {
+ if (cancelled) return;
+ misskeyApi('notes/renotes', {
+ noteId: props.note.id,
+ userId: $i?.id,
+ limit: 1,
+ quote: true,
+ }).then((res) => {
+ if (!(res.length > 0)) return;
+ const popupEl = quoteButton.value as HTMLElement | null | undefined;
+ if (popupEl && res.length > 0) {
+ const rect = popupEl.getBoundingClientRect();
+ const x = rect.left + (popupEl.offsetWidth / 2);
+ const y = rect.top + (popupEl.offsetHeight / 2);
+ const { dispose } = os.popup(MkRippleEffect, { x, y }, {
+ end: () => dispose(),
+ });
+ }
- os.toast(i18n.ts.quoted);
- });
+ os.toast(i18n.ts.quoted);
});
- }
+ });
}
-function menu(viaKeyboard = false): void {
- const { menu, cleanup } = getNoteMenu({ note: props.note, translating, translation, menuButton, isDeleted });
- os.popupMenu(menu, menuButton.value, {
- viaKeyboard,
- }).then(focus).finally(cleanup);
+function menu(): void {
+ const { popupMenu, cleanup } = getNoteMenu({ note: props.note, translating, translation, isDeleted });
+ os.popupMenu(popupMenu, menuButton.value).then(focus).finally(cleanup);
}
if (props.detail) {
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index c70d0d5581..8e08f135ae 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -884,7 +884,7 @@ async function post(ev?: MouseEvent) {
}
}
- if (defaultStore.state.warnMissingAltText) {
+ if (prefer.s.warnMissingAltText) {
const filesData = toRaw(files.value);
const isMissingAltText = filesData.filter(
@@ -952,7 +952,7 @@ async function post(ev?: MouseEvent) {
}
}
- let token: string | undefined = undefined;
+ let token: string | null | undefined = undefined;
if (postAccount.value) {
const storedAccounts = await getAccounts();
diff --git a/packages/frontend/src/components/MkPostFormAttaches.vue b/packages/frontend/src/components/MkPostFormAttaches.vue
index 43348475e9..d7747413f6 100644
--- a/packages/frontend/src/components/MkPostFormAttaches.vue
+++ b/packages/frontend/src/components/MkPostFormAttaches.vue
@@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { defineAsyncComponent, inject } from 'vue';
import * as Misskey from 'misskey-js';
import type { MenuItem } from '@/types/menu';
-import { copyToClipboard } from '@/utility/copy-to-clipboard';
+import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
diff --git a/packages/frontend/src/components/MkSubNoteContent.vue b/packages/frontend/src/components/MkSubNoteContent.vue
index 2ac34431c4..256c84f9b6 100644
--- a/packages/frontend/src/components/MkSubNoteContent.vue
+++ b/packages/frontend/src/components/MkSubNoteContent.vue
@@ -5,13 +5,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div :class="[$style.root, { [$style.collapsed]: collapsed }]">
- <div :class="{ [$style.clickToOpen]: defaultStore.state.clickToOpen }" @click.stop="defaultStore.state.clickToOpen ? noteclick(note.id) : undefined">
+ <div :class="{ [$style.clickToOpen]: prefer.s.clickToOpen }" @click.stop="prefer.s.clickToOpen ? noteclick(note.id) : undefined">
<span v-if="note.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<span v-if="note.deletedAt" style="opacity: 0.5">({{ i18n.ts.deletedNote }})</span>
<MkA v-if="note.replyId" :class="$style.reply" :to="`/notes/${note.replyId}`" @click.stop><i class="ph-arrow-bend-left-up ph-bold ph-lg"></i></MkA>
<Mfm v-if="note.text" :text="note.text" :isBlock="true" :author="note.user" :nyaize="'respect'" :isAnim="allowAnim" :emojiUrls="note.emojis"/>
<MkButton v-if="!allowAnim && animated && !hideFiles" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
- <MkButton v-else-if="!defaultStore.state.animatedMfm && allowAnim && animated && !hideFiles" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
+ <MkButton v-else-if="!prefer.s.animatedMfm && allowAnim && animated && !hideFiles" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
<div v-if="note.text && translating || note.text && translation" :class="$style.translation">
<MkLoading v-if="translating" mini/>
<div v-else>
@@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<MkA v-if="note.renoteId" :class="$style.rp" :to="`/notes/${note.renoteId}`" @click.stop>RN: ...</MkA>
</div>
- <details v-if="note.files && note.files.length > 0" :open="!defaultStore.state.collapseFiles && !hideFiles">
+ <details v-if="note.files && note.files.length > 0" :open="!prefer.s.collapseFiles && !hideFiles">
<summary>({{ i18n.tsx.withNFiles({ n: note.files.length }) }})</summary>
<MkMediaList :mediaList="note.files"/>
</details>
@@ -47,10 +47,10 @@ import MkMediaList from '@/components/MkMediaList.vue';
import MkPoll from '@/components/MkPoll.vue';
import MkButton from '@/components/MkButton.vue';
import { i18n } from '@/i18n.js';
-import { defaultStore } from '@/store.js';
-import { useRouter } from '@/router/supplier.js';
import * as os from '@/os.js';
import { checkAnimationFromMfm } from '@/utility/check-animated-mfm.js';
+import { useRouter } from '@/router';
+import { prefer } from '@/preferences.js';
const props = defineProps<{
note: Misskey.entities.Note;
@@ -63,7 +63,7 @@ const props = defineProps<{
const router = useRouter();
function noteclick(id: string) {
- const selection = document.getSelection();
+ const selection = window.document.getSelection();
if (selection?.toString().length === 0) {
router.push(`/notes/${id}`);
}
@@ -71,9 +71,9 @@ function noteclick(id: string) {
const parsed = computed(() => props.note.text ? mfm.parse(props.note.text) : null);
const animated = computed(() => parsed.value ? checkAnimationFromMfm(parsed.value) : null);
-let allowAnim = ref(defaultStore.state.advancedMfm && defaultStore.state.animatedMfm ? true : false);
+let allowAnim = ref(prefer.s.advancedMfm && prefer.s.animatedMfm);
-const isLong = defaultStore.state.expandLongNote && !props.hideFiles ? false : shouldCollapsed(props.note, []);
+const isLong = prefer.s.expandLongNote && !props.hideFiles ? false : shouldCollapsed(props.note, []);
function animatedMFM() {
if (allowAnim.value) {
diff --git a/packages/frontend/src/components/MkUrlPreview.vue b/packages/frontend/src/components/MkUrlPreview.vue
index 11071f2f60..1e7c5cdf40 100644
--- a/packages/frontend/src/components/MkUrlPreview.vue
+++ b/packages/frontend/src/components/MkUrlPreview.vue
@@ -106,8 +106,9 @@ import { prefer } from '@/preferences.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { warningExternalWebsite } from '@/utility/warning-external-website.js';
+// TODO DynamicNoteSimple
const XNoteSimple = defineAsyncComponent<typeof MkNoteSimple | typeof SkNoteSimple>(() =>
- defaultStore.state.noteDesign === 'misskey'
+ prefer.s.noteDesign === 'misskey'
? import('@/components/MkNoteSimple.vue')
: import('@/components/SkNoteSimple.vue'),
);
diff --git a/packages/frontend/src/components/MkUrlWarningDialog.vue b/packages/frontend/src/components/MkUrlWarningDialog.vue
index 3bec6eecdd..f9a979f33e 100644
--- a/packages/frontend/src/components/MkUrlWarningDialog.vue
+++ b/packages/frontend/src/components/MkUrlWarningDialog.vue
@@ -34,7 +34,7 @@ import MkModal from '@/components/MkModal.vue';
import MkButton from '@/components/MkButton.vue';
import MkSwitch from '@/components/MkSwitch.vue';
import { i18n } from '@/i18n.js';
-import { defaultStore } from '@/store.js';
+import { prefer } from '@/preferences.js';
type Result = string | number | true | null;
@@ -62,8 +62,8 @@ function done(canceled: boolean, result?: Result): void { // eslint-disable-line
async function ok() {
const result = true;
- if (!defaultStore.state.trustedDomains.includes(domain.value) && trustThisDomain.value) {
- await defaultStore.set('trustedDomains', defaultStore.state.trustedDomains.concat(domain.value));
+ if (!prefer.s.trustedDomains.includes(domain.value) && trustThisDomain.value) {
+ prefer.r.trustedDomains.value = prefer.s.trustedDomains.concat(domain.value);
}
done(false, result);
}
@@ -77,11 +77,11 @@ function onKeydown(evt: KeyboardEvent) {
}
onMounted(() => {
- document.addEventListener('keydown', onKeydown);
+ window.document.addEventListener('keydown', onKeydown);
});
onBeforeUnmount(() => {
- document.removeEventListener('keydown', onKeydown);
+ window.document.removeEventListener('keydown', onKeydown);
});
</script>
diff --git a/packages/frontend/src/components/MkVisibilityPicker.vue b/packages/frontend/src/components/MkVisibilityPicker.vue
index 659a82d8f2..c52bbbd44f 100644
--- a/packages/frontend/src/components/MkVisibilityPicker.vue
+++ b/packages/frontend/src/components/MkVisibilityPicker.vue
@@ -53,9 +53,10 @@ const props = withDefaults(defineProps<{
currentVisibility: typeof Misskey.noteVisibilities[number];
isSilenced: boolean;
localOnly: boolean;
- src?: HTMLElement;
+ src?: HTMLElement | null;
isReplyVisibilitySpecified?: boolean;
}>(), {
+ src: null,
});
const emit = defineEmits<{
diff --git a/packages/frontend/src/components/SkFetchNote.vue b/packages/frontend/src/components/SkFetchNote.vue
index d325ef1687..a40b99ae8d 100644
--- a/packages/frontend/src/components/SkFetchNote.vue
+++ b/packages/frontend/src/components/SkFetchNote.vue
@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { ref, watch } from 'vue';
import * as Misskey from 'misskey-js';
import { i18n } from '@/i18n.js';
-import { misskeyApi } from '@/utility/misskey-api';
+import { misskeyApi } from '@/utility/misskey-api.js';
import DynamicNote from '@/components/DynamicNote.vue';
const props = withDefaults(defineProps<{
diff --git a/packages/frontend/src/components/SkFlashPlayer.vue b/packages/frontend/src/components/SkFlashPlayer.vue
index 2b61974ef7..0cdc7bf104 100644
--- a/packages/frontend/src/components/SkFlashPlayer.vue
+++ b/packages/frontend/src/components/SkFlashPlayer.vue
@@ -6,14 +6,14 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div :class="$style.flash_player_container">
<canvas :class="$style.ratio" height="300" width="300"></canvas>
-
+
<div v-if="hide" :class="$style.flash_player_disabled" @click="toggleVisible()">
<div>
<b><i class="ph-eye ph-bold ph-lg"></i> {{ i18n.ts.sensitive }}</b>
<span>{{ i18n.ts.clickToShow }}</span>
</div>
</div>
-
+
<div v-else :class="$style.flash_player_enabled">
<div :class="$style.flash_display">
<div v-if="playerHide" :class="$style.player_hide" @click="dismissWarning()">
@@ -59,12 +59,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { ref, onDeactivated } from 'vue';
import * as Misskey from 'misskey-js';
+import type { PublicAPI, PublicAPILike } from '@/types/ruffle/setup';
+import type { PlayerElement } from '@/types/ruffle/player.js';
import MkEllipsis from '@/components/global/MkEllipsis.vue';
import MkLoading from '@/components/global/MkLoading.vue';
import { i18n } from '@/i18n.js';
-import { defaultStore } from '@/store.js';
-import { PublicAPI, PublicAPILike } from '@/types/ruffle/setup'; // This gives us the types for window.RufflePlayer, etc via side effects
-import { PlayerElement } from '@/types/ruffle/player';
+import { prefer } from '@/preferences.js';
const props = defineProps<{
flashFile: Misskey.entities.DriveFile
@@ -73,7 +73,7 @@ const props = defineProps<{
const isSensitive = props.flashFile.isSensitive;
const url = props.flashFile.url;
const comment = props.flashFile.comment ?? '';
-let hide = ref((defaultStore.state.nsfw === 'force') || isSensitive && (defaultStore.state.nsfw !== 'ignore'));
+let hide = ref((prefer.s.nsfw === 'force') || isSensitive && (prefer.s.nsfw !== 'ignore'));
let playerHide = ref(true);
let ruffleContainer = ref<HTMLDivElement>();
let playPauseButtonKey = ref<number>(0);
@@ -126,7 +126,7 @@ async function loadRuffle() {
'maxExecutionDuration': 15,
'logLevel': 'error',
'base': null,
- 'menu': true,
+ 'popupMenu': true,
'salign': '',
'forceAlign': false,
'scale': 'showAll',
diff --git a/packages/frontend/src/components/SkModPlayer.vue b/packages/frontend/src/components/SkModPlayer.vue
index 82f5705d00..572e01c748 100644
--- a/packages/frontend/src/components/SkModPlayer.vue
+++ b/packages/frontend/src/components/SkModPlayer.vue
@@ -44,9 +44,9 @@ SPDX-License-Identifier: AGPL-3.0-only
import { ref, nextTick, watch, onDeactivated, onMounted } from 'vue';
import * as Misskey from 'misskey-js';
import { i18n } from '@/i18n.js';
-import { defaultStore } from '@/store.js';
import { ChiptuneJsPlayer, ChiptuneJsConfig } from '@/utility/chiptune2.js';
import { isTouchUsing } from '@/utility/touch.js';
+import { prefer } from '@/preferences.js';
const colours = {
background: '#000000',
@@ -72,7 +72,7 @@ const props = defineProps<{
const isSensitive = props.module.isSensitive;
const url = props.module.url;
-let hide = ref((defaultStore.state.nsfw === 'force') ? true : isSensitive && (defaultStore.state.nsfw !== 'ignore'));
+let hide = ref((prefer.s.nsfw === 'force') ? true : isSensitive && (prefer.s.nsfw !== 'ignore'));
let patternHide = ref(false);
let playing = ref(false);
let displayCanvas = ref<HTMLCanvasElement>();
diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue
index 67c82f95aa..10552ea861 100644
--- a/packages/frontend/src/components/SkNote.vue
+++ b/packages/frontend/src/components/SkNote.vue
@@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
v-show="!isDeleted"
ref="rootEl"
v-hotkey="keymap"
- :class="[$style.root, { [$style.showActionsOnlyHover]: defaultStore.state.showNoteActionsOnlyHover, [$style.skipRender]: defaultStore.state.skipNoteRender }]"
+ :class="[$style.root, { [$style.showActionsOnlyHover]: prefer.s.showNoteActionsOnlyHover, [$style.skipRender]: prefer.s.skipNoteRender }]"
:tabindex="isDeleted ? '-1' : '0'"
>
<SkNoteSub v-if="appearNote.reply" v-show="!renoteCollapsed && !inReplyToCollapsed" :note="appearNote.reply" :class="$style.replyTo"/>
@@ -60,7 +60,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<SkNoteHeader :note="appearNote" :mini="true"/>
</div>
</div>
- <div :class="[{ [$style.clickToOpen]: defaultStore.state.clickToOpen }]" @click.stop="defaultStore.state.clickToOpen ? noteclick(appearNote.id) : undefined">
+ <div :class="[{ [$style.clickToOpen]: prefer.s.clickToOpen }]" @click.stop="prefer.s.clickToOpen ? noteclick(appearNote.id) : undefined">
<div style="container-type: inline-size;">
<p v-if="mergedCW != null" :class="$style.cw">
<Mfm
@@ -97,7 +97,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
- <MkButton v-else-if="!defaultStore.state.animatedMfm && allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
+ <MkButton v-else-if="!prefer.s.animatedMfm && allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
</div>
<div v-if="appearNote.files && appearNote.files.length > 0">
<MkMediaList ref="galleryEl" :mediaList="appearNote.files" @click.stop/>
@@ -160,9 +160,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<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="ph-smiley ph-bold ph-lg"></i>
- <p v-if="(appearNote.reactionAcceptance === 'likeOnly' || defaultStore.state.showReactionsCount) && appearNote.reactionCount > 0" :class="$style.footerButtonCount">{{ number(appearNote.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="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" :class="$style.footerButton" class="_button" @mousedown.prevent="clip()">
+ <button v-if="prefer.s.showClipButtonInNoteFooter" ref="clipButton" :class="$style.footerButton" class="_button" @mousedown.prevent="clip()">
<i class="ti ti-paperclip"></i>
</button>
<button ref="menuButton" :class="$style.footerButton" class="_button" @mousedown.prevent="showMenu()">
@@ -215,6 +215,8 @@ import { shouldCollapsed } from '@@/js/collapsed.js';
import { host } from '@@/js/config.js';
import { computeMergedCw } from '@@/js/compute-merged-cw.js';
import type { MenuItem } from '@/types/menu.js';
+import type { Keymap } from '@/utility/hotkey.js';
+import type { Visibility } from '@/utility/boost-quote.js';
import SkNoteSub from '@/components/SkNoteSub.vue';
import SkNoteHeader from '@/components/SkNoteHeader.vue';
import SkNoteSimple from '@/components/SkNoteSimple.vue';
@@ -234,27 +236,27 @@ import number from '@/filters/number.js';
import * as os from '@/os.js';
import { misskeyApi, misskeyApiGet } from '@/utility/misskey-api.js';
import * as sound from '@/utility/sound.js';
-import { defaultStore, noteViewInterruptors } from '@/store.js';
import { reactionPicker } from '@/utility/reaction-picker.js';
import { extractUrlFromMfm } from '@/utility/extract-url-from-mfm.js';
import { checkAnimationFromMfm } from '@/utility/check-animated-mfm.js';
-import { $i } from '@/account.js';
import { i18n } from '@/i18n.js';
import { getAbuseNoteMenu, getCopyNoteLinkMenu, getNoteClipMenu, getNoteMenu } from '@/utility/get-note-menu.js';
import { getNoteVersionsMenu } from '@/utility/get-note-versions-menu.js';
-import { useNoteCapture } from '@/utility/use-note-capture.js';
+import { useNoteCapture } from '@/use/use-note-capture.js';
import { deepClone } from '@/utility/clone.js';
-import { useTooltip } from '@/utility/use-tooltip.js';
+import { useTooltip } from '@/use/use-tooltip.js';
import { claimAchievement } from '@/utility/achievements.js';
import { getNoteSummary } from '@/utility/get-note-summary.js';
import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { showMovedDialog } from '@/utility/show-moved-dialog.js';
-import { useRouter } from '@/router/supplier.js';
-import { boostMenuItems, type Visibility, computeRenoteTooltip } from '@/utility/boost-quote.js';
+import { boostMenuItems, computeRenoteTooltip } from '@/utility/boost-quote.js';
import { isEnabledUrlPreview } from '@/instance.js';
-import { type Keymap } from '@/utility/hotkey.js';
import { focusPrev, focusNext } from '@/utility/focus.js';
import { getAppearNote } from '@/utility/get-appear-note.js';
+import { $i } from '@/i';
+import { prefer } from '@/preferences';
+import { useRouter } from '@/router';
+import { getPluginHandlers } from '@/plugin.js';
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
@@ -282,13 +284,14 @@ const currentClip = inject<Ref<Misskey.entities.Clip> | null>('currentClip', nul
const note = ref(deepClone(props.note));
function noteclick(id: string) {
- const selection = document.getSelection();
+ const selection = window.document.getSelection();
if (selection?.toString().length === 0) {
router.push(`/notes/${id}`);
}
}
// plugin
+const noteViewInterruptors = getPluginHandlers('note_view_interruptor');
if (noteViewInterruptors.length > 0) {
onMounted(async () => {
let result: Misskey.entities.Note | null = deepClone(note.value);
@@ -321,30 +324,30 @@ const likeButton = shallowRef<HTMLElement>();
const appearNote = computed(() => getAppearNote(note.value));
const galleryEl = shallowRef<InstanceType<typeof MkMediaList>>();
const isMyRenote = $i && ($i.id === note.value.userId);
-const showContent = ref(defaultStore.state.uncollapseCW);
+const showContent = ref(prefer.s.uncollapseCW);
const parsed = computed(() => appearNote.value.text ? mfm.parse(appearNote.value.text) : null);
const urls = computed(() => parsed.value ? extractUrlFromMfm(parsed.value).filter((url) => appearNote.value.renote?.url !== url && appearNote.value.renote?.uri !== url) : null);
const isLong = shouldCollapsed(appearNote.value, urls.value ?? []);
-const collapsed = ref(defaultStore.state.expandLongNote && appearNote.value.cw == null && isLong ? false : appearNote.value.cw == null && isLong);
+const collapsed = ref(prefer.s.expandLongNote && appearNote.value.cw == null && isLong ? false : appearNote.value.cw == null && isLong);
const isDeleted = ref(false);
const renoted = ref(false);
const muted = ref(checkMute(appearNote.value, $i?.mutedWords));
const hardMuted = ref(props.withHardMute && checkMute(appearNote.value, $i?.hardMutedWords, true));
-const showSoftWordMutedWord = computed(() => defaultStore.state.showSoftWordMutedWord);
+const showSoftWordMutedWord = computed(() => prefer.s.showSoftWordMutedWord);
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 showTicker = (prefer.s.instanceTicker === 'always') || (prefer.s.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 && (
+ prefer.s.collapseRenotes && isRenote && (
($i && ($i.id === note.value.userId || $i.id === appearNote.value.userId)) || // `||` must be `||`! See https://github.com/misskey-dev/misskey/issues/13131
(appearNote.value.myReaction != null)
)
);
-const inReplyToCollapsed = ref(defaultStore.state.collapseNotesRepliedTo);
-const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
+const inReplyToCollapsed = ref(prefer.s.collapseNotesRepliedTo);
+const defaultLike = computed(() => prefer.s.like ? prefer.s.like : null);
const animated = computed(() => parsed.value ? checkAnimationFromMfm(parsed.value) : null);
-const allowAnim = ref(defaultStore.state.advancedMfm && defaultStore.state.animatedMfm ? true : false);
+const allowAnim = ref(prefer.s.advancedMfm && prefer.s.animatedMfm ? true : false);
const mergedCW = computed(() => computeMergedCw(appearNote.value));
@@ -393,7 +396,7 @@ const keymap = {
},
'q': () => {
if (renoteCollapsed.value) return;
- if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost);
+ if (canRenote.value && !renoted.value && !renoting) renote(prefer.s.visibilityOnBoost);
},
'm': () => {
if (renoteCollapsed.value) return;
@@ -401,7 +404,7 @@ const keymap = {
},
'c': () => {
if (renoteCollapsed.value) return;
- if (!defaultStore.state.showClipButtonInNoteFooter) return;
+ if (!prefer.s.showClipButtonInNoteFooter) return;
clip();
},
'o': () => {
@@ -531,8 +534,8 @@ if (!props.mock) {
function boostVisibility(forceMenu: boolean = false) {
if (renoting) return;
- if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
- renote(defaultStore.state.visibilityOnBoost);
+ if (!prefer.s.showVisibilitySelectorOnBoost && !forceMenu) {
+ renote(prefer.s.visibilityOnBoost);
} else {
os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
}
@@ -781,12 +784,12 @@ function onContextmenu(ev: MouseEvent): void {
if (ev.target && isLink(ev.target as HTMLElement)) return;
if (window.getSelection()?.toString() !== '') return;
- if (defaultStore.state.useReactionPickerForContextMenu) {
+ if (prefer.s.useReactionPickerForContextMenu) {
ev.preventDefault();
react();
} else {
- const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
- os.contextMenu(menu, ev).then(focus).finally(cleanup);
+ const { popupMenu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
+ os.contextMenu(popupMenu, ev).then(focus).finally(cleanup);
}
}
@@ -795,8 +798,8 @@ function showMenu(): void {
return;
}
- const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
- os.popupMenu(menu, menuButton.value).then(focus).finally(cleanup);
+ const { popupMenu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
+ os.popupMenu(popupMenu, menuButton.value).then(focus).finally(cleanup);
}
async function menuVersions(viaKeyboard = false): Promise<void> {
diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index 8870d12164..a088fd5684 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -116,7 +116,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
<MkButton v-if="!allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-play ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.play }}</MkButton>
- <MkButton v-else-if="!defaultStore.state.animatedMfm && allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
+ <MkButton v-else-if="!prefer.s.animatedMfm && allowAnim && animated" :class="$style.playMFMButton" :small="true" @click="animatedMFM()" @click.stop><i class="ph-stop ph-bold ph-lg "></i> {{ i18n.ts._animatedMFM.stop }}</MkButton>
<div v-if="appearNote.files && appearNote.files.length > 0">
<MkMediaList ref="galleryEl" :mediaList="appearNote.files"/>
</div>
@@ -174,9 +174,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<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="ph-smiley ph-bold ph-lg"></i>
- <p v-if="(appearNote.reactionAcceptance === 'likeOnly' || defaultStore.state.showReactionsCount) && appearNote.reactionCount > 0" :class="$style.noteFooterButtonCount">{{ number(appearNote.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="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown.prevent="clip()">
+ <button v-if="prefer.s.showClipButtonInNoteFooter" ref="clipButton" class="_button" :class="$style.noteFooterButton" @mousedown.prevent="clip()">
<i class="ti ti-paperclip"></i>
</button>
<button ref="menuButton" class="_button" :class="$style.noteFooterButton" @mousedown.prevent="showMenu()">
@@ -338,7 +338,7 @@ const likeButton = shallowRef<HTMLElement>();
const appearNote = computed(() => getAppearNote(note.value));
const galleryEl = shallowRef<InstanceType<typeof MkMediaList>>();
const isMyRenote = $i && ($i.id === note.value.userId);
-const showContent = ref(defaultStore.state.uncollapseCW);
+const showContent = ref(prefer.s.uncollapseCW);
const isDeleted = ref(false);
const renoted = ref(false);
const muted = ref($i ? checkWordMute(appearNote.value, $i, $i.mutedWords) : false);
@@ -347,13 +347,13 @@ const translating = ref(false);
const parsed = appearNote.value.text ? mfm.parse(appearNote.value.text) : null;
const urls = parsed ? extractUrlFromMfm(parsed).filter((url) => appearNote.value.renote?.url !== url && appearNote.value.renote?.uri !== url) : null;
const animated = computed(() => parsed ? checkAnimationFromMfm(parsed) : null);
-const allowAnim = ref(defaultStore.state.advancedMfm && defaultStore.state.animatedMfm ? true : false);
-const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.value.user.instance);
+const allowAnim = ref(prefer.s.advancedMfm && prefer.s.animatedMfm ? true : false);
+const showTicker = (prefer.s.instanceTicker === 'always') || (prefer.s.instanceTicker === 'remote' && appearNote.value.user.instance);
const conversation = ref<Misskey.entities.Note[]>([]);
const replies = ref<Misskey.entities.Note[]>([]);
const quotes = ref<Misskey.entities.Note[]>([]);
const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || (appearNote.value.visibility === 'followers' && appearNote.value.userId === $i?.id));
-const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
+const defaultLike = computed(() => prefer.s.like ? prefer.s.like : null);
const mergedCW = computed(() => computeMergedCw(appearNote.value));
@@ -383,10 +383,10 @@ const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({
const keymap = {
'r': () => reply(),
'e|a|plus': () => react(),
- 'q': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); },
+ 'q': () => { if (canRenote.value && !renoted.value && !renoting) renote(prefer.s.visibilityOnBoost); },
'm': () => showMenu(),
'c': () => {
- if (!defaultStore.state.showClipButtonInNoteFooter) return;
+ if (!prefer.s.showClipButtonInNoteFooter) return;
clip();
},
'o': () => galleryEl.value?.openGallery(),
@@ -493,8 +493,8 @@ useTooltip(quoteButton, async (showing) => {
function boostVisibility(forceMenu: boolean = false) {
if (renoting) return;
- if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
- renote(defaultStore.state.visibilityOnBoost);
+ if (!prefer.s.showVisibilitySelectorOnBoost && !forceMenu) {
+ renote(prefer.s.visibilityOnBoost);
} else {
os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
}
@@ -734,18 +734,18 @@ function onContextmenu(ev: MouseEvent): void {
if (ev.target && isLink(ev.target as HTMLElement)) return;
if (window.getSelection()?.toString() !== '') return;
- if (defaultStore.state.useReactionPickerForContextMenu) {
+ if (prefer.s.useReactionPickerForContextMenu) {
ev.preventDefault();
react();
} else {
- const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
- os.contextMenu(menu, ev).then(focus).finally(cleanup);
+ const { popupMenu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
+ os.contextMenu(popupMenu, ev).then(focus).finally(cleanup);
}
}
function showMenu(): void {
- const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
- os.popupMenu(menu, menuButton.value).then(focus).finally(cleanup);
+ const { popupMenu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
+ os.popupMenu(popupMenu, menuButton.value).then(focus).finally(cleanup);
}
async function menuVersions(): Promise<void> {
@@ -824,7 +824,7 @@ function loadConversation() {
});
}
-if (appearNote.value.reply && appearNote.value.reply.replyId && defaultStore.state.autoloadConversation) loadConversation();
+if (appearNote.value.reply && appearNote.value.reply.replyId && prefer.s.autoloadConversation) loadConversation();
function animatedMFM() {
if (allowAnim.value) {
diff --git a/packages/frontend/src/components/SkNoteHeader.vue b/packages/frontend/src/components/SkNoteHeader.vue
index 12ba9f187a..9c6e6d9b67 100644
--- a/packages/frontend/src/components/SkNoteHeader.vue
+++ b/packages/frontend/src/components/SkNoteHeader.vue
@@ -54,7 +54,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="note.user.badgeRoles" :class="$style.badgeRoles">
<img v-for="role in note.user.badgeRoles" :key="role.id" v-tooltip="role.name" :class="$style.badgeRole" :src="role.iconUrl"/>
</div>
- <SkInstanceTicker v-if="showTicker && !isMobile && defaultStore.state.showTickerOnReplies" style="cursor: pointer; max-height: 5px; top: 3px; position: relative; margin-top: 0px !important;" :instance="note.user.instance" :host="note.user.host" @click.stop="showOnRemote()"/>
+ <SkInstanceTicker v-if="showTicker && !isMobile && prefer.s.showTickerOnReplies" style="cursor: pointer; max-height: 5px; top: 3px; position: relative; margin-top: 0px !important;" :instance="note.user.instance" :host="note.user.host" @click.stop="showOnRemote()"/>
<div :class="$style.classicInfo">
<div v-if="mock">
<MkTime :time="note.createdAt" colored/>
@@ -95,7 +95,7 @@ const props = defineProps<{
const menuVersionsButton = shallowRef<HTMLElement>();
const router = useRouter();
-const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && props.note.user.instance);
+const showTicker = (prefer.s.instanceTicker === 'always') || (prefer.s.instanceTicker === 'remote' && props.note.user.instance);
const MOBILE_THRESHOLD = 500;
const isMobile = ref(deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD);
diff --git a/packages/frontend/src/components/SkNoteSimple.vue b/packages/frontend/src/components/SkNoteSimple.vue
index 71a5bd4df8..d15f52d29b 100644
--- a/packages/frontend/src/components/SkNoteSimple.vue
+++ b/packages/frontend/src/components/SkNoteSimple.vue
@@ -36,7 +36,7 @@ const props = defineProps<{
hideFiles?: boolean;
}>();
-let showContent = ref(defaultStore.state.uncollapseCW);
+let showContent = ref(prefer.s.uncollapseCW);
const mergedCW = computed(() => computeMergedCw(props.note));
diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue
index aa05e1b0cf..a890489459 100644
--- a/packages/frontend/src/components/SkNoteSub.vue
+++ b/packages/frontend/src/components/SkNoteSub.vue
@@ -73,7 +73,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</footer>
</div>
</div>
- <template v-if="depth < numberOfReplies">
+ <template v-if="depth < store.s.numberOfReplies">
<SkNoteSub v-for="reply in replies" :key="reply.id" :note="reply" :class="[$style.reply, { [$style.single]: replies.length === 1 }]" :detail="true" :depth="depth + 1" :expandAllCws="props.expandAllCws" :onDeleteCallback="removeReply" :isReply="props.isReply"/>
</template>
<div v-else :class="$style.more">
@@ -95,6 +95,9 @@ SPDX-License-Identifier: AGPL-3.0-only
import { computed, ref, shallowRef, watch } from 'vue';
import * as Misskey from 'misskey-js';
import { computeMergedCw } from '@@/js/compute-merged-cw.js';
+import { host } from '@@/js/config.js';
+import type { OpenOnRemoteOptions } from '@/utility/please-login.js';
+import type { Visibility } from '@/utility/boost-quote.js';
import SkNoteHeader from '@/components/SkNoteHeader.vue';
import MkReactionsViewer from '@/components/MkReactionsViewer.vue';
import MkSubNoteContent from '@/components/MkSubNoteContent.vue';
@@ -104,22 +107,22 @@ import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import * as sound from '@/utility/sound.js';
import { i18n } from '@/i18n.js';
-import { $i } from '@/account.js';
import { userPage } from '@/filters/user.js';
import { checkWordMute } from '@/utility/check-word-mute.js';
-import { defaultStore } from '@/store.js';
-import { host } from '@@/js/config.js';
-import { pleaseLogin, type OpenOnRemoteOptions } from '@/utility/please-login.js';
+import { pleaseLogin } from '@/utility/please-login.js';
import { showMovedDialog } from '@/utility/show-moved-dialog.js';
import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { reactionPicker } from '@/utility/reaction-picker.js';
import { claimAchievement } from '@/utility/achievements.js';
import { getNoteMenu } from '@/utility/get-note-menu.js';
-import { useNoteCapture } from '@/utility/use-note-capture.js';
-import { boostMenuItems, type Visibility, computeRenoteTooltip } from '@/utility/boost-quote.js';
+import { useNoteCapture } from '@/use/use-note-capture.js';
+import { boostMenuItems, computeRenoteTooltip } from '@/utility/boost-quote.js';
+import { prefer } from '@/preferences';
+import { store } from '@/store';
+import { $i } from '@/i.js';
const canRenote = computed(() => ['public', 'home'].includes(props.note.visibility) || props.note.userId === $i.id);
-const hideLine = computed(() => { return props.detail ? true : false; });
+const hideLine = computed(() => props.detail);
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
@@ -144,7 +147,6 @@ const translation = ref<any>(null);
const translating = ref(false);
const isDeleted = ref(false);
const renoted = ref(false);
-const numberOfReplies = ref(defaultStore.state.numberOfReplies);
const reactButton = shallowRef<HTMLElement>();
const renoteButton = shallowRef<HTMLElement>();
const quoteButton = shallowRef<HTMLElement>();
@@ -154,7 +156,7 @@ const likeButton = shallowRef<HTMLElement>();
const renoteTooltip = computeRenoteTooltip(renoted);
let appearNote = computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);
-const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null);
+const defaultLike = computed(() => prefer.s.like ? prefer.s.like : null);
const replies = ref<Misskey.entities.Note[]>([]);
const mergedCW = computed(() => computeMergedCw(appearNote.value));
@@ -189,8 +191,8 @@ useNoteCapture({
note: appearNote,
isDeletedRef: isDeleted,
// only update replies if we are, in fact, showing replies
- onReplyCallback: props.detail && props.depth < numberOfReplies.value ? addReplyTo : undefined,
- onDeleteCallback: props.detail && props.depth < numberOfReplies.value ? props.onDeleteCallback : undefined,
+ onReplyCallback: props.detail && props.depth < store.s.numberOfReplies ? addReplyTo : undefined,
+ onDeleteCallback: props.detail && props.depth < store.s.numberOfReplies ? props.onDeleteCallback : undefined,
});
if ($i) {
@@ -299,15 +301,15 @@ function undoRenote() : void {
}
}
-let showContent = ref(defaultStore.state.uncollapseCW);
+let showContent = ref(prefer.s.uncollapseCW);
watch(() => props.expandAllCws, (expandAllCws) => {
if (expandAllCws !== showContent.value) showContent.value = expandAllCws;
});
function boostVisibility(forceMenu: boolean = false) {
- if (!defaultStore.state.showVisibilitySelectorOnBoost && !forceMenu) {
- renote(defaultStore.state.visibilityOnBoost);
+ if (!prefer.s.showVisibilitySelectorOnBoost && !forceMenu) {
+ renote(prefer.s.visibilityOnBoost);
} else {
os.popupMenu(boostMenuItems(appearNote, renote), renoteButton.value);
}
@@ -415,17 +417,15 @@ function quote() {
}
}
-function menu(viaKeyboard = false): void {
- const { menu, cleanup } = getNoteMenu({ note: props.note, translating, translation, menuButton, isDeleted });
- os.popupMenu(menu, menuButton.value, {
- viaKeyboard,
- }).then(focus).finally(cleanup);
+function menu(): void {
+ const { popupMenu, cleanup } = getNoteMenu({ note: props.note, translating, translation, isDeleted });
+ os.popupMenu(popupMenu, menuButton.value).then(focus).finally(cleanup);
}
if (props.detail) {
misskeyApi('notes/children', {
noteId: props.note.id,
- limit: numberOfReplies.value,
+ limit: store.s.numberOfReplies,
showQuotes: false,
}).then(res => {
replies.value = res;
diff --git a/packages/frontend/src/components/SkOldNoteWindow.vue b/packages/frontend/src/components/SkOldNoteWindow.vue
index 52b135649d..463a71ccd0 100644
--- a/packages/frontend/src/components/SkOldNoteWindow.vue
+++ b/packages/frontend/src/components/SkOldNoteWindow.vue
@@ -92,11 +92,12 @@ import MkPoll from '@/components/MkPoll.vue';
import MkUrlPreview from '@/components/MkUrlPreview.vue';
import MkInstanceTicker from '@/components/MkInstanceTicker.vue';
import { userPage } from '@/filters/user.js';
-import { defaultStore, noteViewInterruptors } from '@/store.js';
import { extractUrlFromMfm } from '@/utility/extract-url-from-mfm.js';
import { i18n } from '@/i18n.js';
import { deepClone } from '@/utility/clone.js';
import { dateTimeFormat } from '@/utility/intl-const.js';
+import { prefer } from '@/preferences';
+import { getPluginHandlers } from '@/plugin.js';
const props = defineProps<{
note: Misskey.entities.Note;
@@ -113,6 +114,7 @@ const inChannel = inject('inChannel', null);
let note = ref(deepClone(props.note));
// plugin
+const noteViewInterruptors = getPluginHandlers('note_view_interruptor');
if (noteViewInterruptors.length > 0) {
onMounted(async () => {
let result = deepClone(note.value);
@@ -132,7 +134,7 @@ replaceContent();
const isRenote = (
note.value.renote != null &&
note.value.text == null &&
- note.value.fileIds.length === 0 &&
+ !note.value.fileIds?.length &&
note.value.poll == null
);
@@ -145,7 +147,7 @@ const showContent = ref(false);
const translation = ref(null);
const translating = ref(false);
const urls = appearNote.value.text ? extractUrlFromMfm(mfm.parse(appearNote.value.text)).filter(u => u !== renoteUrl && u !== renoteUri) : null;
-const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.value.user.instance);
+const showTicker = (prefer.s.instanceTicker === 'always') || (prefer.s.instanceTicker === 'remote' && appearNote.value.user.instance);
</script>
diff --git a/packages/frontend/src/components/global/MkMfm.ts b/packages/frontend/src/components/global/MkMfm.ts
index 424150e9a3..7ec2b34751 100644
--- a/packages/frontend/src/components/global/MkMfm.ts
+++ b/packages/frontend/src/components/global/MkMfm.ts
@@ -66,7 +66,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
//provide('linkNavigationBehavior', props.linkNavigationBehavior);
const isNote = props.isNote ?? true;
- const shouldNyaize = props.nyaize === 'respect' && props.author?.isCat && props.author?.speakAsCat && !defaultStore.state.disableCatSpeak;
+ const shouldNyaize = props.nyaize === 'respect' && props.author?.isCat && props.author?.speakAsCat && !prefer.s.disableCatSpeak;
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (props.text == null || props.text === '') return;