From 56572bd255c5d626d88acfb27d2b22f551412dcf Mon Sep 17 00:00:00 2001 From: hanhvs Date: Tue, 8 Sep 2026 11:34:15 +0700 Subject: [PATCH] feat(settings): SQL File Size tab with configurable web upload limit Group SQL file size settings into a dedicated settings tab: - Editor limit (from previous commit) moves from the Data tab - New web upload limit for the web Execute SQL File streaming path, persisted in storage (default 200 MB, clamped 1-4096 MB), editable from the web settings dialog and exposed via GET/PUT /api/app-settings/sql-file-upload-max-bytes - The /sql-file/preview body limit becomes a hard upper bound; the effective per-request limit is enforced in the handlers - Web dialog fetches the effective limit for its client-side pre-check - i18n across all locales; settings search + transfer category maps --- .../editor/EditorSettingsDialog.vue | 121 +++++++++++++++--- .../sql-file/SqlFileExecutionDialog.vue | 23 +++- apps/desktop/src/i18n/locales/en.ts | 4 + apps/desktop/src/i18n/locales/es.ts | 4 + apps/desktop/src/i18n/locales/it.ts | 4 + apps/desktop/src/i18n/locales/ja.ts | 4 + apps/desktop/src/i18n/locales/ko.ts | 4 + apps/desktop/src/i18n/locales/pt-BR.ts | 4 + apps/desktop/src/i18n/locales/tr.ts | 4 + apps/desktop/src/i18n/locales/zh-CN.ts | 4 + apps/desktop/src/i18n/locales/zh-TW.ts | 4 + apps/desktop/src/lib/backend/api.ts | 2 + apps/desktop/src/lib/backend/http.ts | 13 ++ apps/desktop/src/lib/backend/tauri.ts | 8 ++ .../src/lib/settings/settingsSearch.ts | 4 +- .../src/lib/settings/settingsTransfer.ts | 1 + crates/dbx-core/src/sql_file_import.rs | 7 + crates/dbx-core/src/storage.rs | 69 +++++++++- crates/dbx-web/src/main.rs | 9 +- crates/dbx-web/src/routes/app_settings.rs | 19 +++ crates/dbx-web/src/routes/sql_file.rs | 54 ++++++-- 21 files changed, 329 insertions(+), 37 deletions(-) diff --git a/apps/desktop/src/components/editor/EditorSettingsDialog.vue b/apps/desktop/src/components/editor/EditorSettingsDialog.vue index 0f2781fe52..58693204d1 100644 --- a/apps/desktop/src/components/editor/EditorSettingsDialog.vue +++ b/apps/desktop/src/components/editor/EditorSettingsDialog.vue @@ -138,6 +138,8 @@ import { saveMaxAgentTurns, loadMaxRetries, saveMaxRetries, + loadSqlFileUploadMaxBytes, + saveSqlFileUploadMaxMb, saveWebdavSyncSecretsPreference, saveWebdavSavedPassword, saveSnippetSavedToken, @@ -2389,6 +2391,7 @@ const settingsCategoryNav = computed<{ value: SettingsCategory; label: string }[ { value: "formatter", label: t("settings.sqlFormatterTab") }, { value: "navigation", label: t("settings.navigationTab") }, { value: "data", label: t("settings.dataTab") }, + { value: "sqlFile", label: t("settings.sqlFileSizeTab") }, ...(isWeb ? [] : [{ value: "backups" as const, label: t("databaseBackup.title") }]), { value: "tunnels", label: t("settings.tunnelsTab") }, { value: "shortcuts", label: t("settings.shortcutsTab") }, @@ -2399,7 +2402,7 @@ const settingsCategoryNav = computed<{ value: SettingsCategory; label: string }[ ...(isWeb ? [{ value: "security" as const, label: t("settings.securityTab") }] : []), { value: "about", label: t("settings.aboutTab") }, ]); -const settingsTabsWithApplyFooter = new Set(["editor", "formatter", "appearance", "navigation", "data", "shortcuts", "snippets"]); +const settingsTabsWithApplyFooter = new Set(["editor", "formatter", "appearance", "navigation", "data", "sqlFile", "shortcuts", "snippets"]); function hasSettingsApplyFooter(value: SettingsCategory): boolean { return settingsTabsWithApplyFooter.has(value); @@ -3847,6 +3850,7 @@ watch(activeSettingsTab, async (tab) => { await promptTemplateStore.ensureLoaded(); editGlobalInstructions.value = promptTemplateStore.globalInstructions; } + if (tab === "sqlFile" && isWeb) void loadWebSqlFileUploadMaxMbSetting(); if (tab === "about" && !appSupportInfo.value) void refreshAppSupportInfo(); if (tab === "appearance") { checkLayoutDescTruncation(); @@ -4154,6 +4158,52 @@ function normalizeMaxRetries(value: number | undefined): number { return Math.min(10, Math.max(0, rounded)); } +const editWebSqlFileUploadMaxMb = ref(undefined); +const webSqlFileUploadMaxMbSaving = ref(false); +const webSqlFileUploadMaxMbLoaded = ref(false); +const webSqlFileUploadMaxMbLoading = ref(false); +const webSqlFileUploadMaxMbLoadError = ref(""); + +async function loadWebSqlFileUploadMaxMbSetting() { + if (webSqlFileUploadMaxMbLoaded.value || webSqlFileUploadMaxMbLoading.value) return; + webSqlFileUploadMaxMbLoading.value = true; + webSqlFileUploadMaxMbLoadError.value = ""; + try { + const bytes = await loadSqlFileUploadMaxBytes(); + editWebSqlFileUploadMaxMb.value = Math.round(bytes / (1024 * 1024)); + webSqlFileUploadMaxMbLoaded.value = true; + } catch (e: any) { + webSqlFileUploadMaxMbLoadError.value = e?.message || String(e); + toast(webSqlFileUploadMaxMbLoadError.value, 5000); + } finally { + webSqlFileUploadMaxMbLoading.value = false; + } +} + +function normalizeWebSqlFileUploadMaxMb(value: number | undefined): number { + const rounded = typeof value === "number" && Number.isFinite(value) ? Math.round(value) : 200; + return Math.min(MAX_EXTERNAL_SQL_EDITOR_FILE_MB, Math.max(MIN_EXTERNAL_SQL_EDITOR_FILE_MB, rounded)); +} + +function webSqlFileUploadMaxMbOutOfRange(value: number | undefined): boolean { + return typeof value === "number" && (value < MIN_EXTERNAL_SQL_EDITOR_FILE_MB || value > MAX_EXTERNAL_SQL_EDITOR_FILE_MB); +} + +async function saveWebSqlFileUploadMaxMbSetting() { + if (!webSqlFileUploadMaxMbLoaded.value) return; + const clamped = normalizeWebSqlFileUploadMaxMb(editWebSqlFileUploadMaxMb.value); + webSqlFileUploadMaxMbSaving.value = true; + try { + await saveSqlFileUploadMaxMb(clamped); + editWebSqlFileUploadMaxMb.value = clamped; + toast(t("settings.sqlFileUploadMaxMbSaved")); + } catch (e: any) { + toast(e?.message || String(e), 5000); + } finally { + webSqlFileUploadMaxMbSaving.value = false; + } +} + // AI Config Delete Confirmation const aiDeleteConfirmOpen = ref(false); const aiDeleteConfigId = ref(null); @@ -6971,26 +7021,6 @@ onUnmounted(() => { -
-
- -

- {{ t("settings.externalSqlEditorMaxMbDescription", { min: MIN_EXTERNAL_SQL_EDITOR_FILE_MB, max: MAX_EXTERNAL_SQL_EDITOR_FILE_MB }) }} -

-
- -
+
+
+
+ +

+ {{ t("settings.externalSqlEditorMaxMbDescription", { min: MIN_EXTERNAL_SQL_EDITOR_FILE_MB, max: MAX_EXTERNAL_SQL_EDITOR_FILE_MB }) }} +

+
+ +
+
+
+ +

+ {{ t("settings.webSqlFileUploadMaxMbDescription", { min: MIN_EXTERNAL_SQL_EDITOR_FILE_MB, max: MAX_EXTERNAL_SQL_EDITOR_FILE_MB }) }} +

+
+
+ + +
+
+
+
diff --git a/apps/desktop/src/components/sql-file/SqlFileExecutionDialog.vue b/apps/desktop/src/components/sql-file/SqlFileExecutionDialog.vue index e909477bfe..9a2f52e4da 100644 --- a/apps/desktop/src/components/sql-file/SqlFileExecutionDialog.vue +++ b/apps/desktop/src/components/sql-file/SqlFileExecutionDialog.vue @@ -1,5 +1,5 @@