diff --git a/src/main/main.ts b/src/main/main.ts index 3dd73fe879dbb43fc229e3d49e2959253f65e9c3..82d141fe05234808a25c3965207c45c8a22ec0f0 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -10,7 +10,15 @@ * `./src/main.js` using webpack. This gives us some performance wins. */ import path from 'path'; -import { app, BrowserWindow, shell, ipcMain, utilityProcess } from 'electron'; +import { + app, + BrowserWindow, + shell, + ipcMain, + utilityProcess, + Menu, + dialog, +} from 'electron'; import { autoUpdater } from 'electron-updater'; import log from 'electron-log'; import Store from 'electron-store'; @@ -106,14 +114,6 @@ ipcMain.handle('server:checkDependencies', async (event) => { return await checkDependencies(); }); -class AppUpdater { - constructor() { - log.transports.file.level = 'info'; - autoUpdater.logger = log; - autoUpdater.checkForUpdatesAndNotify(); - } -} - let mainWindow: BrowserWindow | null = null; process.on('uncaughtException', function (error) { @@ -132,6 +132,28 @@ if (isDebug) { require('electron-debug')(); } +if (isDebug) { + autoUpdater.forceDevUpdateConfig = true; + console.log('Looking for dev-app-update.yml in', app.getAppPath()); + // autoUpdater.updateConfigPath = path.join(__dirname, 'dev-app-update.yml'); + autoUpdater.on('error', (error) => { + dialog.showErrorBox( + 'AutoUpdate Error: ', + error == null ? 'unknown' : (error.stack || error).toString() + ); + }); +} + +autoUpdater.autoDownload = false; + +class AppUpdater { + constructor() { + log.transports.file.level = 'info'; + autoUpdater.logger = log; + autoUpdater.checkForUpdates(); + } +} + const installExtensions = async () => { const installer = require('electron-devtools-installer'); const forceDownload = !!process.env.UPGRADE_EXTENSIONS; @@ -259,10 +281,82 @@ app.on('before-quit', async (e) => { import sshClient from './ssh-client'; // ///////////////////////////// +// AUTO UPDATER +let updater; + +function sendStatusToWindow(text) { + log.info(text); + mainWindow?.webContents.send('autoUpdater', text); +} + +autoUpdater.on('checking-for-update', () => { + console.log('main.js: Checking for update...'); + sendStatusToWindow('Checking for update...'); +}); +autoUpdater.on('update-available', (info) => { + console.log('main.js: Update available...'); + // sendStatusToWindow('Update available.'); + + dialog + .showMessageBox({ + type: 'info', + title: 'Found Updates', + message: + 'An updated version of Transformer Lab is available, do you want update now?', + buttons: ['Yes', 'No'], + }) + .then((buttonIndex) => { + if (buttonIndex.response === 0) { + autoUpdater.downloadUpdate(); + } else { + updater.enabled = true; + updater = null; + } + }); +}); +autoUpdater.on('update-not-available', (info) => { + console.log('main.js: Update not available...'); + // sendStatusToWindow('Update not available.'); + // dialog.showMessageBox({ + // title: 'No Updates', + // message: 'Current version is up-to-date.', + // }); + // updater.enabled = true; + // updater = null; +}); +autoUpdater.on('error', (err) => { + sendStatusToWindow('main.js: Error in auto-updater. ' + err); +}); +autoUpdater.on('download-progress', (progressObj) => { + let log_message = 'Download speed: ' + progressObj.bytesPerSecond; + log_message = log_message + ' - Downloaded ' + progressObj.percent + '%'; + log_message = + log_message + + ' (' + + progressObj.transferred + + '/' + + progressObj.total + + ')'; + sendStatusToWindow(log_message); +}); +autoUpdater.on('update-downloaded', (info) => { + console.log('main.js: Update downloaded...'); + // sendStatusToWindow('Update downloaded'); + dialog + .showMessageBox({ + title: 'Install Updates', + message: 'Updates downloaded. Press ok to update and restart now.', + }) + .then(() => { + setImmediate(() => autoUpdater.quitAndInstall()); + }); +}); + app .whenReady() .then(() => { createWindow(); + app.on('activate', () => { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. diff --git a/src/main/preload.ts b/src/main/preload.ts index 9ecb63c0b3be2d90b5203d972f56e23883df995b..a85af3ca0b766c2de50e4bf08305049b0cc20cae 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts @@ -92,3 +92,7 @@ contextBridge.exposeInMainWorld('sshClient', { ipcRenderer.removeAllListeners('ssh:connected'); }, }); + +contextBridge.exposeInMainWorld('autoUpdater', { + onMessage: (data) => ipcRenderer.on('autoUpdater', data), +}); diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 9486465ced90e8501831b07dc4c25b1f73f65698..b9f1fa1ba895928f288afc1671e3b1471598b865 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -15,7 +15,8 @@ import * as chatAPI from 'renderer/lib/transformerlab-api-sdk'; import useSWR from 'swr'; import XtermJSDrawer from './components/Connect/XtermJS'; -import OutputTerminal from './components/OutputTerminal'; +// import OutputTerminal from './components/OutputTerminal'; +// import AutoUpdateModal from './components/AutoUpdateModal'; const fetcher = (url) => fetch(url).then((res) => res.json()); @@ -66,6 +67,7 @@ export default function App() { // backgroundColor: (theme) => theme.vars.palette.background.surface, })} > + {/* <AutoUpdateModal /> */} <Header connection={connection} setConnection={setConnection} @@ -100,12 +102,12 @@ export default function App() { /> </Box> {/* <OutputTerminal /> */} - <LoginModal + {/* <LoginModal setServer={setConnection} connection={connection} setTerminalDrawerOpen={setDrawerOpen} setSSHConnection={setSSHConnection} - /> + /> */} </Box> <XtermJSDrawer sshConnection={sshConnection} diff --git a/src/renderer/components/AutoUpdateModal.tsx b/src/renderer/components/AutoUpdateModal.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4843b175e45135b20caf46a1cd487e5a23e8f0c1 --- /dev/null +++ b/src/renderer/components/AutoUpdateModal.tsx @@ -0,0 +1,44 @@ +import React from 'react'; + +import { Modal, ModalClose, Sheet, Typography } from '@mui/joy'; +window.autoUpdater.onMessage((message) => { + console.log('autoupdate message', message); + var container = document.getElementById('messages'); + var m = document.createElement('div'); + m.innerHTML = text; + container?.appendChild(message); +}); +export default function AutoUpdateModal({}) { + const [open, setOpen] = React.useState<boolean>(true); + + return ( + <Modal open={open} onClose={() => setOpen(false)}> + <Sheet + variant="outlined" + sx={{ + maxWidth: 500, + borderRadius: 'md', + p: 3, + boxShadow: 'lg', + }} + > + <ModalClose variant="plain" sx={{ m: 1 }} /> + <Typography + component="h2" + id="modal-title" + level="h4" + textColor="inherit" + fontWeight="lg" + mb={1} + > + This is the modal title + </Typography> + <Typography id="modal-desc" textColor="text.tertiary"> + Make sure to use <code>aria-labelledby</code> on the modal dialog with + an optional <code>aria-describedby</code> attribute. + <div id="messages"></div> + </Typography> + </Sheet> + </Modal> + ); +}