diff --git a/.cargo/config.toml b/.cargo/config.toml index 398b7f9d6..03feda3c7 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,4 @@ [env] -# Enable SQLite's built-in math functions for rusqlite's bundled libsqlite3. LIBSQLITE3_FLAGS = "SQLITE_ENABLE_MATH_FUNCTIONS" [target.x86_64-pc-windows-msvc] diff --git a/.gitignore b/.gitignore index b4d43dd5f..fbbcce3cb 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,7 @@ agents/*/libs/*.jar # Generated changelog data releases-*.json + +test.pdb +portable/ +DBX_*_x64-portable.zip diff --git a/apps/desktop/src/components/editor/EditorSettingsDialog.vue b/apps/desktop/src/components/editor/EditorSettingsDialog.vue index 10772c1c7..e727dc9c0 100644 --- a/apps/desktop/src/components/editor/EditorSettingsDialog.vue +++ b/apps/desktop/src/components/editor/EditorSettingsDialog.vue @@ -44,8 +44,11 @@ import { type EditorTheme, type DesktopIconTheme, type DisconnectTabHandlingMode, + type CustomThemeColors, + type CustomTheme, } from "@/stores/settingsStore"; import { loadEditorTheme, editorFontTheme } from "@/lib/editorThemes"; +import ThemeCustomizerDialog from "./ThemeCustomizerDialog.vue"; import { isTauriRuntime } from "@/lib/tauriRuntime"; import { useTheme } from "@/composables/useTheme"; import { copyToClipboard } from "@/lib/clipboard"; @@ -103,6 +106,9 @@ const editFontFamily = ref(settingsStore.editorSettings.fontFamily); const editFontSize = ref(settingsStore.editorSettings.fontSize); const editUiScale = ref(settingsStore.editorSettings.uiScale); const editTheme = ref(settingsStore.editorSettings.theme); +const editCustomThemes = ref([...settingsStore.editorSettings.customThemes]); +const editActiveCustomThemeId = ref(settingsStore.editorSettings.activeCustomThemeId); +const showThemeCustomizer = ref(false); const editExecuteMode = ref(settingsStore.editorSettings.executeMode); const editWordWrap = ref(settingsStore.editorSettings.wordWrap); const editConfirmDangerousSqlExecution = ref(settingsStore.editorSettings.confirmDangerousSqlExecution); @@ -256,6 +262,8 @@ watch( editFontSize.value = settingsStore.editorSettings.fontSize; editUiScale.value = settingsStore.editorSettings.uiScale; editTheme.value = settingsStore.editorSettings.theme; + editCustomThemes.value = [...settingsStore.editorSettings.customThemes]; + editActiveCustomThemeId.value = settingsStore.editorSettings.activeCustomThemeId; editExecuteMode.value = settingsStore.editorSettings.executeMode; editWordWrap.value = settingsStore.editorSettings.wordWrap; editConfirmDangerousSqlExecution.value = settingsStore.editorSettings.confirmDangerousSqlExecution; @@ -300,6 +308,8 @@ function hasChanges(): boolean { editFontSize.value !== settingsStore.editorSettings.fontSize || editUiScale.value !== settingsStore.editorSettings.uiScale || editTheme.value !== settingsStore.editorSettings.theme || + JSON.stringify(editCustomThemes.value) !== JSON.stringify(settingsStore.editorSettings.customThemes) || + editActiveCustomThemeId.value !== settingsStore.editorSettings.activeCustomThemeId || editExecuteMode.value !== settingsStore.editorSettings.executeMode || editWordWrap.value !== settingsStore.editorSettings.wordWrap || editConfirmDangerousSqlExecution.value !== settingsStore.editorSettings.confirmDangerousSqlExecution || @@ -333,6 +343,8 @@ async function persistSettings() { fontSize: editFontSize.value, uiScale: editUiScale.value, theme: editTheme.value, + customThemes: editCustomThemes.value, + activeCustomThemeId: editActiveCustomThemeId.value, executeMode: editExecuteMode.value, wordWrap: editWordWrap.value, confirmDangerousSqlExecution: editConfirmDangerousSqlExecution.value, @@ -375,6 +387,8 @@ function resetDefaults() { editFontSize.value = DEFAULT_EDITOR_SETTINGS.fontSize; editUiScale.value = DEFAULT_EDITOR_SETTINGS.uiScale; editTheme.value = DEFAULT_EDITOR_SETTINGS.theme; + editCustomThemes.value = [...DEFAULT_EDITOR_SETTINGS.customThemes]; + editActiveCustomThemeId.value = DEFAULT_EDITOR_SETTINGS.activeCustomThemeId; editExecuteMode.value = DEFAULT_EDITOR_SETTINGS.executeMode; editWordWrap.value = DEFAULT_EDITOR_SETTINGS.wordWrap; editConfirmDangerousSqlExecution.value = DEFAULT_EDITOR_SETTINGS.confirmDangerousSqlExecution; @@ -405,8 +419,43 @@ function onFontFamilyChange(v: any) { if (typeof v === "string") editFontFamily.value = v; } +const themeSelectValue = computed(() => { + if (editTheme.value === "custom") { + return `custom:${editActiveCustomThemeId.value}`; + } + return editTheme.value; +}); + +const themeSelectOptions = computed(() => [ + ...EDITOR_THEMES.filter((theme) => theme.value !== "custom").map((theme) => ({ + value: theme.value, + label: theme.value === "app" ? t("settings.followAppTheme") : theme.label, + dark: theme.dark, + isCustom: false, + })), + ...editCustomThemes.value.map((theme) => ({ + value: `custom:${theme.id}`, + label: theme.name, + dark: true, + isCustom: true, + })), +]); + function onThemeChange(v: any) { - if (typeof v === "string") editTheme.value = v as typeof DEFAULT_EDITOR_SETTINGS.theme; + if (typeof v !== "string") return; + if (v.startsWith("custom:")) { + editTheme.value = "custom"; + editActiveCustomThemeId.value = v.slice(7); + } else { + editTheme.value = v as typeof DEFAULT_EDITOR_SETTINGS.theme; + } +} + +function handleThemeSave(updatedThemes: CustomTheme[], activeId: string) { + editCustomThemes.value = updatedThemes; + editActiveCustomThemeId.value = activeId; + editTheme.value = "custom"; + showThemeCustomizer.value = false; } function onDisconnectTabHandlingModeChange(v: any) { @@ -1036,16 +1085,24 @@ async function aiTestConn() { const previewRef = ref(); const previewView = shallowRef(null); +function getPreviewCustomThemeColors(): CustomThemeColors | undefined { + if (editTheme.value !== "custom") return undefined; + const activeTheme = editCustomThemes.value.find((t) => t.id === editActiveCustomThemeId.value); + return activeTheme?.colors; +} + const previewSettings = computed<{ fontFamily: string; fontSize: number; theme: EditorTheme; appAppearance: AppThemeAppearance; + customColors?: CustomThemeColors; }>(() => ({ fontFamily: editFontFamily.value, fontSize: editFontSize.value, theme: editTheme.value, appAppearance: isDark.value ? "dark" : "light", + customColors: getPreviewCustomThemeColors(), })); const previewSql = `SELECT u.id, u.name @@ -1057,11 +1114,11 @@ let themeComp: import("@codemirror/state").Compartment | null = null; let editorViewModule: typeof import("@codemirror/view") | null = null; watch( - previewSettings, - async (ss) => { + [previewSettings, editCustomThemes, editActiveCustomThemeId], + async ([ss]) => { if (!previewView.value || !fontThemeComp || !themeComp || !editorViewModule) return; - const themeExt = await loadEditorTheme(ss.theme, ss.appAppearance); + const themeExt = await loadEditorTheme(ss.theme, ss.appAppearance, ss.customColors); previewView.value.dispatch({ effects: [ themeComp.reconfigure(themeExt), @@ -1102,7 +1159,7 @@ watch(previewRef, async (el) => { themeComp = new Compartment(); const ss = previewSettings.value; - const themeExt = await loadEditorTheme(ss.theme, ss.appAppearance); + const themeExt = await loadEditorTheme(ss.theme, ss.appAppearance, ss.customColors); const state = EditorState.create({ doc: previewSql, @@ -1160,9 +1217,9 @@ watch(
-
+
-
+
- -
- - + +
+
+ + +
+
@@ -2548,6 +2616,14 @@ watch(
+ + + diff --git a/apps/desktop/src/components/editor/QueryEditor.vue b/apps/desktop/src/components/editor/QueryEditor.vue index 17652fe23..475e064f2 100644 --- a/apps/desktop/src/components/editor/QueryEditor.vue +++ b/apps/desktop/src/components/editor/QueryEditor.vue @@ -1,5 +1,15 @@ + +