diff --git a/desktop/main.js b/desktop/main.js index f8a6534..b143652 100644 --- a/desktop/main.js +++ b/desktop/main.js @@ -7,7 +7,7 @@ // answers, then points a BrowserWindow at it. 'use strict'; -const { app, BrowserWindow, shell, dialog, Menu } = require('electron'); +const { app, BrowserWindow, shell, dialog, Menu, ipcMain } = require('electron'); const { spawn } = require('child_process'); const http = require('http'); const https = require('https'); @@ -120,7 +120,25 @@ function waitForServer(port, timeoutMs) { }); } +// Native folder picker for the "Add project" flow. Returns the chosen absolute +// path, or null on cancel. Registered once (guarded) so re-creating the window +// doesn't stack duplicate handlers. +let _pickFolderRegistered = false; +function registerIpc() { + if (_pickFolderRegistered) return; + _pickFolderRegistered = true; + ipcMain.handle('codbash:pick-folder', async function () { + const res = await dialog.showOpenDialog(win, { + title: 'Choose a project folder', + properties: ['openDirectory', 'createDirectory'], + }); + if (res.canceled || !res.filePaths || !res.filePaths.length) return null; + return res.filePaths[0]; + }); +} + async function createWindow() { + registerIpc(); win = new BrowserWindow({ width: 1320, height: 860, @@ -128,7 +146,12 @@ async function createWindow() { minHeight: 600, title: 'codbash', backgroundColor: '#0b0d12', - webPreferences: { contextIsolation: true, nodeIntegration: false, spellcheck: false }, + webPreferences: { + contextIsolation: true, + nodeIntegration: false, + spellcheck: false, + preload: path.join(__dirname, 'preload.js'), + }, }); // http/https links open in the user's real browser, not inside the app. diff --git a/desktop/preload.js b/desktop/preload.js new file mode 100644 index 0000000..7472d54 --- /dev/null +++ b/desktop/preload.js @@ -0,0 +1,12 @@ +'use strict'; + +// Minimal, safe bridge exposed to the loaded dashboard page. contextIsolation +// is on and nodeIntegration off, so the renderer only sees exactly what we +// expose here — a single method that opens the native folder picker. +const { contextBridge, ipcRenderer } = require('electron'); + +contextBridge.exposeInMainWorld('codbashDesktop', { + isDesktop: true, + // Resolves to the chosen absolute folder path, or null if the user cancels. + pickFolder: () => ipcRenderer.invoke('codbash:pick-folder'), +}); diff --git a/src/frontend/app.js b/src/frontend/app.js index 2e2917c..57f0e69 100644 --- a/src/frontend/app.js +++ b/src/frontend/app.js @@ -4085,9 +4085,26 @@ function openAddProject() { var input = document.getElementById('apLocalPath'); if (input) { input.value = ''; setTimeout(function() { input.focus(); }, 50); } var err = document.getElementById('apLocalError'); if (err) err.textContent = ''; + // Desktop app only: reveal the native "Browse…" folder picker (the browser + // has no way to open a Finder folder dialog and return an absolute path). + var browse = document.getElementById('apBrowseBtn'); + if (browse) browse.style.display = + (window.codbashDesktop && typeof window.codbashDesktop.pickFolder === 'function') ? '' : 'none'; _installModalFocusTrap(overlay); } +// Open the OS folder picker (Finder) in the desktop app and drop the chosen +// absolute path into the input. No-op in the browser (button stays hidden). +function browseForProjectFolder() { + if (!(window.codbashDesktop && typeof window.codbashDesktop.pickFolder === 'function')) return; + window.codbashDesktop.pickFolder().then(function (dir) { + if (!dir) return; + var input = document.getElementById('apLocalPath'); + if (input) { input.value = dir; input.focus(); } + var err = document.getElementById('apLocalError'); if (err) err.textContent = ''; + }).catch(function () {}); +} + function closeAddProject() { var overlay = document.getElementById('addProjectOverlay'); if (overlay) { diff --git a/src/frontend/index.html b/src/frontend/index.html index 2ea5287..64268ac 100644 --- a/src/frontend/index.html +++ b/src/frontend/index.html @@ -300,9 +300,12 @@

Add project

- +
+ + +
-
Start typing to pick from your known project folders. ~ is expanded.
+
Start typing to pick from your known project folders, or Browse… in the desktop app. ~ is expanded.