feat: enhance bug reporting by adding localStorage and config data capture, and fix submit button state

This commit is contained in:
Flavio Fois
2026-02-10 23:05:15 +01:00
parent 3eb95cca7f
commit 18c256ebf9
4 changed files with 76 additions and 7 deletions

View File

@@ -4,6 +4,8 @@
1) Aggiunti i pulsanti "Download" al MailViewer, PDF e Image viewer, per scaricare il file invece di aprirlo direttamente.2 1) Aggiunti i pulsanti "Download" al MailViewer, PDF e Image viewer, per scaricare il file invece di aprirlo direttamente.2
2) Refactor del sistema di bug report. 2) Refactor del sistema di bug report.
3) Rimosso temporaneamente il fetching dei dati macchina all'apertura della pagine delle impostazioni, per evitare problemi di performance. 3) Rimosso temporaneamente il fetching dei dati macchina all'apertura della pagine delle impostazioni, per evitare problemi di performance.
4) Fixato un bug dove, nel Bug Reporting, non si disattivaa il pulsante di invio, se tutti i campi erano compilati.
5) Aggiunto il supprto all'allegare i file di localStorage e config.ini al Bug Report, per investigare meglio i problemi legati all'ambiente dell'utente.

View File

@@ -5,7 +5,7 @@
# Existing Features # Existing Features
- [ ] Add seperated "Updater" binary, that will start on User login (via Scheduled Task), with a silent install mode. - [ ] Add seperated "Updater" binary, that will start on User login (via Scheduled Task), with a silent install mode.
- [ ] Attach localStorage, config file to the "Bug Reporter" ZIP file, to investigate the issue with the user enviroment. - [x] Attach localStorage, config file to the "Bug Reporter" ZIP file, to investigate the issue with the user enviroment.
- [ ] Auto-send the "Bug Reporter" ZIP file to the support team, to investigate the issue with the user enviroment. - [ ] Auto-send the "Bug Reporter" ZIP file to the support team, to investigate the issue with the user enviroment.
# Bugs # Bugs

View File

