From f81a195db5064890f9b6cf2f4151e96044e4b51d Mon Sep 17 00:00:00 2001 From: Karan-05 Date: Thu, 5 Feb 2026 08:59:21 -0500 Subject: [PATCH 1/5] feat: auto install react devtools --- README.md | 6 +++++ package.json | 1 + pnpm-lock.yaml | 64 ++++++++++++++++++++++++++++++++++++++++++-- src/main/devtools.ts | 31 +++++++++++++++++++++ src/main/index.ts | 2 ++ src/main/menu.ts | 8 ++++++ 6 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 src/main/devtools.ts diff --git a/README.md b/README.md index cff4a9ad0..ea2a4c894 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,12 @@ Please visit our [Gitify FAQs][faqs] for all commonly asked questions. Please read our [Contributing Guidelines](CONTRIBUTING.md) for more information. +### Development + +Running `pnpm start` installs the React Developer Tools extension automatically so +you can inspect the renderer process. You can reinstall it at any time from the +tray context menu under **Developer → Reinstall React DevTools**. + ### License Gitify is licensed under the MIT Open Source license. diff --git a/package.json b/package.json index f6b55eea5..af30c8275 100644 --- a/package.json +++ b/package.json @@ -117,6 +117,7 @@ "css-minimizer-webpack-plugin": "7.0.4", "date-fns": "4.1.0", "dotenv": "17.2.3", + "electron-devtools-installer": "4.0.0", "electron": "40.1.0", "electron-builder": "26.6.0", "final-form": "5.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 81439fb6e..d8e6e6752 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -144,6 +144,9 @@ importers: electron-builder: specifier: 26.6.0 version: 26.6.0(electron-builder-squirrel-windows@24.13.3) + electron-devtools-installer: + specifier: 4.0.0 + version: 4.0.0 final-form: specifier: 5.0.0 version: 5.0.0 @@ -3232,6 +3235,9 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + electron-devtools-installer@4.0.0: + resolution: {integrity: sha512-9Tntu/jtfSn0n6N/ZI6IdvRqXpDyLQiDuuIbsBI+dL+1Ef7C8J2JwByw58P3TJiNeuqyV3ZkphpNWuZK5iSY2w==} + electron-log@5.4.3: resolution: {integrity: sha512-sOUsM3LjZdugatazSQ/XTyNcw8dfvH1SYhXWiJyfYodAAKOZdHs0txPiLDXFzOZbhXgAgshQkshH2ccq0feyLQ==} engines: {node: '>= 14'} @@ -3567,6 +3573,7 @@ packages: glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@13.0.0: @@ -3575,7 +3582,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me global-agent@3.0.0: resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} @@ -3772,6 +3779,9 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + immutable@3.7.6: resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} engines: {node: '>=0.8.0'} @@ -4193,6 +4203,9 @@ packages: jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -4211,6 +4224,9 @@ packages: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + lightningcss-android-arm64@1.30.2: resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} engines: {node: '>= 12.0.0'} @@ -4544,6 +4560,10 @@ packages: resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} engines: {node: '>= 18'} + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} @@ -4701,6 +4721,9 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + param-case@3.0.4: resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} @@ -5533,7 +5556,7 @@ packages: tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} - deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me tar@7.5.7: resolution: {integrity: sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==} @@ -5759,6 +5782,9 @@ packages: unrs-resolver@1.8.1: resolution: {integrity: sha512-M5++xH5Tu/m3NNAc0+dBHidXfF6bTC08mfhQ3AB5UTonEzQSH9ASC/a7EbZN3WU5m0OWMTvf12GHVJZ3uUmPtA==} + unzip-crx-3@0.2.0: + resolution: {integrity: sha512-0+JiUq/z7faJ6oifVB5nSwt589v1KCduqIJupNVDoWSXZtWDmjDGO3RAEOvwJ07w90aoXoP4enKsR7ecMrJtWQ==} + update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true @@ -5948,6 +5974,9 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} + yaku@0.16.7: + resolution: {integrity: sha512-Syu3IB3rZvKvYk7yTiyl1bo/jiEFaaStrgv1V2TIJTqYPStSMQVO8EQjg/z+DRzLq/4LIIharNT3iH1hylEIRw==} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -9748,6 +9777,10 @@ snapshots: - electron-builder-squirrel-windows - supports-color + electron-devtools-installer@4.0.0: + dependencies: + unzip-crx-3: 0.2.0 + electron-log@5.4.3: {} electron-positioner@4.1.0: {} @@ -10357,6 +10390,8 @@ snapshots: ignore@5.3.2: {} + immediate@3.0.6: {} + immutable@3.7.6: {} import-fresh@3.3.0: @@ -10980,6 +11015,13 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jszip@3.10.1: + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -10994,6 +11036,10 @@ snapshots: leven@3.1.0: {} + lie@3.3.0: + dependencies: + immediate: 3.0.6 + lightningcss-android-arm64@1.30.2: optional: true @@ -11275,6 +11321,10 @@ snapshots: dependencies: minipass: 7.1.2 + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + mkdirp@1.0.4: {} ms@2.1.3: {} @@ -11415,6 +11465,8 @@ snapshots: package-json-from-dist@1.0.1: {} + pako@1.0.11: {} + param-case@3.0.4: dependencies: dot-case: 3.0.4 @@ -12468,6 +12520,12 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.8.1 '@unrs/resolver-binding-win32-x64-msvc': 1.8.1 + unzip-crx-3@0.2.0: + dependencies: + jszip: 3.10.1 + mkdirp: 0.5.6 + yaku: 0.16.7 + update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: browserslist: 4.28.1 @@ -12662,6 +12720,8 @@ snapshots: y18n@5.0.8: {} + yaku@0.16.7: {} + yallist@3.1.1: {} yallist@4.0.0: {} diff --git a/src/main/devtools.ts b/src/main/devtools.ts new file mode 100644 index 000000000..f5d2153c3 --- /dev/null +++ b/src/main/devtools.ts @@ -0,0 +1,31 @@ +import log from 'electron-log'; + +let installTask: Promise | null = null; + +export async function installReactDevtools() { + if (process.env.NODE_ENV === 'production') { + return; + } + + if (installTask) { + await installTask; + return; + } + + installTask = (async () => { + try { + const { default: installExtension, REACT_DEVELOPER_TOOLS } = await import( + 'electron-devtools-installer' + ); + + const name = await installExtension(REACT_DEVELOPER_TOOLS); + log.info(`[devtools] Installed ${name}`); + } catch (error) { + log.warn('[devtools] Failed to install React DevTools', error); + } finally { + installTask = null; + } + })(); + + await installTask; +} diff --git a/src/main/index.ts b/src/main/index.ts index cf18866d5..b9ca02419 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -20,6 +20,7 @@ import { } from '../shared/events'; import { logInfo, logWarn } from '../shared/logger'; +import { installReactDevtools } from './devtools'; import { handleMainEvent, onMainEvent, sendRendererEvent } from './events'; import { onFirstRunMaybe } from './first-run'; import { TrayIcons } from './icons'; @@ -80,6 +81,7 @@ let shouldUseUnreadActiveIcon = true; app.whenReady().then(async () => { preventSecondInstance(); + await installReactDevtools(); await onFirstRunMaybe(); appUpdater.start(); diff --git a/src/main/menu.ts b/src/main/menu.ts index da6f9f8f3..39be7d503 100644 --- a/src/main/menu.ts +++ b/src/main/menu.ts @@ -5,6 +5,7 @@ import type { Menubar } from 'menubar'; import { APPLICATION } from '../shared/constants'; import { isMacOS } from '../shared/platform'; +import { installReactDevtools } from './devtools'; import { openLogsDirectory, resetApp, takeScreenshot } from './utils'; export default class MenuBuilder { @@ -66,6 +67,13 @@ export default class MenuBuilder { role: 'toggleDevTools', accelerator: isMacOS() ? 'Alt+Cmd+I' : 'Ctrl+Shift+I', }, + { + label: 'Reinstall React DevTools', + enabled: process.env.NODE_ENV !== 'production', + click: () => { + void installReactDevtools(); + }, + }, { label: 'Take Screenshot', accelerator: 'CommandOrControl+S', From 38958019ae3f58089452e802edc8f7cc9bc706ee Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Thu, 5 Feb 2026 16:54:13 -0500 Subject: [PATCH 2/5] feat: react dev tools Signed-off-by: Adam Setch --- pnpm-lock.yaml | 91 +++++++++++++++++++++++++++++++++++++++----- src/main/devtools.ts | 41 +++++++++++++++++--- 2 files changed, 116 insertions(+), 16 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d8e6e6752..12f2f49b4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -246,6 +246,10 @@ packages: resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.28.6': resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==} engines: {node: '>=6.9.0'} @@ -855,6 +859,10 @@ packages: resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} @@ -2529,6 +2537,9 @@ packages: async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -3281,6 +3292,9 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + enhanced-resolve@5.18.3: resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} engines: {node: '>=10.13.0'} @@ -3482,6 +3496,10 @@ packages: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + form-data@4.0.5: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} @@ -3576,6 +3594,11 @@ packages: deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + glob@13.0.0: resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} engines: {node: 20 || >=22} @@ -3920,6 +3943,10 @@ packages: resolution: {integrity: sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==} engines: {node: '>= 18.0.0'} + isbinaryfile@5.0.7: + resolution: {integrity: sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==} + engines: {node: '>= 18.0.0'} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -4153,6 +4180,10 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + jsbn@1.1.0: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} @@ -5286,6 +5317,10 @@ packages: sax@1.3.0: resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} + sax@1.4.4: + resolution: {integrity: sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==} + engines: {node: '>=11.0.0'} + saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} @@ -6063,6 +6098,12 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/compat-data@7.28.6': {} '@babel/core@7.28.6': @@ -6821,6 +6862,8 @@ snapshots: '@babel/runtime@7.28.4': {} + '@babel/runtime@7.28.6': {} + '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 @@ -8355,8 +8398,8 @@ snapshots: '@testing-library/dom@10.0.0': dependencies: - '@babel/code-frame': 7.28.6 - '@babel/runtime': 7.28.4 + '@babel/code-frame': 7.29.0 + '@babel/runtime': 7.28.6 '@types/aria-query': 5.0.4 aria-query: 5.3.0 chalk: 4.1.2 @@ -8836,8 +8879,8 @@ snapshots: fs-extra: 10.1.0 hosted-git-info: 4.1.0 is-ci: 3.0.1 - isbinaryfile: 5.0.2 - js-yaml: 4.1.0 + isbinaryfile: 5.0.7 + js-yaml: 4.1.1 lazy-val: 1.0.5 minimatch: 5.1.6 read-config-file: 6.3.2 @@ -8920,7 +8963,7 @@ snapshots: archiver@5.3.2: dependencies: archiver-utils: 2.1.0 - async: 3.2.5 + async: 3.2.6 buffer-crc32: 0.2.13 readable-stream: 3.6.2 readdir-glob: 1.1.3 @@ -8953,6 +8996,8 @@ snapshots: async@3.2.5: {} + async@3.2.6: {} + asynckit@0.4.0: {} at-least-node@1.0.0: {} @@ -9105,7 +9150,7 @@ snapshots: builder-util-runtime@9.2.4: dependencies: debug: 4.4.3 - sax: 1.3.0 + sax: 1.4.4 transitivePeerDependencies: - supports-color @@ -9130,7 +9175,7 @@ snapshots: http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-ci: 3.0.1 - js-yaml: 4.1.0 + js-yaml: 4.1.1 source-map-support: 0.5.21 stat-mode: 1.0.0 temp-file: 3.4.0 @@ -9370,7 +9415,7 @@ snapshots: config-file-ts@0.2.6: dependencies: - glob: 10.4.5 + glob: 10.5.0 typescript: 5.9.3 constant-case@3.0.4: @@ -9850,6 +9895,10 @@ snapshots: dependencies: once: 1.4.0 + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 @@ -10047,6 +10096,11 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + form-data@4.0.5: dependencies: asynckit: 0.4.0 @@ -10152,6 +10206,15 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + glob@13.0.0: dependencies: minimatch: 10.1.1 @@ -10504,6 +10567,8 @@ snapshots: isbinaryfile@5.0.2: {} + isbinaryfile@5.0.7: {} + isexe@2.0.0: {} isexe@3.1.1: {} @@ -10950,6 +11015,10 @@ snapshots: dependencies: argparse: 2.0.1 + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + jsbn@1.1.0: {} jsdom@26.1.0: @@ -11858,7 +11927,7 @@ snapshots: config-file-ts: 0.2.6 dotenv: 9.0.2 dotenv-expand: 5.1.0 - js-yaml: 4.1.0 + js-yaml: 4.1.1 json5: 2.2.3 lazy-val: 1.0.5 @@ -12025,6 +12094,8 @@ snapshots: sax@1.3.0: {} + sax@1.4.4: {} + saxes@6.0.0: dependencies: xmlchars: 2.2.0 @@ -12295,7 +12366,7 @@ snapshots: tar-stream@2.2.0: dependencies: bl: 4.1.0 - end-of-stream: 1.4.4 + end-of-stream: 1.4.5 fs-constants: 1.0.0 inherits: 2.0.4 readable-stream: 3.6.2 diff --git a/src/main/devtools.ts b/src/main/devtools.ts index f5d2153c3..2e4dfc156 100644 --- a/src/main/devtools.ts +++ b/src/main/devtools.ts @@ -1,4 +1,9 @@ -import log from 'electron-log'; +import { session } from 'electron'; +import installExtension, { + REACT_DEVELOPER_TOOLS, +} from 'electron-devtools-installer'; + +import { logInfo, logWarn } from '../shared/logger'; let installTask: Promise | null = null; @@ -14,14 +19,38 @@ export async function installReactDevtools() { installTask = (async () => { try { - const { default: installExtension, REACT_DEVELOPER_TOOLS } = await import( - 'electron-devtools-installer' + const result = await installExtension(REACT_DEVELOPER_TOOLS, { + loadExtensionOptions: { + allowFileAccess: true, + }, + forceDownload: false, + }); + + logInfo('devtools', `Installed ${result.name} v${result.version}`); + + // Verify the extension is loaded + const extensions = session.defaultSession.extensions.getAllExtensions(); + const installedReactDevTools = extensions.find((ext) => + ext.name.includes('React Developer Tools'), ); - const name = await installExtension(REACT_DEVELOPER_TOOLS); - log.info(`[devtools] Installed ${name}`); + if (installedReactDevTools) { + logInfo( + 'devtools', + `React Developer Tools verified: ${installedReactDevTools.name} v${installedReactDevTools.version}`, + ); + } else { + logWarn( + 'devtools', + 'React Developer Tools not found after installation', + ); + } } catch (error) { - log.warn('[devtools] Failed to install React DevTools', error); + logWarn( + 'devtools', + 'Failed to install React DevTools via installer', + error, + ); } finally { installTask = null; } From 4678d7e7083488e657a8554a96554a3210898ad6 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Thu, 5 Feb 2026 17:00:24 -0500 Subject: [PATCH 3/5] feat: react dev tools Signed-off-by: Adam Setch --- src/main/menu.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/main/menu.ts b/src/main/menu.ts index 39be7d503..da6f9f8f3 100644 --- a/src/main/menu.ts +++ b/src/main/menu.ts @@ -5,7 +5,6 @@ import type { Menubar } from 'menubar'; import { APPLICATION } from '../shared/constants'; import { isMacOS } from '../shared/platform'; -import { installReactDevtools } from './devtools'; import { openLogsDirectory, resetApp, takeScreenshot } from './utils'; export default class MenuBuilder { @@ -67,13 +66,6 @@ export default class MenuBuilder { role: 'toggleDevTools', accelerator: isMacOS() ? 'Alt+Cmd+I' : 'Ctrl+Shift+I', }, - { - label: 'Reinstall React DevTools', - enabled: process.env.NODE_ENV !== 'production', - click: () => { - void installReactDevtools(); - }, - }, { label: 'Take Screenshot', accelerator: 'CommandOrControl+S', From 3cfc63d62d72407ad68dc0e7fb12281a63a4e7eb Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Thu, 5 Feb 2026 17:04:30 -0500 Subject: [PATCH 4/5] Merge branch 'main' into feat/react-devtools Signed-off-by: Adam Setch --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 625a14787..b8a62b6e8 100644 --- a/package.json +++ b/package.json @@ -158,4 +158,4 @@ "*": "biome check --no-errors-on-unmatched", "*.{js,ts,tsx}": "pnpm test:changed --passWithNoTests --updateSnapshot" } -} +} \ No newline at end of file From dc3ed1f8477d56820dc66b285f449d2e965b7a90 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Thu, 5 Feb 2026 17:07:54 -0500 Subject: [PATCH 5/5] feat: react dev tools Signed-off-by: Adam Setch --- src/main/devtools.ts | 4 +++- src/main/first-run.ts | 3 ++- src/main/utils.ts | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/devtools.ts b/src/main/devtools.ts index 2e4dfc156..f17316aac 100644 --- a/src/main/devtools.ts +++ b/src/main/devtools.ts @@ -5,10 +5,12 @@ import installExtension, { import { logInfo, logWarn } from '../shared/logger'; +import { isDevMode } from './utils'; + let installTask: Promise | null = null; export async function installReactDevtools() { - if (process.env.NODE_ENV === 'production') { + if (!isDevMode) { return; } diff --git a/src/main/first-run.ts b/src/main/first-run.ts index 224d79c8b..c799578ae 100644 --- a/src/main/first-run.ts +++ b/src/main/first-run.ts @@ -7,6 +7,8 @@ import { APPLICATION } from '../shared/constants'; import { logError } from '../shared/logger'; import { isMacOS } from '../shared/platform'; +import { isDevMode } from './utils'; + export async function onFirstRunMaybe() { if (isFirstRun()) { await promptMoveToApplicationsFolder(); @@ -21,7 +23,6 @@ async function promptMoveToApplicationsFolder() { return; } - const isDevMode = !!process.defaultApp; if (isDevMode || app.isInApplicationsFolder()) { return; } diff --git a/src/main/utils.ts b/src/main/utils.ts index 907d89fff..d3db239b2 100644 --- a/src/main/utils.ts +++ b/src/main/utils.ts @@ -12,6 +12,8 @@ import { logError, logInfo } from '../shared/logger'; import { sendRendererEvent } from './events'; +export const isDevMode = !!process.defaultApp; + export function takeScreenshot(mb: Menubar) { const date = new Date(); const dateStr = date.toISOString().replaceAll(':', '-');