diff --git a/apps/desktop/src/renderer/main/pages/settings/advanced/index.tsx b/apps/desktop/src/renderer/main/pages/settings/advanced/index.tsx index 753dd77..ac2ad84 100644 --- a/apps/desktop/src/renderer/main/pages/settings/advanced/index.tsx +++ b/apps/desktop/src/renderer/main/pages/settings/advanced/index.tsx @@ -32,6 +32,8 @@ export default function AdvancedSettingsPage() { const settingsQuery = api.settings.getSettings.useQuery(); const telemetryQuery = api.settings.getTelemetrySettings.useQuery(); const dataPathQuery = api.settings.getDataPath.useQuery(); + const logFilePathQuery = api.settings.getLogFilePath.useQuery(); + const machineIdQuery = api.settings.getMachineId.useQuery(); const utils = api.useUtils(); const updateTranscriptionSettingsMutation = @@ -73,6 +75,17 @@ export default function AdvancedSettingsPage() { }, }); + const downloadLogFileMutation = api.settings.downloadLogFile.useMutation({ + onSuccess: (data) => { + if (data.success) { + toast.success("Log file saved successfully"); + } + }, + onError: () => { + toast.error("Failed to save log file"); + }, + }); + // Load settings when query data is available useEffect(() => { if (settingsQuery.data?.transcription) { @@ -99,6 +112,13 @@ export default function AdvancedSettingsPage() { window.electronAPI.openExternal("https://amical.ai/docs/telemetry"); }; + const handleCopyMachineId = async () => { + if (machineIdQuery.data) { + await navigator.clipboard.writeText(machineIdQuery.data); + toast.success("Machine ID copied to clipboard"); + } + }; + return (
@@ -176,6 +196,44 @@ export default function AdvancedSettingsPage() { className="cursor-default" />
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
diff --git a/apps/desktop/src/trpc/routers/settings.ts b/apps/desktop/src/trpc/routers/settings.ts index 6e70429..27335e8 100644 --- a/apps/desktop/src/trpc/routers/settings.ts +++ b/apps/desktop/src/trpc/routers/settings.ts @@ -481,6 +481,44 @@ export const settingsRouter = createRouter({ return app.getPath("userData"); }), + // Get log file path + getLogFilePath: procedure.query(() => { + const isDev = process.env.NODE_ENV === "development" || !app.isPackaged; + return isDev + ? path.join(app.getPath("userData"), "logs", "amical-dev.log") + : path.join(app.getPath("logs"), "amical.log"); + }), + + // Get machine ID for display + getMachineId: procedure.query(async ({ ctx }) => { + const telemetryService = ctx.serviceManager.getService("telemetryService"); + return telemetryService?.getMachineId() ?? ""; + }), + + // Download log file via save dialog + downloadLogFile: procedure.mutation(async () => { + const { dialog, BrowserWindow } = await import("electron"); + const isDev = process.env.NODE_ENV === "development" || !app.isPackaged; + const logPath = isDev + ? path.join(app.getPath("userData"), "logs", "amical-dev.log") + : path.join(app.getPath("logs"), "amical.log"); + + const focusedWindow = BrowserWindow.getFocusedWindow(); + const saveOptions = { + defaultPath: `amical-logs-${new Date().toISOString().split("T")[0]}.log`, + filters: [{ name: "Log Files", extensions: ["log", "txt"] }], + }; + const { filePath } = focusedWindow + ? await dialog.showSaveDialog(focusedWindow, saveOptions) + : await dialog.showSaveDialog(saveOptions); + + if (filePath) { + await fs.copyFile(logPath, filePath); + return { success: true, path: filePath }; + } + return { success: false }; + }), + // Get app preferences (launch at login, minimize to tray, etc.) getPreferences: procedure.query(async ({ ctx }) => { const settingsService = ctx.serviceManager.getService("settingsService");