Refine preferences (#15597)

* 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 41bffd3a13.

* 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 <dev@taichan.site>
Co-authored-by: taichan <40626578+tai-cha@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
This commit is contained in:
syuilo
2025-03-09 12:34:08 +09:00
committed by GitHub
parent 05cdc095c0
commit d30ddd4c2e
181 changed files with 3437 additions and 2463 deletions

View File

@@ -5,15 +5,15 @@
import { markRaw, ref } from 'vue';
import * as Misskey from 'misskey-js';
import { hemisphere } from '@@/js/intl-const.js';
import lightTheme from '@@/themes/l-light.json5';
import darkTheme from '@@/themes/d-green-lime.json5';
import type { SoundType } from '@/scripts/sound.js';
import type { Ast } from '@syuilo/aiscript';
import { hemisphere } from '@@/js/intl-const.js';
import type { DeviceKind } from '@/scripts/device-kind.js';
import { DEFAULT_DEVICE_KIND } from '@/scripts/device-kind.js';
import type { Plugin } from '@/plugin.js';
import type { Column } from '@/deck.js';
import { miLocalStorage } from '@/local-storage.js';
import { Storage } from '@/pizzax.js';
import { DEFAULT_DEVICE_KIND } from '@/scripts/device-kind.js';
interface PostFormAction {
title: string,
@@ -42,22 +42,6 @@ interface PageViewInterruptor {
handler: (page: Misskey.entities.Page) => unknown;
}
/** サウンド設定 */
export type SoundStore = {
type: Exclude<SoundType, '_driveFile_'>;
volume: number;
} | {
type: '_driveFile_';
/** ドライブのファイルID */
fileId: string;
/** ファイルURLこちらが優先される */
fileUrl: string;
volume: number;
};
export const postFormActions: PostFormAction[] = [];
export const userActions: UserAction[] = [];
export const noteActions: NoteAction[] = [];
@@ -65,9 +49,10 @@ export const noteViewInterruptors: NoteViewInterruptor[] = [];
export const notePostInterruptors: NotePostInterruptor[] = [];
export const pageViewInterruptors: PageViewInterruptor[] = [];
// TODO: それぞれいちいちwhereとかdefaultというキーを付けなきゃいけないの冗長なのでなんとかする(ただ型定義が面倒になりそう)
// あと、現行の定義の仕方なら「whereが何であるかに関わらずキー名の重複不可」という制約を付けられるメリットもあるからそのメリットを引き継ぐ方法も考えないといけない
export const defaultStore = markRaw(new Storage('base', {
/**
* 「状態」を管理するストア(not「設定」)
*/
export const store = markRaw(new Storage('base', {
accountSetupWizard: {
where: 'account',
default: 0,
@@ -85,38 +70,6 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'account',
default: false,
},
keepCw: {
where: 'account',
default: true,
},
collapseRenotes: {
where: 'account',
default: true,
},
rememberNoteVisibility: {
where: 'account',
default: false,
},
defaultNoteVisibility: {
where: 'account',
default: 'public' as (typeof Misskey.noteVisibilities)[number],
},
defaultNoteLocalOnly: {
where: 'account',
default: false,
},
uploadFolder: {
where: 'account',
default: null as string | null,
},
pastedFileName: {
where: 'account',
default: 'yyyy-MM-dd HH-mm-ss [{{number}}]',
},
keepOriginalUploading: {
where: 'account',
default: false,
},
memo: {
where: 'account',
default: null,
@@ -137,22 +90,6 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'account',
default: [] as string[],
},
menu: {
where: 'deviceAccount',
default: [
'notifications',
'clips',
'drive',
'followRequests',
'-',
'explore',
'announcements',
'search',
'-',
'ui',
],
},
visibility: {
where: 'deviceAccount',
default: 'public' as (typeof Misskey.noteVisibilities)[number],
@@ -165,17 +102,6 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device',
default: false,
},
statusbars: {
where: 'deviceAccount',
default: [] as {
name: string;
id: string;
type: string;
size: 'verySmall' | 'small' | 'medium' | 'large' | 'veryLarge';
black: boolean;
props: Record<string, any>;
}[],
},
widgets: {
where: 'account',
default: [] as {
@@ -198,15 +124,120 @@ export const defaultStore = markRaw(new Storage('base', {
},
},
},
pinnedUserLists: {
where: 'deviceAccount',
default: [] as Misskey.entities.UserList[],
},
overridedDeviceKind: {
where: 'device',
default: null as DeviceKind | null,
},
darkMode: {
where: 'device',
default: false,
},
recentlyUsedEmojis: {
where: 'device',
default: [] as string[],
},
recentlyUsedUsers: {
where: 'device',
default: [] as string[],
},
menuDisplay: {
where: 'device',
default: 'sideFull' as 'sideFull' | 'sideIcon' | 'top',
},
postFormWithHashtags: {
where: 'device',
default: false,
},
postFormHashtags: {
where: 'device',
default: '',
},
additionalUnicodeEmojiIndexes: {
where: 'device',
default: {} as Record<string, Record<string, string[]>>,
},
defaultWithReplies: {
where: 'account',
default: false,
},
pluginTokens: {
where: 'deviceAccount',
default: {} as Record<string, string>, // plugin id, token
},
'deck.profile': {
where: 'deviceAccount',
default: 'default',
},
'deck.columns': {
where: 'deviceAccount',
default: [] as Column[],
},
'deck.layout': {
where: 'deviceAccount',
default: [] as Column['id'][][],
},
enablePreferencesAutoCloudBackup: {
where: 'device',
default: false,
},
showPreferencesAutoCloudBackupSuggestion: {
where: 'device',
default: true,
},
//#region TODO: そのうち消す (preferに移行済み)
defaultSideView: {
where: 'device',
default: false,
},
defaultNoteVisibility: {
where: 'account',
default: 'public' as (typeof Misskey.noteVisibilities)[number],
},
defaultNoteLocalOnly: {
where: 'account',
default: false,
},
keepCw: {
where: 'account',
default: true,
},
collapseRenotes: {
where: 'account',
default: true,
},
rememberNoteVisibility: {
where: 'account',
default: false,
},
uploadFolder: {
where: 'account',
default: null as string | null,
},
keepOriginalUploading: {
where: 'account',
default: false,
},
menu: {
where: 'deviceAccount',
default: [],
},
statusbars: {
where: 'deviceAccount',
default: [] as {
name: string;
id: string;
type: string;
size: 'verySmall' | 'small' | 'medium' | 'large' | 'veryLarge';
black: boolean;
props: Record<string, any>;
}[],
},
pinnedUserLists: {
where: 'deviceAccount',
default: [] as Misskey.entities.UserList[],
},
serverDisconnectedBehavior: {
where: 'device',
default: 'quiet' as 'quiet' | 'reload' | 'dialog',
@@ -287,10 +318,6 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device',
default: false,
},
darkMode: {
where: 'device',
default: false,
},
instanceTicker: {
where: 'device',
default: 'remote' as 'none' | 'remote' | 'always',
@@ -311,22 +338,6 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device',
default: 'auto' as 'auto' | 'popup' | 'drawer',
},
recentlyUsedEmojis: {
where: 'device',
default: [] as string[],
},
recentlyUsedUsers: {
where: 'device',
default: [] as string[],
},
defaultSideView: {
where: 'device',
default: false,
},
menuDisplay: {
where: 'device',
default: 'sideFull' as 'sideFull' | 'sideIcon' | 'top',
},
reportError: {
where: 'device',
default: false,
@@ -339,18 +350,6 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device',
default: true,
},
postFormWithHashtags: {
where: 'device',
default: false,
},
postFormHashtags: {
where: 'device',
default: '',
},
themeInitial: {
where: 'device',
default: true,
},
numberOfPageCache: {
where: 'device',
default: 3,
@@ -399,18 +398,10 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device',
default: true,
},
additionalUnicodeEmojiIndexes: {
where: 'device',
default: {} as Record<string, Record<string, string[]>>,
},
keepScreenOn: {
where: 'device',
default: false,
},
defaultWithReplies: {
where: 'account',
default: false,
},
disableStreamingTimeline: {
where: 'device',
default: false,
@@ -432,17 +423,6 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device',
default: false,
},
dropAndFusion: {
where: 'device',
default: {
bgmVolume: 0.25,
sfxVolume: 1,
},
},
hemisphere: {
where: 'device',
default: hemisphere as 'N' | 'S',
},
enableHorizontalSwipe: {
where: 'device',
default: true,
@@ -479,7 +459,10 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device',
default: false,
},
hemisphere: {
where: 'device',
default: hemisphere as 'N' | 'S',
},
sound_masterVolume: {
where: 'device',
default: 0.3,
@@ -494,56 +477,49 @@ export const defaultStore = markRaw(new Storage('base', {
},
sound_note: {
where: 'device',
default: { type: 'syuilo/n-aec', volume: 1 } as SoundStore,
default: { type: 'syuilo/n-aec', volume: 1 },
},
sound_noteMy: {
where: 'device',
default: { type: 'syuilo/n-cea-4va', volume: 1 } as SoundStore,
default: { type: 'syuilo/n-cea-4va', volume: 1 },
},
sound_notification: {
where: 'device',
default: { type: 'syuilo/n-ea', volume: 1 } as SoundStore,
default: { type: 'syuilo/n-ea', volume: 1 },
},
sound_reaction: {
where: 'device',
default: { type: 'syuilo/bubble2', volume: 1 } as SoundStore,
default: { type: 'syuilo/bubble2', volume: 1 },
},
dropAndFusion: {
where: 'device',
default: {
bgmVolume: 0.25,
sfxVolume: 1,
},
},
//#endregion
}));
// TODO: 他のタブと永続化されたstateを同期
const PREFIX = 'miux:' as const;
export type Plugin = {
id: string;
name: string;
active: boolean;
config?: Record<string, { default: any }>;
configData: Record<string, any>;
token: string;
src: string | null;
version: string;
ast: Ast.Node[];
author?: string;
description?: string;
permissions?: string[];
};
interface Watcher {
key: string;
callback: (value: unknown) => void;
}
// TODO: 消す(preferに移行済みのため)
/**
* 常にメモリにロードしておく必要がないような設定情報を保管するストレージ(非リアクティブ)
*/
export class ColdDeviceStorage {
public static default = {
lightTheme,
darkTheme,
syncDeviceDarkMode: true,
plugins: [] as Plugin[],
lightTheme, // TODO: 消す(preferに移行済みのため)
darkTheme, // TODO: 消す(preferに移行済みのため)
syncDeviceDarkMode: true, // TODO: 消す(preferに移行済みのため)
plugins: [] as Plugin[], // TODO: 消す(preferに移行済みのため)
};
public static watchers: Watcher[] = [];