From e9929747d28c83ea591fd9a8a65a48ba0a8af736 Mon Sep 17 00:00:00 2001 From: Youwes09 Date: Mon, 25 May 2026 12:31:23 -0500 Subject: [PATCH] Chore: Fix Zoom & Attempt Theming --- src/app.css | 143 +------------------------------ src/hooks.client.ts | 5 -- src/lib/core/theme.ts | 87 ++++++++----------- src/lib/state/settings.svelte.ts | 10 +++ src/lib/styles/themes.css | 139 ++++++++++++++++++++++++++++++ src/routes/+layout.svelte | 48 +++++++++-- 6 files changed, 229 insertions(+), 203 deletions(-) create mode 100644 src/lib/styles/themes.css diff --git a/src/app.css b/src/app.css index 27393ac..e394630 100644 --- a/src/app.css +++ b/src/app.css @@ -1,4 +1,5 @@ @import '$lib/components/settings/Settings.css'; +@import '$lib/styles/themes.css'; :root { --bg-void: #080808; @@ -90,146 +91,6 @@ --z-settings: 150; } -[data-theme="dark"] { - --bg-void: #000000; - --bg-base: #080808; - --bg-surface: #0d0d0d; - --bg-raised: #111111; - --bg-overlay: #171717; - --bg-subtle: #1e1e1e; - - --border-dim: #252525; - --border-base: #303030; - --border-strong: #3e3e3e; - --border-focus: #5a7a5a; - - --text-primary: #ffffff; - --text-secondary: #e8e6e0; - --text-muted: #b0aea8; - --text-faint: #6e6c68; - --text-disabled: #303030; - - --accent: #7aaa7a; - --accent-dim: #2e4a2e; - --accent-muted: #1e2e1e; - --accent-fg: #bcd8bc; - --accent-bright: #9fcf9f; -} - -[data-theme="light"] { - --bg-void: #d8d4ce; - --bg-base: #e2deda; - --bg-surface: #ece8e2; - --bg-raised: #f5f2ec; - --bg-overlay: #ffffff; - --bg-subtle: #e4e0d8; - - --border-dim: #c4c0b8; - --border-base: #b0aca4; - --border-strong: #989490; - --border-focus: #3a5a3a; - - --text-primary: #080806; - --text-secondary: #181612; - --text-muted: #38342e; - --text-faint: #706c64; - --text-disabled: #b0aca4; - - --accent: #2a5a2a; - --accent-dim: #b0ccb0; - --accent-muted: #c8dcc8; - --accent-fg: #183818; - --accent-bright: #1e4e1e; - - --color-error: #8a1a1a; - --color-error-bg: #f8e0e0; - --color-read: #e0dcd4; -} - -[data-theme="midnight"] { - --bg-void: #050810; - --bg-base: #080c18; - --bg-surface: #0c1020; - --bg-raised: #101428; - --bg-overlay: #151a30; - --bg-subtle: #1a2038; - - --border-dim: #1a2035; - --border-base: #222840; - --border-strong: #2c3450; - --border-focus: #4a5c8a; - - --text-primary: #eeeef8; - --text-secondary: #c0c4d8; - --text-muted: #808498; - --text-faint: #404860; - --text-disabled: #202840; - - --accent: #6a7ab8; - --accent-dim: #252d50; - --accent-muted: #181e38; - --accent-fg: #a8b4e8; - --accent-bright: #8896d0; -} - -[data-theme="original"] { - --bg-void: #080808; - --bg-base: #0c0c0c; - --bg-surface: #101010; - --bg-raised: #151515; - --bg-overlay: #1a1a1a; - --bg-subtle: #202020; - - --border-dim: #1c1c1c; - --border-base: #242424; - --border-strong: #2e2e2e; - --border-focus: #4a5c4a; - - --text-primary: #f0efec; - --text-secondary: #c8c6c0; - --text-muted: #8a8880; - --text-faint: #4e4d4a; - --text-disabled: #2a2a28; - - --accent: #6b8f6b; - --accent-dim: #2a3d2a; - --accent-muted: #1a251a; - --accent-fg: #a8c4a8; - --accent-bright: #8fb88f; - - --color-error: #c47a7a; - --color-error-bg: #1f1212; - --color-success: #7aab7a; - --color-info: #7a9ec4; - --color-info-bg: #121a1f; -} - -[data-theme="warm"] { - --bg-void: #0c0a06; - --bg-base: #100e08; - --bg-surface: #16130c; - --bg-raised: #1c1810; - --bg-overlay: #221e14; - --bg-subtle: #28241a; - - --border-dim: #201c10; - --border-base: #2c2818; - --border-strong: #3a3420; - --border-focus: #6a5a30; - - --text-primary: #f5f0e0; - --text-secondary: #d8d0b0; - --text-muted: #988c60; - --text-faint: #584e30; - --text-disabled: #302a18; - - --accent: #c0902a; - --accent-dim: #3a2c10; - --accent-muted: #261e0c; - --accent-fg: #e0b860; - --accent-bright: #d0a040; -} - *, *::before, *::after { box-sizing: border-box; margin: 0; @@ -339,4 +200,4 @@ body { background-size: 200% 100%; animation: shimmer 1.4s ease infinite; border-radius: var(--radius-sm); -} +} \ No newline at end of file diff --git a/src/hooks.client.ts b/src/hooks.client.ts index ce0f2c3..09896e4 100644 --- a/src/hooks.client.ts +++ b/src/hooks.client.ts @@ -59,11 +59,6 @@ async function boot() { appState.serverUrl = savedUrl appState.authMode = savedAuth.mode - if (isTauri() && platformAdapter.isSupported('server-management')) { - // jarPath/port/dataPath come from persisted server config; omitted here - // until settings UI writes them — server auto-launch handled by Tauri side - } - configureAuth(savedUrl, savedAuth.mode, savedAuth.user, savedAuth.pass) await serverAdapter.connect({ diff --git a/src/lib/core/theme.ts b/src/lib/core/theme.ts index 6a0bc1f..8478a42 100644 --- a/src/lib/core/theme.ts +++ b/src/lib/core/theme.ts @@ -1,67 +1,56 @@ -import { settingsState, updateSettings } from "$lib/state/settings.svelte"; +import type { CustomTheme } from '$lib/types/settings' -let themeStyleEl: HTMLStyleElement | null = null; -let mediaQuery: MediaQueryList | null = null; -let mediaHandler: (() => void) | null = null; +let themeStyleEl: HTMLStyleElement | null = null +let mediaQuery: MediaQueryList | null = null +let mediaHandler: (() => void) | null = null -export function applyTheme() { - const themeId = settingsState.theme ?? "dark"; - const isCustom = themeId.startsWith("custom:"); +export function applyTheme(themeId: string, customThemes: CustomTheme[] = []) { + const custom = customThemes.find(t => t.id === themeId) - if (!isCustom) { - themeStyleEl?.remove(); - themeStyleEl = null; - document.documentElement.setAttribute("data-theme", themeId); - return; + if (custom) { + const vars = Object.entries(custom.tokens) + .map(([k, v]) => ` --${k}: ${v};`) + .join('\n') + if (!themeStyleEl) { + themeStyleEl = document.createElement('style') + themeStyleEl.id = 'moku-custom-theme' + document.head.appendChild(themeStyleEl) + } + themeStyleEl.textContent = `:root {\n${vars}\n}` + document.documentElement.removeAttribute('data-theme') + return } - const custom = settingsState.customThemes?.find(t => t.id === themeId); - if (!custom) { - themeStyleEl?.remove(); - themeStyleEl = null; - document.documentElement.setAttribute("data-theme", "dark"); - return; + if (themeStyleEl) { + themeStyleEl.remove() + themeStyleEl = null } - - const vars = Object.entries(custom.tokens) - .map(([k, v]) => ` --${k}: ${v};`) - .join("\n"); - const css = `[data-theme="custom"] {\n${vars}\n}`; - - if (!themeStyleEl) { - themeStyleEl = document.createElement("style"); - themeStyleEl.id = "moku-custom-theme"; - document.head.appendChild(themeStyleEl); - } - themeStyleEl.textContent = css; - document.documentElement.setAttribute("data-theme", "custom"); + document.documentElement.setAttribute('data-theme', themeId) } -function applySystemTheme(dark: boolean) { - const themeId = dark - ? (settingsState.systemThemeDark ?? "dark") - : (settingsState.systemThemeLight ?? "light"); - updateSettings({ theme: themeId }); -} - -export function mountSystemThemeSync() { +export function mountSystemThemeSync( + enabled: boolean, + darkTheme: string, + lightTheme: string, + onSwitch: (themeId: string) => void +) { if (mediaQuery && mediaHandler) { - mediaQuery.removeEventListener("change", mediaHandler); - mediaHandler = null; + mediaQuery.removeEventListener('change', mediaHandler) + mediaHandler = null } - if (!settingsState.systemThemeSync) return; + if (!enabled) { mediaQuery = null; return } - mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - mediaHandler = () => applySystemTheme(mediaQuery!.matches); - mediaQuery.addEventListener("change", mediaHandler); - applySystemTheme(mediaQuery.matches); + mediaQuery = window.matchMedia('(prefers-color-scheme: dark)') + mediaHandler = () => onSwitch(mediaQuery!.matches ? darkTheme : lightTheme) + mediaQuery.addEventListener('change', mediaHandler) + onSwitch(mediaQuery.matches ? darkTheme : lightTheme) } export function unmountSystemThemeSync() { if (mediaQuery && mediaHandler) { - mediaQuery.removeEventListener("change", mediaHandler); - mediaHandler = null; - mediaQuery = null; + mediaQuery.removeEventListener('change', mediaHandler) + mediaHandler = null + mediaQuery = null } } \ No newline at end of file diff --git a/src/lib/state/settings.svelte.ts b/src/lib/state/settings.svelte.ts index 8e59096..527e6ac 100644 --- a/src/lib/state/settings.svelte.ts +++ b/src/lib/state/settings.svelte.ts @@ -17,9 +17,19 @@ function save(s: Settings) { export const settingsState = $state({ settings: load() }) +if (typeof document !== 'undefined') { + document.documentElement.style.zoom = String(settingsState.settings.uiZoom ?? 1.0) +} + export function updateSettings(patch: Partial) { Object.assign(settingsState.settings, patch) save(settingsState.settings) + + if (typeof document !== 'undefined') { + if (patch.uiZoom !== undefined) { + document.documentElement.style.zoom = String(patch.uiZoom) + } + } } export function resetSettings() { diff --git a/src/lib/styles/themes.css b/src/lib/styles/themes.css new file mode 100644 index 0000000..7d8cacc --- /dev/null +++ b/src/lib/styles/themes.css @@ -0,0 +1,139 @@ +[data-theme="dark"] { + --bg-void: #000000; + --bg-base: #080808; + --bg-surface: #0d0d0d; + --bg-raised: #111111; + --bg-overlay: #171717; + --bg-subtle: #1e1e1e; + + --border-dim: #252525; + --border-base: #303030; + --border-strong: #3e3e3e; + --border-focus: #5a7a5a; + + --text-primary: #ffffff; + --text-secondary: #e8e6e0; + --text-muted: #b0aea8; + --text-faint: #6e6c68; + --text-disabled: #303030; + + --accent: #7aaa7a; + --accent-dim: #2e4a2e; + --accent-muted: #1e2e1e; + --accent-fg: #bcd8bc; + --accent-bright: #9fcf9f; +} + +[data-theme="light"] { + --bg-void: #d8d4ce; + --bg-base: #e2deda; + --bg-surface: #ece8e2; + --bg-raised: #f5f2ec; + --bg-overlay: #ffffff; + --bg-subtle: #e4e0d8; + + --border-dim: #c4c0b8; + --border-base: #b0aca4; + --border-strong: #989490; + --border-focus: #3a5a3a; + + --text-primary: #080806; + --text-secondary: #181612; + --text-muted: #38342e; + --text-faint: #706c64; + --text-disabled: #b0aca4; + + --accent: #2a5a2a; + --accent-dim: #b0ccb0; + --accent-muted: #c8dcc8; + --accent-fg: #183818; + --accent-bright: #1e4e1e; + + --color-error: #8a1a1a; + --color-error-bg: #f8e0e0; + --color-read: #e0dcd4; +} + +[data-theme="midnight"] { + --bg-void: #050810; + --bg-base: #080c18; + --bg-surface: #0c1020; + --bg-raised: #101428; + --bg-overlay: #151a30; + --bg-subtle: #1a2038; + + --border-dim: #1a2035; + --border-base: #222840; + --border-strong: #2c3450; + --border-focus: #4a5c8a; + + --text-primary: #eeeef8; + --text-secondary: #c0c4d8; + --text-muted: #808498; + --text-faint: #404860; + --text-disabled: #202840; + + --accent: #6a7ab8; + --accent-dim: #252d50; + --accent-muted: #181e38; + --accent-fg: #a8b4e8; + --accent-bright: #8896d0; +} + +[data-theme="original"] { + --bg-void: #080808; + --bg-base: #0c0c0c; + --bg-surface: #101010; + --bg-raised: #151515; + --bg-overlay: #1a1a1a; + --bg-subtle: #202020; + + --border-dim: #1c1c1c; + --border-base: #242424; + --border-strong: #2e2e2e; + --border-focus: #4a5c4a; + + --text-primary: #f0efec; + --text-secondary: #c8c6c0; + --text-muted: #8a8880; + --text-faint: #4e4d4a; + --text-disabled: #2a2a28; + + --accent: #6b8f6b; + --accent-dim: #2a3d2a; + --accent-muted: #1a251a; + --accent-fg: #a8c4a8; + --accent-bright: #8fb88f; + + --color-error: #c47a7a; + --color-error-bg: #1f1212; + --color-success: #7aab7a; + --color-info: #7a9ec4; + --color-info-bg: #121a1f; +} + +[data-theme="warm"] { + --bg-void: #0c0a06; + --bg-base: #100e08; + --bg-surface: #16130c; + --bg-raised: #1c1810; + --bg-overlay: #221e14; + --bg-subtle: #28241a; + + --border-dim: #201c10; + --border-base: #2c2818; + --border-strong: #3a3420; + --border-focus: #6a5a30; + + --text-primary: #f5f0e0; + --text-secondary: #d8d0b0; + --text-muted: #988c60; + --text-faint: #584e30; + --text-disabled: #302a18; + + --accent: #c0902a; + --accent-dim: #3a2c10; + --accent-muted: #261e0c; + --accent-fg: #e0b860; + --accent-bright: #d0a040; +} \ No newline at end of file diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 3ec78b4..ebbc351 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,13 +1,16 @@