diff --git a/browser_tests/colorPalette.spec.ts b/browser_tests/colorPalette.spec.ts index 7b0ac58b4..d827e22d0 100644 --- a/browser_tests/colorPalette.spec.ts +++ b/browser_tests/colorPalette.spec.ts @@ -1,8 +1,9 @@ import { expect } from '@playwright/test' +import type { Palette } from '../src/types/colorPaletteTypes' import { comfyPageFixture as test } from './fixtures/ComfyPage' -const customColorPalettes = { +const customColorPalettes: Record = { obsidian: { version: 102, id: 'obsidian', @@ -128,6 +129,19 @@ const customColorPalettes = { 'tr-odd-bg-color': 'rgba(19,19,19,.9)' } } + }, + // A custom light theme with fg color red + light_red: { + id: 'light_red', + name: 'Light Red', + light_theme: true, + colors: { + node_slot: {}, + litegraph_base: {}, + comfy_base: { + 'fg-color': '#ff0000' + } + } } } @@ -142,6 +156,12 @@ test.describe('Color Palette', () => { await expect(comfyPage.canvas).toHaveScreenshot( 'custom-color-palette-obsidian-dark.png' ) + await comfyPage.setSetting('Comfy.ColorPalette', 'light_red') + await comfyPage.nextFrame() + await expect(comfyPage.canvas).toHaveScreenshot( + 'custom-color-palette-light-red.png' + ) + await comfyPage.setSetting('Comfy.ColorPalette', 'dark') await comfyPage.nextFrame() await expect(comfyPage.canvas).toHaveScreenshot('default-color-palette.png') diff --git a/browser_tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-2x-linux.png b/browser_tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-2x-linux.png new file mode 100644 index 000000000..a1cc98aa4 Binary files /dev/null and b/browser_tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-2x-linux.png differ diff --git a/browser_tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-linux.png b/browser_tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-linux.png new file mode 100644 index 000000000..39a07b274 Binary files /dev/null and b/browser_tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-linux.png differ diff --git a/src/assets/palettes/light.json b/src/assets/palettes/light.json index 2496b3546..52a0a6a57 100644 --- a/src/assets/palettes/light.json +++ b/src/assets/palettes/light.json @@ -1,6 +1,7 @@ { "id": "light", "name": "Light", + "light_theme": true, "colors": { "node_slot": { "CLIP": "#FFA726", @@ -13,7 +14,12 @@ "MASK": "#9CCC65", "MODEL": "#7E57C2", "STYLE_MODEL": "#D4E157", - "VAE": "#FF7043" + "VAE": "#FF7043", + "NOISE": "#B0B0B0", + "GUIDER": "#66FFFF", + "SAMPLER": "#ECB4B4", + "SIGMAS": "#CDFFCD", + "TAESD": "#DCC274" }, "litegraph_base": { "BACKGROUND_IMAGE": "data:image/gif;base64,R0lGODlhZABkALMAAAAAAP///+vr6+rq6ujo6Ofn5+bm5uXl5d3d3f///wAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAkALAAAAABkAGQAAAT/UMhJq7046827HkcoHkYxjgZhnGG6si5LqnIM0/fL4qwwIMAg0CAsEovBIxKhRDaNy2GUOX0KfVFrssrNdpdaqTeKBX+dZ+jYvEaTf+y4W66mC8PUdrE879f9d2mBeoNLfH+IhYBbhIx2jkiHiomQlGKPl4uZe3CaeZifnnijgkESBqipqqusra6vsLGys62SlZO4t7qbuby7CLa+wqGWxL3Gv3jByMOkjc2lw8vOoNSi0czAncXW3Njdx9Pf48/Z4Kbbx+fQ5evZ4u3k1fKR6cn03vHlp7T9/v8A/8Gbp4+gwXoFryXMB2qgwoMMHyKEqA5fxX322FG8tzBcRnMW/zlulPbRncmQGidKjMjyYsOSKEF2FBlJQMCbOHP6c9iSZs+UnGYCdbnSo1CZI5F64kn0p1KnTH02nSoV3dGTV7FFHVqVq1dtWcMmVQZTbNGu72zqXMuW7danVL+6e4t1bEy6MeueBYLXrNO5Ze36jQtWsOG97wIj1vt3St/DjTEORss4nNq2mDP3e7w4r1bFkSET5hy6s2TRlD2/mSxXtSHQhCunXo26NevCpmvD/UU6tuullzULH76q92zdZG/Ltv1a+W+osI/nRmyc+fRi1Xdbh+68+0vv10dH3+77KD/i6IdnX669/frn5Zsjh4/2PXju8+8bzc9/6fj27LFnX11/+IUnXWl7BJfegm79FyB9JOl3oHgSklefgxAC+FmFGpqHIYcCfkhgfCohSKKJVo044YUMttggiBkmp6KFXw1oII24oYhjiDByaKOOHcp3Y5BD/njikSkO+eBREQAAOw==", diff --git a/src/components/sidebar/SidebarThemeToggleIcon.vue b/src/components/sidebar/SidebarThemeToggleIcon.vue index 6428b8b92..c6bdb2f5b 100644 --- a/src/components/sidebar/SidebarThemeToggleIcon.vue +++ b/src/components/sidebar/SidebarThemeToggleIcon.vue @@ -11,14 +11,15 @@ import { computed } from 'vue' import { useCommandStore } from '@/stores/commandStore' -import { useSettingStore } from '@/stores/settingStore' +import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore' import SidebarIcon from './SidebarIcon.vue' -const settingStore = useSettingStore() -const currentTheme = computed(() => settingStore.get('Comfy.ColorPalette')) +const colorPaletteStore = useColorPaletteStore() const icon = computed(() => - currentTheme.value !== 'light' ? 'pi pi-moon' : 'pi pi-sun' + colorPaletteStore.completedActivePalette.light_theme + ? 'pi pi-sun' + : 'pi pi-moon' ) const commandStore = useCommandStore() diff --git a/src/constants/coreColorPalettes.ts b/src/constants/coreColorPalettes.ts index b6a70cb81..e65c68de9 100644 --- a/src/constants/coreColorPalettes.ts +++ b/src/constants/coreColorPalettes.ts @@ -4,7 +4,7 @@ import github from '@/assets/palettes/github.json' import light from '@/assets/palettes/light.json' import nord from '@/assets/palettes/nord.json' import solarized from '@/assets/palettes/solarized.json' -import type { ColorPalettes } from '@/types/colorPaletteTypes' +import type { ColorPalettes, CompletedPalette } from '@/types/colorPaletteTypes' export const CORE_COLOR_PALETTES: ColorPalettes = { dark, @@ -15,4 +15,6 @@ export const CORE_COLOR_PALETTES: ColorPalettes = { github } as const -export const DEFAULT_COLOR_PALETTE = dark +export const DEFAULT_COLOR_PALETTE: CompletedPalette = dark +export const DEFAULT_DARK_COLOR_PALETTE: CompletedPalette = dark +export const DEFAULT_LIGHT_COLOR_PALETTE: CompletedPalette = light diff --git a/src/hooks/coreCommandHooks.ts b/src/hooks/coreCommandHooks.ts index 1db6a2b1e..4d498b85b 100644 --- a/src/hooks/coreCommandHooks.ts +++ b/src/hooks/coreCommandHooks.ts @@ -5,6 +5,10 @@ import { LiteGraph } from '@comfyorg/litegraph' +import { + DEFAULT_DARK_COLOR_PALETTE, + DEFAULT_LIGHT_COLOR_PALETTE +} from '@/constants/coreColorPalettes' import { api } from '@/scripts/api' import { app } from '@/scripts/app' import { useDialogService } from '@/services/dialogService' @@ -16,6 +20,7 @@ import { useSettingStore } from '@/stores/settingStore' import { useToastStore } from '@/stores/toastStore' import { type ComfyWorkflow, useWorkflowStore } from '@/stores/workflowStore' import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore' +import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore' import { useSearchBoxStore } from '@/stores/workspace/searchBoxStore' import { useWorkspaceStore } from '@/stores/workspaceStore' @@ -23,6 +28,7 @@ export function useCoreCommands(): ComfyCommand[] { const workflowService = useWorkflowService() const workflowStore = useWorkflowStore() const dialogService = useDialogService() + const colorPaletteStore = useColorPaletteStore() const getTracker = () => workflowStore.activeWorkflow?.changeTracker const getSelectedNodes = (): LGraphNode[] => { @@ -410,18 +416,18 @@ export function useCoreCommands(): ComfyCommand[] { label: 'Toggle Theme (Dark/Light)', versionAdded: '1.3.12', function: (() => { - let previousDarkTheme: string = 'dark' + let previousDarkTheme: string = DEFAULT_DARK_COLOR_PALETTE.id + let previousLightTheme: string = DEFAULT_LIGHT_COLOR_PALETTE.id - // Official light theme is the only light theme supported now. - const isDarkMode = (themeId: string) => themeId !== 'light' return () => { const settingStore = useSettingStore() - const currentTheme = settingStore.get('Comfy.ColorPalette') - if (isDarkMode(currentTheme)) { - previousDarkTheme = currentTheme - settingStore.set('Comfy.ColorPalette', 'light') - } else { + const theme = colorPaletteStore.completedActivePalette + if (theme.light_theme) { + previousLightTheme = theme.id settingStore.set('Comfy.ColorPalette', previousDarkTheme) + } else { + previousDarkTheme = theme.id + settingStore.set('Comfy.ColorPalette', previousLightTheme) } } })() diff --git a/src/stores/workspace/colorPaletteStore.ts b/src/stores/workspace/colorPaletteStore.ts index ae09ddfad..3157b7cc9 100644 --- a/src/stores/workspace/colorPaletteStore.ts +++ b/src/stores/workspace/colorPaletteStore.ts @@ -3,7 +3,9 @@ import { computed, ref } from 'vue' import { CORE_COLOR_PALETTES, - DEFAULT_COLOR_PALETTE + DEFAULT_COLOR_PALETTE, + DEFAULT_DARK_COLOR_PALETTE, + DEFAULT_LIGHT_COLOR_PALETTE } from '@/constants/coreColorPalettes' import type { ColorPalettes, @@ -63,20 +65,24 @@ export const useColorPaletteStore = defineStore('colorPalette', () => { palette.colors.comfy_base['comfy-menu-bg'] } + const defaultPalette = palette.light_theme + ? DEFAULT_LIGHT_COLOR_PALETTE + : DEFAULT_DARK_COLOR_PALETTE + return { ...palette, colors: { ...palette.colors, node_slot: { - ...DEFAULT_COLOR_PALETTE.colors.node_slot, + ...defaultPalette.colors.node_slot, ...palette.colors.node_slot }, litegraph_base: { - ...DEFAULT_COLOR_PALETTE.colors.litegraph_base, + ...defaultPalette.colors.litegraph_base, ...palette.colors.litegraph_base }, comfy_base: { - ...DEFAULT_COLOR_PALETTE.colors.comfy_base, + ...defaultPalette.colors.comfy_base, ...palette.colors.comfy_base } } diff --git a/src/types/colorPaletteTypes.ts b/src/types/colorPaletteTypes.ts index cac100260..051012445 100644 --- a/src/types/colorPaletteTypes.ts +++ b/src/types/colorPaletteTypes.ts @@ -92,7 +92,8 @@ export const paletteSchema = z .object({ id: z.string(), name: z.string(), - colors: partialColorsSchema + colors: partialColorsSchema, + light_theme: z.boolean().optional() }) .passthrough() diff --git a/src/views/GraphView.vue b/src/views/GraphView.vue index f0d0af5c8..71721f333 100644 --- a/src/views/GraphView.vue +++ b/src/views/GraphView.vue @@ -13,7 +13,7 @@ import { useEventListener } from '@vueuse/core' import type { ToastMessageOptions } from 'primevue/toast' import { useToast } from 'primevue/usetoast' -import { computed, onBeforeUnmount, onMounted, watch, watchEffect } from 'vue' +import { onBeforeUnmount, onMounted, watch, watchEffect } from 'vue' import { useI18n } from 'vue-i18n' import BrowserTabTitle from '@/components/BrowserTabTitle.vue' @@ -41,6 +41,7 @@ import { import { useServerConfigStore } from '@/stores/serverConfigStore' import { useSettingStore } from '@/stores/settingStore' import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore' +import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore' import { useSidebarTabStore } from '@/stores/workspace/sidebarTabStore' import { useWorkspaceStore } from '@/stores/workspaceStore' import { StatusWsMessageStatus } from '@/types/apiTypes' @@ -51,18 +52,16 @@ const { t } = useI18n() const toast = useToast() const settingStore = useSettingStore() const executionStore = useExecutionStore() - -const theme = computed(() => settingStore.get('Comfy.ColorPalette')) +const colorPaletteStore = useColorPaletteStore() watch( - theme, + () => colorPaletteStore.completedActivePalette, (newTheme) => { const DARK_THEME_CLASS = 'dark-theme' - const isDarkTheme = newTheme !== 'light' - if (isDarkTheme) { - document.body.classList.add(DARK_THEME_CLASS) - } else { + if (newTheme.light_theme) { document.body.classList.remove(DARK_THEME_CLASS) + } else { + document.body.classList.add(DARK_THEME_CLASS) } }, { immediate: true }