@@ -38,6 +38,10 @@ type BugReportInput struct {
Description string `json:"description"` Description string `json:"description"`
// ScreenshotData is the base64-encoded PNG screenshot (captured before dialog opens) // ScreenshotData is the base64-encoded PNG screenshot (captured before dialog opens)
ScreenshotData string `json:"screenshotData"` ScreenshotData string `json:"screenshotData"`
// LocalStorageData is the JSON-encoded localStorage data
LocalStorageData string `json:"localStorageData"`
// ConfigData is the JSON-encoded config.ini data
ConfigData string `json:"configData"`
} }
// SubmitBugReportResult contains the result of submitting a bug report. // SubmitBugReportResult contains the result of submitting a bug report.
@@ -120,10 +124,12 @@ func (a *App) CreateBugReportFolder() (*BugReportResult, error) {
// - User-provided description (report.txt) // - User-provided description (report.txt)
// - Screenshot (captured before dialog opens) // - Screenshot (captured before dialog opens)
// - Currently loaded mail file (if any) // - Currently loaded mail file (if any)
// - localStorage data (localStorage.json)
// - Config.ini data (config.json)
// - System information (hostname, OS version, hardware ID) // - System information (hostname, OS version, hardware ID)
// //
// Parameters: // Parameters:
// - input: User-provided bug report details including pre-captured screenshot // - input: User-provided bug report details including pre-captured screenshot, localStorage, and config data
// //
// Returns: // Returns:
// - *SubmitBugReportResult: Paths to the zip file and folder // - *SubmitBugReportResult: Paths to the zip file and folder
@@ -168,6 +174,22 @@ func (a *App) SubmitBugReport(input BugReportInput) (*SubmitBugReportResult, err
} }
} }
// Save localStorage data if provided
if input.LocalStorageData != "" {
localStoragePath := filepath.Join(bugReportFolder, "localStorage.json")
if err := os.WriteFile(localStoragePath, []byte(input.LocalStorageData), 0644); err != nil {
Log("Failed to save localStorage data:", err)
}
}
// Save config data if provided
if input.ConfigData != "" {
configPath := filepath.Join(bugReportFolder, "config.json")
if err := os.WriteFile(configPath, []byte(input.ConfigData), 0644); err != nil {
Log("Failed to save config data:", err)
}
}
// Create the report.txt file with user's description // Create the report.txt file with user's description
reportContent := fmt.Sprintf(`EMLy Bug Report reportContent := fmt.Sprintf(`EMLy Bug Report
================ ================

View File

@@ -8,7 +8,8 @@
import { Textarea } from "$lib/components/ui/textarea/index.js"; import { Textarea } from "$lib/components/ui/textarea/index.js";
import { CheckCircle, Copy, FolderOpen, Camera, Loader2 } from "@lucide/svelte"; import { CheckCircle, Copy, FolderOpen, Camera, Loader2 } from "@lucide/svelte";
import { toast } from "svelte-sonner"; import { toast } from "svelte-sonner";
import { TakeScreenshot, SubmitBugReport, OpenFolderInExplorer } from "$lib/wailsjs/go/main/App"; import { TakeScreenshot, SubmitBugReport, OpenFolderInExplorer, GetConfig } from "$lib/wailsjs/go/main/App";
import { browser } from "$app/environment";
// Bug report form state // Bug report form state
let userName = $state(""); let userName = $state("");
@@ -19,16 +20,27 @@
let screenshotData = $state(""); let screenshotData = $state("");
let isCapturing = $state(false); let isCapturing = $state(false);
// Bug report system data
let localStorageData = $state("");
let configData = $state("");
// Bug report UI state // Bug report UI state
let isSubmitting = $state(false); let isSubmitting = $state(false);
let isSuccess = $state(false); let isSuccess = $state(false);
let resultZipPath = $state(""); let resultZipPath = $state("");
let canSubmit: boolean = $derived(
bugDescription.trim().length > 0 && userName.trim().length > 0 && userEmail.trim().length > 0 && !isSubmitting && !isCapturing
);
// Bug report dialog effects // Bug report dialog effects
$effect(() => { $effect(() => {
if ($bugReportDialogOpen) { if ($bugReportDialogOpen) {
// Capture screenshot immediately when dialog opens // Capture screenshot immediately when dialog opens
captureScreenshot(); captureScreenshot();
// Capture localStorage data
captureLocalStorage();
// Capture config.ini data
captureConfig();
} else { } else {
// Reset form when dialog closes // Reset form when dialog closes
resetBugReportForm(); resetBugReportForm();
@@ -48,11 +60,42 @@
} }
} }
function captureLocalStorage() {
if (!browser) return;
try {
const data: Record<string, string> = {};
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key) {
data[key] = localStorage.getItem(key) || "";
}
}
localStorageData = JSON.stringify(data, null, 2);
console.log("localStorage data captured");
} catch (err) {
console.error("Failed to capture localStorage:", err);
localStorageData = "Error capturing localStorage";
}
}
async function captureConfig() {
try {
const config = await GetConfig();
configData = JSON.stringify(config, null, 2);
console.log("Config data captured");
} catch (err) {
console.error("Failed to capture config:", err);
configData = "Error capturing config";
}
}
function resetBugReportForm() { function resetBugReportForm() {
userName = ""; userName = "";
userEmail = ""; userEmail = "";
bugDescription = ""; bugDescription = "";
screenshotData = ""; screenshotData = "";
localStorageData = "";
configData = "";
isCapturing = false; isCapturing = false;
isSubmitting = false; isSubmitting = false;
isSuccess = false; isSuccess = false;
@@ -74,7 +117,9 @@
name: userName, name: userName,
email: userEmail, email: userEmail,
description: bugDescription, description: bugDescription,
screenshotData: screenshotData screenshotData: screenshotData,
localStorageData: localStorageData,
configData: configData
}); });
resultZipPath = result.zipPath; resultZipPath = result.zipPath;
@@ -112,7 +157,7 @@
</script> </script>
<Dialog.Root bind:open={$bugReportDialogOpen}> <Dialog.Root bind:open={$bugReportDialogOpen}>
<Dialog.Content class="sm:max-w-[500px] w-full max-h-[80vh] overflow-y-auto custom-scrollbar"> <Dialog.Content class="sm:max-w-125 w-full max-h-[80vh] overflow-y-auto custom-scrollbar">
{#if isSuccess} {#if isSuccess}
<!-- Success State --> <!-- Success State -->
<Dialog.Header> <Dialog.Header>
@@ -186,7 +231,7 @@
placeholder={m.bugreport_text_placeholder()} placeholder={m.bugreport_text_placeholder()}
bind:value={bugDescription} bind:value={bugDescription}
disabled={isSubmitting} disabled={isSubmitting}
class="min-h-[120px]" class="min-h-30"
/> />
</div> </div>
@@ -225,7 +270,7 @@
<button type="button" class={buttonVariants({ variant: "outline" })} disabled={isSubmitting} onclick={closeBugReportDialog}> <button type="button" class={buttonVariants({ variant: "outline" })} disabled={isSubmitting} onclick={closeBugReportDialog}>
{m.bugreport_cancel()} {m.bugreport_cancel()}
</button> </button>
<Button type="submit" disabled={isSubmitting || isCapturing}> <Button type="submit" disabled={!canSubmit}>
{#if isSubmitting} {#if isSubmitting}
<Loader2 class="h-4 w-4 mr-2 animate-spin" /> <Loader2 class="h-4 w-4 mr-2 animate-spin" />
{m.bugreport_submitting()} {m.bugreport_submitting()}