feat: implement application restart functionality and update UI reload options
This commit is contained in:
27
app.go
27
app.go
@@ -4,8 +4,10 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -141,6 +143,31 @@ func (a *App) QuitApp() {
|
|||||||
os.Exit(133)
|
os.Exit(133)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RestartApp performs a full application restart, including the Go backend.
|
||||||
|
// It schedules a new process via PowerShell with a short delay to ensure the
|
||||||
|
// single-instance lock is released before the new instance starts, then exits.
|
||||||
|
func (a *App) RestartApp() error {
|
||||||
|
exe, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
Log("RestartApp: failed to get executable path:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escape single quotes in the path for PowerShell string literal
|
||||||
|
safePath := strings.ReplaceAll(exe, "'", "''")
|
||||||
|
script := fmt.Sprintf(`Start-Sleep -Seconds 1; Start-Process '%s'`, safePath)
|
||||||
|
|
||||||
|
cmd := exec.Command("powershell", "-WindowStyle", "Hidden", "-Command", script)
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
Log("RestartApp: failed to schedule restart:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
Log("RestartApp: scheduled restart, quitting current instance...")
|
||||||
|
runtime.Quit(a.ctx)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Configuration Management
|
// Configuration Management
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
[EMLy]
|
[EMLy]
|
||||||
SDK_DECODER_SEMVER = 1.4.2
|
SDK_DECODER_SEMVER = 1.4.2
|
||||||
SDK_DECODER_RELEASE_CHANNEL = beta
|
SDK_DECODER_RELEASE_CHANNEL = beta
|
||||||
GUI_SEMVER = 1.6.0
|
GUI_SEMVER = 1.6.1
|
||||||
GUI_RELEASE_CHANNEL = beta
|
GUI_RELEASE_CHANNEL = beta
|
||||||
LANGUAGE = it
|
LANGUAGE = it
|
||||||
UPDATE_CHECK_ENABLED = false
|
UPDATE_CHECK_ENABLED = true
|
||||||
UPDATE_PATH =
|
UPDATE_PATH = "\\dc-rm2\logo\update"
|
||||||
UPDATE_AUTO_CHECK = false
|
UPDATE_AUTO_CHECK = false
|
||||||
BUGREPORT_API_URL = "https://api.emly.ffois.it"
|
BUGREPORT_API_URL = "https://api.emly.ffois.it"
|
||||||
BUGREPORT_API_KEY = "emly_1BaQdBknsMGcY5DynSby71JnWOKXtJvnuUprkgWT0pujpLFxj5HaTXP9vtJAMk63"
|
BUGREPORT_API_KEY = "emly_1BaQdBknsMGcY5DynSby71JnWOKXtJvnuUprkgWT0pujpLFxj5HaTXP9vtJAMk63"
|
||||||
@@ -41,9 +41,11 @@
|
|||||||
"settings_danger_reset_label": "Reset App Data",
|
"settings_danger_reset_label": "Reset App Data",
|
||||||
"settings_danger_reset_hint": "This will clear all your settings and return the app to its default state.",
|
"settings_danger_reset_hint": "This will clear all your settings and return the app to its default state.",
|
||||||
"settings_danger_reset_button": "Reset data",
|
"settings_danger_reset_button": "Reset data",
|
||||||
"settings_danger_reload_label": "Reload App",
|
"settings_danger_reload_ui_label": "Reload UI",
|
||||||
|
"settings_danger_reload_app_label": "Reload App",
|
||||||
"settings_danger_reload_hint": "Reloads the application interface. Useful if the UI becomes unresponsive.",
|
"settings_danger_reload_hint": "Reloads the application interface. Useful if the UI becomes unresponsive.",
|
||||||
"settings_danger_reload_button": "Reload",
|
"settings_danger_reload_button_ui": "Reload UI",
|
||||||
|
"settings_danger_reload_button_app": "Reload app",
|
||||||
"settings_danger_reset_dialog_title": "Are you absolutely sure?",
|
"settings_danger_reset_dialog_title": "Are you absolutely sure?",
|
||||||
"settings_danger_reset_dialog_description": "This action cannot be undone. This will permanently delete your current settings and return the app to its default state.",
|
"settings_danger_reset_dialog_description": "This action cannot be undone. This will permanently delete your current settings and return the app to its default state.",
|
||||||
"settings_danger_reset_dialog_cancel": "Cancel",
|
"settings_danger_reset_dialog_cancel": "Cancel",
|
||||||
|
|||||||
@@ -41,9 +41,11 @@
|
|||||||
"settings_danger_reset_label": "Reimposta Dati App",
|
"settings_danger_reset_label": "Reimposta Dati App",
|
||||||
"settings_danger_reset_hint": "Questo cancellerà tutte le tue impostazioni e riporterà l'app allo stato predefinito.",
|
"settings_danger_reset_hint": "Questo cancellerà tutte le tue impostazioni e riporterà l'app allo stato predefinito.",
|
||||||
"settings_danger_reset_button": "Reimposta dati",
|
"settings_danger_reset_button": "Reimposta dati",
|
||||||
"settings_danger_reload_label": "Ricarica App",
|
"settings_danger_reload_ui_label": "Ricarica UI",
|
||||||
|
"settings_danger_reload__app_label": "Ricarica App",
|
||||||
"settings_danger_reload_hint": "Ricarica l'interfaccia dell'applicazione. Utile se l'UI non risponde.",
|
"settings_danger_reload_hint": "Ricarica l'interfaccia dell'applicazione. Utile se l'UI non risponde.",
|
||||||
"settings_danger_reload_button": "Ricarica",
|
"settings_danger_reload_button_ui": "Ricarica UI",
|
||||||
|
"settings_danger_reload_button_app": "Ricarica app",
|
||||||
"settings_danger_reset_dialog_title": "Sei assolutamente sicuro?",
|
"settings_danger_reset_dialog_title": "Sei assolutamente sicuro?",
|
||||||
"settings_danger_reset_dialog_description": "Questa azione non può essere annullata. Questo eliminerà permanentemente le tue impostazioni attuali e riporterà l'app allo stato predefinito.",
|
"settings_danger_reset_dialog_description": "Questa azione non può essere annullata. Questo eliminerà permanentemente le tue impostazioni attuali e riporterà l'app allo stato predefinito.",
|
||||||
"settings_danger_reset_dialog_cancel": "Annulla",
|
"settings_danger_reset_dialog_cancel": "Annulla",
|
||||||
|
|||||||
@@ -298,8 +298,8 @@
|
|||||||
href="/"
|
href="/"
|
||||||
class={`${buttonVariants({ variant: "destructive" })} cursor-pointer hover:cursor-pointer`}
|
class={`${buttonVariants({ variant: "destructive" })} cursor-pointer hover:cursor-pointer`}
|
||||||
style="text-decoration: none; margin-left: auto; height: 24px; font-size: 12px; padding: 0 8px;"
|
style="text-decoration: none; margin-left: auto; height: 24px; font-size: 12px; padding: 0 8px;"
|
||||||
aria-label={m.settings_danger_reload_button()}
|
aria-label={m.settings_danger_reload_button_ui()}
|
||||||
title={m.settings_danger_reload_button() + " app"}
|
title={m.settings_danger_reload_button_ui()}
|
||||||
>
|
>
|
||||||
<RefreshCcwDot />
|
<RefreshCcwDot />
|
||||||
</a>
|
</a>
|
||||||
@@ -308,8 +308,8 @@
|
|||||||
href="#"
|
href="#"
|
||||||
class={`${buttonVariants({ variant: "destructive" })} cursor-pointer hover:cursor-pointer`}
|
class={`${buttonVariants({ variant: "destructive" })} cursor-pointer hover:cursor-pointer`}
|
||||||
style="text-decoration: none; height: 24px; font-size: 12px; padding: 0 8px;"
|
style="text-decoration: none; height: 24px; font-size: 12px; padding: 0 8px;"
|
||||||
aria-label={m.settings_danger_reload_button()}
|
aria-label={m.settings_danger_reload_button_ui()}
|
||||||
title={m.settings_danger_reload_button() + " app"}
|
title={m.settings_danger_reload_button_ui() }
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
$bugReportDialogOpen = !$bugReportDialogOpen;
|
$bugReportDialogOpen = !$bugReportDialogOpen;
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import { Label } from "$lib/components/ui/label";
|
import { Label } from "$lib/components/ui/label";
|
||||||
import { Separator } from "$lib/components/ui/separator";
|
import { Separator } from "$lib/components/ui/separator";
|
||||||
import { Switch } from "$lib/components/ui/switch";
|
import { Switch } from "$lib/components/ui/switch";
|
||||||
import { ChevronLeft, Flame, Download, Upload, RefreshCw, CheckCircle2, AlertCircle, Sun, Moon } from "@lucide/svelte";
|
import { ChevronLeft, Flame, Download, Upload, RefreshCw, CheckCircle2, AlertCircle, Sun, Moon, RefreshCcw } from "@lucide/svelte";
|
||||||
import type { EMLy_GUI_Settings } from "$lib/types";
|
import type { EMLy_GUI_Settings } from "$lib/types";
|
||||||
import { toast } from "svelte-sonner";
|
import { toast } from "svelte-sonner";
|
||||||
import { It, Us } from "svelte-flags";
|
import { It, Us } from "svelte-flags";
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
import { setLocale } from "$lib/paraglide/runtime";
|
import { setLocale } from "$lib/paraglide/runtime";
|
||||||
import { mailState } from "$lib/stores/mail-state.svelte.js";
|
import { mailState } from "$lib/stores/mail-state.svelte.js";
|
||||||
import { dev } from '$app/environment';
|
import { dev } from '$app/environment';
|
||||||
import { ExportSettings, ImportSettings, CheckForUpdates, DownloadUpdate, InstallUpdate, GetUpdateStatus, SetUpdateCheckerEnabled } from "$lib/wailsjs/go/main/App";
|
import { ExportSettings, ImportSettings, CheckForUpdates, DownloadUpdate, InstallUpdate, GetUpdateStatus, SetUpdateCheckerEnabled, RestartApp } from "$lib/wailsjs/go/main/App";
|
||||||
import { EventsOn, EventsOff } from "$lib/wailsjs/runtime/runtime";
|
import { EventsOn, EventsOff } from "$lib/wailsjs/runtime/runtime";
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
@@ -257,6 +257,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function restartEntireApp() {
|
||||||
|
try {
|
||||||
|
await RestartApp();
|
||||||
|
} catch(e) {
|
||||||
|
toast.error("Error while trying to reload the app");
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Update System State
|
// Update System State
|
||||||
type UpdateStatus = {
|
type UpdateStatus = {
|
||||||
currentVersion: string;
|
currentVersion: string;
|
||||||
@@ -858,7 +868,7 @@
|
|||||||
class="flex items-center justify-between gap-4 rounded-lg border border-destructive/30 bg-card p-4"
|
class="flex items-center justify-between gap-4 rounded-lg border border-destructive/30 bg-card p-4"
|
||||||
>
|
>
|
||||||
<div class="space-y-1">
|
<div class="space-y-1">
|
||||||
<Label class="text-sm">{m.settings_danger_reload_label()}</Label>
|
<Label class="text-sm">{m.settings_danger_reload_ui_label()}</Label>
|
||||||
<div class="text-sm text-muted-foreground">
|
<div class="text-sm text-muted-foreground">
|
||||||
{m.settings_danger_reload_hint()}
|
{m.settings_danger_reload_hint()}
|
||||||
</div>
|
</div>
|
||||||
@@ -870,9 +880,29 @@
|
|||||||
class={`${buttonVariants({ variant: "destructive" })} cursor-pointer hover:cursor-pointer`}
|
class={`${buttonVariants({ variant: "destructive" })} cursor-pointer hover:cursor-pointer`}
|
||||||
style="text-decoration: none;"
|
style="text-decoration: none;"
|
||||||
>
|
>
|
||||||
{m.settings_danger_reload_button()}
|
{m.settings_danger_reload_button_ui()}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex items-center justify-between gap-4 rounded-lg border border-destructive/30 bg-card p-4"
|
||||||
|
>
|
||||||
|
<div class="space-y-1">
|
||||||
|
<Label class="text-sm">{m.settings_danger_reload_app_label()}</Label>
|
||||||
|
<div class="text-sm text-muted-foreground">
|
||||||
|
{m.settings_danger_reload_hint()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
class={`${buttonVariants({ variant: "destructive" })} cursor-pointer hover:cursor-pointer`}
|
||||||
|
onclick={restartEntireApp}
|
||||||
|
style="text-decoration: none;"
|
||||||
|
>
|
||||||
|
{m.settings_danger_reload_button_app()}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|||||||
Reference in New Issue
Block a user