|
@@ -9,7 +9,8 @@ import { DesktopPreferences } from './preferences.mjs'
|
|
|
import { DesktopCredentials } from './credentials.mjs'
|
|
import { DesktopCredentials } from './credentials.mjs'
|
|
|
import { synchronizeLocalService, stopLocalService, migrateLocalData } from './service-sync.mjs'
|
|
import { synchronizeLocalService, stopLocalService, migrateLocalData } from './service-sync.mjs'
|
|
|
import { resolveDataHome } from './data-home.mjs'
|
|
import { resolveDataHome } from './data-home.mjs'
|
|
|
-import { DesktopEnvironmentHost } from './environment-host.mjs'
|
|
|
|
|
|
|
+import { DesktopEnvironmentHost, DesktopHostCore } from './environment-host.mjs'
|
|
|
|
|
+import { DesktopHostManager } from './host-manager.mjs'
|
|
|
import { DesktopUpdateManager } from './update-manager.mjs'
|
|
import { DesktopUpdateManager } from './update-manager.mjs'
|
|
|
import { installComputerViewer } from './computer-viewer.mjs'
|
|
import { installComputerViewer } from './computer-viewer.mjs'
|
|
|
|
|
|
|
@@ -21,7 +22,7 @@ app.setName('夭夭')
|
|
|
if (!app.requestSingleInstanceLock()) { app.quit() }
|
|
if (!app.requestSingleInstanceLock()) { app.quit() }
|
|
|
else {
|
|
else {
|
|
|
let window, tray, manager, runnerManager, quitting = false, closing = false, timer
|
|
let window, tray, manager, runnerManager, quitting = false, closing = false, timer
|
|
|
- let updateWindow, updater, environmentHost
|
|
|
|
|
|
|
+ let updateWindow, updater, environmentHost, hostManager
|
|
|
const closeComputerViewer = installComputerViewer({ owner: () => window, origin: () => manager?.state.url,
|
|
const closeComputerViewer = installComputerViewer({ owner: () => window, origin: () => manager?.state.url,
|
|
|
preload: join(desktopRoot, 'preload.cjs'), quitting: () => quitting })
|
|
preload: join(desktopRoot, 'preload.cjs'), quitting: () => quitting })
|
|
|
app.on('will-quit', closeComputerViewer)
|
|
app.on('will-quit', closeComputerViewer)
|
|
@@ -181,6 +182,7 @@ else {
|
|
|
setImmediate(() => { void (async()=>{
|
|
setImmediate(() => { void (async()=>{
|
|
|
try {
|
|
try {
|
|
|
await environmentHost?.close()
|
|
await environmentHost?.close()
|
|
|
|
|
+ await hostManager?.stop()
|
|
|
await runnerManager?.stop()
|
|
await runnerManager?.stop()
|
|
|
if (stopBackground) await manager?.stopBackground()
|
|
if (stopBackground) await manager?.stopBackground()
|
|
|
else await manager?.stop()
|
|
else await manager?.stop()
|
|
@@ -194,6 +196,7 @@ else {
|
|
|
else {
|
|
else {
|
|
|
closing=false
|
|
closing=false
|
|
|
await manager?.reconnect().catch(error=>log(error.message))
|
|
await manager?.reconnect().catch(error=>log(error.message))
|
|
|
|
|
+ await hostManager?.start().catch(error=>log(error.message))
|
|
|
await runnerManager?.start().catch(error=>log(error.message))
|
|
await runnerManager?.start().catch(error=>log(error.message))
|
|
|
stateChanged(manager.state)
|
|
stateChanged(manager.state)
|
|
|
timer=setInterval(()=>{void manager.check()},10000);timer.unref()
|
|
timer=setInterval(()=>{void manager.check()},10000);timer.unref()
|
|
@@ -247,6 +250,16 @@ else {
|
|
|
fork:()=>utilityProcess.fork(join(root,'runner.mjs'),['--desktop-ipc'],{cwd:root,stdio:'pipe',env:{HOME:homedir(),PATH:[join(homedir(),'.local/bin'),join(homedir(),'.orbstack/bin'),'/opt/homebrew/bin','/usr/local/bin',process.env.PATH||'/usr/bin:/bin'].join(':'),NODE_ENV:'production',NODE_USE_ENV_PROXY:'0'}}),
|
|
fork:()=>utilityProcess.fork(join(root,'runner.mjs'),['--desktop-ipc'],{cwd:root,stdio:'pipe',env:{HOME:homedir(),PATH:[join(homedir(),'.local/bin'),join(homedir(),'.orbstack/bin'),'/opt/homebrew/bin','/usr/local/bin',process.env.PATH||'/usr/bin:/bin'].join(':'),NODE_ENV:'production',NODE_USE_ENV_PROXY:'0'}}),
|
|
|
})
|
|
})
|
|
|
async function runnerAction(action){try{await action()}catch(error){await dialog.showMessageBox(window,{type:'error',message:'执行节点操作未完成',detail:error.message})}}
|
|
async function runnerAction(action){try{await action()}catch(error){await dialog.showMessageBox(window,{type:'error',message:'执行节点操作未完成',detail:error.message})}}
|
|
|
|
|
+ hostManager=new DesktopHostManager({home,root,dataRoot:app.getPath('userData'),
|
|
|
|
|
+ createCore:({root,dataRoot})=>new DesktopHostCore({root,dataRoot}),
|
|
|
|
|
+ encrypt:value=>credentials.encrypt(value),
|
|
|
|
|
+ decrypt:bytes=>credentials.decrypt(bytes),
|
|
|
|
|
+ onState:message=>{log(`桌面主机: ${message}`);const item=Menu.getApplicationMenu()?.getMenuItemById('desktop-host-status');if(item)item.label=message}})
|
|
|
|
|
+ async function hostAction(action){try{await action()}catch(error){await dialog.showMessageBox(window,{type:'error',message:'桌面主机操作未完成',detail:error.message})}}
|
|
|
|
|
+ async function importDesktopHost(){
|
|
|
|
|
+ const selection=await dialog.showOpenDialog(window,{title:'导入桌面主机配置',properties:['openFile'],filters:[{name:'桌面主机配置',extensions:['json']}]})
|
|
|
|
|
+ if(!selection.canceled&&selection.filePaths[0]&&!closing)await hostAction(()=>hostManager.importFile(selection.filePaths[0]))
|
|
|
|
|
+ }
|
|
|
async function importRunner(){
|
|
async function importRunner(){
|
|
|
const selection=await dialog.showOpenDialog(window,{title:'导入执行节点配置',properties:['openFile'],filters:[{name:'Runner 配置',extensions:['json']}]})
|
|
const selection=await dialog.showOpenDialog(window,{title:'导入执行节点配置',properties:['openFile'],filters:[{name:'Runner 配置',extensions:['json']}]})
|
|
|
if(!selection.canceled&&selection.filePaths[0]&&!closing)await runnerAction(()=>runnerManager.importFile(selection.filePaths[0]))
|
|
if(!selection.canceled&&selection.filePaths[0]&&!closing)await runnerAction(()=>runnerManager.importFile(selection.filePaths[0]))
|
|
@@ -271,13 +284,17 @@ else {
|
|
|
{ type: 'separator' },
|
|
{ type: 'separator' },
|
|
|
{ role: 'hide', label: '隐藏夭夭' }, { role: 'hideOthers', label: '隐藏其他' }, { role: 'unhide', label: '显示全部' },
|
|
{ role: 'hide', label: '隐藏夭夭' }, { role: 'hideOthers', label: '隐藏其他' }, { role: 'unhide', label: '显示全部' },
|
|
|
{ type: 'separator' },
|
|
{ type: 'separator' },
|
|
|
- {label:'撤销本机控制授权',click:()=>environmentHost.revoke()},
|
|
|
|
|
|
|
+ {label:'撤销本机控制授权',click:()=>{void environmentHost.revoke();void hostManager?.revoke()}},
|
|
|
{ id:'desktop-quit',label:'退出夭夭(后台继续运行)',accelerator:'CommandOrControl+Q',click:()=>requestQuit() },
|
|
{ id:'desktop-quit',label:'退出夭夭(后台继续运行)',accelerator:'CommandOrControl+Q',click:()=>requestQuit() },
|
|
|
{ id:'desktop-stop-and-quit',label:'停止后台服务并退出',click:()=>requestQuit(true) }] },
|
|
{ id:'desktop-stop-and-quit',label:'停止后台服务并退出',click:()=>requestQuit(true) }] },
|
|
|
{label:'执行节点',submenu:[{id:'runner-status',label:'未配置执行节点',enabled:false},{type:'separator'},
|
|
{label:'执行节点',submenu:[{id:'runner-status',label:'未配置执行节点',enabled:false},{type:'separator'},
|
|
|
{id:'runner-import',label:'导入节点配置…',click:importRunner},
|
|
{id:'runner-import',label:'导入节点配置…',click:importRunner},
|
|
|
{id:'runner-reconnect',label:'重新连接',click:()=>runnerAction(()=>runnerManager.start())},
|
|
{id:'runner-reconnect',label:'重新连接',click:()=>runnerAction(()=>runnerManager.start())},
|
|
|
{id:'runner-forget',label:'断开并忘记配置',click:()=>runnerAction(()=>runnerManager.forget())}]},
|
|
{id:'runner-forget',label:'断开并忘记配置',click:()=>runnerAction(()=>runnerManager.forget())}]},
|
|
|
|
|
+ {label:'桌面主机',submenu:[{id:'desktop-host-status',label:'未配置桌面主机',enabled:false},{type:'separator'},
|
|
|
|
|
+ {id:'desktop-host-import',label:'导入主机配置…',click:importDesktopHost},
|
|
|
|
|
+ {id:'desktop-host-reconnect',label:'重新连接',click:()=>hostAction(()=>hostManager.start())},
|
|
|
|
|
+ {id:'desktop-host-forget',label:'断开并忘记配置',click:()=>hostAction(()=>hostManager.forget())}]},
|
|
|
{ role: 'editMenu', label: '编辑' }, { role: 'viewMenu', label: '显示' }, { role: 'windowMenu', label: '窗口' },
|
|
{ role: 'editMenu', label: '编辑' }, { role: 'viewMenu', label: '显示' }, { role: 'windowMenu', label: '窗口' },
|
|
|
]))
|
|
]))
|
|
|
const icon = nativeImage.createFromPath(join(desktopRoot, 'icon.png')).resize({ width: 20, height: 20 })
|
|
const icon = nativeImage.createFromPath(join(desktopRoot, 'icon.png')).resize({ width: 20, height: 20 })
|
|
@@ -291,6 +308,7 @@ else {
|
|
|
timer = setInterval(() => { void manager.check() }, 10_000); timer.unref()
|
|
timer = setInterval(() => { void manager.check() }, 10_000); timer.unref()
|
|
|
await manager.start().catch(error => log(error.message))
|
|
await manager.start().catch(error => log(error.message))
|
|
|
if(!closing)environmentHost.start()
|
|
if(!closing)environmentHost.start()
|
|
|
|
|
+ if(!closing)hostManager.start().catch(error=>{hostManager.publish(error.message)})
|
|
|
if(!closing&&manager.state.phase==='ready')await runnerManager.start().catch(error=>{runnerManager.publish(error.message)})
|
|
if(!closing&&manager.state.phase==='ready')await runnerManager.start().catch(error=>{runnerManager.publish(error.message)})
|
|
|
}).catch(error => { log(error.stack || error.message); quitting = true; app.quit() })
|
|
}).catch(error => { log(error.stack || error.message); quitting = true; app.quit() })
|
|
|
}
|
|
}
|