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");