Skip to content

Commit b19416f

Browse files
author
JooHyung Park
committed
[ai-assisted] Fix app quit shortcut handling
1 parent 58b476d commit b19416f

4 files changed

Lines changed: 66 additions & 19 deletions

File tree

src/main.ts

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,46 @@ let mainWindow: BrowserWindow | null = null;
6363
let tray: TalkToFigmaTray | null = null;
6464
let serverManager: TalkToFigmaServerManager | null = null;
6565
let service: TalkToFigmaService | null = null;
66+
let quitRequested = false;
67+
let shutdownComplete = false;
6668

6769
const rendererLoaderOptions = {
6870
devServerUrl: MAIN_WINDOW_VITE_DEV_SERVER_URL,
6971
rendererName: MAIN_WINDOW_VITE_NAME,
7072
logger,
7173
};
7274

75+
const requestAppQuit = async () => {
76+
if (quitRequested) {
77+
logger.info('Quit already requested');
78+
return;
79+
}
80+
81+
quitRequested = true;
82+
logger.info('Quit requested');
83+
84+
try {
85+
await shutdownApp({
86+
logger,
87+
service,
88+
tray,
89+
flushMCPToolSuccessBatch,
90+
trackAppQuit,
91+
});
92+
} finally {
93+
shutdownComplete = true;
94+
app.exit(0);
95+
}
96+
};
97+
7398
const createWindow = () => {
7499
mainWindow = createMainWindow({
75100
preloadPath: path.join(__dirname, 'preload.cjs'),
76101
logger,
77102
loadRenderer: (window) => loadRenderer(window, rendererLoaderOptions),
78103
registerIpcHandlers,
79104
setLoggerWindow: setMainWindow,
80-
createMenu,
105+
createMenu: (window) => createMenu(window, requestAppQuit),
81106
});
82107
};
83108

@@ -89,7 +114,7 @@ const createTray = () => {
89114
return;
90115
}
91116

92-
tray = new TalkToFigmaTray(serverManager);
117+
tray = new TalkToFigmaTray(serverManager, requestAppQuit);
93118
tray.create();
94119

95120
logger.info('System tray created');
@@ -119,7 +144,7 @@ const initializeServers = (window: BrowserWindow) => {
119144

120145
service.setMenuUpdateCallback(() => {
121146
if (mainWindow && !mainWindow.isDestroyed()) {
122-
createMenu(mainWindow);
147+
createMenu(mainWindow, requestAppQuit);
123148
}
124149
});
125150

@@ -186,7 +211,7 @@ app.on('ready', async () => {
186211
app.on('window-all-closed', () => {
187212
if (process.platform !== 'darwin') {
188213
logger.info('All windows closed, quitting app');
189-
app.quit();
214+
void requestAppQuit();
190215
}
191216
});
192217

@@ -196,14 +221,13 @@ app.on('activate', () => {
196221
}
197222
});
198223

199-
app.on('before-quit', async () => {
200-
await shutdownApp({
201-
logger,
202-
service,
203-
tray,
204-
flushMCPToolSuccessBatch,
205-
trackAppQuit,
206-
});
224+
app.on('before-quit', (event) => {
225+
if (shutdownComplete) {
226+
return;
227+
}
228+
229+
event.preventDefault();
230+
void requestAppQuit();
207231
});
208232

209233
app.on('will-quit', () => {

src/main/bootstrap/shutdown.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ function closeWindows(logger: LoggerLike): void {
6666
window.webContents.closeDevTools();
6767
}
6868
if (!window.isDestroyed()) {
69-
window.close();
69+
window.destroy();
7070
}
7171
} catch (error) {
7272
logger.error('Error closing window:', { error });

src/main/menu.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { TalkToFigmaService } from './server/TalkToFigmaService';
1414
* Create application menu
1515
* Based on Tray menu structure for consistency
1616
*/
17-
export function createMenu(mainWindow: BrowserWindow) {
17+
export function createMenu(mainWindow: BrowserWindow, requestQuit: () => void | Promise<void>) {
1818
const isMac = process.platform === 'darwin';
1919
const { canCheckForUpdates } = getUpdateCapabilities();
2020
const serverManager = TalkToFigmaServerManager.getInstance();
@@ -67,11 +67,33 @@ export function createMenu(mainWindow: BrowserWindow) {
6767
{ role: 'hideOthers' },
6868
{ role: 'unhide' },
6969
{ type: 'separator' },
70-
{ role: 'quit' }
70+
{
71+
label: `Quit ${app.name}`,
72+
accelerator: 'Command+Q',
73+
click: () => {
74+
void requestQuit();
75+
},
76+
}
7177
]
7278
} as MenuItemConstructorOptions]
7379
: []),
7480

81+
// File Menu (Windows/Linux)
82+
...(!isMac
83+
? [{
84+
label: 'File',
85+
submenu: [
86+
{
87+
label: 'Quit',
88+
accelerator: 'Alt+F4',
89+
click: () => {
90+
void requestQuit();
91+
},
92+
},
93+
],
94+
} as MenuItemConstructorOptions]
95+
: []),
96+
7597
// Edit Menu (clipboard shortcuts: cut/copy/paste/select all)
7698
{ role: 'editMenu' },
7799

src/main/server/TalkToFigmaTray.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ export class TalkToFigmaTray {
3737
private tray: Tray | null = null;
3838
private manager: TalkToFigmaServerManager;
3939
private service: TalkToFigmaService;
40+
private requestQuit: () => void | Promise<void>;
4041

41-
constructor(manager: TalkToFigmaServerManager) {
42+
constructor(manager: TalkToFigmaServerManager, requestQuit: () => void | Promise<void> = () => app.quit()) {
4243
this.manager = manager;
4344
this.service = TalkToFigmaService.getInstance();
45+
this.requestQuit = requestQuit;
4446

4547
// Register this tray to be updated when server status changes
4648
this.service.setTrayUpdateCallback(() => {
@@ -166,9 +168,8 @@ export class TalkToFigmaTray {
166168
// ═══ EXIT ═══
167169
{
168170
label: 'Quit',
169-
click: async () => {
170-
await this.manager.stopAll();
171-
app.quit();
171+
click: () => {
172+
void this.requestQuit();
172173
},
173174
},
174175
];

0 commit comments

Comments
 (0)