Skip to content

Commit 39ac100

Browse files
authored
Merge pull request #216 from beNative/codex/add-button-to-open-executable-folder
Align About modal actions horizontally
2 parents 3a985c1 + db3bb39 commit 39ac100

4 files changed

Lines changed: 51 additions & 11 deletions

File tree

components/AboutModal.tsx

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import React, { useRef } from 'react';
1+
import React, { useCallback, useRef } from 'react';
22
import Modal from './Modal';
3+
import Button from './Button';
34

45
const appIconUrl = new URL('../assets/icon.svg', import.meta.url).href;
56

@@ -9,6 +10,16 @@ interface AboutModalProps {
910

1011
const AboutModal: React.FC<AboutModalProps> = ({ onClose }) => {
1112
const githubLinkRef = useRef<HTMLAnchorElement>(null);
13+
const handleOpenExecutableFolder = useCallback(async () => {
14+
try {
15+
const result = await window.electronAPI?.openExecutableFolder?.();
16+
if (result && !result.success && result.error) {
17+
console.error('Failed to open executable folder:', result.error);
18+
}
19+
} catch (error) {
20+
console.error('Failed to open executable folder:', error);
21+
}
22+
}, []);
1223

1324
return (
1425
<Modal title="About DocForge" onClose={onClose} initialFocusRef={githubLinkRef}>
@@ -22,15 +33,27 @@ const AboutModal: React.FC<AboutModalProps> = ({ onClose }) => {
2233
<p className="text-sm text-text-secondary">© 2025 Tim Sinaeve. All rights reserved.</p>
2334
</div>
2435
</div>
25-
<a
26-
ref={githubLinkRef}
27-
href="https://github.com/beNative/docforge"
28-
target="_blank"
29-
rel="noopener noreferrer"
30-
className="inline-flex items-center justify-center px-3 py-1.5 text-xs font-semibold rounded-md border border-transparent bg-primary text-primary-text hover:bg-primary-hover focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:ring-offset-background transition-colors duration-150"
31-
>
32-
View source on GitHub
33-
</a>
36+
<div className="flex flex-col items-center space-y-2">
37+
<div className="flex flex-wrap items-center justify-center gap-2">
38+
<a
39+
ref={githubLinkRef}
40+
href="https://github.com/beNative/docforge"
41+
target="_blank"
42+
rel="noopener noreferrer"
43+
className="inline-flex items-center justify-center px-3 py-1.5 text-xs font-semibold rounded-md border border-transparent bg-primary text-primary-text hover:bg-primary-hover focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:ring-offset-background transition-colors duration-150"
44+
>
45+
View source on GitHub
46+
</a>
47+
<Button
48+
type="button"
49+
variant="secondary"
50+
onClick={handleOpenExecutableFolder}
51+
className="text-xs"
52+
>
53+
Open installation folder
54+
</Button>
55+
</div>
56+
</div>
3457
</div>
3558
</Modal>
3659
);

electron/main.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Fix: This file was previously a placeholder. This is the full implementation for the Electron main process.
2-
import { app, BrowserWindow, ipcMain, dialog, clipboard } from 'electron';
2+
import { app, BrowserWindow, ipcMain, dialog, clipboard, shell } from 'electron';
33
// Fix: Import 'platform' from 'process' for type-safe access to the current OS identifier.
44
import { platform } from 'process';
55
import path from 'path';
@@ -656,6 +656,21 @@ ipcMain.handle('app:get-version', () => app.getVersion());
656656
// Fix: Error on line 145 is resolved by importing 'platform' from 'process'.
657657
ipcMain.handle('app:get-platform', () => platform);
658658
ipcMain.handle('app:get-log-path', () => log.transports.file.getFile().path);
659+
ipcMain.handle('app:open-executable-folder', async () => {
660+
const execDir = path.dirname(process.execPath);
661+
try {
662+
const error = await shell.openPath(execDir);
663+
if (error) {
664+
console.error('Failed to open executable folder:', error);
665+
return { success: false, error };
666+
}
667+
return { success: true, path: execDir };
668+
} catch (error) {
669+
const message = error instanceof Error ? error.message : String(error);
670+
console.error('Failed to open executable folder:', error);
671+
return { success: false, error: message };
672+
}
673+
});
659674

660675
ipcMain.on('updater:set-allow-prerelease', (_, allow: boolean) => {
661676
autoUpdater.allowPrerelease = allow;

electron/preload.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ contextBridge.exposeInMainWorld('electronAPI', {
6060
getAppVersion: () => ipcRenderer.invoke('app:get-version'),
6161
getPlatform: () => ipcRenderer.invoke('app:get-platform'),
6262
getLogPath: () => ipcRenderer.invoke('app:get-log-path'),
63+
openExecutableFolder: () => ipcRenderer.invoke('app:open-executable-folder'),
6364
renderPlantUML: (diagram: string, format: 'svg' = 'svg') => ipcRenderer.invoke('plantuml:render-svg', diagram, format),
6465
updaterSetAllowPrerelease: (allow: boolean) => ipcRenderer.send('updater:set-allow-prerelease', allow),
6566
updaterSetAutoCheckEnabled: (enabled: boolean) => ipcRenderer.send('updater:set-auto-check-enabled', enabled),

types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ declare global {
3636
getAppVersion: () => Promise<string>;
3737
getPlatform: () => Promise<string>;
3838
getLogPath: () => Promise<string>;
39+
openExecutableFolder: () => Promise<{ success: boolean; path?: string; error?: string }>;
3940
renderPlantUML: (
4041
diagram: string,
4142
format?: 'svg'

0 commit comments

Comments
 (0)