@@ -20,7 +20,7 @@ export const APP_BUNDLE_ID = isDevelopment
2020 ? `com.t3tools.t3code.dev.${ devBundleIdSuffix || "local" } `
2121 : "com.t3tools.t3code" ;
2222const APP_PROTOCOL_SCHEMES = isDevelopment ? [ "t3code-dev" ] : [ "t3code" ] ;
23- const LAUNCHER_VERSION = 12 ;
23+ const LAUNCHER_VERSION = 14 ;
2424const defaultIconPath = NodePath . join ( desktopDir , "resources" , "icon.icns" ) ;
2525const developmentMacIconPngPath = NodePath . join (
2626 repoRoot ,
@@ -220,11 +220,12 @@ function ensureDevelopmentIconIcns(runtimeDir) {
220220 }
221221}
222222
223- function patchMainBundleInfoPlist ( appBundlePath , iconPath ) {
223+ function patchMainBundleInfoPlist ( appBundlePath , iconPath , executableName ) {
224224 const infoPlistPath = NodePath . join ( appBundlePath , "Contents" , "Info.plist" ) ;
225225 setPlistString ( infoPlistPath , "CFBundleDisplayName" , APP_DISPLAY_NAME ) ;
226226 setPlistString ( infoPlistPath , "CFBundleName" , APP_DISPLAY_NAME ) ;
227227 setPlistString ( infoPlistPath , "CFBundleIdentifier" , APP_BUNDLE_ID ) ;
228+ setPlistString ( infoPlistPath , "CFBundleExecutable" , executableName ) ;
228229 setPlistString ( infoPlistPath , "CFBundleIconFile" , "icon.icns" ) ;
229230 setPlistJson ( infoPlistPath , "CFBundleURLTypes" , [
230231 {
@@ -277,11 +278,25 @@ function readJson(path) {
277278 }
278279}
279280
281+ export function resolveMacLauncherPaths ( appBundlePath , displayName = APP_DISPLAY_NAME ) {
282+ const executableDir = NodePath . join ( appBundlePath , "Contents" , "MacOS" ) ;
283+ const launcherExecutableName = `${ displayName } Launcher` ;
284+ return {
285+ launcherExecutableName,
286+ launcherBinaryPath : NodePath . join ( executableDir , launcherExecutableName ) ,
287+ runtimeElectronBinaryPath : NodePath . join ( executableDir , "Electron" ) ,
288+ } ;
289+ }
290+
280291function buildMacLauncher ( electronBinaryPath ) {
281292 const sourceAppBundlePath = NodePath . resolve ( NodePath . dirname ( electronBinaryPath ) , "../.." ) ;
282293 const runtimeDir = NodePath . join ( desktopDir , ".electron-runtime" ) ;
283294 const targetAppBundlePath = NodePath . join ( runtimeDir , `${ APP_DISPLAY_NAME } .app` ) ;
284- const targetBinaryPath = NodePath . join ( targetAppBundlePath , "Contents" , "MacOS" , "Electron" ) ;
295+ const developmentPaths = resolveMacLauncherPaths ( targetAppBundlePath ) ;
296+ const runtimeElectronBinaryPath = developmentPaths . runtimeElectronBinaryPath ;
297+ const launcherBinaryPath = isDevelopment
298+ ? developmentPaths . launcherBinaryPath
299+ : runtimeElectronBinaryPath ;
285300 const iconPath = isDevelopment ? ensureDevelopmentIconIcns ( runtimeDir ) : defaultIconPath ;
286301 const metadataPath = NodePath . join ( runtimeDir , "metadata.json" ) ;
287302
@@ -298,18 +313,19 @@ function buildMacLauncher(electronBinaryPath) {
298313
299314 const currentMetadata = readJson ( metadataPath ) ;
300315 if (
301- NodeFS . existsSync ( targetBinaryPath ) &&
316+ NodeFS . existsSync ( launcherBinaryPath ) &&
317+ ( ! isDevelopment || NodeFS . existsSync ( runtimeElectronBinaryPath ) ) &&
302318 currentMetadata &&
303319 JSON . stringify ( currentMetadata ) === JSON . stringify ( expectedMetadata )
304320 ) {
305321 if ( isDevelopment ) {
306322 // The launcher also handles protocol activations outside the dev runner,
307323 // so refresh its fallback environment on every launch. Never let a value
308324 // captured by an older parent app override the live dev-runner environment.
309- writeDevelopmentLauncherScript ( targetBinaryPath , electronBinaryPath ) ;
325+ writeDevelopmentLauncherScript ( launcherBinaryPath , runtimeElectronBinaryPath ) ;
310326 }
311327 registerMacLauncherBundle ( targetAppBundlePath ) ;
312- return targetBinaryPath ;
328+ return launcherBinaryPath ;
313329 }
314330
315331 NodeFS . rmSync ( targetAppBundlePath , { recursive : true , force : true } ) ;
@@ -321,15 +337,24 @@ function buildMacLauncher(electronBinaryPath) {
321337 recursive : true ,
322338 verbatimSymlinks : true ,
323339 } ) ;
324- patchMainBundleInfoPlist ( targetAppBundlePath , iconPath ) ;
340+ patchMainBundleInfoPlist (
341+ targetAppBundlePath ,
342+ iconPath ,
343+ isDevelopment ? developmentPaths . launcherExecutableName : "Electron" ,
344+ ) ;
325345 patchHelperBundleInfoPlists ( targetAppBundlePath ) ;
326346 if ( isDevelopment ) {
327- writeDevelopmentLauncherScript ( targetBinaryPath , electronBinaryPath ) ;
347+ // Keep Electron's native executable inside the branded bundle. Launching the
348+ // node_modules copy makes macOS associate the process (and Dock label) with
349+ // Electron.app even though this bundle's Info.plist has the T3 Code name.
350+ // Its conventional executable name also keeps Electron's default-app runtime
351+ // in development mode instead of making app.isPackaged report true.
352+ writeDevelopmentLauncherScript ( launcherBinaryPath , runtimeElectronBinaryPath ) ;
328353 }
329354 NodeFS . writeFileSync ( metadataPath , `${ JSON . stringify ( expectedMetadata , null , 2 ) } \n` ) ;
330355 registerMacLauncherBundle ( targetAppBundlePath ) ;
331356
332- return targetBinaryPath ;
357+ return launcherBinaryPath ;
333358}
334359
335360function isLinuxSetuidSandboxConfigured ( electronBinaryPath ) {
0 commit comments