feat: add export and import settings functionality with UI integration

This commit is contained in:
Flavio Fois
2026-02-05 22:19:39 +01:00
parent 6a44eba7ca
commit f551efd5bf
4 changed files with 167 additions and 3 deletions

View File

@@ -109,5 +109,16 @@
"bugreport_open_folder": "Open Folder",
"bugreport_close": "Close",
"bugreport_error": "Failed to create bug report.",
"bugreport_copied": "Path copied to clipboard!"
"bugreport_copied": "Path copied to clipboard!",
"settings_export_import_title": "Export / Import Settings",
"settings_export_import_description": "Export your current settings to a file or import settings from a previously exported file.",
"settings_export_button": "Export Settings",
"settings_export_hint": "Save your current settings to a JSON file.",
"settings_import_button": "Import Settings",
"settings_import_hint": "Load settings from a previously exported JSON file.",
"settings_export_success": "Settings exported successfully!",
"settings_export_error": "Failed to export settings.",
"settings_import_success": "Settings imported successfully!",
"settings_import_error": "Failed to import settings.",
"settings_import_invalid": "Invalid settings file."
}

View File

@@ -109,5 +109,16 @@
"bugreport_open_folder": "Apri Cartella",
"bugreport_close": "Chiudi",
"bugreport_error": "Impossibile creare la segnalazione bug.",
"bugreport_copied": "Percorso copiato negli appunti!"
"bugreport_copied": "Percorso copiato negli appunti!",
"settings_export_import_title": "Esporta / Importa Impostazioni",
"settings_export_import_description": "Esporta le impostazioni correnti in un file o importa impostazioni da un file precedentemente esportato.",
"settings_export_button": "Esporta Impostazioni",
"settings_export_hint": "Salva le impostazioni correnti in un file JSON.",
"settings_import_button": "Importa Impostazioni",
"settings_import_hint": "Carica impostazioni da un file JSON precedentemente esportato.",
"settings_export_success": "Impostazioni esportate con successo!",
"settings_export_error": "Impossibile esportare le impostazioni.",
"settings_import_success": "Impostazioni importate con successo!",
"settings_import_error": "Impossibile importare le impostazioni.",
"settings_import_invalid": "File impostazioni non valido."
}

View File

@@ -6,7 +6,7 @@
import { Label } from "$lib/components/ui/label";
import { Separator } from "$lib/components/ui/separator";
import { Switch } from "$lib/components/ui/switch";
import { ChevronLeft, Flame } from "@lucide/svelte";
import { ChevronLeft, Flame, Download, Upload } from "@lucide/svelte";
import type { EMLy_GUI_Settings } from "$lib/types";
import { toast } from "svelte-sonner";
import { It, Us } from "svelte-flags";
@@ -25,6 +25,7 @@
import { setLocale } from "$lib/paraglide/runtime";
import { mailState } from "$lib/stores/mail-state.svelte.js";
import { dev } from '$app/environment';
import { ExportSettings, ImportSettings } from "$lib/wailsjs/go/main/App";
let { data } = $props();
let config = $derived(data.config);
@@ -173,6 +174,42 @@
previousDangerZoneEnabled = $dangerZoneEnabled;
})();
});
async function exportSettings() {
try {
const settingsJSON = JSON.stringify(form, null, 2);
const result = await ExportSettings(settingsJSON);
if (result) {
toast.success(m.settings_export_success());
}
} catch (err) {
console.error("Failed to export settings:", err);
toast.error(m.settings_export_error());
}
}
async function importSettings() {
try {
const result = await ImportSettings();
if (result) {
try {
const imported = JSON.parse(result) as EMLy_GUI_Settings;
// Validate that it looks like a valid settings object
if (typeof imported === 'object' && imported !== null) {
form = normalizeSettings(imported);
toast.success(m.settings_import_success());
} else {
toast.error(m.settings_import_invalid());
}
} catch {
toast.error(m.settings_import_invalid());
}
}
} catch (err) {
console.error("Failed to import settings:", err);
toast.error(m.settings_import_error());
}
}
</script>
<div class="min-h-[calc(100vh-1rem)] from-background to-muted/30">
@@ -244,6 +281,52 @@
</Card.Content>
</Card.Root>
<Card.Root>
<Card.Header class="space-y-1">
<Card.Title>{m.settings_export_import_title()}</Card.Title>
<Card.Description>{m.settings_export_import_description()}</Card.Description>
</Card.Header>
<Card.Content class="space-y-4">
<div
class="flex items-center justify-between gap-4 rounded-lg border bg-card p-4"
>
<div>
<div class="font-medium">{m.settings_export_button()}</div>
<div class="text-sm text-muted-foreground">
{m.settings_export_hint()}
</div>
</div>
<Button
variant="outline"
class="cursor-pointer hover:cursor-pointer"
onclick={exportSettings}
>
<Download class="size-4 mr-2" />
{m.settings_export_button()}
</Button>
</div>
<Separator />
<div
class="flex items-center justify-between gap-4 rounded-lg border bg-card p-4"
>
<div>
<div class="font-medium">{m.settings_import_button()}</div>
<div class="text-sm text-muted-foreground">
{m.settings_import_hint()}
</div>
</div>
<Button
variant="outline"
class="cursor-pointer hover:cursor-pointer"
onclick={importSettings}
>
<Upload class="size-4 mr-2" />
{m.settings_import_button()}
</Button>
</div>
</Card.Content>
</Card.Root>
<Card.Root>
<Card.Header class="space-y-1">
<Card.Title>{m.settings_preview_page_title()}</Card.Title>