커밋.
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
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
|
||||
}
|
||||
|
||||
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) return null
|
||||
|
||||
try {
|
||||
const payload = JSON.parse(readFileSync(filePath, 'utf8')) as LauncherAuthPayload
|
||||
rmSync(filePath, { force: true })
|
||||
return payload
|
||||
} catch {
|
||||
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'
|
||||
}
|
||||
|
||||
contextBridge.exposeInMainWorld('electron', electronAPI)
|
||||
contextBridge.exposeInMainWorld('launcherAuth', launcherAuth)
|
||||
contextBridge.exposeInMainWorld('titlebar', {
|
||||
minimize: () => ipcRenderer.send('titlebar-minimize'),
|
||||
maximize: () => ipcRenderer.send('titlebar-maximize'),
|
||||
close: () => ipcRenderer.send('titlebar-close')
|
||||
})
|
||||
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),
|
||||
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) => ipcRenderer.invoke('modules:install', moduleName, workspaceRoot, folderName, templateRepositoryUrl, studentRepositoryUrl),
|
||||
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) => ipcRenderer.invoke('modules:start', moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId),
|
||||
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) => ipcRenderer.invoke('modules:restart', moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId),
|
||||
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),
|
||||
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),
|
||||
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) => ipcRenderer.invoke('local-workspace:modules:install', moduleName, workspaceRoot, folderName, templateRepositoryUrl, studentRepositoryUrl),
|
||||
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) => ipcRenderer.invoke('local-workspace:modules:start', moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId),
|
||||
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) => ipcRenderer.invoke('local-workspace:modules:restart', moduleName, workspaceRoot, folderName, rosParams, gpuEnabled, rosDomainId),
|
||||
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)
|
||||
},
|
||||
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),
|
||||
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),
|
||||
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) => ipcRenderer.invoke('remote-workspace:modules:install', target, moduleName, folderName, templateRepositoryUrl, studentRepositoryUrl),
|
||||
start: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string) => ipcRenderer.invoke('remote-workspace:modules:start', target, moduleName, folderName, rosParams, gpuEnabled, rosDomainId),
|
||||
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 }>) => ipcRenderer.invoke('remote-workspace:modules:reset-session', target, modules),
|
||||
restart: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string, rosParams?: string, gpuEnabled?: boolean, rosDomainId?: string) => ipcRenderer.invoke('remote-workspace:modules:restart', target, moduleName, folderName, rosParams, gpuEnabled, rosDomainId),
|
||||
logs: (target: RemoteWorkspaceTarget, moduleName: string, folderName?: string) => ipcRenderer.invoke('remote-workspace:modules:logs', target, moduleName, folderName)
|
||||
},
|
||||
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),
|
||||
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)
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user