-
Notifications
You must be signed in to change notification settings - Fork 2.6k
add diagnostics report #552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ import { | |
| ChevronDown, | ||
| Crop, | ||
| Download, | ||
| FileDown, | ||
| Film, | ||
| Image, | ||
| Lock, | ||
|
|
@@ -240,6 +241,7 @@ interface SettingsPanelProps { | |
| webcamSizePreset?: WebcamSizePreset; | ||
| onWebcamSizePresetChange?: (size: WebcamSizePreset) => void; | ||
| onWebcamSizePresetCommit?: () => void; | ||
| onSaveDiagnostic?: () => Promise<void>; | ||
| } | ||
|
|
||
| export default SettingsPanel; | ||
|
|
@@ -327,6 +329,7 @@ export function SettingsPanel({ | |
| webcamSizePreset = DEFAULT_WEBCAM_SIZE_PRESET, | ||
| onWebcamSizePresetChange, | ||
| onWebcamSizePresetCommit, | ||
| onSaveDiagnostic, | ||
| }: SettingsPanelProps) { | ||
| const t = useScopedT("settings"); | ||
| // Resolved URLs are for DOM rendering only (backgroundImage). The canonical | ||
|
|
@@ -1682,6 +1685,16 @@ export function SettingsPanel({ | |
| <Bug className="w-3 h-3 text-[#34B27B]" /> | ||
| {t("links.reportBug")} | ||
| </button> | ||
| {onSaveDiagnostic && ( | ||
| <button | ||
| type="button" | ||
| onClick={onSaveDiagnostic} | ||
| className="flex-1 flex items-center justify-center gap-1.5 text-[10px] text-slate-500 hover:text-slate-300 py-1.5 transition-colors" | ||
| > | ||
| <FileDown className="w-3 h-3 text-slate-400" /> | ||
| Save Diagnostics | ||
| </button> | ||
| )} | ||
|
Comment on lines
+1688
to
+1697
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Button label should go through i18n.
🤖 Prompt for AI Agents |
||
| <button | ||
| type="button" | ||
| onClick={() => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1730,6 +1730,19 @@ export default function VideoEditor() { | |
| } | ||
| }, []); | ||
|
|
||
| const handleSaveDiagnostic = useCallback(async () => { | ||
| const result = await window.electronAPI.saveDiagnostic({ | ||
| error: exportError ?? "Manual diagnostic export", | ||
| projectState: editorState, | ||
| logs: [], | ||
| }); | ||
| if (result.success) { | ||
| toast.success("Diagnostic file saved"); | ||
| } else if (!result.canceled) { | ||
| toast.error("Failed to save diagnostic file"); | ||
| } | ||
| }, [exportError, editorState]); | ||
|
Comment on lines
+1733
to
+1744
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please localize the new diagnostic strings. Right now 🤖 Prompt for AI Agents |
||
|
|
||
| if (loading) { | ||
| return ( | ||
| <div className="flex items-center justify-center h-screen bg-background"> | ||
|
|
@@ -2100,6 +2113,7 @@ export default function VideoEditor() { | |
| onSpeedDelete={handleSpeedDelete} | ||
| unsavedExport={unsavedExport} | ||
| onSaveUnsavedExport={handleSaveUnsavedExport} | ||
| onSaveDiagnostic={handleSaveDiagnostic} | ||
| /> | ||
| </div> | ||
| </div> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard the whole diagnostic IPC flow with a top-level
try/catch.Right now, failures from
showSaveDialogcan reject the IPC call instead of returning the expected object shape. that’s kinda cursed for caller handling paths.💡 Suggested patch
ipcMain.handle( "save-diagnostic", async ( _, payload: { error: string; stack?: string; projectState: unknown; logs: string[] }, ) => { - const { filePath, canceled } = await dialog.showSaveDialog({ - title: "Save Diagnostic File", - defaultPath: `openscreen-diagnostic-${Date.now()}.json`, - filters: [{ name: "JSON", extensions: ["json"] }], - }); - - if (canceled || !filePath) return { success: false, canceled: true }; - - const diagnostic = { - timestamp: new Date().toISOString(), - appVersion: app.getVersion(), - platform: process.platform, - arch: process.arch, - osRelease: os.release(), - osVersion: os.version(), - totalMemoryMB: Math.round(os.totalmem() / 1024 / 1024), - nodeVersion: process.versions.node, - electronVersion: process.versions.electron, - chromeVersion: process.versions.chrome, - error: payload.error, - stack: payload.stack, - projectState: payload.projectState, - recentLogs: payload.logs, - }; - try { + const { filePath, canceled } = await dialog.showSaveDialog({ + title: "Save Diagnostic File", + defaultPath: `openscreen-diagnostic-${Date.now()}.json`, + filters: [{ name: "JSON", extensions: ["json"] }], + }); + + if (canceled || !filePath) return { success: false, canceled: true }; + + const diagnostic = { + timestamp: new Date().toISOString(), + appVersion: app.getVersion(), + platform: process.platform, + arch: process.arch, + osRelease: os.release(), + osVersion: os.version(), + totalMemoryMB: Math.round(os.totalmem() / 1024 / 1024), + nodeVersion: process.versions.node, + electronVersion: process.versions.electron, + chromeVersion: process.versions.chrome, + error: payload.error, + stack: payload.stack, + projectState: payload.projectState, + recentLogs: payload.logs, + }; + await fs.writeFile(filePath, JSON.stringify(diagnostic, null, 2), "utf-8"); return { success: true, path: filePath }; } catch (error) { console.error("Failed to write diagnostic file:", error); return { success: false, error: String(error) }; } }, );📝 Committable suggestion
🤖 Prompt for AI Agents