From 01de615321c455e775391259d9eac22c6194cbb2 Mon Sep 17 00:00:00 2001 From: Romot Date: Wed, 17 Jul 2024 00:20:16 +0900 Subject: [PATCH] =?UTF-8?q?=E4=BB=95=E6=8E=9B=E3=81=8B=E3=82=8A:=20?= =?UTF-8?q?=E3=82=AB=E3=83=A9=E3=83=BC=E3=82=B9=E3=82=AD=E3=83=BC=E3=83=A0?= =?UTF-8?q?=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/electron/main.ts | 2 +- src/components/Sing/ColorSchemeEditor.vue | 358 +++++++++++++++ src/components/Sing/SingEditor.vue | 2 + src/components/Sing/ThemeChanger.vue | 502 ---------------------- src/helpers/colors.ts | 80 +--- src/store/setting.ts | 101 +++-- src/store/type.ts | 19 + src/type/preload.ts | 72 ++++ 8 files changed, 538 insertions(+), 598 deletions(-) create mode 100644 src/components/Sing/ColorSchemeEditor.vue delete mode 100644 src/components/Sing/ThemeChanger.vue diff --git a/src/backend/electron/main.ts b/src/backend/electron/main.ts index 97ac778fc8..61ae3400db 100644 --- a/src/backend/electron/main.ts +++ b/src/backend/electron/main.ts @@ -19,7 +19,6 @@ import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer"; import log from "electron-log/main"; import dayjs from "dayjs"; import windowStateKeeper from "electron-window-state"; -import { ColorSchemeConfig } from "../../helpers/colors"; import { hasSupportedGpu } from "./device"; import EngineManager from "./manager/engineManager"; import VvppManager, { isVvppFile } from "./manager/vvppManager"; @@ -47,6 +46,7 @@ import { defaultToolbarButtonSetting, engineSettingSchema, EngineId, + ColorSchemeConfig, } from "@/type/preload"; type SingleInstanceLockData = { diff --git a/src/components/Sing/ColorSchemeEditor.vue b/src/components/Sing/ColorSchemeEditor.vue new file mode 100644 index 0000000000..b16ea3f5a1 --- /dev/null +++ b/src/components/Sing/ColorSchemeEditor.vue @@ -0,0 +1,358 @@ + + + + + diff --git a/src/components/Sing/SingEditor.vue b/src/components/Sing/SingEditor.vue index b2c8999867..19eaaf0a78 100644 --- a/src/components/Sing/SingEditor.vue +++ b/src/components/Sing/SingEditor.vue @@ -20,6 +20,7 @@ + @@ -27,6 +28,7 @@ import { computed, ref, watch } from "vue"; import ToolBar from "./ToolBar/ToolBar.vue"; import ScoreSequencer from "./ScoreSequencer.vue"; +import ColorSchemeEditor from "@/components/Sing/ColorSchemeEditor.vue"; import EngineStartupOverlay from "@/components/EngineStartupOverlay.vue"; import { useStore } from "@/store"; import onetimeWatch from "@/helpers/onetimeWatch"; diff --git a/src/components/Sing/ThemeChanger.vue b/src/components/Sing/ThemeChanger.vue deleted file mode 100644 index d4271a73a3..0000000000 --- a/src/components/Sing/ThemeChanger.vue +++ /dev/null @@ -1,502 +0,0 @@ - - - - - diff --git a/src/helpers/colors.ts b/src/helpers/colors.ts index f27d977220..51a86126c4 100644 --- a/src/helpers/colors.ts +++ b/src/helpers/colors.ts @@ -15,76 +15,14 @@ import { MaterialDynamicColors, } from "@material/material-color-utilities"; -// カラースキーマの種類 -export type SchemeVariant = - | "content" - | "tonalSpot" - | "neutral" - | "vibrant" - | "expressive" - | "fidelity" - | "monochrome" - | "rainbow" - | "fruitSalad"; - -// カラーパレットのキー(M3準拠) -export type PaletteKey = - | "primary" - | "secondary" - | "tertiary" - | "neutral" - | "neutralVariant" - | "error"; - -// カラー調整 -export interface ColorAdjustment { - hue?: number; - chroma?: number; - tone?: number; - hex?: string; -} - -// テーマオプション -export interface ThemeOptions { - sourceColor: string; - variant?: SchemeVariant; - isDark?: boolean; - contrastLevel?: number; - adjustments?: Partial>; -} - -// 定義済みカスタムカラー -export interface CustomDefinedColor { - name: string; - value: string; - blend: boolean; -} - -// パレットから取得するカスタムカラー -export interface CustomPaletteColor { - name: string; - palette: PaletteKey; - lightTone: number; - darkTone: number; - blend: boolean; -} - -// カラーパレットオプション -export interface TonalPaletteOptions { - color: string; - tonalOffset?: number; -} - -export interface ColorSchemeConfig { - name: string; - sourceColor: string; - variant: SchemeVariant; - isDark: boolean; - contrastLevel: number; - adjustments: Partial>; - customPaletteColors: CustomPaletteColor[]; - customDefinedColors: CustomDefinedColor[]; -} +import { + ColorSchemeConfig, + PaletteKey, + ColorAdjustment, + ThemeOptions, + SchemeVariant, + ColorTheme, +} from "@/type/preload"; // カラースキーマのコンストラクタ const SCHEME_CONSTRUCTORS: Record = { @@ -130,7 +68,7 @@ export const adjustPalette = ( const hexHct = Hct.fromInt(argbFromHex(adjustment.hex)); return TonalPalette.fromHueAndChroma(hexHct.hue, hexHct.chroma); } else { - // 色相、彩度、明度を指定されている場合はテーマを調整 + // 色相、彩度、明度を指定されている場合はテーマパレットを調整 const hue = adjustment.hue != undefined ? adjustment.hue : palette.hue; const chroma = adjustment.chroma != undefined ? adjustment.chroma : palette.chroma; diff --git a/src/store/setting.ts b/src/store/setting.ts index c8a9cf6ae1..e5321041d6 100644 --- a/src/store/setting.ts +++ b/src/store/setting.ts @@ -1,11 +1,8 @@ import { Dark, setCssVar, colors } from "quasar"; -import { - generateColorTheme, - colorThemeToCssVariables, -} from "../helpers/colors"; import { SettingStoreState, SettingStoreTypes } from "./type"; import { createUILockAction } from "./ui"; import { createPartialStore } from "./vuex"; +import { generateColorTheme, colorThemeToCssVariables } from "@/helpers/colors"; import { HotkeySettingType, SavingSetting, @@ -16,6 +13,7 @@ import { EngineId, ConfirmedTips, RootMiscSettingType, + ColorSchemeConfig, } from "@/type/preload"; import { IsEqual } from "@/type/utility"; @@ -40,6 +38,10 @@ export const settingStoreState: SettingStoreState = { currentTheme: "Default", availableThemes: [], }, + colorSchemeSetting: { + colorScheme: undefined, + availableColorSchemes: [], + }, editorFont: "default", showTextLineNumber: false, showAddAudioItemButton: true, @@ -93,6 +95,9 @@ export const settingStore = createPartialStore({ }); } + // TODO: Hydrate + dispatch("INITIALIZE_COLOR_SCHEME"); + dispatch("SET_ACCEPT_RETRIEVE_TELEMETRY", { acceptRetrieveTelemetry: await window.backend.getSetting( "acceptRetrieveTelemetry", @@ -279,35 +284,83 @@ export const settingStore = createPartialStore({ window.backend.setNativeTheme(theme.isDark ? "dark" : "light"); - // NOTE: 以下をどこかで設定ファイル化 - // カラーを変更したい場合 - // 1. ソースカラーを変更する(テーマ全体) - // 2. ソースカラーからtertiaryカラー(アクセント)を変更する - // 3. テーマの調整をする(adjustments) - // 4. パレットから取得するカラーを設定する - // 5. 定義済みカスタムカラーを設定する(パレット外) - // 6. テーマオプションを設定する(tonalSpot, monochrome, vibrant...etc) - // 7. コントラスト比を設定する - - // ソースカラー - // カラースキーマの読み込み - window.backend.getColorSchemeConfigs().then((configs) => { - const defaultSchemeConfig = configs[0]; + commit("SET_THEME_SETTING", { + currentTheme: currentTheme, + }); + }, + }, + + INITIALIZE_COLOR_SCHEME: { + mutation(state, { colorScheme, availableColorSchemes }) { + state.colorSchemeSetting.colorScheme = colorScheme; + state.colorSchemeSetting.availableColorSchemes = availableColorSchemes; + }, + action: createUILockAction(async ({ commit, state }) => { + try { + const availableColorSchemes = + await window.backend.getColorSchemeConfigs(); + const defaultSchemeConfig = availableColorSchemes[0]; + const isDark = state.themeSetting.currentTheme.isDark ?? false; const colorTheme = generateColorTheme({ ...defaultSchemeConfig, - isDark: theme.isDark, + isDark, }); + + // CSS変数に変換 const cssVariables = colorThemeToCssVariables(colorTheme); - // CSSに適用する + + // CSSに適用 Object.entries(cssVariables).forEach(([key, value]) => { document.documentElement.style.setProperty(key, value); }); - }); - commit("SET_THEME_SETTING", { - currentTheme: currentTheme, - }); + commit("INITIALIZE_COLOR_SCHEME", { + colorScheme: defaultSchemeConfig, + availableColorSchemes, + }); + } catch (error) { + console.error("Error initializing color scheme:", error); + await window.backend.showMessageDialog({ + type: "error", + title: "カラースキーム初期化エラー", + message: "カラースキームの初期化中にエラーが発生しました。", + }); + } + }), + }, + + SET_COLOR_SCHEME_SETTING: { + mutation(state, { colorScheme }) { + state.colorSchemeSetting.colorScheme = colorScheme; }, + action: createUILockAction( + async ( + { commit, state }, + { colorScheme }: { colorScheme: ColorSchemeConfig }, + ) => { + try { + const isDark = state.themeSetting.currentTheme.isDark ?? false; + const colorTheme = generateColorTheme({ + ...colorScheme, + isDark, + }); + const cssVariables = colorThemeToCssVariables(colorTheme); + + Object.entries(cssVariables).forEach(([key, value]) => { + document.documentElement.style.setProperty(key, value); + }); + + commit("SET_COLOR_SCHEME_SETTING", { colorScheme: colorScheme }); + } catch (error) { + console.error("Error setting color scheme:", error); + await window.backend.showMessageDialog({ + type: "error", + title: "カラースキーム設定エラー", + message: "カラースキームの設定中にエラーが発生しました。", + }); + } + }, + ), }, SET_ACCEPT_RETRIEVE_TELEMETRY: { diff --git a/src/store/type.ts b/src/store/type.ts index b94864d7aa..7f47a317cb 100644 --- a/src/store/type.ts +++ b/src/store/type.ts @@ -52,6 +52,7 @@ import { RootMiscSettingType, EditorType, NoteId, + ColorSchemeConfig, } from "@/type/preload"; import { IEngineConnectorFactory } from "@/infrastructures/EngineConnector"; import { @@ -1573,6 +1574,24 @@ export type SettingStoreTypes = { action(payload: { currentTheme: string }): void; }; + INITIALIZE_COLOR_SCHEME: { + mutation: { + colorScheme: ColorSchemeConfig; + availableColorSchemes: ColorSchemeConfig[]; + }; + action(payload: { + colorScheme: ColorSchemeConfig; + availableColorSchemes: ColorSchemeConfig[]; + }): void; + }; + + SET_COLOR_SCHEME_SETTING: { + mutation: { + colorScheme: ColorSchemeConfig; + }; + action(payload: { colorScheme: ColorSchemeConfig }): void; + }; + SET_ACCEPT_RETRIEVE_TELEMETRY: { mutation: { acceptRetrieveTelemetry: AcceptRetrieveTelemetryStatus }; action(payload: { diff --git a/src/type/preload.ts b/src/type/preload.ts index 56786c61b2..8d4efe627a 100644 --- a/src/type/preload.ts +++ b/src/type/preload.ts @@ -558,6 +558,78 @@ export type ThemeSetting = { availableThemes: ThemeConf[]; }; +// カラースキーマの種類 +export type SchemeVariant = + | "content" + | "tonalSpot" + | "neutral" + | "vibrant" + | "expressive" + | "fidelity" + | "monochrome" + | "rainbow" + | "fruitSalad"; + +// カラーパレットのキー(M3準拠) +export type PaletteKey = + | "primary" + | "secondary" + | "tertiary" + | "neutral" + | "neutralVariant" + | "error"; + +// カラー調整 +export interface ColorAdjustment { + hue?: number; + chroma?: number; + tone?: number; + hex?: string; +} + +// テーマオプション +export interface ThemeOptions { + sourceColor: string; + variant?: SchemeVariant; + isDark?: boolean; + contrastLevel?: number; + adjustments?: Partial>; +} + +// 定義済みカスタムカラー +export interface CustomDefinedColor { + name: string; + value: string; + blend: boolean; +} + +// パレットから取得するカスタムカラー +export interface CustomPaletteColor { + name: string; + palette: PaletteKey; + lightTone: number; + darkTone: number; + blend: boolean; +} + +// カラーパレットオプション +export interface TonalPaletteOptions { + color: string; + tonalOffset?: number; +} + +// カラースキーマの設定 +export interface ColorSchemeConfig { + name: string; + sourceColor: string; + variant: SchemeVariant; + isDark: boolean; + contrastLevel: number; + adjustments: Partial>; + customPaletteColors: CustomPaletteColor[]; + customDefinedColors: CustomDefinedColor[]; +} + export const experimentalSettingSchema = z.object({ enablePreset: z.boolean().default(false), shouldApplyDefaultPresetOnVoiceChanged: z.boolean().default(false),