From d30ddd4c2ebcacc0d0b49c74e8dfe05b5422ba2e Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sun, 9 Mar 2025 12:34:08 +0900 Subject: Refine preferences (#15597) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * wip * wip * wip * test * wip rollup pluginでsearchIndexの情報生成 * wip * SPDX * wip: markerIdを自動付与 * rollupでビルド時・devモード時に毎回uuidを生成するように * 開発サーバーでだけ必要な挙動は開発サーバーのみで * 条件が逆 * wip: childrenの生成 * update comment * update comment * rename auto generated file * hashをパスと行数から決定 * Update privacy.vue * Update privacy.vue * wip * Update general.vue * Update general.vue * wip * wip * Update SearchMarker.vue * wip * Update profile.vue * Update mute-block.vue * Update mute-block.vue * Update general.vue * Update general.vue * childrenがduplicate key errorを吐く問題をいったん解決 * マーカーの形を成形 * loggerを置きかえ * とりあえず省略記法に対応 * Refactor and Format codes * wip * Update settings-search-index.ts * wip * wip * とりあえず不確定要因の仮置きidを削除 * hashの生成を正規化(絶対パスになっていたのを緩和) * pathの入力を省略可能に * adminでもパス生成できるように * Update settings-search-index.ts * Update privacy.vue * wip * build searchIndex * wip * build * Update general.vue * build * Update sounds.vue * build * build * Update sounds.vue * 🎨 * 🎨 * Update privacy.vue * Update privacy.vue * Update security.vue * create-search-indexを多少改善 * build * Update 2fa.vue * wip * 必ずtransformCodeCacheを利用するように, キャッシュの明確な受け渡しを定義 * キャッシュはdevServerでなくても更新 * Revert "wip" This reverts commit 41bffd3a13f55618bf939dc1c9acb2a77ead4054. * inlining * wip * Update theme.vue * 🎨 * wip normalize * Update theme.vue * キャッシュのパス変換 * build * wip * wip * Update SearchMarker.vue * i18n.ts['key'] の形式が取り出せない問題のFix * build * 仮でpath入れ * 必ず絶対パスが使われるように * wip * 🎨 * storybookビルド時はcreateSearchIndexをしない * inliningの構造化 * format code * Update index.vue * wip * wip * 🎨 * wip * wip * wip * wip * wip * wip * wip * wip * clean up * wip * wip * wip * Update rollup-plugin-unwind-css-module-class-name.test.ts * Update navbar.vue * clean up * wip * wip * wip * wip * wip * Update preferences-backups.vue * Update common.ts * Update preferences.ts * wip * wip * wip * wip * Update MkPreferenceContainer.vue * Update MkPreferenceContainer.vue * Update MkPreferenceContainer.vue * enhance: 検索で上下矢印を使用することで検索結果を移動できるように * Update main-boot.ts * refactor * wip * Update sounds.vue * fix(frontend): PageWindowでSearchMarkerが動作するように * enhance(frontend): SearchMarkerの点滅を一定時間で止める * wip * lint fix * fix: 子要素監視が抜けていたのを修正 * アニメーションの回数はCSSで制御するように * refactor * enhance(frontend): 検索インデックス作成時のログを削減 * revert * fix * fix * Update preferences.ts * Update preferences.ts * wip * Update preferences.ts * wip * 🎨 * wip * Update MkPreferenceContainer.vue * wip * Update preferences.ts * wip * Update preferences.ts * Update preferences.ts * wip * wip * Update preferences.ts * wip * wip * Update preferences.ts * Update CHANGELOG.md * Update preferences.ts * Update deck-store.ts * deckStoreをdefaultStoreに統合 * wip * defaultStore -> store * Update profile.ts * wip * refactor * wip: plugin * plugin * plugin * plugin * Update plugin.ts * wip * Update plugin.vue * Update preferences.ts * Update main-boot.ts * wip * fix test * Update plugin.vue * Update plugin.vue * Update utility.ts * wip * wip * Update utility.ts * wip * wip * clean up * Update utility.ts --------- Co-authored-by: tai-cha Co-authored-by: taichan <40626578+tai-cha@users.noreply.github.com> Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> --- packages/frontend/src/boot/common.ts | 60 +-- packages/frontend/src/boot/main-boot.ts | 128 +++++- .../frontend/src/components/MkAutocomplete.vue | 13 +- packages/frontend/src/components/MkCaptcha.vue | 4 +- packages/frontend/src/components/MkChart.vue | 4 +- packages/frontend/src/components/MkCode.core.vue | 4 +- packages/frontend/src/components/MkCode.vue | 6 +- packages/frontend/src/components/MkContainer.vue | 10 +- packages/frontend/src/components/MkContextMenu.vue | 10 +- .../frontend/src/components/MkCropperDialog.vue | 8 +- .../src/components/MkDateSeparatedList.vue | 6 +- .../frontend/src/components/MkDrive.folder.vue | 12 +- packages/frontend/src/components/MkDrive.vue | 8 +- packages/frontend/src/components/MkEmojiPicker.vue | 22 +- .../src/components/MkEmojiPickerDialog.vue | 8 +- .../frontend/src/components/MkFoldableSection.vue | 10 +- packages/frontend/src/components/MkFolder.vue | 10 +- .../frontend/src/components/MkFollowButton.vue | 9 +- .../src/components/MkGalleryPostPreview.vue | 4 +- packages/frontend/src/components/MkHeatmap.vue | 4 +- .../frontend/src/components/MkHorizontalSwipe.vue | 11 +- .../frontend/src/components/MkImgWithBlurhash.vue | 16 +- packages/frontend/src/components/MkLaunchPad.vue | 4 +- packages/frontend/src/components/MkMediaAudio.vue | 18 +- packages/frontend/src/components/MkMediaBanner.vue | 4 +- packages/frontend/src/components/MkMediaImage.vue | 20 +- packages/frontend/src/components/MkMediaList.vue | 12 +- packages/frontend/src/components/MkMediaVideo.vue | 18 +- packages/frontend/src/components/MkMention.vue | 4 +- packages/frontend/src/components/MkModal.vue | 8 +- packages/frontend/src/components/MkNote.vue | 29 +- .../frontend/src/components/MkNoteDetailed.vue | 23 +- packages/frontend/src/components/MkNoteHeader.vue | 1 - .../frontend/src/components/MkNoteMediaGrid.vue | 18 +- .../frontend/src/components/MkNotifications.vue | 8 +- packages/frontend/src/components/MkPagination.vue | 17 +- packages/frontend/src/components/MkPostForm.vue | 44 +- .../frontend/src/components/MkPostFormAttaches.vue | 4 +- .../src/components/MkPreferenceContainer.vue | 94 +++++ .../src/components/MkReactionsViewer.reaction.vue | 10 +- .../frontend/src/components/MkReactionsViewer.vue | 12 +- .../frontend/src/components/MkRetentionHeatmap.vue | 4 +- .../src/components/MkRetentionLineChart.vue | 4 +- packages/frontend/src/components/MkTimeline.vue | 8 +- packages/frontend/src/components/MkToast.vue | 10 +- packages/frontend/src/components/MkTooltip.vue | 10 +- packages/frontend/src/components/MkUrlPreview.vue | 7 +- .../frontend/src/components/MkUrlPreviewPopup.vue | 4 +- packages/frontend/src/components/MkUserInfo.vue | 4 +- packages/frontend/src/components/MkUserPopup.vue | 12 +- .../frontend/src/components/MkUserSelectDialog.vue | 8 +- .../frontend/src/components/MkUserSetupDialog.vue | 12 +- .../MkVisitorDashboard.ActiveUsersChart.vue | 4 +- packages/frontend/src/components/MkWindow.vue | 10 +- .../frontend/src/components/MkYouTubePlayer.vue | 6 +- packages/frontend/src/components/global/MkAd.vue | 11 +- .../frontend/src/components/global/MkAvatar.vue | 13 +- .../src/components/global/MkCustomEmoji.vue | 4 +- .../frontend/src/components/global/MkEmoji.vue | 8 +- .../frontend/src/components/global/MkError.vue | 4 +- .../src/components/global/MkFooterSpacer.vue | 4 +- packages/frontend/src/components/global/MkMfm.ts | 20 +- .../src/components/global/MkPageHeader.tabs.vue | 22 +- .../frontend/src/components/global/RouterView.vue | 4 +- .../src/components/global/SearchMarker.vue | 2 +- packages/frontend/src/deck.ts | 306 ++++++++++++++ packages/frontend/src/directives/click-anime.ts | 4 +- packages/frontend/src/directives/ripple.ts | 4 +- packages/frontend/src/local-storage.ts | 7 +- packages/frontend/src/os.ts | 10 +- packages/frontend/src/pages/_error_.vue | 6 +- packages/frontend/src/pages/about-misskey.vue | 4 +- packages/frontend/src/pages/admin/abuses.vue | 6 +- .../admin/custom-emojis-manager.local.register.vue | 16 +- .../src/pages/admin/overview.active-users.vue | 4 +- .../src/pages/admin/overview.ap-requests.vue | 4 +- .../src/pages/admin/overview.instances.vue | 6 +- .../src/pages/admin/overview.moderators.vue | 6 +- .../src/pages/admin/overview.queue.chart.vue | 4 +- .../frontend/src/pages/admin/overview.stats.vue | 4 +- .../frontend/src/pages/admin/overview.users.vue | 6 +- .../frontend/src/pages/admin/queue.chart.chart.vue | 4 +- packages/frontend/src/pages/announcement.vue | 10 +- packages/frontend/src/pages/channel.vue | 8 +- .../frontend/src/pages/drop-and-fusion.game.vue | 28 +- packages/frontend/src/pages/flash/flash.vue | 6 +- packages/frontend/src/pages/gallery/post.vue | 8 +- packages/frontend/src/pages/install-extensions.vue | 8 +- packages/frontend/src/pages/my-lists/list.vue | 4 +- packages/frontend/src/pages/note.vue | 4 +- packages/frontend/src/pages/page.vue | 15 +- .../frontend/src/pages/settings/accessibility.vue | 79 ++-- .../frontend/src/pages/settings/appearance.vue | 231 +++++----- packages/frontend/src/pages/settings/deck.vue | 10 +- packages/frontend/src/pages/settings/drive.vue | 37 +- .../frontend/src/pages/settings/emoji-picker.vue | 94 +++-- .../frontend/src/pages/settings/import-export.vue | 4 +- packages/frontend/src/pages/settings/index.vue | 20 +- .../frontend/src/pages/settings/mute-block.vue | 4 +- packages/frontend/src/pages/settings/navbar.vue | 14 +- packages/frontend/src/pages/settings/other.vue | 13 +- .../frontend/src/pages/settings/plugin.install.vue | 2 +- packages/frontend/src/pages/settings/plugin.vue | 164 ++++---- .../src/pages/settings/preferences-backups.vue | 465 --------------------- .../frontend/src/pages/settings/preferences.vue | 275 +++++++----- packages/frontend/src/pages/settings/privacy.vue | 65 +-- packages/frontend/src/pages/settings/profile.vue | 4 +- packages/frontend/src/pages/settings/sounds.vue | 50 ++- .../src/pages/settings/statusbar.statusbar.vue | 12 +- packages/frontend/src/pages/settings/statusbar.vue | 8 +- .../frontend/src/pages/settings/theme.install.vue | 2 +- packages/frontend/src/pages/settings/theme.vue | 32 +- packages/frontend/src/pages/tag.vue | 10 +- packages/frontend/src/pages/theme-editor.vue | 15 +- packages/frontend/src/pages/timeline.vue | 45 +- .../frontend/src/pages/user/activity.following.vue | 4 +- .../frontend/src/pages/user/activity.notes.vue | 4 +- packages/frontend/src/pages/user/activity.pv.vue | 4 +- packages/frontend/src/pages/user/home.vue | 4 +- packages/frontend/src/pizzax.ts | 4 +- packages/frontend/src/plugin.ts | 223 ++++++++-- packages/frontend/src/preferences.ts | 81 ++++ packages/frontend/src/preferences/def.ts | 308 ++++++++++++++ packages/frontend/src/preferences/profile.ts | 236 +++++++++++ packages/frontend/src/preferences/store.ts | 92 ++++ packages/frontend/src/preferences/utility.ts | 222 ++++++++++ packages/frontend/src/router/definition.ts | 4 - .../src/scripts/autogen/settings-search-index.ts | 141 ++++--- packages/frontend/src/scripts/code-highlighter.ts | 32 +- packages/frontend/src/scripts/emoji-picker.ts | 4 +- .../frontend/src/scripts/get-drive-file-menu.ts | 6 +- packages/frontend/src/scripts/get-note-menu.ts | 15 +- packages/frontend/src/scripts/get-user-menu.ts | 13 +- packages/frontend/src/scripts/init-chart.ts | 4 +- packages/frontend/src/scripts/install-plugin.ts | 131 ------ packages/frontend/src/scripts/install-theme.ts | 38 -- packages/frontend/src/scripts/reaction-picker.ts | 4 +- packages/frontend/src/scripts/select-file.ts | 10 +- packages/frontend/src/scripts/sound.ts | 23 +- packages/frontend/src/scripts/theme.ts | 32 ++ packages/frontend/src/scripts/upload.ts | 8 +- packages/frontend/src/store.ts | 300 ++++++------- packages/frontend/src/theme-store.ts | 33 +- .../frontend/src/ui/_common_/PreferenceRestore.vue | 73 ++++ packages/frontend/src/ui/_common_/common.vue | 24 +- .../frontend/src/ui/_common_/navbar-for-mobile.vue | 4 +- packages/frontend/src/ui/_common_/navbar.vue | 11 +- packages/frontend/src/ui/_common_/statusbars.vue | 4 +- .../frontend/src/ui/_common_/stream-indicator.vue | 4 +- packages/frontend/src/ui/classic.header.vue | 7 +- packages/frontend/src/ui/classic.sidebar.vue | 9 +- packages/frontend/src/ui/classic.vue | 27 +- packages/frontend/src/ui/deck.vue | 54 +-- packages/frontend/src/ui/deck/antenna-column.vue | 10 +- packages/frontend/src/ui/deck/channel-column.vue | 8 +- packages/frontend/src/ui/deck/column.vue | 6 +- packages/frontend/src/ui/deck/deck-store.ts | 318 +------------- packages/frontend/src/ui/deck/direct-column.vue | 2 +- packages/frontend/src/ui/deck/list-column.vue | 10 +- packages/frontend/src/ui/deck/main-column.vue | 12 +- packages/frontend/src/ui/deck/mentions-column.vue | 2 +- .../frontend/src/ui/deck/notifications-column.vue | 4 +- .../frontend/src/ui/deck/role-timeline-column.vue | 8 +- packages/frontend/src/ui/deck/tl-column.vue | 7 +- .../frontend/src/ui/deck/tl-note-notification.ts | 2 +- packages/frontend/src/ui/deck/widgets-column.vue | 4 +- packages/frontend/src/ui/universal.vue | 44 +- packages/frontend/src/ui/universal.widgets.vue | 26 +- packages/frontend/src/ui/visitor.vue | 11 +- packages/frontend/src/widgets/WidgetFederation.vue | 6 +- packages/frontend/src/widgets/WidgetJobQueue.vue | 4 +- packages/frontend/src/widgets/WidgetMemo.vue | 8 +- packages/frontend/src/widgets/WidgetPhotos.vue | 4 +- packages/frontend/src/widgets/WidgetTrends.vue | 6 +- 174 files changed, 3313 insertions(+), 2443 deletions(-) create mode 100644 packages/frontend/src/components/MkPreferenceContainer.vue create mode 100644 packages/frontend/src/deck.ts delete mode 100644 packages/frontend/src/pages/settings/preferences-backups.vue create mode 100644 packages/frontend/src/preferences.ts create mode 100644 packages/frontend/src/preferences/def.ts create mode 100644 packages/frontend/src/preferences/profile.ts create mode 100644 packages/frontend/src/preferences/store.ts create mode 100644 packages/frontend/src/preferences/utility.ts delete mode 100644 packages/frontend/src/scripts/install-plugin.ts delete mode 100644 packages/frontend/src/scripts/install-theme.ts create mode 100644 packages/frontend/src/ui/_common_/PreferenceRestore.vue (limited to 'packages/frontend/src') diff --git a/packages/frontend/src/boot/common.ts b/packages/frontend/src/boot/common.ts index d09b98efe0..7b35d12a80 100644 --- a/packages/frontend/src/boot/common.ts +++ b/packages/frontend/src/boot/common.ts @@ -6,6 +6,8 @@ import { computed, watch, version as vueVersion } from 'vue'; import { compareVersions } from 'compare-versions'; import { version, lang, updateLocale, locale } from '@@/js/config.js'; +import defaultLightTheme from '@@/themes/l-light.json5'; +import defaultDarkTheme from '@@/themes/d-green-lime.json5'; import type { App } from 'vue'; import widgets from '@/widgets/index.js'; import directives from '@/directives/index.js'; @@ -14,7 +16,7 @@ import { applyTheme } from '@/scripts/theme.js'; import { isDeviceDarkmode } from '@/scripts/is-device-darkmode.js'; import { updateI18n, i18n } from '@/i18n.js'; import { $i, refreshAccount, login } from '@/account.js'; -import { defaultStore, ColdDeviceStorage } from '@/store.js'; +import { store } from '@/store.js'; import { fetchInstance, instance } from '@/instance.js'; import { deviceKind, updateDeviceKind } from '@/scripts/device-kind.js'; import { reloadChannel } from '@/scripts/unison-reload.js'; @@ -26,6 +28,7 @@ import { miLocalStorage } from '@/local-storage.js'; import { fetchCustomEmojis } from '@/custom-emojis.js'; import { setupRouter } from '@/router/main.js'; import { createMainRouter } from '@/router/definition.js'; +import { prefer } from '@/preferences.js'; export async function common(createVue: () => App) { console.info(`Misskey v${version}`); @@ -38,7 +41,7 @@ export async function common(createVue: () => App) { // eslint-disable-next-line @typescript-eslint/no-explicit-any (window as any).$i = $i; // eslint-disable-next-line @typescript-eslint/no-explicit-any - (window as any).$store = defaultStore; + (window as any).$store = store; window.addEventListener('error', event => { console.error(event); @@ -123,7 +126,7 @@ export async function common(createVue: () => App) { html.setAttribute('lang', lang); //#endregion - await defaultStore.ready; + await store.ready; await deckStore.ready; const fetchInstanceMetaPromise = fetchInstance(); @@ -151,56 +154,63 @@ export async function common(createVue: () => App) { //#endregion // NOTE: この処理は必ずクライアント更新チェック処理より後に来ること(テーマ再構築のため) - watch(defaultStore.reactiveState.darkMode, (darkMode) => { - applyTheme(darkMode ? ColdDeviceStorage.get('darkTheme') : ColdDeviceStorage.get('lightTheme')); + watch(store.reactiveState.darkMode, (darkMode) => { + applyTheme(darkMode + ? (prefer.s.darkTheme ?? defaultDarkTheme) + : (prefer.s.lightTheme ?? defaultLightTheme), + ); }, { immediate: miLocalStorage.getItem('theme') == null }); - document.documentElement.dataset.colorScheme = defaultStore.state.darkMode ? 'dark' : 'light'; + document.documentElement.dataset.colorScheme = store.state.darkMode ? 'dark' : 'light'; - const darkTheme = computed(ColdDeviceStorage.makeGetterSetter('darkTheme')); - const lightTheme = computed(ColdDeviceStorage.makeGetterSetter('lightTheme')); + const darkTheme = prefer.model('darkTheme'); + const lightTheme = prefer.model('lightTheme'); watch(darkTheme, (theme) => { - if (defaultStore.state.darkMode) { - applyTheme(theme); + if (store.state.darkMode) { + applyTheme(theme ?? defaultDarkTheme); } }); watch(lightTheme, (theme) => { - if (!defaultStore.state.darkMode) { - applyTheme(theme); + if (!store.state.darkMode) { + applyTheme(theme ?? defaultLightTheme); } }); //#region Sync dark mode - if (ColdDeviceStorage.get('syncDeviceDarkMode')) { - defaultStore.set('darkMode', isDeviceDarkmode()); + if (prefer.s.syncDeviceDarkMode) { + store.set('darkMode', isDeviceDarkmode()); } window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (mql) => { - if (ColdDeviceStorage.get('syncDeviceDarkMode')) { - defaultStore.set('darkMode', mql.matches); + if (prefer.s.syncDeviceDarkMode) { + store.set('darkMode', mql.matches); } }); //#endregion + if (prefer.s.darkTheme && store.state.darkMode) { + if (miLocalStorage.getItem('themeId') !== prefer.s.darkTheme.id) applyTheme(prefer.s.darkTheme); + } else if (prefer.s.lightTheme && !store.state.darkMode) { + if (miLocalStorage.getItem('themeId') !== prefer.s.lightTheme.id) applyTheme(prefer.s.lightTheme); + } + fetchInstanceMetaPromise.then(() => { - if (defaultStore.state.themeInitial) { - if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON.parse(instance.defaultLightTheme)); - if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON.parse(instance.defaultDarkTheme)); - defaultStore.set('themeInitial', false); - } + // TODO: instance.defaultLightTheme/instance.defaultDarkThemeが不正な形式だった場合のケア + if (prefer.s.lightTheme == null && instance.defaultLightTheme != null) prefer.set('lightTheme', JSON.parse(instance.defaultLightTheme)); + if (prefer.s.darkTheme == null && instance.defaultDarkTheme != null) prefer.set('darkTheme', JSON.parse(instance.defaultDarkTheme)); }); - watch(defaultStore.reactiveState.overridedDeviceKind, (kind) => { + watch(store.reactiveState.overridedDeviceKind, (kind) => { updateDeviceKind(kind); }, { immediate: true }); - watch(defaultStore.reactiveState.useBlurEffectForModal, v => { + watch(prefer.r.useBlurEffectForModal, v => { document.documentElement.style.setProperty('--MI-modalBgFilter', v ? 'blur(4px)' : 'none'); }, { immediate: true }); - watch(defaultStore.reactiveState.useBlurEffect, v => { + watch(prefer.r.useBlurEffect, v => { if (v) { document.documentElement.style.removeProperty('--MI-blur'); } else { @@ -214,7 +224,7 @@ export async function common(createVue: () => App) { navigator.wakeLock.request('screen'); } }); - if (defaultStore.state.keepScreenOn && 'wakeLock' in navigator) { + if (prefer.s.keepScreenOn && 'wakeLock' in navigator) { navigator.wakeLock.request('screen') .then(onVisibilityChange) .catch(() => { diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 3a43c6794b..0ebe55ed1d 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -5,26 +5,29 @@ import { createApp, defineAsyncComponent, markRaw } from 'vue'; import { ui } from '@@/js/config.js'; -import { common } from './common.js'; import * as Misskey from 'misskey-js'; +import { common } from './common.js'; import type { Component } from 'vue'; +import type { Keymap } from '@/scripts/hotkey.js'; import { i18n } from '@/i18n.js'; import { alert, confirm, popup, post, toast } from '@/os.js'; import { useStream } from '@/stream.js'; import * as sound from '@/scripts/sound.js'; import { $i, signout, updateAccountPartial } from '@/account.js'; import { instance } from '@/instance.js'; -import { ColdDeviceStorage, defaultStore } from '@/store.js'; +import { ColdDeviceStorage, store } from '@/store.js'; import { reactionPicker } from '@/scripts/reaction-picker.js'; import { miLocalStorage } from '@/local-storage.js'; import { claimAchievement, claimedAchievements } from '@/scripts/achievements.js'; import { initializeSw } from '@/scripts/initialize-sw.js'; -import { deckStore } from '@/ui/deck/deck-store.js'; import { emojiPicker } from '@/scripts/emoji-picker.js'; import { mainRouter } from '@/router/main.js'; import { makeHotkey } from '@/scripts/hotkey.js'; -import type { Keymap } from '@/scripts/hotkey.js'; import { addCustomEmoji, removeCustomEmojis, updateCustomEmojis } from '@/custom-emojis.js'; +import { prefer } from '@/preferences.js'; +import { misskeyApi } from '@/scripts/misskey-api.js'; +import { deckStore } from '@/ui/deck/deck-store.js'; +import { launchPlugin } from '@/plugin.js'; export async function mainBoot() { const { isClientUpdated } = await common(() => { @@ -34,7 +37,7 @@ export async function mainBoot() { if (!$i) uiStyle = 'visitor'; if (searchParams.has('zen')) uiStyle = 'zen'; - if (uiStyle === 'deck' && deckStore.state.useSimpleUiForNonRootPages && location.pathname !== '/') uiStyle = 'zen'; + if (uiStyle === 'deck' && prefer.s['deck.useSimpleUiForNonRootPages'] && location.pathname !== '/') uiStyle = 'zen'; if (searchParams.has('ui')) uiStyle = searchParams.get('ui'); @@ -73,9 +76,9 @@ export async function mainBoot() { let reloadDialogShowing = false; stream.on('_disconnected_', async () => { - if (defaultStore.state.serverDisconnectedBehavior === 'reload') { + if (prefer.s.serverDisconnectedBehavior === 'reload') { location.reload(); - } else if (defaultStore.state.serverDisconnectedBehavior === 'dialog') { + } else if (prefer.s.serverDisconnectedBehavior === 'dialog') { if (reloadDialogShowing) return; reloadDialogShowing = true; const { canceled } = await confirm({ @@ -102,18 +105,14 @@ export async function mainBoot() { removeCustomEmojis(emojiData.emojis); }); - for (const plugin of ColdDeviceStorage.get('plugins').filter(p => p.active)) { - import('@/plugin.js').then(async ({ install }) => { - // Workaround for https://bugs.webkit.org/show_bug.cgi?id=242740 - await new Promise(r => setTimeout(r, 0)); - install(plugin); - }); + for (const plugin of prefer.s.plugins.filter(p => p.active)) { + launchPlugin(plugin); } try { - if (defaultStore.state.enableSeasonalScreenEffect) { + if (prefer.s.enableSeasonalScreenEffect) { const month = new Date().getMonth() + 1; - if (defaultStore.state.hemisphere === 'S') { + if (prefer.s.hemisphere === 'S') { // ▼南半球 if (month === 7 || month === 8) { const SnowfallEffect = (await import('@/scripts/snowfall-effect.js')).SnowfallEffect; @@ -138,8 +137,99 @@ export async function mainBoot() { } if ($i) { - defaultStore.loaded.then(() => { - if (defaultStore.state.accountSetupWizard !== -1) { + store.loaded.then(async () => { + // prefereces migration + // TODO: そのうち消す + if (store.state.menu.length > 0) { + const themes = await misskeyApi('i/registry/get', { scope: ['client'], key: 'themes' }).catch(() => []); + if (themes.length > 0) { + prefer.set('themes', themes); + } + const plugins = ColdDeviceStorage.get('plugins'); + prefer.set('plugins', plugins.map(p => ({ + ...p, + installId: (p as any).id, + id: undefined, + }))); + prefer.set('lightTheme', ColdDeviceStorage.get('lightTheme')); + prefer.set('darkTheme', ColdDeviceStorage.get('darkTheme')); + prefer.set('syncDeviceDarkMode', ColdDeviceStorage.get('syncDeviceDarkMode')); + prefer.set('keepCw', store.state.keepCw); + prefer.set('collapseRenotes', store.state.collapseRenotes); + prefer.set('rememberNoteVisibility', store.state.rememberNoteVisibility); + prefer.set('uploadFolder', store.state.uploadFolder); + prefer.set('keepOriginalUploading', store.state.keepOriginalUploading); + prefer.set('menu', store.state.menu); + prefer.set('statusbars', store.state.statusbars); + prefer.set('pinnedUserLists', store.state.pinnedUserLists); + prefer.set('serverDisconnectedBehavior', store.state.serverDisconnectedBehavior); + prefer.set('nsfw', store.state.nsfw); + prefer.set('highlightSensitiveMedia', store.state.highlightSensitiveMedia); + prefer.set('animation', store.state.animation); + prefer.set('animatedMfm', store.state.animatedMfm); + prefer.set('advancedMfm', store.state.advancedMfm); + prefer.set('showReactionsCount', store.state.showReactionsCount); + prefer.set('enableQuickAddMfmFunction', store.state.enableQuickAddMfmFunction); + prefer.set('loadRawImages', store.state.loadRawImages); + prefer.set('imageNewTab', store.state.imageNewTab); + prefer.set('disableShowingAnimatedImages', store.state.disableShowingAnimatedImages); + prefer.set('emojiStyle', store.state.emojiStyle); + prefer.set('menuStyle', store.state.menuStyle); + prefer.set('useBlurEffectForModal', store.state.useBlurEffectForModal); + prefer.set('useBlurEffect', store.state.useBlurEffect); + prefer.set('showFixedPostForm', store.state.showFixedPostForm); + prefer.set('showFixedPostFormInChannel', store.state.showFixedPostFormInChannel); + prefer.set('enableInfiniteScroll', store.state.enableInfiniteScroll); + prefer.set('useReactionPickerForContextMenu', store.state.useReactionPickerForContextMenu); + prefer.set('showGapBetweenNotesInTimeline', store.state.showGapBetweenNotesInTimeline); + prefer.set('instanceTicker', store.state.instanceTicker); + prefer.set('emojiPickerScale', store.state.emojiPickerScale); + prefer.set('emojiPickerWidth', store.state.emojiPickerWidth); + prefer.set('emojiPickerHeight', store.state.emojiPickerHeight); + prefer.set('emojiPickerStyle', store.state.emojiPickerStyle); + prefer.set('reportError', store.state.reportError); + prefer.set('squareAvatars', store.state.squareAvatars); + prefer.set('showAvatarDecorations', store.state.showAvatarDecorations); + prefer.set('numberOfPageCache', store.state.numberOfPageCache); + prefer.set('showNoteActionsOnlyHover', store.state.showNoteActionsOnlyHover); + prefer.set('showClipButtonInNoteFooter', store.state.showClipButtonInNoteFooter); + prefer.set('reactionsDisplaySize', store.state.reactionsDisplaySize); + prefer.set('limitWidthOfReaction', store.state.limitWidthOfReaction); + prefer.set('forceShowAds', store.state.forceShowAds); + prefer.set('aiChanMode', store.state.aiChanMode); + prefer.set('devMode', store.state.devMode); + prefer.set('mediaListWithOneImageAppearance', store.state.mediaListWithOneImageAppearance); + prefer.set('notificationPosition', store.state.notificationPosition); + prefer.set('notificationStackAxis', store.state.notificationStackAxis); + prefer.set('enableCondensedLine', store.state.enableCondensedLine); + prefer.set('keepScreenOn', store.state.keepScreenOn); + prefer.set('disableStreamingTimeline', store.state.disableStreamingTimeline); + prefer.set('useGroupedNotifications', store.state.useGroupedNotifications); + prefer.set('dataSaver', store.state.dataSaver); + prefer.set('enableSeasonalScreenEffect', store.state.enableSeasonalScreenEffect); + prefer.set('enableHorizontalSwipe', store.state.enableHorizontalSwipe); + prefer.set('useNativeUiForVideoAudioPlayer', store.state.useNativeUIForVideoAudioPlayer); + prefer.set('keepOriginalFilename', store.state.keepOriginalFilename); + prefer.set('alwaysConfirmFollow', store.state.alwaysConfirmFollow); + prefer.set('confirmWhenRevealingSensitiveMedia', store.state.confirmWhenRevealingSensitiveMedia); + prefer.set('contextMenu', store.state.contextMenu); + prefer.set('skipNoteRender', store.state.skipNoteRender); + prefer.set('showSoftWordMutedWord', store.state.showSoftWordMutedWord); + prefer.set('confirmOnReact', store.state.confirmOnReact); + prefer.set('sound.masterVolume', store.state.sound_masterVolume); + prefer.set('sound.notUseSound', store.state.sound_notUseSound); + prefer.set('sound.useSoundOnlyWhenActive', store.state.sound_useSoundOnlyWhenActive); + prefer.set('sound.on.note', store.state.sound_note as any); + prefer.set('sound.on.noteMy', store.state.sound_noteMy as any); + prefer.set('sound.on.notification', store.state.sound_notification as any); + prefer.set('sound.on.reaction', store.state.sound_reaction as any); + store.set('deck.profile', deckStore.state.profile); + store.set('deck.columns', deckStore.state.columns); + store.set('deck.layout', deckStore.state.layout); + store.set('menu', []); + } + + if (store.state.accountSetupWizard !== -1) { const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, { closed: () => dispose(), }); @@ -154,7 +244,7 @@ export async function mainBoot() { }); } - function onAnnouncementCreated (ev: { announcement: Misskey.entities.Announcement }) { + function onAnnouncementCreated(ev: { announcement: Misskey.entities.Announcement }) { const announcement = ev.announcement; if (announcement.display === 'dialog') { const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { @@ -412,7 +502,7 @@ export async function mainBoot() { post(); }, 'd': () => { - defaultStore.set('darkMode', !defaultStore.state.darkMode); + store.set('darkMode', !store.state.darkMode); }, 's': () => { mainRouter.push('/search'); diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue index 33495c8af6..1a68353331 100644 --- a/packages/frontend/src/components/MkAutocomplete.vue +++ b/packages/frontend/src/components/MkAutocomplete.vue @@ -54,17 +54,18 @@ import contains from '@/scripts/contains.js'; import { acct } from '@/filters/user.js'; import * as os from '@/os.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; -import { defaultStore } from '@/store.js'; +import { store } from '@/store.js'; import { i18n } from '@/i18n.js'; import { miLocalStorage } from '@/local-storage.js'; import { customEmojis } from '@/custom-emojis.js'; import { searchEmoji } from '@/scripts/search-emoji.js'; +import { prefer } from '@/preferences.js'; const lib = emojilist.filter(x => x.category !== 'flags'); const emojiDb = computed(() => { //#region Unicode Emoji - const char2path = defaultStore.reactiveState.emojiStyle.value === 'twemoji' ? char2twemojiFilePath : char2fluentEmojiFilePath; + const char2path = prefer.r.emojiStyle.value === 'twemoji' ? char2twemojiFilePath : char2fluentEmojiFilePath; const unicodeEmojiDB: EmojiDef[] = lib.map(x => ({ emoji: x.char, @@ -72,7 +73,7 @@ const emojiDb = computed(() => { url: char2path(x.char), })); - for (const index of Object.values(defaultStore.state.additionalUnicodeEmojiIndexes)) { + for (const index of Object.values(store.state.additionalUnicodeEmojiIndexes)) { for (const [emoji, keywords] of Object.entries(index)) { for (const k of keywords) { unicodeEmojiDB.push({ @@ -154,10 +155,10 @@ function complete(type: string, value: any) { emit('done', { type, value }); emit('closed'); if (type === 'emoji') { - let recents = defaultStore.state.recentlyUsedEmojis; + let recents = store.state.recentlyUsedEmojis; recents = recents.filter((emoji: any) => emoji !== value); recents.unshift(value); - defaultStore.set('recentlyUsedEmojis', recents.splice(0, 32)); + store.set('recentlyUsedEmojis', recents.splice(0, 32)); } } @@ -237,7 +238,7 @@ function exec() { } else if (props.type === 'emoji') { if (!props.q || props.q === '') { // 最近使った絵文字をサジェスト - emojis.value = defaultStore.state.recentlyUsedEmojis.map(emoji => emojiDb.value.find(dbEmoji => dbEmoji.emoji === emoji)).filter(x => x) as EmojiDef[]; + emojis.value = store.state.recentlyUsedEmojis.map(emoji => emojiDb.value.find(dbEmoji => dbEmoji.emoji === emoji)).filter(x => x) as EmojiDef[]; return; } diff --git a/packages/frontend/src/components/MkCaptcha.vue b/packages/frontend/src/components/MkCaptcha.vue index 134f8226d4..05b8264a83 100644 --- a/packages/frontend/src/components/MkCaptcha.vue +++ b/packages/frontend/src/components/MkCaptcha.vue @@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only + + diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue index 41e475eade..2e453aeb8f 100644 --- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue +++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue @@ -8,11 +8,11 @@ SPDX-License-Identifier: AGPL-3.0-only ref="buttonEl" v-ripple="canToggle" class="_button" - :class="[$style.root, { [$style.reacted]: note.myReaction == reaction, [$style.canToggle]: canToggle, [$style.small]: defaultStore.state.reactionsDisplaySize === 'small', [$style.large]: defaultStore.state.reactionsDisplaySize === 'large' }]" + :class="[$style.root, { [$style.reacted]: note.myReaction == reaction, [$style.canToggle]: canToggle, [$style.small]: prefer.s.reactionsDisplaySize === 'small', [$style.large]: prefer.s.reactionsDisplaySize === 'large' }]" @click="toggleReaction()" @contextmenu.prevent.stop="menu" > - + {{ count }} @@ -30,11 +30,11 @@ import { useTooltip } from '@/scripts/use-tooltip.js'; import { $i } from '@/account.js'; import MkReactionEffect from '@/components/MkReactionEffect.vue'; import { claimAchievement } from '@/scripts/achievements.js'; -import { defaultStore } from '@/store.js'; import { i18n } from '@/i18n.js'; import * as sound from '@/scripts/sound.js'; import { checkReactionPermissions } from '@/scripts/check-reaction-permissions.js'; import { customEmojisMap } from '@/custom-emojis.js'; +import { prefer } from '@/preferences.js'; const props = defineProps<{ reaction: string; @@ -90,7 +90,7 @@ async function toggleReaction() { } }); } else { - if (defaultStore.state.confirmOnReact) { + if (prefer.s.confirmOnReact) { const confirm = await os.confirm({ type: 'question', text: i18n.tsx.reactAreYouSure({ emoji: props.reaction.replace('@.', '') }), @@ -135,7 +135,7 @@ async function menu(ev) { } function anime() { - if (document.hidden || !defaultStore.state.animation || buttonEl.value == null) return; + if (document.hidden || !prefer.s.animation || buttonEl.value == null) return; const rect = buttonEl.value.getBoundingClientRect(); const x = rect.left + 16; diff --git a/packages/frontend/src/components/MkReactionsViewer.vue b/packages/frontend/src/components/MkReactionsViewer.vue index 63b202f9f3..bb60db8d34 100644 --- a/packages/frontend/src/components/MkReactionsViewer.vue +++ b/packages/frontend/src/components/MkReactionsViewer.vue @@ -5,11 +5,11 @@ SPDX-License-Identifier: AGPL-3.0-only