280 lines
25 KiB
TypeScript
280 lines
25 KiB
TypeScript
import { contextBridge, ipcRenderer } from 'electron'
|
|
import { electronAPI } from '@electron-toolkit/preload'
|
|
import { readFileSync, rmSync } from 'fs'
|
|
|
|
type LauncherAuthPayload = {
|
|
appUrl?: string | null
|
|
handoffToken?: string | null
|
|
audienceApp?: string | null
|
|
}
|
|
|
|
type RemoteWorkspaceTarget = {
|
|
host: string
|
|
user?: string | null
|
|
port?: number | null
|
|
workspaceRoot?: string | null
|
|
}
|
|
|
|
type ModulePrebuiltArtifact = {
|
|
type?: string | null
|
|
url?: string | null
|
|
fileName?: string | null
|
|
checksumSha256?: string | null
|
|
extractPath?: string | null
|
|
required?: boolean | null
|
|
}
|
|
|
|
type RuntimeImageArtifact = {
|
|
image?: string | null
|
|
url?: string | null
|
|
fileName?: string | null
|
|
checksumSha256?: string | null
|
|
required?: boolean | null
|
|
}
|
|
|
|
type ModuleInstallOptions = {
|
|
prebuiltArtifacts?: ModulePrebuiltArtifact[] | null
|
|
runtimeImages?: RuntimeImageArtifact[] | null
|
|
}
|
|
|
|
const decodeArgValue = (prefix: string): string | null => {
|
|
const rawValue = process.argv.find((arg) => arg.startsWith(prefix))?.slice(prefix.length)
|
|
if (!rawValue) return null
|
|
|
|
try {
|
|
return decodeURIComponent(rawValue)
|
|
} catch {
|
|
return rawValue
|
|
}
|
|
}
|
|
|
|
const readLauncherAuthFile = (): LauncherAuthPayload | null => {
|
|
const filePath = process.env.ATNMY_HANDOFF_FILE
|
|
if (!filePath) {
|
|
console.info('[lms-preload] launcher auth file env is empty')
|
|
return null
|
|
}
|
|
|
|
try {
|
|
const payload = JSON.parse(readFileSync(filePath, 'utf8')) as LauncherAuthPayload
|
|
rmSync(filePath, { force: true })
|
|
console.info('[lms-preload] launcher auth file loaded', {
|
|
hasHandoffToken: Boolean(payload.handoffToken),
|
|
audienceApp: payload.audienceApp ?? null
|
|
})
|
|
return payload
|
|
} catch (error) {
|
|
console.warn('[lms-preload] launcher auth file read failed', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
const launcherAuthFile = readLauncherAuthFile()
|
|
|
|
const launcherAuth = {
|
|
appUrl: launcherAuthFile?.appUrl ?? decodeArgValue('--url=') ?? process.env.ATNMY_APP_URL ?? null,
|
|
handoffToken: launcherAuthFile?.handoffToken ?? decodeArgValue('--handoff-token=') ?? process.env.ATNMY_HANDOFF_TOKEN ?? null,
|
|
audienceApp: launcherAuthFile?.audienceApp ?? decodeArgValue('--audience-app=') ?? process.env.ATNMY_AUDIENCE_APP ?? 'LMS'
|
|
}
|
|
|
|
console.info('[lms-preload] launcher auth resolved', {
|
|
hasHandoffToken: Boolean(launcherAuth.handoffToken),
|
|
audienceApp: launcherAuth.audienceApp
|
|
})
|
|
|
|
contextBridge.exposeInMainWorld('electron', electronAPI)
|
|
contextBridge.exposeInMainWorld('launcherAuth', launcherAuth)
|
|
contextBridge.exposeInMainWorld('lmsBootSplash', {
|
|
status: (message: string) => ipcRenderer.send('lms-boot-status', message),
|
|
done: () => ipcRenderer.send('lms-boot-done')
|
|
})
|
|
contextBridge.exposeInMainWorld('titlebar', {
|
|
minimize: () => ipcRenderer.send('titlebar-minimize'),
|
|
maximize: () => ipcRenderer.send('titlebar-maximize'),
|
|
close: () => ipcRenderer.send('titlebar-close')
|
|
})
|
|
contextBridge.exposeInMainWorld('appLifecycle', {
|
|
quit: () => ipcRenderer.send('app-quit')
|
|
})
|
|
contextBridge.exposeInMainWorld('learningVideo', {
|
|
open: (url: string, title?: string) => ipcRenderer.invoke('learning-video:open', { url, title })
|
|
})
|
|
contextBridge.exposeInMainWorld('moduleFiles', {
|
|
read: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('module-files:read', moduleName, workspaceRoot, folderName),
|
|
image: (moduleName: string, path: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('module-files:image', moduleName, path, workspaceRoot, folderName),
|
|
create: (moduleName: string, path: string, kind: 'file' | 'folder', workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('module-files:create', moduleName, path, kind, workspaceRoot, folderName),
|
|
write: (moduleName: string, path: string, content: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('module-files:write', moduleName, path, content, workspaceRoot, folderName),
|
|
copy: (moduleName: string, fromPath: string, toPath: string, mode: 'copy' | 'cut', workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('module-files:copy', moduleName, fromPath, toPath, mode, workspaceRoot, folderName),
|
|
rename: (moduleName: string, fromPath: string, toPath: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('module-files:rename', moduleName, fromPath, toPath, workspaceRoot, folderName),
|
|
delete: (moduleName: string, path: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('module-files:delete', moduleName, path, workspaceRoot, folderName)
|
|
})
|
|
contextBridge.exposeInMainWorld('modules', {
|
|
list: (workspaceRoot?: string, modules?: Array<{ sortOrder?: number | null; category: string; name: string; folderName: string; templateRepositoryUrl?: string | null }>) => ipcRenderer.invoke('modules:list', workspaceRoot, modules),
|
|
install: (moduleName: string, workspaceRoot?: string, folderName?: string, templateRepositoryUrl?: string | null, studentRepositoryUrl?: string | null, options?: ModuleInstallOptions | null) => ipcRenderer.invoke('modules:install', moduleName, workspaceRoot, folderName, templateRepositoryUrl, studentRepositoryUrl, options),
|
|
delete: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('modules:delete', moduleName, workspaceRoot, folderName),
|
|
start: (moduleName: string, workspaceRoot?: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('modules:start', moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages),
|
|
build: (moduleName: string, workspaceRoot?: string, folderName?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('modules:build', moduleName, workspaceRoot, folderName, gpuEnabled, rosDomainId, runtimeImages),
|
|
stop: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('modules:stop', moduleName, workspaceRoot, folderName),
|
|
stopMany: (modules: Array<{ moduleName: string; folderName?: string | null }>, workspaceRoot?: string) => ipcRenderer.invoke('modules:stop-many', modules, workspaceRoot),
|
|
stopRunning: () => ipcRenderer.invoke('modules:stop-running'),
|
|
restart: (moduleName: string, workspaceRoot?: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('modules:restart', moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages),
|
|
logs: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('modules:logs', moduleName, workspaceRoot, folderName),
|
|
updateParameters: (moduleName: string, workspaceRoot?: string, folderName?: string, rosParams?: string) => ipcRenderer.invoke('modules:update-parameters', moduleName, workspaceRoot, folderName, rosParams)
|
|
})
|
|
contextBridge.exposeInMainWorld('git', {
|
|
status: (moduleName: string, workspaceRoot?: string, folderName?: string, selectedFilePath?: string | null) => ipcRenderer.invoke('git:status', moduleName, workspaceRoot, folderName, selectedFilePath),
|
|
submit: (moduleName: string, workspaceRoot?: string, folderName?: string, message?: string, authorName?: string, authorEmail?: string, submissionId?: string) => ipcRenderer.invoke('git:submit', moduleName, workspaceRoot, folderName, message, authorName, authorEmail, submissionId),
|
|
submissions: (modules: Array<{ moduleName: string; folderName?: string | null }>, workspaceRoot?: string) => ipcRenderer.invoke('git:submissions', modules, workspaceRoot),
|
|
commitDiff: (moduleName: string, workspaceRoot?: string, folderName?: string, commitHash?: string) => ipcRenderer.invoke('git:commit-diff', moduleName, workspaceRoot, folderName, commitHash)
|
|
})
|
|
contextBridge.exposeInMainWorld('exampleCode', {
|
|
read: () => ipcRenderer.invoke('example-code:read')
|
|
})
|
|
contextBridge.exposeInMainWorld('terminal', {
|
|
start: (moduleName?: string, cols?: number, rows?: number, sessionId?: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('terminal-start', moduleName, cols, rows, sessionId, workspaceRoot, folderName),
|
|
resize: (cols?: number, rows?: number, sessionId?: string) => ipcRenderer.invoke('terminal-resize', cols, rows, sessionId),
|
|
changeDirectory: (moduleName: string, sessionId?: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('terminal-change-directory', moduleName, sessionId, workspaceRoot, folderName),
|
|
write: (data: string, sessionId?: string) => ipcRenderer.send('terminal-write', data, sessionId),
|
|
stop: (sessionId?: string) => ipcRenderer.send('terminal-stop', sessionId),
|
|
onData: (callback: (data: string) => void, sessionId = 'default') => {
|
|
const listener = (_event: Electron.IpcRendererEvent, dataSessionId: string, data: string): void => {
|
|
if (dataSessionId === sessionId) callback(data)
|
|
}
|
|
ipcRenderer.on('terminal-data', listener)
|
|
return () => ipcRenderer.removeListener('terminal-data', listener)
|
|
},
|
|
onSuppressData: (callback: (data: string) => void, sessionId = 'default') => {
|
|
const listener = (_event: Electron.IpcRendererEvent, dataSessionId: string, data: string): void => {
|
|
if (dataSessionId === sessionId) callback(data)
|
|
}
|
|
ipcRenderer.on('terminal-suppress-data', listener)
|
|
return () => ipcRenderer.removeListener('terminal-suppress-data', listener)
|
|
}
|
|
})
|
|
contextBridge.exposeInMainWorld('visualization', {
|
|
status: () => ipcRenderer.invoke('visualization:status'),
|
|
start: (stack?: 'autoware' | 'nav2' | 'slam', workspaceRoot?: string, rosDomainId?: string, environmentProfile?: unknown) => ipcRenderer.invoke('visualization:start', stack, workspaceRoot, rosDomainId, environmentProfile),
|
|
stop: (environmentProfile?: unknown) => ipcRenderer.invoke('visualization:stop', environmentProfile)
|
|
})
|
|
contextBridge.exposeInMainWorld('localWorkspace', {
|
|
moduleFiles: {
|
|
read: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:module-files:read', moduleName, workspaceRoot, folderName),
|
|
image: (moduleName: string, path: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:module-files:image', moduleName, path, workspaceRoot, folderName),
|
|
create: (moduleName: string, path: string, kind: 'file' | 'folder', workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:module-files:create', moduleName, path, kind, workspaceRoot, folderName),
|
|
write: (moduleName: string, path: string, content: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:module-files:write', moduleName, path, content, workspaceRoot, folderName),
|
|
copy: (moduleName: string, fromPath: string, toPath: string, mode: 'copy' | 'cut', workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:module-files:copy', moduleName, fromPath, toPath, mode, workspaceRoot, folderName),
|
|
rename: (moduleName: string, fromPath: string, toPath: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:module-files:rename', moduleName, fromPath, toPath, workspaceRoot, folderName),
|
|
delete: (moduleName: string, path: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:module-files:delete', moduleName, path, workspaceRoot, folderName)
|
|
},
|
|
modules: {
|
|
list: (workspaceRoot?: string, modules?: Array<{ sortOrder?: number | null; category: string; name: string; folderName: string; templateRepositoryUrl?: string | null }>) => ipcRenderer.invoke('local-workspace:modules:list', workspaceRoot, modules),
|
|
install: (moduleName: string, workspaceRoot?: string, folderName?: string, templateRepositoryUrl?: string | null, studentRepositoryUrl?: string | null, options?: ModuleInstallOptions | null) => ipcRenderer.invoke('local-workspace:modules:install', moduleName, workspaceRoot, folderName, templateRepositoryUrl, studentRepositoryUrl, options),
|
|
delete: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:modules:delete', moduleName, workspaceRoot, folderName),
|
|
start: (moduleName: string, workspaceRoot?: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('local-workspace:modules:start', moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages),
|
|
build: (moduleName: string, workspaceRoot?: string, folderName?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('local-workspace:modules:build', moduleName, workspaceRoot, folderName, gpuEnabled, rosDomainId, runtimeImages),
|
|
stop: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:modules:stop', moduleName, workspaceRoot, folderName),
|
|
stopMany: (modules: Array<{ moduleName: string; folderName?: string | null }>, workspaceRoot?: string) => ipcRenderer.invoke('local-workspace:modules:stop-many', modules, workspaceRoot),
|
|
stopRunning: () => ipcRenderer.invoke('local-workspace:modules:stop-running'),
|
|
restart: (moduleName: string, workspaceRoot?: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('local-workspace:modules:restart', moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages),
|
|
logs: (moduleName: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:modules:logs', moduleName, workspaceRoot, folderName),
|
|
updateParameters: (moduleName: string, workspaceRoot?: string, folderName?: string, rosParams?: string) => ipcRenderer.invoke('local-workspace:modules:update-parameters', moduleName, workspaceRoot, folderName, rosParams)
|
|
},
|
|
nav2: {
|
|
setSimulatorPose: (pose: { x: number; y: number; yaw: number }) => ipcRenderer.invoke('local-workspace:nav2:set-simulator-pose', pose),
|
|
addRuntimeObstacle: (obstacle: { id: string; x: number; y: number; yaw: number; length: number; depth: number; height: number }) => ipcRenderer.invoke('local-workspace:nav2:add-runtime-obstacle', obstacle),
|
|
clearRuntimeObstacles: () => ipcRenderer.invoke('local-workspace:nav2:clear-runtime-obstacles')
|
|
},
|
|
worldLayout: {
|
|
read: (workspaceRoot?: string) => ipcRenderer.invoke('local-workspace:world-layout:read', workspaceRoot),
|
|
write: (workspaceRoot: string | undefined, layout: unknown) => ipcRenderer.invoke('local-workspace:world-layout:write', workspaceRoot, layout)
|
|
},
|
|
visualization: {
|
|
status: () => ipcRenderer.invoke('local-workspace:visualization:status'),
|
|
start: (stack?: 'autoware' | 'nav2' | 'slam', workspaceRoot?: string, rosDomainId?: string, environmentProfile?: unknown) => ipcRenderer.invoke('local-workspace:visualization:start', stack, workspaceRoot, rosDomainId, environmentProfile),
|
|
stop: (environmentProfile?: unknown) => ipcRenderer.invoke('local-workspace:visualization:stop', environmentProfile)
|
|
},
|
|
git: {
|
|
status: (moduleName: string, workspaceRoot?: string, folderName?: string, selectedFilePath?: string | null) => ipcRenderer.invoke('local-workspace:git:status', moduleName, workspaceRoot, folderName, selectedFilePath),
|
|
submit: (moduleName: string, workspaceRoot?: string, folderName?: string, message?: string, authorName?: string, authorEmail?: string, submissionId?: string) => ipcRenderer.invoke('local-workspace:git:submit', moduleName, workspaceRoot, folderName, message, authorName, authorEmail, submissionId),
|
|
restoreFile: (moduleName: string, workspaceRoot?: string, folderName?: string, filePath?: string, status?: string) => ipcRenderer.invoke('local-workspace:git:restore-file', moduleName, workspaceRoot, folderName, filePath, status),
|
|
submissions: (modules: Array<{ moduleName: string; folderName?: string | null }>, workspaceRoot?: string) => ipcRenderer.invoke('local-workspace:git:submissions', modules, workspaceRoot),
|
|
commitDiff: (moduleName: string, workspaceRoot?: string, folderName?: string, commitHash?: string) => ipcRenderer.invoke('local-workspace:git:commit-diff', moduleName, workspaceRoot, folderName, commitHash)
|
|
},
|
|
terminal: {
|
|
start: (moduleName?: string, cols?: number, rows?: number, sessionId?: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:terminal:start', moduleName, cols, rows, sessionId, workspaceRoot, folderName),
|
|
resize: (cols?: number, rows?: number, sessionId?: string) => ipcRenderer.invoke('local-workspace:terminal:resize', cols, rows, sessionId),
|
|
changeDirectory: (moduleName: string, sessionId?: string, workspaceRoot?: string, folderName?: string) => ipcRenderer.invoke('local-workspace:terminal:change-directory', moduleName, sessionId, workspaceRoot, folderName),
|
|
write: (data: string, sessionId?: string) => ipcRenderer.send('local-workspace:terminal:write', data, sessionId),
|
|
stop: (sessionId?: string) => ipcRenderer.send('local-workspace:terminal:stop', sessionId),
|
|
onData: (callback: (data: string) => void, sessionId = 'default') => {
|
|
const listener = (_event: Electron.IpcRendererEvent, dataSessionId: string, data: string): void => {
|
|
if (dataSessionId === sessionId) callback(data)
|
|
}
|
|
ipcRenderer.on('terminal-data', listener)
|
|
return () => ipcRenderer.removeListener('terminal-data', listener)
|
|
},
|
|
onSuppressData: (callback: (data: string) => void, sessionId = 'default') => {
|
|
const listener = (_event: Electron.IpcRendererEvent, dataSessionId: string, data: string): void => {
|
|
if (dataSessionId === sessionId) callback(data)
|
|
}
|
|
ipcRenderer.on('terminal-suppress-data', listener)
|
|
return () => ipcRenderer.removeListener('terminal-suppress-data', listener)
|
|
}
|
|
}
|
|
})
|
|
contextBridge.exposeInMainWorld('remoteWorkspace', {
|
|
moduleFiles: {
|
|
read: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:module-files:read', target, moduleName, folderName),
|
|
image: (target: RemoteWorkspaceTarget, moduleName: string, path: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:module-files:image', target, moduleName, path, folderName),
|
|
create: (target: RemoteWorkspaceTarget, moduleName: string, path: string, kind: 'file' | 'folder', folderName?: string) => ipcRenderer.invoke('remote-workspace:module-files:create', target, moduleName, path, kind, folderName),
|
|
write: (target: RemoteWorkspaceTarget, moduleName: string, path: string, content: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:module-files:write', target, moduleName, path, content, folderName),
|
|
copy: (target: RemoteWorkspaceTarget, moduleName: string, fromPath: string, toPath: string, mode: 'copy' | 'cut', folderName?: string) => ipcRenderer.invoke('remote-workspace:module-files:copy', target, moduleName, fromPath, toPath, mode, folderName),
|
|
rename: (target: RemoteWorkspaceTarget, moduleName: string, fromPath: string, toPath: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:module-files:rename', target, moduleName, fromPath, toPath, folderName),
|
|
delete: (target: RemoteWorkspaceTarget, moduleName: string, path: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:module-files:delete', target, moduleName, path, folderName)
|
|
},
|
|
modules: {
|
|
list: (target: RemoteWorkspaceTarget, modules?: Array<{ sortOrder?: number | null; category: string; name: string; folderName: string; templateRepositoryUrl?: string | null }>) => ipcRenderer.invoke('remote-workspace:modules:list', target, modules),
|
|
install: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, templateRepositoryUrl?: string | null, studentRepositoryUrl?: string | null, options?: ModuleInstallOptions | null) => ipcRenderer.invoke('remote-workspace:modules:install', target, moduleName, folderName, templateRepositoryUrl, studentRepositoryUrl, options),
|
|
start: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('remote-workspace:modules:start', target, moduleName, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages),
|
|
build: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('remote-workspace:modules:build', target, moduleName, folderName, gpuEnabled, rosDomainId, runtimeImages),
|
|
stop: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:modules:stop', target, moduleName, folderName),
|
|
stopMany: (target: RemoteWorkspaceTarget, modules: Array<{ moduleName: string; folderName?: string | null }>) => ipcRenderer.invoke('remote-workspace:modules:stop-many', target, modules),
|
|
resetSession: (target: RemoteWorkspaceTarget, modules: Array<{ moduleName: string; folderName?: string | null; templateRepositoryUrl?: string | null }>) => ipcRenderer.invoke('remote-workspace:modules:reset-session', target, modules),
|
|
restart: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string, runtimeImages?: RuntimeImageArtifact[] | null) => ipcRenderer.invoke('remote-workspace:modules:restart', target, moduleName, folderName, rosParams, gpuEnabled, rosDomainId, runtimeImages),
|
|
logs: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:modules:logs', target, moduleName, folderName)
|
|
},
|
|
visualization: {
|
|
status: (target: RemoteWorkspaceTarget) => ipcRenderer.invoke('remote-workspace:visualization:status', target),
|
|
start: (target: RemoteWorkspaceTarget, stack?: 'autoware' | 'nav2' | 'slam', rosDomainId?: string, environmentProfile?: unknown) => ipcRenderer.invoke('remote-workspace:visualization:start', target, stack, rosDomainId, environmentProfile),
|
|
stop: (target: RemoteWorkspaceTarget) => ipcRenderer.invoke('remote-workspace:visualization:stop', target)
|
|
},
|
|
git: {
|
|
status: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, selectedFilePath?: string | null) => ipcRenderer.invoke('remote-workspace:git:status', target, moduleName, folderName, selectedFilePath),
|
|
submit: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, message?: string, authorName?: string, authorEmail?: string, submissionId?: string) => ipcRenderer.invoke('remote-workspace:git:submit', target, moduleName, folderName, message, authorName, authorEmail, submissionId),
|
|
restoreFile: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, filePath?: string, status?: string) => ipcRenderer.invoke('remote-workspace:git:restore-file', target, moduleName, folderName, filePath, status),
|
|
submissions: (target: RemoteWorkspaceTarget, modules: Array<{ moduleName: string; folderName?: string | null }>) => ipcRenderer.invoke('remote-workspace:git:submissions', target, modules),
|
|
commitDiff: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, commitHash?: string) => ipcRenderer.invoke('remote-workspace:git:commit-diff', target, moduleName, folderName, commitHash)
|
|
},
|
|
terminal: {
|
|
start: (target: RemoteWorkspaceTarget, moduleName?: string, cols?: number, rows?: number, sessionId?: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:terminal:start', target, moduleName, cols, rows, sessionId, folderName),
|
|
resize: (target: RemoteWorkspaceTarget, cols?: number, rows?: number, sessionId?: string) => ipcRenderer.invoke('remote-workspace:terminal:resize', target, cols, rows, sessionId),
|
|
changeDirectory: (target: RemoteWorkspaceTarget, moduleName: string, sessionId?: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:terminal:change-directory', target, moduleName, sessionId, folderName),
|
|
write: (data: string, sessionId?: string) => ipcRenderer.send('remote-workspace:terminal:write', data, sessionId),
|
|
stop: (sessionId?: string) => ipcRenderer.send('remote-workspace:terminal:stop', sessionId),
|
|
onData: (callback: (data: string) => void, sessionId = 'default') => {
|
|
const listener = (_event: Electron.IpcRendererEvent, incomingSessionId: string, data: string) => {
|
|
if (incomingSessionId === sessionId) callback(data)
|
|
}
|
|
ipcRenderer.on('terminal-data', listener)
|
|
return () => ipcRenderer.removeListener('terminal-data', listener)
|
|
},
|
|
onSuppressData: (callback: (data: string) => void, sessionId = 'default') => {
|
|
const listener = (_event: Electron.IpcRendererEvent, incomingSessionId: string, data: string) => {
|
|
if (incomingSessionId === sessionId) callback(data)
|
|
}
|
|
ipcRenderer.on('terminal-suppress-data', listener)
|
|
return () => ipcRenderer.removeListener('terminal-suppress-data', listener)
|
|
}
|
|
}
|
|
})
|