mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-24 02:39:42 +02:00
feat: add directory picker for new session dialog
- Add Browse button to open native directory picker - Add selectDirectory IPC handler using dialog.showOpenDialog - User can still type path manually or use system picker Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* IPC handlers for main process
|
||||
* Registers all IPC handlers for communication with renderer process
|
||||
*/
|
||||
import { ipcMain } from 'electron'
|
||||
import { ipcMain, dialog } from 'electron'
|
||||
import { IPC_CHANNELS } from '../../shared/ipc-channels'
|
||||
import { DEFAULT_AGENTS } from '../config/defaults'
|
||||
import type { Conductor } from '../conductor/Conductor'
|
||||
@@ -107,5 +107,20 @@ export function registerIPCHandlers(conductor: Conductor): void {
|
||||
return config
|
||||
})
|
||||
|
||||
// --- Dialog handlers ---
|
||||
|
||||
ipcMain.handle(IPC_CHANNELS.DIALOG_SELECT_DIRECTORY, async () => {
|
||||
const result = await dialog.showOpenDialog({
|
||||
properties: ['openDirectory', 'createDirectory'],
|
||||
title: 'Select Working Directory',
|
||||
})
|
||||
|
||||
if (result.canceled || result.filePaths.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
return result.filePaths[0]
|
||||
})
|
||||
|
||||
console.log('[IPC] All handlers registered')
|
||||
}
|
||||
|
||||
@@ -41,6 +41,9 @@ const electronAPI: ElectronAPI = {
|
||||
|
||||
updateConfig: (config) => ipcRenderer.invoke(IPC_CHANNELS.CONFIG_UPDATE, config),
|
||||
|
||||
// Dialog
|
||||
selectDirectory: () => ipcRenderer.invoke(IPC_CHANNELS.DIALOG_SELECT_DIRECTORY),
|
||||
|
||||
// Event listeners
|
||||
onAgentMessage: (callback) => {
|
||||
const listener = (_event: Electron.IpcRendererEvent, message: unknown) =>
|
||||
|
||||
@@ -130,18 +130,28 @@ function App(): React.JSX.Element {
|
||||
<label className="mb-2 block text-sm text-[var(--color-text-muted)]">
|
||||
Working Directory
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newSessionCwd}
|
||||
onChange={(e) => setNewSessionCwd(e.target.value)}
|
||||
placeholder="/path/to/project"
|
||||
className="mb-4 w-full rounded-lg border border-[var(--color-border)] bg-[var(--color-background)] px-4 py-2 text-[var(--color-text)] outline-none placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-primary)]"
|
||||
autoFocus
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') handleCreateSession()
|
||||
if (e.key === 'Escape') setShowNewSession(false)
|
||||
}}
|
||||
/>
|
||||
<div className="mb-4 flex gap-2">
|
||||
<input
|
||||
type="text"
|
||||
value={newSessionCwd}
|
||||
onChange={(e) => setNewSessionCwd(e.target.value)}
|
||||
placeholder="Select a directory..."
|
||||
className="flex-1 rounded-lg border border-[var(--color-border)] bg-[var(--color-background)] px-4 py-2 text-[var(--color-text)] outline-none placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-primary)]"
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') handleCreateSession()
|
||||
if (e.key === 'Escape') setShowNewSession(false)
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
onClick={async () => {
|
||||
const dir = await window.electronAPI.selectDirectory()
|
||||
if (dir) setNewSessionCwd(dir)
|
||||
}}
|
||||
className="flex-shrink-0 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface-hover)] px-4 py-2 text-[var(--color-text)] transition-colors hover:bg-[var(--color-border)]"
|
||||
>
|
||||
Browse...
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-2">
|
||||
<button
|
||||
|
||||
3
src/shared/electron-api.d.ts
vendored
3
src/shared/electron-api.d.ts
vendored
@@ -38,6 +38,9 @@ export interface ElectronAPI {
|
||||
getConfig(): Promise<AppConfig>
|
||||
updateConfig(config: Partial<AppConfig>): Promise<AppConfig>
|
||||
|
||||
// Dialog
|
||||
selectDirectory(): Promise<string | null>
|
||||
|
||||
// Event listeners (return unsubscribe function)
|
||||
onAgentMessage(callback: (message: AgentMessage) => void): () => void
|
||||
onAgentStatus(callback: (status: AgentStatus) => void): () => void
|
||||
|
||||
@@ -24,6 +24,9 @@ export const IPC_CHANNELS = {
|
||||
CONFIG_GET: 'config:get',
|
||||
CONFIG_UPDATE: 'config:update',
|
||||
|
||||
// Dialog
|
||||
DIALOG_SELECT_DIRECTORY: 'dialog:select-directory',
|
||||
|
||||
// File system (V2)
|
||||
FILE_APPROVAL_REQUEST: 'file:approval-request',
|
||||
FILE_APPROVAL_RESPONSE: 'file:approval-response',
|
||||
|
||||
Reference in New Issue
Block a user