From aec0d6a1b6de14d43018e181b142f18ffac401e2 Mon Sep 17 00:00:00 2001 From: jonathondouglasyager-debug Date: Tue, 10 Mar 2026 17:54:51 -0400 Subject: [PATCH 1/2] Add macOS compatibility: GPU detection, OAuth login, Cmd shortcuts, build config - Fix GPU detection to recognize macOS Metal GPU (was only checking Linux dev nodes) - Fix headless detection to skip DISPLAY/WAYLAND check on macOS/Windows - Set Chrome User-Agent on persist:grok session so OAuth providers don't reject Electron - Allow Google/Apple OAuth popups to open as real BrowserWindows with shared session - Auto-close OAuth popups when auth redirects back to grok.com - Use Cmd (meta) instead of Ctrl for keyboard shortcuts on macOS - Add mac build target (dmg) to package.json and electron-builder config Co-Authored-By: Claude Opus 4.6 --- index.html | 9 ++++++- package.json | 11 +++++++- src/main.js | 75 ++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 79 insertions(+), 16 deletions(-) diff --git a/index.html b/index.html index 8e689bc..2597045 100644 --- a/index.html +++ b/index.html @@ -674,7 +674,14 @@ }; // Open links that request a new window - webview.addEventListener('new-window', (e) => { e.preventDefault(); handleOpenUrl(e.url); }); + webview.addEventListener('new-window', (e) => { + // Let OAuth popups open as real BrowserWindows (handled by main process) + if (/accounts\.google\.com|appleid\.apple\.com/.test(e.url)) { + return; // Don't prevent — popup opens naturally with shared session + } + e.preventDefault(); + handleOpenUrl(e.url); + }); // Allow internal same-tab nav; open external in browser webview.addEventListener('will-navigate', (e) => { const url = e.url; diff --git a/package.json b/package.json index 56623b1..3c5c63e 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "build-rpm": "npx --yes electron-builder@latest --linux rpm", "build-deb": "npx --yes electron-builder@latest --linux deb", "build-rpm-deb": "npx --yes electron-builder@latest --linux rpm deb", - "build-all": "npx --yes electron-builder@latest --win --x64 --linux" + "build-all": "npx --yes electron-builder@latest --win --x64 --linux", + "build-mac": "npx --yes electron-builder@latest --mac" }, "keywords": [ "electron", @@ -49,6 +50,14 @@ "category": "Network", "icon": "build-resources/icons" }, + "mac": { + "target": [ + "dmg" + ], + "category": "public.app-category.productivity", + "icon": "build-resources/icons/512x512.png", + "artifactName": "Grok-Desktop-v${version}.dmg" + }, "rpm": { "artifactName": "Grok-Desktop-v${version}.${ext}" }, diff --git a/src/main.js b/src/main.js index 1631d61..30711b6 100644 --- a/src/main.js +++ b/src/main.js @@ -7,17 +7,22 @@ const { exec } = require('child_process'); // GPU acceleration detection and graceful fallback function configureGpuAcceleration() { // Check if we're in a headless environment or container - const isHeadless = !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY; + // macOS and Windows don't use DISPLAY/WAYLAND_DISPLAY — only check on Linux + const isHeadless = process.platform === 'linux' && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY; const isContainer = fs.existsSync('/.dockerenv') || process.env.container === 'docker'; - // Check for NVIDIA/AMD GPU availability (basic detection) + // Check for GPU availability (platform-aware detection) let hasGpu = false; try { - // Check for NVIDIA GPU + // macOS always has a GPU (Metal/integrated graphics) — never disable acceleration + if (process.platform === 'darwin') { + hasGpu = true; + } + // Check for NVIDIA GPU (Linux/Windows) if (fs.existsSync('/dev/nvidia0') || process.env.NVIDIA_VISIBLE_DEVICES) { hasGpu = true; } - // Check for AMD GPU + // Check for AMD/Intel GPU (Linux) if (fs.existsSync('/dev/dri/card0')) { hasGpu = true; } @@ -346,6 +351,15 @@ function createWindow() { if (typeof grokSession.setSpellCheckerLanguages === 'function') { grokSession.setSpellCheckerLanguages(languages); } + + // Override User-Agent to match a real Chrome browser so login/OAuth flows work. + // Electron's default UA includes "Electron" which many auth providers reject. + const chromeVersion = process.versions.chrome || '131.0.0.0'; + const platform = process.platform === 'darwin' ? 'Macintosh; Intel Mac OS X 10_15_7' + : process.platform === 'win32' ? 'Windows NT 10.0; Win64; x64' + : 'X11; Linux x86_64'; + const chromeUA = `Mozilla/5.0 (${platform}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${chromeVersion} Safari/537.36`; + grokSession.setUserAgent(chromeUA); } } catch (_) {} @@ -443,15 +457,48 @@ app.on('window-all-closed', () => { function setupUrlHandling() { // Handle navigation events from webContents app.on('web-contents-created', (event, contents) => { - // Intercept new window requests; always deny BrowserWindow creation - // Internal domains will be handled by the renderer's webview 'new-window' handler contents.setWindowOpenHandler(({ url }) => { const isInternal = allowedUrlPatterns.some(pattern => pattern.test(url)); if (!isInternal) { shell.openExternal(url); + return { action: 'deny' }; + } + + // Allow OAuth popups to open as real BrowserWindows so login flows work. + // Google/Apple OAuth require a proper popup with window.opener context. + const isOAuth = /^https?:\/\/(accounts\.google\.com|appleid\.apple\.com)/i.test(url); + if (isOAuth) { + return { + action: 'allow', + overrideBrowserWindowOptions: { + width: 500, + height: 700, + webPreferences: { + partition: 'persist:grok', + nodeIntegration: false, + contextIsolation: true + } + } + }; } + + // Other internal URLs are handled by the renderer's webview new-window handler return { action: 'deny' }; }); + + // Manage OAuth popup lifecycle — close when auth redirects back to grok.com + contents.on('did-create-window', (popup) => { + popup.webContents.on('did-navigate', (_e, navUrl) => { + if (/^https?:\/\/grok\.com/i.test(navUrl)) { + popup.close(); + } + }); + popup.webContents.on('will-redirect', (_e, navUrl) => { + if (/^https?:\/\/grok\.com/i.test(navUrl)) { + popup.close(); + } + }); + }); }); } @@ -754,8 +801,9 @@ function attachShortcutHandlers(contents) { try { contents.on('before-input-event', (event, input) => { try { - // Only handle keyDown with Control on Windows/Linux - if (input.type !== 'keyDown' || !input.control) return; + // Handle keyDown with Control (Windows/Linux) or Meta/Cmd (macOS) + const modifier = process.platform === 'darwin' ? input.meta : input.control; + if (input.type !== 'keyDown' || !modifier) return; const key = input.key; // Deliver to the hosting window (handles webviews as well) @@ -763,29 +811,28 @@ function attachShortcutHandlers(contents) { const win = BrowserWindow.fromWebContents(host); if (!win || win.isDestroyed()) return; - // Ctrl+K -> Remap to Ctrl+Shift+K for grok.com search + // Cmd/Ctrl+K -> Remap to Cmd/Ctrl+Shift+K for grok.com search // grok.com responds to Ctrl+Shift+K, not Ctrl+K (which Chromium intercepts for omnibox) + const modKey = process.platform === 'darwin' ? 'meta' : 'control'; if ((key === 'k' || key === 'K') && !input.shift) { event.preventDefault(); - // Send Ctrl+Shift+K to the webContents using sendInputEvent (creates trusted OS-level events) contents.sendInputEvent({ type: 'keyDown', keyCode: 'K', - modifiers: ['control', 'shift'] + modifiers: [modKey, 'shift'] }); - // Send keyUp after a short delay setTimeout(() => { try { contents.sendInputEvent({ type: 'keyUp', keyCode: 'K', - modifiers: ['control', 'shift'] + modifiers: [modKey, 'shift'] }); } catch (_) {} }, 10); return; } - // Don't intercept Ctrl+Shift+K - let it pass through naturally (it already works) + // Don't intercept Cmd/Ctrl+Shift+K - let it pass through naturally (it already works) // Ctrl+T -> new tab if (key === 't' || key === 'T') { From 8609159eb118dc70a586154676f3f0021c0f4182 Mon Sep 17 00:00:00 2001 From: jonathondouglasyager-debug Date: Thu, 12 Mar 2026 10:59:11 -0400 Subject: [PATCH 2/2] fix: resolve merge conflicts in README and .gitignore, correct license field - Resolved merge conflict markers in README.md (kept development branch's better-structured Building from Source section) - Resolved merge conflict markers in .gitignore (combined both sides) - Fixed package.json license from "ISC" to "GPL-2.0" to match LICENSE file Co-Authored-By: Claude Opus 4.6 --- .gitignore | 11 +---------- README.md | 34 ---------------------------------- package.json | 2 +- 3 files changed, 2 insertions(+), 45 deletions(-) diff --git a/.gitignore b/.gitignore index af4b07f..32b1f30 100644 --- a/.gitignore +++ b/.gitignore @@ -70,21 +70,13 @@ temp/ # Keep lockfiles tracked (do not ignore package-lock.json) -# Task list -<<<<<<< HEAD +# Task lists task-list.md -======= tasklist.md ->>>>>>> development # Security reports security_reports/ -<<<<<<< HEAD -# Task lists -tasklist.md - -======= # Regression test checklist REGRESSION_TEST_CHECKLIST.md @@ -93,4 +85,3 @@ release.md # copyparty copyparty_1.19.22.exe ->>>>>>> development diff --git a/README.md b/README.md index cbf2f5b..f93f57f 100644 --- a/README.md +++ b/README.md @@ -87,39 +87,6 @@ Grok-Desktop/ └── README.md # This file ``` -<<<<<<< HEAD -## Build Grok-Desktop -1. Install Node.js from [nodejs.org](https://nodejs.org/). -2. Clone this repository or download the files. -3. Install dependencies if needed: `npm install` -4. Build using npm scripts: - - Directory build (unpacked): `npm run build-dir` - - Portable executable: `npm run build-portable` - - Full installers (NSIS + MSI): `npm run build-installer` - -Notes: -- These scripts use `npx electron-builder@latest` (no global install required). -- All build outputs are written to the `build` directory. - -## Usage -- After building, install `Grok-Desktop` with `Grok-Desktop_Installer-v1.2.3.exe` from the `build` directory -- Launch `Grok-Desktop` from the Start Menu -- Log in via `grok.com`, using Google, Apple, or xAI authentication as needed. -- Use the + button in the top toolbar (or Ctrl+T) to add new tabs. -- Click the AOT button in the top right to toggle always-on-top functionality. -- Use keyboard shortcuts to work faster: - - Ctrl+T: Open a new tab - - Ctrl+Tab / Ctrl+Shift+Tab: Cycle through open tabs (next/previous) - - Ctrl+R: Reload the currently active tab - - Ctrl+I: Show information/about dialog - -## Keyboard Shortcuts -- Ctrl+T: Open a new tab -- Ctrl+Tab: Switch to the next tab -- Ctrl+Shift+Tab: Switch to the previous tab -- Ctrl+R: Reload the active tab (does not reload the entire app window) -- Ctrl+I: Show information/about dialog -======= ## Building from Source ### Prerequisites @@ -129,7 +96,6 @@ Notes: 4. Install dependencies: `npm install` ### Build Commands ->>>>>>> development #### Windows ```bash diff --git a/package.json b/package.json index 3c5c63e..a5f696c 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "tabs" ], "author": "AnRkey ", - "license": "ISC", + "license": "GPL-2.0", "type": "commonjs", "dependencies": { "electron-tabs": "^1.0.4"