diff --git a/locales/index.d.ts b/locales/index.d.ts index 9ef6f9aa39..560335bf35 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -5350,6 +5350,14 @@ export interface Locale extends ILocale { * チャット */ "chat": string; + /** + * 旧設定情報を移行 + */ + "migrateOldSettings": string; + /** + * 通常これは自動で行われていますが、何らかの理由により上手く移行されなかった場合は手動で移行処理をトリガーできます。現在の設定情報は上書きされます。 + */ + "migrateOldSettings_description": string; "_chat": { /** * まだメッセージはありません diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index fccf24e759..9b4d74fbfb 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1333,6 +1333,8 @@ postForm: "投稿フォーム" textCount: "文字数" information: "情報" chat: "チャット" +migrateOldSettings: "旧設定情報を移行" +migrateOldSettings_description: "通常これは自動で行われていますが、何らかの理由により上手く移行されなかった場合は手動で移行処理をトリガーできます。現在の設定情報は上書きされます。" _chat: noMessagesYet: "まだメッセージはありません" diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 19371dff0e..58873f684e 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -6,19 +6,17 @@ import { createApp, defineAsyncComponent, markRaw } from 'vue'; import { ui } from '@@/js/config.js'; import * as Misskey from 'misskey-js'; -import { v4 as uuid } from 'uuid'; import { compareVersions } from 'compare-versions'; import { common } from './common.js'; import type { Component } from 'vue'; import type { Keymap } from '@/utility/hotkey.js'; -import type { DeckProfile } from '@/deck.js'; import { i18n } from '@/i18n.js'; -import { alert, confirm, popup, post, toast } from '@/os.js'; +import { alert, confirm, popup, post } from '@/os.js'; import { useStream } from '@/stream.js'; import * as sound from '@/utility/sound.js'; import { $i } from '@/i.js'; import { instance } from '@/instance.js'; -import { ColdDeviceStorage, store } from '@/store.js'; +import { store } from '@/store.js'; import { reactionPicker } from '@/utility/reaction-picker.js'; import { miLocalStorage } from '@/local-storage.js'; import { claimAchievement, claimedAchievements } from '@/utility/achievements.js'; @@ -28,12 +26,10 @@ import { mainRouter } from '@/router.js'; import { makeHotkey } from '@/utility/hotkey.js'; import { addCustomEmoji, removeCustomEmojis, updateCustomEmojis } from '@/custom-emojis.js'; import { prefer } from '@/preferences.js'; -import { misskeyApi } from '@/utility/misskey-api.js'; -import { deckStore } from '@/ui/deck/deck-store.js'; import { launchPlugins } from '@/plugin.js'; -import { unisonReload } from '@/utility/unison-reload.js'; import { updateCurrentAccountPartial } from '@/accounts.js'; import { signout } from '@/signout.js'; +import { migrateOldSettings } from '@/pref-migrate.js'; export async function mainBoot() { const { isClientUpdated, lastVersion } = await common(() => { @@ -82,132 +78,7 @@ export async function mainBoot() { if (lastVersion && (compareVersions('2025.3.2-alpha.0', lastVersion) === 1)) { console.log('Preferences migration'); - store.loaded.then(async () => { - const themes = await misskeyApi('i/registry/get', { scope: ['client'], key: 'themes' }).catch(() => []); - if (themes.length > 0) { - prefer.commit('themes', themes); - } - - const plugins = ColdDeviceStorage.get('plugins'); - prefer.commit('plugins', plugins.map(p => ({ - ...p, - installId: (p as any).id, - id: undefined, - }))); - - prefer.commit('deck.profile', deckStore.s.profile); - misskeyApi('i/registry/keys', { - scope: ['client', 'deck', 'profiles'], - }).then(async keys => { - const profiles: DeckProfile[] = []; - for (const key of keys) { - const deck = await misskeyApi('i/registry/get', { - scope: ['client', 'deck', 'profiles'], - key: key, - }); - profiles.push({ - id: uuid(), - name: key, - columns: deck.columns, - layout: deck.layout, - }); - } - prefer.commit('deck.profiles', profiles); - }); - - prefer.commit('lightTheme', ColdDeviceStorage.get('lightTheme')); - prefer.commit('darkTheme', ColdDeviceStorage.get('darkTheme')); - prefer.commit('syncDeviceDarkMode', ColdDeviceStorage.get('syncDeviceDarkMode')); - prefer.commit('emojiPalettes', [{ - id: 'reactions', - name: '', - emojis: store.s.reactions, - }, { - id: 'pinnedEmojis', - name: '', - emojis: store.s.pinnedEmojis, - }]); - prefer.commit('emojiPaletteForMain', 'pinnedEmojis'); - prefer.commit('emojiPaletteForReaction', 'reactions'); - prefer.commit('overridedDeviceKind', store.s.overridedDeviceKind); - prefer.commit('widgets', store.s.widgets); - prefer.commit('keepCw', store.s.keepCw); - prefer.commit('collapseRenotes', store.s.collapseRenotes); - prefer.commit('rememberNoteVisibility', store.s.rememberNoteVisibility); - prefer.commit('uploadFolder', store.s.uploadFolder); - prefer.commit('keepOriginalUploading', store.s.keepOriginalUploading); - prefer.commit('menu', store.s.menu); - prefer.commit('statusbars', store.s.statusbars); - prefer.commit('pinnedUserLists', store.s.pinnedUserLists); - prefer.commit('serverDisconnectedBehavior', store.s.serverDisconnectedBehavior); - prefer.commit('nsfw', store.s.nsfw); - prefer.commit('highlightSensitiveMedia', store.s.highlightSensitiveMedia); - prefer.commit('animation', store.s.animation); - prefer.commit('animatedMfm', store.s.animatedMfm); - prefer.commit('advancedMfm', store.s.advancedMfm); - prefer.commit('showReactionsCount', store.s.showReactionsCount); - prefer.commit('enableQuickAddMfmFunction', store.s.enableQuickAddMfmFunction); - prefer.commit('loadRawImages', store.s.loadRawImages); - prefer.commit('imageNewTab', store.s.imageNewTab); - prefer.commit('disableShowingAnimatedImages', store.s.disableShowingAnimatedImages); - prefer.commit('emojiStyle', store.s.emojiStyle); - prefer.commit('menuStyle', store.s.menuStyle); - prefer.commit('useBlurEffectForModal', store.s.useBlurEffectForModal); - prefer.commit('useBlurEffect', store.s.useBlurEffect); - prefer.commit('showFixedPostForm', store.s.showFixedPostForm); - prefer.commit('showFixedPostFormInChannel', store.s.showFixedPostFormInChannel); - prefer.commit('enableInfiniteScroll', store.s.enableInfiniteScroll); - prefer.commit('useReactionPickerForContextMenu', store.s.useReactionPickerForContextMenu); - prefer.commit('showGapBetweenNotesInTimeline', store.s.showGapBetweenNotesInTimeline); - prefer.commit('instanceTicker', store.s.instanceTicker); - prefer.commit('emojiPickerScale', store.s.emojiPickerScale); - prefer.commit('emojiPickerWidth', store.s.emojiPickerWidth); - prefer.commit('emojiPickerHeight', store.s.emojiPickerHeight); - prefer.commit('emojiPickerStyle', store.s.emojiPickerStyle); - prefer.commit('reportError', store.s.reportError); - prefer.commit('squareAvatars', store.s.squareAvatars); - prefer.commit('showAvatarDecorations', store.s.showAvatarDecorations); - prefer.commit('numberOfPageCache', store.s.numberOfPageCache); - prefer.commit('showNoteActionsOnlyHover', store.s.showNoteActionsOnlyHover); - prefer.commit('showClipButtonInNoteFooter', store.s.showClipButtonInNoteFooter); - prefer.commit('reactionsDisplaySize', store.s.reactionsDisplaySize); - prefer.commit('limitWidthOfReaction', store.s.limitWidthOfReaction); - prefer.commit('forceShowAds', store.s.forceShowAds); - prefer.commit('aiChanMode', store.s.aiChanMode); - prefer.commit('devMode', store.s.devMode); - prefer.commit('mediaListWithOneImageAppearance', store.s.mediaListWithOneImageAppearance); - prefer.commit('notificationPosition', store.s.notificationPosition); - prefer.commit('notificationStackAxis', store.s.notificationStackAxis); - prefer.commit('enableCondensedLine', store.s.enableCondensedLine); - prefer.commit('keepScreenOn', store.s.keepScreenOn); - prefer.commit('disableStreamingTimeline', store.s.disableStreamingTimeline); - prefer.commit('useGroupedNotifications', store.s.useGroupedNotifications); - prefer.commit('dataSaver', store.s.dataSaver); - prefer.commit('enableSeasonalScreenEffect', store.s.enableSeasonalScreenEffect); - prefer.commit('enableHorizontalSwipe', store.s.enableHorizontalSwipe); - prefer.commit('useNativeUiForVideoAudioPlayer', store.s.useNativeUIForVideoAudioPlayer); - prefer.commit('keepOriginalFilename', store.s.keepOriginalFilename); - prefer.commit('alwaysConfirmFollow', store.s.alwaysConfirmFollow); - prefer.commit('confirmWhenRevealingSensitiveMedia', store.s.confirmWhenRevealingSensitiveMedia); - prefer.commit('contextMenu', store.s.contextMenu); - prefer.commit('skipNoteRender', store.s.skipNoteRender); - prefer.commit('showSoftWordMutedWord', store.s.showSoftWordMutedWord); - prefer.commit('confirmOnReact', store.s.confirmOnReact); - prefer.commit('defaultFollowWithReplies', store.s.defaultWithReplies); - prefer.commit('sound.masterVolume', store.s.sound_masterVolume); - prefer.commit('sound.notUseSound', store.s.sound_notUseSound); - prefer.commit('sound.useSoundOnlyWhenActive', store.s.sound_useSoundOnlyWhenActive); - prefer.commit('sound.on.note', store.s.sound_note as any); - prefer.commit('sound.on.noteMy', store.s.sound_noteMy as any); - prefer.commit('sound.on.notification', store.s.sound_notification as any); - prefer.commit('sound.on.reaction', store.s.sound_reaction as any); - prefer.commit('defaultNoteVisibility', store.s.defaultNoteVisibility); - prefer.commit('defaultNoteLocalOnly', store.s.defaultNoteLocalOnly); - - window.setTimeout(() => { - unisonReload(); - }, 5000); - }); + migrateOldSettings(); } } diff --git a/packages/frontend/src/pages/settings/other.vue b/packages/frontend/src/pages/settings/other.vue index d81c6fc93d..6736572e0b 100644 --- a/packages/frontend/src/pages/settings/other.vue +++ b/packages/frontend/src/pages/settings/other.vue @@ -115,6 +115,13 @@ SPDX-License-Identifier: AGPL-3.0-only <hr> <FormLink to="/registry"><template #icon><i class="ti ti-adjustments"></i></template>{{ i18n.ts.registry }}</FormLink> + + <hr> + + <FormSlot> + <MkButton danger @click="migrate"><i class="ti ti-refresh"></i> {{ i18n.ts.migrateOldSettings }}</MkButton> + <template #caption>{{ i18n.ts.migrateOldSettings_description }}</template> + </FormSlot> </div> </SearchMarker> </template> @@ -128,6 +135,7 @@ import MkFolder from '@/components/MkFolder.vue'; import FormInfo from '@/components/MkInfo.vue'; import MkKeyValue from '@/components/MkKeyValue.vue'; import MkButton from '@/components/MkButton.vue'; +import FormSlot from '@/components/form/slot.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; import { ensureSignin } from '@/i.js'; @@ -138,6 +146,7 @@ import FormSection from '@/components/form/section.vue'; import { prefer } from '@/preferences.js'; import MkRolePreview from '@/components/MkRolePreview.vue'; import { signout } from '@/signout.js'; +import { migrateOldSettings } from '@/pref-migrate.js'; const $i = ensureSignin(); @@ -175,6 +184,11 @@ async function deleteAccount() { await signout(); } +function migrate() { + os.waiting(); + migrateOldSettings(); +} + const headerActions = computed(() => []); const headerTabs = computed(() => []); diff --git a/packages/frontend/src/pref-migrate.ts b/packages/frontend/src/pref-migrate.ts new file mode 100644 index 0000000000..beeaac8383 --- /dev/null +++ b/packages/frontend/src/pref-migrate.ts @@ -0,0 +1,142 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { v4 as uuid } from 'uuid'; +import type { DeckProfile } from '@/deck.js'; +import { ColdDeviceStorage, store } from '@/store.js'; +import { prefer } from '@/preferences.js'; +import { misskeyApi } from '@/utility/misskey-api.js'; +import { deckStore } from '@/ui/deck/deck-store.js'; +import { unisonReload } from '@/utility/unison-reload.js'; + +// TODO: そのうち消す +export function migrateOldSettings() { + store.loaded.then(async () => { + const themes = await misskeyApi('i/registry/get', { scope: ['client'], key: 'themes' }).catch(() => []); + if (themes.length > 0) { + prefer.commit('themes', themes); + } + + const plugins = ColdDeviceStorage.get('plugins'); + prefer.commit('plugins', plugins.map(p => ({ + ...p, + installId: (p as any).id, + id: undefined, + }))); + + prefer.commit('deck.profile', deckStore.s.profile); + misskeyApi('i/registry/keys', { + scope: ['client', 'deck', 'profiles'], + }).then(async keys => { + const profiles: DeckProfile[] = []; + for (const key of keys) { + const deck = await misskeyApi('i/registry/get', { + scope: ['client', 'deck', 'profiles'], + key: key, + }); + profiles.push({ + id: uuid(), + name: key, + columns: deck.columns, + layout: deck.layout, + }); + } + prefer.commit('deck.profiles', profiles); + }); + + prefer.commit('lightTheme', ColdDeviceStorage.get('lightTheme')); + prefer.commit('darkTheme', ColdDeviceStorage.get('darkTheme')); + prefer.commit('syncDeviceDarkMode', ColdDeviceStorage.get('syncDeviceDarkMode')); + prefer.commit('emojiPalettes', [{ + id: 'reactions', + name: '', + emojis: store.s.reactions, + }, { + id: 'pinnedEmojis', + name: '', + emojis: store.s.pinnedEmojis, + }]); + prefer.commit('emojiPaletteForMain', 'pinnedEmojis'); + prefer.commit('emojiPaletteForReaction', 'reactions'); + prefer.commit('overridedDeviceKind', store.s.overridedDeviceKind); + prefer.commit('widgets', store.s.widgets); + prefer.commit('keepCw', store.s.keepCw); + prefer.commit('collapseRenotes', store.s.collapseRenotes); + prefer.commit('rememberNoteVisibility', store.s.rememberNoteVisibility); + prefer.commit('uploadFolder', store.s.uploadFolder); + prefer.commit('keepOriginalUploading', store.s.keepOriginalUploading); + prefer.commit('menu', store.s.menu); + prefer.commit('statusbars', store.s.statusbars); + prefer.commit('pinnedUserLists', store.s.pinnedUserLists); + prefer.commit('serverDisconnectedBehavior', store.s.serverDisconnectedBehavior); + prefer.commit('nsfw', store.s.nsfw); + prefer.commit('highlightSensitiveMedia', store.s.highlightSensitiveMedia); + prefer.commit('animation', store.s.animation); + prefer.commit('animatedMfm', store.s.animatedMfm); + prefer.commit('advancedMfm', store.s.advancedMfm); + prefer.commit('showReactionsCount', store.s.showReactionsCount); + prefer.commit('enableQuickAddMfmFunction', store.s.enableQuickAddMfmFunction); + prefer.commit('loadRawImages', store.s.loadRawImages); + prefer.commit('imageNewTab', store.s.imageNewTab); + prefer.commit('disableShowingAnimatedImages', store.s.disableShowingAnimatedImages); + prefer.commit('emojiStyle', store.s.emojiStyle); + prefer.commit('menuStyle', store.s.menuStyle); + prefer.commit('useBlurEffectForModal', store.s.useBlurEffectForModal); + prefer.commit('useBlurEffect', store.s.useBlurEffect); + prefer.commit('showFixedPostForm', store.s.showFixedPostForm); + prefer.commit('showFixedPostFormInChannel', store.s.showFixedPostFormInChannel); + prefer.commit('enableInfiniteScroll', store.s.enableInfiniteScroll); + prefer.commit('useReactionPickerForContextMenu', store.s.useReactionPickerForContextMenu); + prefer.commit('showGapBetweenNotesInTimeline', store.s.showGapBetweenNotesInTimeline); + prefer.commit('instanceTicker', store.s.instanceTicker); + prefer.commit('emojiPickerScale', store.s.emojiPickerScale); + prefer.commit('emojiPickerWidth', store.s.emojiPickerWidth); + prefer.commit('emojiPickerHeight', store.s.emojiPickerHeight); + prefer.commit('emojiPickerStyle', store.s.emojiPickerStyle); + prefer.commit('reportError', store.s.reportError); + prefer.commit('squareAvatars', store.s.squareAvatars); + prefer.commit('showAvatarDecorations', store.s.showAvatarDecorations); + prefer.commit('numberOfPageCache', store.s.numberOfPageCache); + prefer.commit('showNoteActionsOnlyHover', store.s.showNoteActionsOnlyHover); + prefer.commit('showClipButtonInNoteFooter', store.s.showClipButtonInNoteFooter); + prefer.commit('reactionsDisplaySize', store.s.reactionsDisplaySize); + prefer.commit('limitWidthOfReaction', store.s.limitWidthOfReaction); + prefer.commit('forceShowAds', store.s.forceShowAds); + prefer.commit('aiChanMode', store.s.aiChanMode); + prefer.commit('devMode', store.s.devMode); + prefer.commit('mediaListWithOneImageAppearance', store.s.mediaListWithOneImageAppearance); + prefer.commit('notificationPosition', store.s.notificationPosition); + prefer.commit('notificationStackAxis', store.s.notificationStackAxis); + prefer.commit('enableCondensedLine', store.s.enableCondensedLine); + prefer.commit('keepScreenOn', store.s.keepScreenOn); + prefer.commit('disableStreamingTimeline', store.s.disableStreamingTimeline); + prefer.commit('useGroupedNotifications', store.s.useGroupedNotifications); + prefer.commit('dataSaver', store.s.dataSaver); + prefer.commit('enableSeasonalScreenEffect', store.s.enableSeasonalScreenEffect); + prefer.commit('enableHorizontalSwipe', store.s.enableHorizontalSwipe); + prefer.commit('useNativeUiForVideoAudioPlayer', store.s.useNativeUIForVideoAudioPlayer); + prefer.commit('keepOriginalFilename', store.s.keepOriginalFilename); + prefer.commit('alwaysConfirmFollow', store.s.alwaysConfirmFollow); + prefer.commit('confirmWhenRevealingSensitiveMedia', store.s.confirmWhenRevealingSensitiveMedia); + prefer.commit('contextMenu', store.s.contextMenu); + prefer.commit('skipNoteRender', store.s.skipNoteRender); + prefer.commit('showSoftWordMutedWord', store.s.showSoftWordMutedWord); + prefer.commit('confirmOnReact', store.s.confirmOnReact); + prefer.commit('defaultFollowWithReplies', store.s.defaultWithReplies); + prefer.commit('sound.masterVolume', store.s.sound_masterVolume); + prefer.commit('sound.notUseSound', store.s.sound_notUseSound); + prefer.commit('sound.useSoundOnlyWhenActive', store.s.sound_useSoundOnlyWhenActive); + prefer.commit('sound.on.note', store.s.sound_note as any); + prefer.commit('sound.on.noteMy', store.s.sound_noteMy as any); + prefer.commit('sound.on.notification', store.s.sound_notification as any); + prefer.commit('sound.on.reaction', store.s.sound_reaction as any); + prefer.commit('defaultNoteVisibility', store.s.defaultNoteVisibility); + prefer.commit('defaultNoteLocalOnly', store.s.defaultNoteLocalOnly); + + window.setTimeout(() => { + unisonReload(); + }, 5000); + }); +}