feat: configurable toolbar visibility with settings UI
This commit is contained in:
parent
4a264d638c
commit
21fd98d0ee
|
|
@ -14,7 +14,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
|
|||
import { Separator } from "@/components/ui/separator";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from "@/components/ui/tooltip";
|
||||
import {
|
||||
useSettingsStore,
|
||||
AI_PROVIDER_PRESETS,
|
||||
|
|
@ -104,6 +104,7 @@ const editSidebarHiddenTablePrefixes = ref(settingsStore.editorSettings.sidebarH
|
|||
const editSidebarHideTableComments = ref(settingsStore.editorSettings.sidebarHideTableComments);
|
||||
const editSidebarAllowHorizontalScroll = ref(settingsStore.editorSettings.sidebarAllowHorizontalScroll);
|
||||
const editExportBatchSize = ref(settingsStore.editorSettings.exportBatchSize);
|
||||
const editToolbarItems = ref({ ...settingsStore.editorSettings.toolbarItems });
|
||||
const redisScanPageSizeOptions = [200, 1000, 5000, 10000];
|
||||
const systemFonts = ref<string[]>([]);
|
||||
const systemFontsLoading = ref(false);
|
||||
|
|
@ -263,6 +264,7 @@ watch(
|
|||
editSidebarHideTableComments.value = settingsStore.editorSettings.sidebarHideTableComments;
|
||||
editSidebarAllowHorizontalScroll.value = settingsStore.editorSettings.sidebarAllowHorizontalScroll;
|
||||
editExportBatchSize.value = settingsStore.editorSettings.exportBatchSize;
|
||||
editToolbarItems.value = { ...settingsStore.editorSettings.toolbarItems };
|
||||
editSnippets.value = settingsStore.editorSettings.snippets.map((s) => ({ ...s }));
|
||||
void loadSystemFontOptions();
|
||||
}
|
||||
|
|
@ -314,6 +316,7 @@ function hasChanges(): boolean {
|
|||
editSidebarHideTableComments.value !== settingsStore.editorSettings.sidebarHideTableComments ||
|
||||
editSidebarAllowHorizontalScroll.value !== settingsStore.editorSettings.sidebarAllowHorizontalScroll ||
|
||||
editExportBatchSize.value !== settingsStore.editorSettings.exportBatchSize ||
|
||||
JSON.stringify(editToolbarItems.value) !== JSON.stringify(settingsStore.editorSettings.toolbarItems) ||
|
||||
JSON.stringify(normalizeSidebarHiddenTablePrefixes(editSidebarHiddenTablePrefixes.value)) !== JSON.stringify(settingsStore.editorSettings.sidebarHiddenTablePrefixes) ||
|
||||
JSON.stringify(editSnippets.value) !== JSON.stringify(settingsStore.editorSettings.snippets)
|
||||
);
|
||||
|
|
@ -349,6 +352,7 @@ async function persistSettings() {
|
|||
sidebarAllowHorizontalScroll: editSidebarAllowHorizontalScroll.value,
|
||||
sidebarHiddenTablePrefixes: normalizeSidebarHiddenTablePrefixes(editSidebarHiddenTablePrefixes.value),
|
||||
exportBatchSize: editExportBatchSize.value,
|
||||
toolbarItems: { ...editToolbarItems.value },
|
||||
snippets: editSnippets.value,
|
||||
});
|
||||
await settingsStore.updateDesktopSettings({
|
||||
|
|
@ -401,6 +405,7 @@ function resetDefaults() {
|
|||
editSidebarAllowHorizontalScroll.value = DEFAULT_EDITOR_SETTINGS.sidebarAllowHorizontalScroll;
|
||||
editSidebarHiddenTablePrefixes.value = DEFAULT_EDITOR_SETTINGS.sidebarHiddenTablePrefixes.join("\n");
|
||||
editExportBatchSize.value = DEFAULT_EDITOR_SETTINGS.exportBatchSize;
|
||||
editToolbarItems.value = { ...DEFAULT_EDITOR_SETTINGS.toolbarItems };
|
||||
editSnippets.value = DEFAULT_SQL_SNIPPETS.map((s) => ({ ...s }));
|
||||
}
|
||||
|
||||
|
|
@ -1602,6 +1607,46 @@ watch(
|
|||
<Switch id="compact-column-header-actions" v-model="editCompactColumnHeaderActions" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<Label>{{ t("settings.toolbarTitle") }}</Label>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<CircleHelp class="h-3.5 w-3.5 text-muted-foreground cursor-help" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent class="max-w-64">
|
||||
<p>{{ t("settings.toolbarHiddenHint") }}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
<div class="grid grid-cols-3 gap-2 mt-2">
|
||||
<div
|
||||
v-for="item in [
|
||||
{ key: 'dataTransfer', label: t('transfer.dataTransfer') },
|
||||
{ key: 'driverManager', label: t('toolbar.driverManager') },
|
||||
{ key: 'sqlFile', label: t('sqlFile.title') },
|
||||
{ key: 'schemaDiff', label: t('diff.title') },
|
||||
{ key: 'dataCompare', label: t('dataCompare.title') },
|
||||
{ key: 'checkUpdates', label: t('updates.check') },
|
||||
{ key: 'sqlLibrary', label: t('sqlLibrary.title') },
|
||||
{ key: 'history', label: t('history.title') },
|
||||
{ key: 'ai', label: 'AI' },
|
||||
{ key: 'theme', label: t('toolbar.theme') },
|
||||
{ key: 'github', label: 'GitHub' },
|
||||
]"
|
||||
:key="item.key"
|
||||
class="flex items-center gap-2"
|
||||
>
|
||||
<Switch :id="`toolbar-${item.key}`" :model-value="(editToolbarItems as any)[item.key]" @update:model-value="(v: boolean) => ((editToolbarItems as any)[item.key] = v)" />
|
||||
<Label :for="`toolbar-${item.key}`" class="text-sm cursor-pointer">{{ item.label }}</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-else-if="activeSettingsTab === 'navigation'" class="flex flex-col gap-5 py-2">
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import LightDropdown from "@/components/ui/LightDropdown.vue";
|
|||
import WindowControls from "@/components/layout/WindowControls.vue";
|
||||
import ExportProgressPopover from "@/components/export/ExportProgressPopover.vue";
|
||||
import { shouldReserveMacTrafficLightInset, useWindowControls } from "@/composables/useWindowControls";
|
||||
import { useSettingsStore } from "@/stores/settingsStore";
|
||||
import type { AppThemeMode } from "@/lib/appTheme";
|
||||
|
||||
const props = defineProps<{
|
||||
|
|
@ -42,6 +43,8 @@ const emit = defineEmits<{
|
|||
}>();
|
||||
|
||||
const { t } = useI18n();
|
||||
const settingsStore = useSettingsStore();
|
||||
const toolbarItems = computed(() => settingsStore.editorSettings.toolbarItems);
|
||||
const { isMac, isDesktop, showControls, isMaximized, isFullscreen, minimize, toggleMaximize, close } = useWindowControls();
|
||||
|
||||
const themeItems = computed(() => [
|
||||
|
|
@ -82,47 +85,89 @@ onBeforeUnmount(() => {
|
|||
resizeObserver?.disconnect();
|
||||
});
|
||||
|
||||
const moreItems = computed(() => [
|
||||
{
|
||||
value: "sql-file",
|
||||
label: t("sqlFile.title"),
|
||||
icon: FileCode,
|
||||
action: () => emit("open-sql-file"),
|
||||
disabled: !props.hasSqlFileConnections,
|
||||
},
|
||||
{
|
||||
value: "schema-diff",
|
||||
label: t("diff.title"),
|
||||
icon: GitCompareArrows,
|
||||
action: () => emit("open-schema-diff"),
|
||||
disabled: !props.hasConnections,
|
||||
},
|
||||
{
|
||||
value: "data-compare",
|
||||
label: t("dataCompare.title"),
|
||||
icon: TableProperties,
|
||||
action: () => emit("open-data-compare"),
|
||||
disabled: !props.hasConnections,
|
||||
},
|
||||
]);
|
||||
const moreItems = computed(() => {
|
||||
const items: Array<{ value: string; label: string; icon: any; action: () => void; disabled: boolean }> = [];
|
||||
|
||||
const collapsedItems = computed(() => [
|
||||
{
|
||||
value: "transfer",
|
||||
label: t("transfer.dataTransfer"),
|
||||
icon: ArrowLeftRight,
|
||||
action: () => emit("open-transfer"),
|
||||
disabled: !props.hasConnections,
|
||||
},
|
||||
...moreItems.value,
|
||||
{
|
||||
value: "driver-store",
|
||||
label: props.agentDriverUpdateCount > 0 ? `${t("toolbar.driverManager")} (${props.agentDriverUpdateCount})` : t("toolbar.driverManager"),
|
||||
icon: Package,
|
||||
action: () => emit("open-driver-store"),
|
||||
disabled: false,
|
||||
},
|
||||
]);
|
||||
// Hidden left-side items go into "更多"
|
||||
if (!toolbarItems.value.dataTransfer) {
|
||||
items.push({
|
||||
value: "transfer",
|
||||
label: t("transfer.dataTransfer"),
|
||||
icon: ArrowLeftRight,
|
||||
action: () => emit("open-transfer"),
|
||||
disabled: !props.hasConnections,
|
||||
});
|
||||
}
|
||||
if (!toolbarItems.value.driverManager) {
|
||||
items.push({
|
||||
value: "driver-store",
|
||||
label: t("toolbar.driverManager"),
|
||||
icon: Package,
|
||||
action: () => emit("open-driver-store"),
|
||||
disabled: false,
|
||||
});
|
||||
}
|
||||
|
||||
// "更多" menu items (individually toggleable)
|
||||
if (toolbarItems.value.sqlFile) {
|
||||
items.push({
|
||||
value: "sql-file",
|
||||
label: t("sqlFile.title"),
|
||||
icon: FileCode,
|
||||
action: () => emit("open-sql-file"),
|
||||
disabled: !props.hasSqlFileConnections,
|
||||
});
|
||||
}
|
||||
if (toolbarItems.value.schemaDiff) {
|
||||
items.push({
|
||||
value: "schema-diff",
|
||||
label: t("diff.title"),
|
||||
icon: GitCompareArrows,
|
||||
action: () => emit("open-schema-diff"),
|
||||
disabled: !props.hasConnections,
|
||||
});
|
||||
}
|
||||
if (toolbarItems.value.dataCompare) {
|
||||
items.push({
|
||||
value: "data-compare",
|
||||
label: t("dataCompare.title"),
|
||||
icon: TableProperties,
|
||||
action: () => emit("open-data-compare"),
|
||||
disabled: !props.hasConnections,
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
});
|
||||
|
||||
const showMoreDropdown = computed(() => moreItems.value.length > 0);
|
||||
|
||||
const collapsedItems = computed(() => {
|
||||
const items: Array<{ value: string; label: string; icon: any; action: () => void; disabled: boolean }> = [];
|
||||
if (toolbarItems.value.dataTransfer) {
|
||||
items.push({
|
||||
value: "transfer",
|
||||
label: t("transfer.dataTransfer"),
|
||||
icon: ArrowLeftRight,
|
||||
action: () => emit("open-transfer"),
|
||||
disabled: !props.hasConnections,
|
||||
});
|
||||
}
|
||||
if (toolbarItems.value.driverManager) {
|
||||
items.push({
|
||||
value: "driver-store",
|
||||
label: props.agentDriverUpdateCount > 0 ? `${t("toolbar.driverManager")} (${props.agentDriverUpdateCount})` : t("toolbar.driverManager"),
|
||||
icon: Package,
|
||||
action: () => emit("open-driver-store"),
|
||||
disabled: false,
|
||||
});
|
||||
}
|
||||
// Always include moreItems (may contain hidden left-side items)
|
||||
if (moreItems.value.length > 0) {
|
||||
items.push(...moreItems.value);
|
||||
}
|
||||
return items;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -138,12 +183,12 @@ const collapsedItems = computed(() => [
|
|||
</Button>
|
||||
|
||||
<template v-if="!toolbarCollapsed">
|
||||
<Button variant="ghost" size="sm" class="h-8 px-2 text-xs gap-1" @click="emit('open-transfer')" :disabled="!hasConnections">
|
||||
<Button v-if="toolbarItems.dataTransfer" variant="ghost" size="sm" class="h-8 px-2 text-xs gap-1" @click="emit('open-transfer')" :disabled="!hasConnections">
|
||||
<ArrowLeftRight class="h-3.5 w-3.5" />
|
||||
{{ t("transfer.dataTransfer") }}
|
||||
</Button>
|
||||
|
||||
<Button variant="ghost" size="sm" class="h-8 px-2 text-xs gap-1" :class="{ 'bg-accent': showDriverStore }" @click="emit('open-driver-store')">
|
||||
<Button v-if="toolbarItems.driverManager" variant="ghost" size="sm" class="h-8 px-2 text-xs gap-1" :class="{ 'bg-accent': showDriverStore }" @click="emit('open-driver-store')">
|
||||
<Package class="h-3.5 w-3.5" />
|
||||
{{ t("toolbar.driverManager") }}
|
||||
<span v-if="agentDriverUpdateCount > 0" class="ml-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-medium leading-none text-white" :aria-label="t('toolbar.updatableDriverCount')">
|
||||
|
|
@ -152,6 +197,7 @@ const collapsedItems = computed(() => [
|
|||
</Button>
|
||||
|
||||
<LightDropdown
|
||||
v-if="showMoreDropdown"
|
||||
model-value=""
|
||||
:items="moreItems"
|
||||
:aria-label="t('common.more')"
|
||||
|
|
@ -172,6 +218,7 @@ const collapsedItems = computed(() => [
|
|||
|
||||
<template v-if="toolbarCollapsed">
|
||||
<LightDropdown
|
||||
v-if="collapsedItems.length > 0"
|
||||
model-value=""
|
||||
:items="collapsedItems"
|
||||
:aria-label="t('common.more')"
|
||||
|
|
@ -192,20 +239,22 @@ const collapsedItems = computed(() => [
|
|||
|
||||
<div class="flex-1" data-tauri-drag-region />
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="relative h-8 w-8" :disabled="checkingUpdates" @click="emit('check-updates')">
|
||||
<Loader2 v-if="checkingUpdates" class="h-4 w-4 animate-spin" />
|
||||
<CloudDownload v-else class="h-4 w-4" />
|
||||
<span v-if="hasUpdateAvailable" class="absolute right-1.5 top-1.5 h-2 w-2 rounded-full bg-red-500 ring-2 ring-background" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("updates.check") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
<template v-if="toolbarItems.checkUpdates">
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="relative h-8 w-8" :disabled="checkingUpdates" @click="emit('check-updates')">
|
||||
<Loader2 v-if="checkingUpdates" class="h-4 w-4 animate-spin" />
|
||||
<CloudDownload v-else class="h-4 w-4" />
|
||||
<span v-if="hasUpdateAvailable" class="absolute right-1.5 top-1.5 h-2 w-2 rounded-full bg-red-500 ring-2 ring-background" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("updates.check") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</template>
|
||||
|
||||
<ExportProgressPopover />
|
||||
|
||||
<Tooltip>
|
||||
<Tooltip v-if="toolbarItems.sqlLibrary">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="h-8 w-8" :class="{ 'bg-accent': showSqlLibrary }" @click="emit('toggle-sql-library')">
|
||||
<BookMarked class="h-4 w-4" />
|
||||
|
|
@ -214,7 +263,7 @@ const collapsedItems = computed(() => [
|
|||
<TooltipContent>{{ t("sqlLibrary.title") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip>
|
||||
<Tooltip v-if="toolbarItems.history">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="h-8 w-8" :class="{ 'bg-accent': showHistory }" @click="emit('toggle-history')">
|
||||
<History class="h-4 w-4" />
|
||||
|
|
@ -223,7 +272,7 @@ const collapsedItems = computed(() => [
|
|||
<TooltipContent>{{ t("history.title") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip>
|
||||
<Tooltip v-if="toolbarItems.ai">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="h-8 w-8" :class="{ 'bg-accent': showAiPanel }" @click="emit('toggle-ai')">
|
||||
<Bot class="h-4 w-4" />
|
||||
|
|
@ -232,7 +281,7 @@ const collapsedItems = computed(() => [
|
|||
<TooltipContent>AI</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip>
|
||||
<Tooltip v-if="toolbarItems.theme">
|
||||
<TooltipTrigger as-child>
|
||||
<span class="inline-flex">
|
||||
<LightDropdown
|
||||
|
|
@ -254,7 +303,7 @@ const collapsedItems = computed(() => [
|
|||
<TooltipContent>{{ t("toolbar.theme") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip>
|
||||
<Tooltip v-if="toolbarItems.github">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="ghost" size="icon" class="h-8 w-8" @click="emit('open-github')">
|
||||
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="currentColor">
|
||||
|
|
|
|||
|
|
@ -1829,6 +1829,8 @@
|
|||
useCustomFont: "Use “{font}”",
|
||||
languageTitle: "Language / 语言",
|
||||
fontSize: "Font Size",
|
||||
toolbarTitle: "Toolbar",
|
||||
toolbarHiddenHint: 'Hidden left-side buttons will appear in the "More" dropdown.',
|
||||
uiScale: "UI Scale",
|
||||
uiScaleDescription: "Scale the entire desktop UI for high-DPI displays. Changes apply immediately and are restored on next launch.",
|
||||
theme: "Theme",
|
||||
|
|
|
|||
|
|
@ -1608,6 +1608,8 @@
|
|||
useCustomFont: "Usar “{font}”",
|
||||
languageTitle: "Idioma / Language",
|
||||
fontSize: "Tamaño de fuente",
|
||||
toolbarTitle: "Barra de herramientas",
|
||||
toolbarHiddenHint: "Los botones ocultos de la izquierda aparecerán en el menú «Más».",
|
||||
uiScale: "Escala de interfaz",
|
||||
uiScaleDescription: "Escala toda la interfaz de escritorio para pantallas de alta densidad. Los cambios se aplican al instante y se restauran al volver a abrir.",
|
||||
theme: "Tema",
|
||||
|
|
|
|||
|
|
@ -1725,6 +1725,8 @@
|
|||
useCustomFont: "Usa “{font}”",
|
||||
languageTitle: "Lingua / Language",
|
||||
fontSize: "Dimensione Carattere",
|
||||
toolbarTitle: "Barra degli strumenti",
|
||||
toolbarHiddenHint: "I pulsanti nascosti a sinistra appariranno nel menu «Altro».",
|
||||
uiScale: "Scala UI",
|
||||
uiScaleDescription: "Scala l'intera interfaccia utente desktop per display ad alta densità (High-DPI). Le modifiche si applicano immediatamente e vengono ripristinate al prossimo avvio.",
|
||||
theme: "Tema",
|
||||
|
|
|
|||
|
|
@ -1725,6 +1725,8 @@
|
|||
useCustomFont: "Usar “{font}”",
|
||||
languageTitle: "Idioma / 语言",
|
||||
fontSize: "Tamanho da fonte",
|
||||
toolbarTitle: "Barra de ferramentas",
|
||||
toolbarHiddenHint: "Os botões ocultos à esquerda aparecerão no menu «Mais».",
|
||||
uiScale: "Escala da UI",
|
||||
uiScaleDescription: "Dimensione toda a UI do desktop para telas de alta resolução (high-DPI). As alterações são aplicadas imediatamente e restauradas na próxima inicialização.",
|
||||
theme: "Tema",
|
||||
|
|
|
|||
|
|
@ -1828,6 +1828,8 @@
|
|||
useCustomFont: "使用“{font}”",
|
||||
languageTitle: "语言 / Language",
|
||||
fontSize: "字号",
|
||||
toolbarTitle: "工具栏",
|
||||
toolbarHiddenHint: '关闭的左侧按钮会自动收进"更多"下拉菜单。',
|
||||
uiScale: "界面缩放",
|
||||
uiScaleDescription: "按比例缩放整个桌面端界面,适合高清屏;修改后立即生效,并在下次启动时恢复。",
|
||||
theme: "主题",
|
||||
|
|
|
|||
|
|
@ -1700,6 +1700,8 @@
|
|||
useCustomFont: "使用「{font}」",
|
||||
languageTitle: "語言 / Language",
|
||||
fontSize: "字級",
|
||||
toolbarTitle: "工具列",
|
||||
toolbarHiddenHint: "關閉的左側按鈕會自動收進「更多」下拉選單。",
|
||||
uiScale: "介面縮放",
|
||||
uiScaleDescription: "按比例縮放整個桌面端介面,適合高 DPI 螢幕;修改後立即生效,並在下次啟動時復原。",
|
||||
theme: "主題",
|
||||
|
|
|
|||
|
|
@ -260,8 +260,37 @@ export interface EditorSettings {
|
|||
customColumnFormatters: Record<string, CustomColumnFormatterConfig>;
|
||||
snippets: SqlSnippet[];
|
||||
exportBatchSize: number;
|
||||
toolbarItems: ToolbarItems;
|
||||
}
|
||||
|
||||
export interface ToolbarItems {
|
||||
dataTransfer: boolean;
|
||||
driverManager: boolean;
|
||||
sqlFile: boolean;
|
||||
schemaDiff: boolean;
|
||||
dataCompare: boolean;
|
||||
checkUpdates: boolean;
|
||||
sqlLibrary: boolean;
|
||||
history: boolean;
|
||||
ai: boolean;
|
||||
theme: boolean;
|
||||
github: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_TOOLBAR_ITEMS: ToolbarItems = {
|
||||
dataTransfer: true,
|
||||
driverManager: true,
|
||||
sqlFile: true,
|
||||
schemaDiff: true,
|
||||
dataCompare: true,
|
||||
checkUpdates: true,
|
||||
sqlLibrary: true,
|
||||
history: true,
|
||||
ai: true,
|
||||
theme: true,
|
||||
github: true,
|
||||
};
|
||||
|
||||
export const EDITOR_THEMES: { value: EditorTheme; label: string; dark: boolean }[] = [
|
||||
{ value: "app", label: "Follow app theme", dark: false },
|
||||
{ value: "one-dark", label: "One Dark", dark: true },
|
||||
|
|
@ -327,6 +356,7 @@ export const DEFAULT_EDITOR_SETTINGS: EditorSettings = {
|
|||
customColumnFormatters: {},
|
||||
snippets: DEFAULT_SQL_SNIPPETS,
|
||||
exportBatchSize: 10000,
|
||||
toolbarItems: { ...DEFAULT_TOOLBAR_ITEMS },
|
||||
};
|
||||
|
||||
export const STORAGE_KEY = "dbx-editor-settings";
|
||||
|
|
@ -404,6 +434,24 @@ function normalizeSqlSnippets(value: unknown, existing?: SqlSnippet[]): SqlSnipp
|
|||
return valid;
|
||||
}
|
||||
|
||||
function normalizeToolbarItems(items: Partial<ToolbarItems> | undefined): ToolbarItems {
|
||||
const defaults = DEFAULT_TOOLBAR_ITEMS;
|
||||
if (!items || typeof items !== "object") return { ...defaults };
|
||||
return {
|
||||
dataTransfer: items.dataTransfer ?? defaults.dataTransfer,
|
||||
driverManager: items.driverManager ?? defaults.driverManager,
|
||||
sqlFile: items.sqlFile ?? defaults.sqlFile,
|
||||
schemaDiff: items.schemaDiff ?? defaults.schemaDiff,
|
||||
dataCompare: items.dataCompare ?? defaults.dataCompare,
|
||||
checkUpdates: items.checkUpdates ?? defaults.checkUpdates,
|
||||
sqlLibrary: items.sqlLibrary ?? defaults.sqlLibrary,
|
||||
history: items.history ?? defaults.history,
|
||||
ai: items.ai ?? defaults.ai,
|
||||
theme: items.theme ?? defaults.theme,
|
||||
github: items.github ?? defaults.github,
|
||||
};
|
||||
}
|
||||
|
||||
export function normalizeEditorSettings(settings: Partial<EditorSettings>, existing?: EditorSettings): EditorSettings {
|
||||
return {
|
||||
fontFamily: settings.fontFamily ?? DEFAULT_EDITOR_SETTINGS.fontFamily,
|
||||
|
|
@ -463,6 +511,7 @@ export function normalizeEditorSettings(settings: Partial<EditorSettings>, exist
|
|||
customColumnFormatters: normalizeCustomColumnFormatters(settings.customColumnFormatters),
|
||||
snippets: normalizeSqlSnippets(settings.snippets, existing?.snippets),
|
||||
exportBatchSize: typeof settings.exportBatchSize === "number" && settings.exportBatchSize >= 100 && settings.exportBatchSize <= 100000 ? Math.round(settings.exportBatchSize) : DEFAULT_EDITOR_SETTINGS.exportBatchSize,
|
||||
toolbarItems: normalizeToolbarItems(settings.toolbarItems),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -617,6 +666,7 @@ export const useSettingsStore = defineStore("settings", () => {
|
|||
if (partial.customColumnFormatters !== undefined) editorSettings.value.customColumnFormatters = partial.customColumnFormatters;
|
||||
if (partial.snippets !== undefined) editorSettings.value.snippets = normalizeSqlSnippets(partial.snippets);
|
||||
if (partial.exportBatchSize !== undefined) editorSettings.value.exportBatchSize = Math.min(100000, Math.max(100, Math.round(partial.exportBatchSize)));
|
||||
if (partial.toolbarItems !== undefined) editorSettings.value.toolbarItems = normalizeToolbarItems(partial.toolbarItems);
|
||||
saveEditorSettings(editorSettings.value);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue