This commit is contained in:
Flavio Fois
2026-02-04 19:57:31 +01:00
parent 0d6157b2ff
commit 0cda0a26fc
25 changed files with 1549 additions and 66 deletions

View File

@@ -7,11 +7,11 @@
import "../layout.css";
import { onMount } from "svelte";
import * as m from "$lib/paraglide/messages.js";
import { GetConfig } from "$lib/wailsjs/go/main/App";
import type { utils } from "$lib/wailsjs/go/models";
import { Toaster } from "$lib/components/ui/sonner/index.js";
import AppSidebar from "$lib/components/SidebarApp.svelte";
import * as Sidebar from "$lib/components/ui/sidebar/index.js";
import { dev } from '$app/environment';
import {
PanelRightClose,
PanelRightOpen,
@@ -20,6 +20,7 @@
} from "@lucide/svelte";
import { Separator } from "$lib/components/ui/separator/index.js";
import { toast } from "svelte-sonner";
import { buttonVariants } from "$lib/components/ui/button/index.js";
import {
WindowMinimise,
@@ -28,6 +29,7 @@
WindowIsMaximised,
Quit,
} from "$lib/wailsjs/runtime/runtime";
import { RefreshCcwDot } from "@lucide/svelte";
let versionInfo: utils.Config | null = $state(null);
let isMaximized = $state(false);
@@ -65,10 +67,10 @@
}
onMount(async () => {
versionInfo = await GetConfig();
versionInfo = data.data as utils.Config;
});
let { children } = $props();
let { data, children } = $props();
const THEME_KEY = "emly_theme";
let theme = $state<"dark" | "light">("dark");
@@ -109,24 +111,24 @@
<div class="title">
<bold>EMLy</bold>
<div class="version-wrapper">
<version
>v{versionInfo?.EMLy.GUISemver}_{versionInfo?.EMLy
.GUIReleaseChannel}</version
>
<version>
{#if dev}
v{versionInfo?.EMLy.GUISemver}_{versionInfo?.EMLy.GUIReleaseChannel} <debug>(DEBUG BUILD)</debug>
{:else}
v{versionInfo?.EMLy.GUISemver}_{versionInfo?.EMLy.GUIReleaseChannel}
{/if}
</version>
{#if versionInfo}
<div class="version-tooltip">
<div class="tooltip-item">
<span class="label">GUI:</span>
<span class="value">v{versionInfo.EMLy.GUISemver}</span>
<span class="channel">({versionInfo.EMLy.GUIReleaseChannel})</span
>
<span class="channel">({versionInfo.EMLy.GUIReleaseChannel})</span>
</div>
<div class="tooltip-item">
<span class="label">SDK:</span>
<span class="value">v{versionInfo.EMLy.SDKDecoderSemver}</span>
<span class="channel"
>({versionInfo.EMLy.SDKDecoderReleaseChannel})</span
>
<span class="channel">({versionInfo.EMLy.SDKDecoderReleaseChannel})</span>
</div>
</div>
{/if}
@@ -159,8 +161,10 @@
{#await navigating?.complete}
<div class="loading-overlay">
<div class="spinner"></div>
<span style="opacity: 0.5; font-size: 13px">Loading...</span>
</div>
<span style="opacity: 0.5; font-size: 13px"
>{m.layout_loading_text()}</span
>
</div>
{:then}
{@render children()}
{/await}
@@ -192,7 +196,7 @@
<House
size="16"
onclick={() => {
if(page.url.pathname !== "/") goto("/");
if (page.url.pathname !== "/") goto("/");
}}
style="cursor: pointer; opacity: 0.7;"
class="hover:opacity-100 transition-opacity"
@@ -200,11 +204,26 @@
<Settings
size="16"
onclick={() => {
if (page.url.pathname !== "/settings" && page.url.pathname !== "/settings/") goto("/settings");
if (
page.url.pathname !== "/settings" &&
page.url.pathname !== "/settings/"
)
goto("/settings");
}}
style="cursor: pointer; opacity: 0.7;"
class="hover:opacity-100 transition-opacity"
/>
<a
data-sveltekit-reload
href="/"
class={`${buttonVariants({ variant: "destructive" })} cursor-pointer hover:cursor-pointer`}
style="text-decoration: none; margin-left: auto; height: 24px; font-size: 12px; padding: 0 8px;"
aria-label={m.settings_danger_reload_button()}
title={m.settings_danger_reload_button() + " app"}
>
<RefreshCcwDot />
</a>
</div>
<div style="display:none">
@@ -275,6 +294,12 @@
opacity: 0.4;
}
.title version debug{
color: #e11d48;
opacity: 1;
font-weight: 600;
}
.version-wrapper {
position: relative;
display: inline-block;

View File

@@ -0,0 +1,12 @@
import type { LayoutLoad } from './$types';
import { GetConfig } from "$lib/wailsjs/go/main/App";
export const load = (async () => {
try {
const config = await GetConfig();
return { data: config, error: null };
} catch (e) {
console.error("Failed to load config:", e);
return { data: null, error: 'Failed to load config' };
}
}) satisfies LayoutLoad;

View File

@@ -1,7 +1,9 @@
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
import { GetViewerData, GetStartupFile, ReadEML } from '$lib/wailsjs/go/main/App';
import { GetViewerData, GetStartupFile, ReadEML, ReadMSG } from '$lib/wailsjs/go/main/App';
import DOMPurify from 'dompurify';
import { settingsStore } from '$lib/stores/settings.svelte';
import type { internal } from '$lib/wailsjs/go/models';
export const load: PageLoad = async () => {
try {
@@ -18,7 +20,15 @@ export const load: PageLoad = async () => {
// Check if opened with a file
const startupFile = await GetStartupFile();
if (startupFile) {
const emlContent = await ReadEML(startupFile);
let emlContent: internal.EmailData;
if (startupFile.toLowerCase().endsWith(".msg")) {
const useExt = settingsStore.settings.useMsgConverter ?? true;
emlContent = await ReadMSG(startupFile, useExt);
} else {
emlContent = await ReadEML(startupFile);
}
if (emlContent) {
emlContent.body = DOMPurify.sanitize(emlContent.body || "");
return { email: emlContent };

View File

@@ -32,6 +32,7 @@
selectedLanguage: "it",
useBuiltinPreview: true,
useBuiltinPDFViewer: true,
useMsgConverter: true,
previewFileSupportedTypes: ["jpg", "jpeg", "png"],
};
@@ -59,6 +60,7 @@
useBuiltinPreview: !!s.useBuiltinPreview,
useBuiltinPDFViewer:
s.useBuiltinPDFViewer ?? defaults.useBuiltinPDFViewer ?? true,
useMsgConverter: s.useMsgConverter ?? defaults.useMsgConverter ?? true,
previewFileSupportedTypes:
s.previewFileSupportedTypes || defaults.previewFileSupportedTypes || [],
};
@@ -69,6 +71,7 @@
(a.selectedLanguage ?? "") === (b.selectedLanguage ?? "") &&
!!a.useBuiltinPreview === !!b.useBuiltinPreview &&
!!a.useBuiltinPDFViewer === !!b.useBuiltinPDFViewer &&
!!a.useMsgConverter === !!b.useMsgConverter &&
JSON.stringify(a.previewFileSupportedTypes?.sort()) ===
JSON.stringify(b.previewFileSupportedTypes?.sort())
);
@@ -363,6 +366,35 @@
</Card.Content>
</Card.Root>
<Card.Root>
<Card.Header class="space-y-1">
<Card.Title>{m.settings_msg_converter_title()}</Card.Title>
<Card.Description
>{m.settings_msg_converter_description()}</Card.Description
>
</Card.Header>
<Card.Content class="space-y-4">
<div class="space-y-3">
<div
class="flex items-center justify-between gap-4 rounded-lg border bg-card p-4"
>
<div>
<Label class="text-base">
{m.settings_msg_converter_label()}
</Label>
<p class="text-sm text-muted-foreground">
{m.settings_msg_converter_hint()}
</p>
</div>
<Switch
bind:checked={form.useMsgConverter}
class="cursor-pointer hover:cursor-pointer"
/>
</div>
</div>
</Card.Content>
</Card.Root>
{#if $dangerZoneEnabled}
<Card.Root class="border-destructive/50 bg-destructive/15">
<Card.Header class="space-y-1">