diff --git a/app_settings.go b/app_settings.go index e52e700..7230b41 100644 --- a/app_settings.go +++ b/app_settings.go @@ -98,3 +98,33 @@ func (a *App) ImportSettings() (string, error) { return string(data), nil } + +// SetUpdateCheckerEnabled updates the UPDATE_CHECK_ENABLED setting in config.ini +// based on the user's preference from the GUI settings. +// +// Parameters: +// - enabled: true to enable update checking, false to disable +// +// Returns: +// - error: Error if loading or saving config fails +func (a *App) SetUpdateCheckerEnabled(enabled bool) error { + // Load current config + config := a.GetConfig() + if config == nil { + return fmt.Errorf("failed to load config") + } + + // Update the setting + if enabled { + config.EMLy.UpdateCheckEnabled = "true" + } else { + config.EMLy.UpdateCheckEnabled = "false" + } + + // Save config back to disk + if err := a.SaveConfig(config); err != nil { + return fmt.Errorf("failed to save config: %w", err) + } + + return nil +} diff --git a/config.ini b/config.ini index 07c991d..8b6f1a3 100644 --- a/config.ini +++ b/config.ini @@ -1,9 +1,9 @@ [EMLy] -SDK_DECODER_SEMVER="1.3.2" -SDK_DECODER_RELEASE_CHANNEL="beta" -GUI_SEMVER="1.4.0" -GUI_RELEASE_CHANNEL="stable" -LANGUAGE="it" -UPDATE_CHECK_ENABLED="true" -UPDATE_PATH="" -UPDATE_AUTO_CHECK="true" \ No newline at end of file +SDK_DECODER_SEMVER = 1.3.2 +SDK_DECODER_RELEASE_CHANNEL = beta +GUI_SEMVER = 1.4.0 +GUI_RELEASE_CHANNEL = stable +LANGUAGE = it +UPDATE_CHECK_ENABLED = false +UPDATE_PATH = +UPDATE_AUTO_CHECK = true diff --git a/frontend/src/lib/components/SidebarApp.svelte b/frontend/src/lib/components/SidebarApp.svelte index 460a709..693ce5e 100644 --- a/frontend/src/lib/components/SidebarApp.svelte +++ b/frontend/src/lib/components/SidebarApp.svelte @@ -3,7 +3,7 @@ import * as Sidebar from "$lib/components/ui/sidebar/index.js"; import { dangerZoneEnabled } from "$lib/stores/app"; import * as m from "$lib/paraglide/messages.js"; - import { Mail, Heart } from "@lucide/svelte/icons"; + import { Mail, Heart, Info } from "@lucide/svelte/icons"; const CLICK_WINDOW_MS = 4000; const REQUIRED_CLICKS = 10; @@ -46,7 +46,7 @@ { title: m.sidebar_credits(), url: "/credits", - icon: Heart, + icon: Info, disabled: false, id: 3, }, diff --git a/frontend/src/lib/stores/settings.svelte.ts b/frontend/src/lib/stores/settings.svelte.ts index 7294249..5d54064 100644 --- a/frontend/src/lib/stores/settings.svelte.ts +++ b/frontend/src/lib/stores/settings.svelte.ts @@ -11,6 +11,7 @@ const defaults: EMLy_GUI_Settings = { previewFileSupportedTypes: ["jpg", "jpeg", "png"], enableAttachedDebuggerProtection: true, useDarkEmailViewer: true, + enableUpdateChecker: true, }; class SettingsStore { diff --git a/frontend/src/lib/types.d.ts b/frontend/src/lib/types.d.ts index ce94a18..f6bc66a 100644 --- a/frontend/src/lib/types.d.ts +++ b/frontend/src/lib/types.d.ts @@ -9,6 +9,25 @@ interface EMLy_GUI_Settings { previewFileSupportedTypes?: SupportedFileTypePreview[]; enableAttachedDebuggerProtection?: boolean; useDarkEmailViewer?: boolean; + enableUpdateChecker?: boolean; } type SupportedLanguages = "en" | "it"; +// Plugin System Types +interface PluginFormatSupport { + extensions: string[]; + mime_types?: string[]; + priority: number; +} + +interface PluginInfo { + name: string; + version: string; + author: string; + description: string; + capabilities: string[]; + status: "unloaded" | "loading" | "active" | "error" | "disabled"; + enabled: boolean; + last_error?: string; + supported_formats?: PluginFormatSupport[]; +} \ No newline at end of file diff --git a/frontend/src/routes/(app)/+layout.svelte b/frontend/src/routes/(app)/+layout.svelte index 590b531..2a9bcec 100644 --- a/frontend/src/routes/(app)/+layout.svelte +++ b/frontend/src/routes/(app)/+layout.svelte @@ -24,6 +24,8 @@ CheckCircle, Camera, Heart, + Info, + Music } from "@lucide/svelte"; import { Separator } from "$lib/components/ui/separator/index.js"; import { toast } from "svelte-sonner"; @@ -380,7 +382,7 @@ style="cursor: pointer; opacity: 0.7;" class="hover:opacity-100 transition-opacity" /> - { if (page.url.pathname !== "/credits" && page.url.pathname !== "/credits/") @@ -389,12 +391,11 @@ style="cursor: pointer; opacity: 0.7;" class="hover:opacity-100 transition-opacity" /> - - - { - $bugReportDialogOpen = !$bugReportDialogOpen; + if (page.url.pathname !== "/inspiration" && page.url.pathname !== "/inspiration/") + goto("/inspiration"); }} style="cursor: pointer; opacity: 0.7;" class="hover:opacity-100 transition-opacity" @@ -410,6 +411,19 @@ > + + { + $bugReportDialogOpen = !$bugReportDialogOpen; + }} + > + + diff --git a/frontend/src/routes/(app)/inspiration/+page.svelte b/frontend/src/routes/(app)/inspiration/+page.svelte new file mode 100644 index 0000000..f8eaf2a --- /dev/null +++ b/frontend/src/routes/(app)/inspiration/+page.svelte @@ -0,0 +1,199 @@ + + +
+
+
+
+

