From 95bf1e748b0a23c227fb01490144ecaaf0fa7b95 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 15:52:02 +0000 Subject: [PATCH 1/8] fix: save logs to file instead of embedding in URL to avoid URL length errors - Add tauri-plugin-fs dependency for file writing - Modify feedback modal to save logs to a file via save dialog - Update checkbox label to reflect new behavior - GitHub issue body now instructs user to attach the saved log file Co-Authored-By: john@hyprnote.com --- Cargo.toml | 1 + apps/desktop/package.json | 3 +- apps/desktop/src-tauri/Cargo.toml | 1 + apps/desktop/src-tauri/src/lib.rs | 1 + .../components/feedback/feedback-modal.tsx | 33 ++++++++++++------- pnpm-lock.yaml | 11 +++++++ 6 files changed, 37 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fa5a7b3730..aefa82bc9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -124,6 +124,7 @@ tauri-plugin-autostart = "2.5" tauri-plugin-clipboard-manager = "2.3" tauri-plugin-deep-link = "2.4" tauri-plugin-dialog = "2.3" +tauri-plugin-fs = "2.2" tauri-plugin-http = { version = "2.5", features = ["unsafe-headers"] } tauri-plugin-opener = "2.5" tauri-plugin-os = "2.3" diff --git a/apps/desktop/package.json b/apps/desktop/package.json index ccb0385800..47e70efc0d 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -44,6 +44,7 @@ "@hypr/plugin-deeplink2": "workspace:*", "@hypr/plugin-detect": "workspace:*", "@hypr/plugin-extensions": "workspace:*", + "@hypr/plugin-flag": "workspace:*", "@hypr/plugin-fs-db": "workspace:*", "@hypr/plugin-fs-sync": "workspace:*", "@hypr/plugin-fs2": "workspace:*", @@ -72,7 +73,6 @@ "@hypr/plugin-tracing": "workspace:*", "@hypr/plugin-updater2": "workspace:*", "@hypr/plugin-windows": "workspace:*", - "@hypr/plugin-flag": "workspace:*", "@hypr/store": "workspace:*", "@hypr/tinybase-utils": "workspace:*", "@hypr/tiptap": "workspace:^", @@ -96,6 +96,7 @@ "@tauri-apps/plugin-autostart": "^2.5.1", "@tauri-apps/plugin-deep-link": "^2.4.6", "@tauri-apps/plugin-dialog": "^2.6.0", + "@tauri-apps/plugin-fs": "^2.4.5", "@tauri-apps/plugin-http": "^2.5.6", "@tauri-apps/plugin-opener": "^2.5.3", "@tauri-apps/plugin-os": "^2.3.2", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index 0184110807..83ff6632e4 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -37,6 +37,7 @@ tauri-plugin-detect = { workspace = true } tauri-plugin-dialog = { workspace = true } tauri-plugin-extensions = { workspace = true } tauri-plugin-flag = { workspace = true } +tauri-plugin-fs = { workspace = true } tauri-plugin-fs-db = { workspace = true } tauri-plugin-fs-sync = { workspace = true } tauri-plugin-fs2 = { workspace = true } diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index 76a0c104f7..7b2a8628de 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -77,6 +77,7 @@ pub async fn main() { .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_opener2::init()) .plugin(tauri_plugin_dialog::init()) + .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_analytics::init()) .plugin(tauri_plugin_bedrock::init()) .plugin(tauri_plugin_importer::init()) diff --git a/apps/desktop/src/components/feedback/feedback-modal.tsx b/apps/desktop/src/components/feedback/feedback-modal.tsx index 39266e7582..57b67d906c 100644 --- a/apps/desktop/src/components/feedback/feedback-modal.tsx +++ b/apps/desktop/src/components/feedback/feedback-modal.tsx @@ -1,3 +1,6 @@ +import { downloadDir } from "@tauri-apps/api/path"; +import { save } from "@tauri-apps/plugin-dialog"; +import { writeTextFile } from "@tauri-apps/plugin-fs"; import { arch, version as osVersion, platform } from "@tauri-apps/plugin-os"; import { Bug, Lightbulb, X } from "lucide-react"; import { useCallback, useEffect, useState } from "react"; @@ -103,18 +106,24 @@ export function FeedbackModal() { if (attachLogs) { const logContent = await getLogContent(); if (logContent) { - logSection = ` - -## Application Logs (last 1000 lines, redacted) -
-Click to expand logs - -\`\`\` -${logContent} -\`\`\` - -
+ const defaultPath = await downloadDir(); + const timestamp = new Date().toISOString().replace(/[:.]/g, "-"); + const defaultFileName = `hyprnote-logs-${timestamp}.txt`; + + const filePath = await save({ + title: "Save Application Logs", + defaultPath: `${defaultPath}/${defaultFileName}`, + filters: [{ name: "Text Files", extensions: ["txt", "log"] }], + }); + + if (filePath) { + await writeTextFile(filePath, logContent); + logSection = ` + +## Application Logs +Logs have been saved to a file. Please attach the saved log file to this issue. `; + } } } @@ -267,7 +276,7 @@ ${logSection} htmlFor="attach-logs" className="text-sm text-neutral-600 cursor-pointer" > - Attach application logs (user info redacted) + Save application logs to file (for manual attachment) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d19284fbd7..f2c45f961f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -437,6 +437,9 @@ importers: '@tauri-apps/plugin-dialog': specifier: ^2.6.0 version: 2.6.0 + '@tauri-apps/plugin-fs': + specifier: ^2.4.5 + version: 2.4.5 '@tauri-apps/plugin-http': specifier: ^2.5.6 version: 2.5.6 @@ -7685,6 +7688,9 @@ packages: '@tauri-apps/plugin-dialog@2.6.0': resolution: {integrity: sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==} + '@tauri-apps/plugin-fs@2.4.5': + resolution: {integrity: sha512-dVxWWGE6VrOxC7/jlhyE+ON/Cc2REJlM35R3PJX3UvFw2XwYhLGQVAIyrehenDdKjotipjYEVc4YjOl3qq90fA==} + '@tauri-apps/plugin-http@2.5.6': resolution: {integrity: sha512-KhCK3TDNDF4vdz75/j+KNQipYKf+295Visa8r32QcXScg0+D3JwShcCM6D+FN8WuDF24X3KSiAB8QtRxW6jKRA==} @@ -15185,6 +15191,7 @@ packages: tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me tar@7.5.2: resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==} @@ -23186,6 +23193,10 @@ snapshots: dependencies: '@tauri-apps/api': 2.9.1 + '@tauri-apps/plugin-fs@2.4.5': + dependencies: + '@tauri-apps/api': 2.9.1 + '@tauri-apps/plugin-http@2.5.6': dependencies: '@tauri-apps/api': 2.9.1 From 68d5e3030314496e221140a499f11771645571f5 Mon Sep 17 00:00:00 2001 From: ComputelessComputer Date: Fri, 30 Jan 2026 01:47:29 +0900 Subject: [PATCH 2/8] Include tauri-plugin-fs and remove git hash from feedback modal Add tauri-plugin-fs to Cargo.lock to ensure the filesystem plugin is included as a dependency. Remove the displayed git hash from the feedback modal UI to avoid showing build identifiers to users; this simplifies the feedback view and reduces exposure of internal commit information. --- Cargo.lock | 1 + apps/desktop/src/components/feedback/feedback-modal.tsx | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35add73cdb..c6c852072f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4326,6 +4326,7 @@ dependencies = [ "tauri-plugin-dialog", "tauri-plugin-extensions", "tauri-plugin-flag", + "tauri-plugin-fs", "tauri-plugin-fs-db", "tauri-plugin-fs-sync", "tauri-plugin-fs2", diff --git a/apps/desktop/src/components/feedback/feedback-modal.tsx b/apps/desktop/src/components/feedback/feedback-modal.tsx index 57b67d906c..c01b368735 100644 --- a/apps/desktop/src/components/feedback/feedback-modal.tsx +++ b/apps/desktop/src/components/feedback/feedback-modal.tsx @@ -279,12 +279,6 @@ ${logSection} Save application logs to file (for manual attachment) - - {gitHash && ( -
- {gitHash} -
- )}
From 5883a6db5f0e3eea8ca8095ed1ce6742e3d6d4ad Mon Sep 17 00:00:00 2001 From: ComputelessComputer Date: Fri, 30 Jan 2026 01:49:41 +0900 Subject: [PATCH 3/8] Ensure logs and type persist when opening GitHub issue Preserve the feedback modal state (type and attachLogs) before async operations so that the correct log attachment behavior and issue type are used when constructing and opening the GitHub issue URL. This prevents the UI close() side effect from changing values during awaits and ensures logs are attached and bugs are handled as intended. --- .../src/components/feedback/feedback-modal.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/desktop/src/components/feedback/feedback-modal.tsx b/apps/desktop/src/components/feedback/feedback-modal.tsx index c01b368735..8e12720e97 100644 --- a/apps/desktop/src/components/feedback/feedback-modal.tsx +++ b/apps/desktop/src/components/feedback/feedback-modal.tsx @@ -102,8 +102,13 @@ export function FeedbackModal() { const title = firstLine || (type === "bug" ? "Bug Report" : "Feature Request"); + const currentType = type; + const shouldAttachLogs = attachLogs; + + close(); + let logSection = ""; - if (attachLogs) { + if (shouldAttachLogs) { const logContent = await getLogContent(); if (logContent) { const defaultPath = await downloadDir(); @@ -127,7 +132,7 @@ Logs have been saved to a file. Please attach the saved log file to this issue. } } - if (type === "bug") { + if (currentType === "bug") { const body = `## Description ${trimmedDescription} @@ -164,8 +169,6 @@ ${logSection} await openerCommands.openUrl(url.toString(), null); } - - close(); } catch (error) { console.error("Failed to submit feedback:", error); } finally { From 50dbef719fdaca59a99b3bf677b547f9d1f441f9 Mon Sep 17 00:00:00 2001 From: ComputelessComputer Date: Fri, 30 Jan 2026 01:52:15 +0900 Subject: [PATCH 4/8] Open feedback page before prompting log download Open the issue/report page first and include a placeholder note about logs in the report body, then prompt the user to save application logs if requested. This reorders the flow so the page opens immediately (improving UX) and moves the file-save dialog after opening the page, avoiding blocking navigation. The change also simplifies the in-body log message and preserves the previous logic to write logs to disk when a file path is chosen. --- .../components/feedback/feedback-modal.tsx | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/apps/desktop/src/components/feedback/feedback-modal.tsx b/apps/desktop/src/components/feedback/feedback-modal.tsx index 8e12720e97..42a0db6489 100644 --- a/apps/desktop/src/components/feedback/feedback-modal.tsx +++ b/apps/desktop/src/components/feedback/feedback-modal.tsx @@ -107,30 +107,13 @@ export function FeedbackModal() { close(); - let logSection = ""; - if (shouldAttachLogs) { - const logContent = await getLogContent(); - if (logContent) { - const defaultPath = await downloadDir(); - const timestamp = new Date().toISOString().replace(/[:.]/g, "-"); - const defaultFileName = `hyprnote-logs-${timestamp}.txt`; - - const filePath = await save({ - title: "Save Application Logs", - defaultPath: `${defaultPath}/${defaultFileName}`, - filters: [{ name: "Text Files", extensions: ["txt", "log"] }], - }); - - if (filePath) { - await writeTextFile(filePath, logContent); - logSection = ` + const logSection = shouldAttachLogs + ? ` ## Application Logs -Logs have been saved to a file. Please attach the saved log file to this issue. -`; - } - } - } +Logs will be saved to a file. Please attach the saved log file to this issue. +` + : ""; if (currentType === "bug") { const body = `## Description @@ -169,6 +152,25 @@ ${logSection} await openerCommands.openUrl(url.toString(), null); } + + if (shouldAttachLogs) { + const logContent = await getLogContent(); + if (logContent) { + const defaultPath = await downloadDir(); + const timestamp = new Date().toISOString().replace(/[:.]/g, "-"); + const defaultFileName = `hyprnote-logs-${timestamp}.txt`; + + const filePath = await save({ + title: "Save Application Logs", + defaultPath: `${defaultPath}/${defaultFileName}`, + filters: [{ name: "Text Files", extensions: ["txt", "log"] }], + }); + + if (filePath) { + await writeTextFile(filePath, logContent); + } + } + } } catch (error) { console.error("Failed to submit feedback:", error); } finally { From b33f63957e31e2500d40abc51f03ecd1ac9cb6b1 Mon Sep 17 00:00:00 2001 From: ComputelessComputer Date: Fri, 30 Jan 2026 01:54:36 +0900 Subject: [PATCH 5/8] Add fs:default capability to Tauri default capabilities Add the "fs:default" permission to apps/desktop/src-tauri/capabilities/default.json to allow filesystem write operations required by feedback submission. The error log showed fs.write_text_file is not allowed; adding this capability grants the necessary FS permissions so feedback can be written. This change ensures the application can perform expected file-write actions (e.g., saving feedback) while keeping other capabilities intact. --- apps/desktop/src-tauri/capabilities/default.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/desktop/src-tauri/capabilities/default.json b/apps/desktop/src-tauri/capabilities/default.json index 70d531f762..7bb2fd199a 100644 --- a/apps/desktop/src-tauri/capabilities/default.json +++ b/apps/desktop/src-tauri/capabilities/default.json @@ -67,6 +67,7 @@ ] }, "misc:default", + "fs:default", "fs-db:default", "fs-sync:default", "fs2:default", From b908cd25776b995c2c4ee65a7135538b36a067e0 Mon Sep 17 00:00:00 2001 From: ComputelessComputer Date: Fri, 30 Jan 2026 02:02:57 +0900 Subject: [PATCH 6/8] Allow write text file capability Add the fs:allow-write-text-file permission to the Tauri desktop capabilities so the application can write text files. The error log showed fs.write_text_file was blocked due to missing permission, so this change enables that capability to allow feedback submission and other text file writes. This addresses the permission denial recorded by the tauri_plugin_tracing error. --- apps/desktop/src-tauri/capabilities/default.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/desktop/src-tauri/capabilities/default.json b/apps/desktop/src-tauri/capabilities/default.json index 7bb2fd199a..5cff3f8a90 100644 --- a/apps/desktop/src-tauri/capabilities/default.json +++ b/apps/desktop/src-tauri/capabilities/default.json @@ -68,6 +68,7 @@ }, "misc:default", "fs:default", + "fs:allow-write-text-file", "fs-db:default", "fs-sync:default", "fs2:default", From a5ce7f39005e311171070c49f43b067b99fe5dec Mon Sep 17 00:00:00 2001 From: ComputelessComputer Date: Fri, 30 Jan 2026 02:06:27 +0900 Subject: [PATCH 7/8] Reveal downloads folder after writing feedback log Open the downloads folder to show the saved feedback log after writing it out. Users asked for the downloads folder to open after saving, so call the existing opener command to reveal the saved file in its directory. This improves discoverability of the saved log and confirms the save succeeded. --- apps/desktop/src/components/feedback/feedback-modal.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/desktop/src/components/feedback/feedback-modal.tsx b/apps/desktop/src/components/feedback/feedback-modal.tsx index 42a0db6489..76b50120d3 100644 --- a/apps/desktop/src/components/feedback/feedback-modal.tsx +++ b/apps/desktop/src/components/feedback/feedback-modal.tsx @@ -168,6 +168,7 @@ ${logSection} if (filePath) { await writeTextFile(filePath, logContent); + await openerCommands.revealItemInDir(filePath); } } } From 71c70c81585707dbe30f08ad80a6b0ad1dca3cc0 Mon Sep 17 00:00:00 2001 From: ComputelessComputer Date: Fri, 30 Jan 2026 02:07:35 +0900 Subject: [PATCH 8/8] error TS6133: 'gitHash' is declared but its value is never read. Please ultrathink before taking any actions --- apps/desktop/src/components/feedback/feedback-modal.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/desktop/src/components/feedback/feedback-modal.tsx b/apps/desktop/src/components/feedback/feedback-modal.tsx index 76b50120d3..96ba51b6d2 100644 --- a/apps/desktop/src/components/feedback/feedback-modal.tsx +++ b/apps/desktop/src/components/feedback/feedback-modal.tsx @@ -45,7 +45,6 @@ export function FeedbackModal() { const [type, setType] = useState(initialType); const [description, setDescription] = useState(""); const [isSubmitting, setIsSubmitting] = useState(false); - const [gitHash, setGitHash] = useState(""); const [attachLogs, setAttachLogs] = useState(false); useEffect(() => { @@ -67,12 +66,8 @@ export function FeedbackModal() { useEffect(() => { if (isOpen) { setType(initialType); - miscCommands.getGitHash().then((result) => { - setGitHash(result.status === "ok" ? result.data : "unknown"); - }); } else { setDescription(""); - setGitHash(""); setAttachLogs(false); } }, [isOpen, initialType]);