+ Musical Inspiration +

+

+ This project was mainly coded to the following tracks +

+
+ +
+ + + + + + + + + FOISX's Soundtrack + + + The albums and tracks that fueled the development of EMLy + + + +
+ {#each inspirationTracks as track} +
+
+ +
+
+
+

{track.name}

+

+ {track.artist} +

+
+ +
+
+ {/each} +
+
+
+ + + + +
+ +
+

The Soundtrack

+

+ These are just a small sample of what helped inspire the project. + Although they represent a wide variety of emotions, themes and genres, some exploring deep meanings + of betrayal, personal struggles, and introspection, they provided solace and strength to the main developer + during challenging times. +
+ Music has a unique way of transforming pain into creative energy.. +

+
+
+
+
+ + +
+

+ Made with + + and + +

+

+ GUI: {config ? `v${config.GUISemver}` : "N/A"} • + SDK: {config ? `v${config.SDKDecoderSemver}` : "N/A"} +

+
+
+
+ + diff --git a/frontend/src/routes/(app)/inspiration/+page.ts b/frontend/src/routes/(app)/inspiration/+page.ts new file mode 100644 index 0000000..ed92a80 --- /dev/null +++ b/frontend/src/routes/(app)/inspiration/+page.ts @@ -0,0 +1,19 @@ +import type { PageLoad } from './$types'; +import { GetConfig } from "$lib/wailsjs/go/main/App"; +import { browser } from '$app/environment'; + +export const load = (async () => { + if (!browser) return { config: null }; + + try { + const configRoot = await GetConfig(); + return { + config: configRoot.EMLy + }; + } catch (e) { + console.error("Failed to load config for inspiration", e); + return { + config: null + }; + } +}) satisfies PageLoad; diff --git a/frontend/src/routes/(app)/settings/+page.svelte b/frontend/src/routes/(app)/settings/+page.svelte index d5d9d9c..66d808a 100644 --- a/frontend/src/routes/(app)/settings/+page.svelte +++ b/frontend/src/routes/(app)/settings/+page.svelte @@ -25,7 +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, CheckForUpdates, DownloadUpdate, InstallUpdate, GetUpdateStatus } from "$lib/wailsjs/go/main/App"; + import { ExportSettings, ImportSettings, CheckForUpdates, DownloadUpdate, InstallUpdate, GetUpdateStatus, SetUpdateCheckerEnabled } from "$lib/wailsjs/go/main/App"; import { EventsOn, EventsOff } from "$lib/wailsjs/runtime/runtime"; let { data } = $props(); @@ -40,6 +40,7 @@ previewFileSupportedTypes: ["jpg", "jpeg", "png"], enableAttachedDebuggerProtection: true, useDarkEmailViewer: true, + enableUpdateChecker: true, }; async function setLanguage( @@ -72,6 +73,8 @@ s.enableAttachedDebuggerProtection ?? defaults.enableAttachedDebuggerProtection ?? true, useDarkEmailViewer: s.useDarkEmailViewer ?? defaults.useDarkEmailViewer ?? true, + enableUpdateChecker: + s.enableUpdateChecker ?? defaults.enableUpdateChecker ?? true, }; } @@ -82,6 +85,7 @@ !!a.useBuiltinPDFViewer === !!b.useBuiltinPDFViewer && !!a.enableAttachedDebuggerProtection === !!b.enableAttachedDebuggerProtection && !!a.useDarkEmailViewer === !!b.useDarkEmailViewer && + !!a.enableUpdateChecker === !!b.enableUpdateChecker && JSON.stringify(a.previewFileSupportedTypes?.sort()) === JSON.stringify(b.previewFileSupportedTypes?.sort()) ); @@ -180,6 +184,23 @@ })(); }); + // Sync update checker setting to backend config.ini + let previousUpdateCheckerEnabled = form.enableUpdateChecker; + $effect(() => { + (async () => { + if (!browser) return; + if (form.enableUpdateChecker !== previousUpdateCheckerEnabled) { + try { + await SetUpdateCheckerEnabled(form.enableUpdateChecker ?? true); + LogDebug(`Update checker ${form.enableUpdateChecker ? 'enabled' : 'disabled'}`); + } catch (err) { + console.error('Failed to sync update checker setting:', err); + } + previousUpdateCheckerEnabled = form.enableUpdateChecker; + } + })(); + }); + async function exportSettings() { try { const settingsJSON = JSON.stringify(form, null, 2); @@ -568,6 +589,7 @@ + {#if form.enableUpdateChecker} Updates @@ -587,10 +609,15 @@ Update Available + {:else if updateStatus.errorMessage && updateStatus.lastCheckTime} +
+ + Check failed +
{:else if updateStatus.lastCheckTime}
- Up to date + No updates found
{/if} @@ -695,6 +722,7 @@
+ {/if} {#if $dangerZoneEnabled || dev} @@ -811,6 +839,25 @@ +
+
+ +
+ Check for application updates from network share +
+
+ +
+
+ Info: When enabled, the app will check for updates from your configured network share. Disable this if you manage updates manually or don't have network access. +
+ +
GUI: {config ? `${config.GUISemver} (${config.GUIReleaseChannel})`