Skip to content

Commit

Permalink
Manual update app from UI (#375)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kitenite authored Sep 17, 2024
1 parent ccf1ae5 commit 3a9dafe
Show file tree
Hide file tree
Showing 13 changed files with 164 additions and 31 deletions.
Binary file modified app/bun.lockb
Binary file not shown.
3 changes: 3 additions & 0 deletions app/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ export enum WebviewChannels {

export enum MainChannels {
OPEN_EXTERNAL_WINDOW = 'open-external-window',
QUIT_AND_INSTALL = 'quit-and-update-app',
UPDATE_DOWNLOADED = 'update-downloaded',
UPDATE_NOT_AVAILABLE = 'update-not-available',

// Code
GET_CODE_BLOCK = 'get-code-block',
Expand Down
2 changes: 1 addition & 1 deletion app/dev-app-update.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
owner: onlook-dev
repo: studio
repo: onlook
provider: github
3 changes: 2 additions & 1 deletion app/electron-builder.json5
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
category: 'public.app-category.developer-tools',
hardenedRuntime: true,
gatekeeperAssess: false,
target: ['zip', 'dmg'],
},
win: {
target: [
Expand Down Expand Up @@ -40,6 +41,6 @@
publish: {
provider: 'github',
owner: 'onlook-dev',
repo: 'studio',
repo: 'onlook',
},
}
8 changes: 8 additions & 0 deletions app/electron/main/events/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ipcMain, shell } from 'electron';
import { updater } from '../update';
import { listenForAnalyticsMessages } from './analytics';
import { listenForAuthMessages } from './auth';
import { listenForCodeMessages } from './code';
Expand All @@ -22,4 +23,11 @@ function listenForGeneralMessages() {
return shell.openExternal(args);
},
);

ipcMain.handle(
MainChannels.QUIT_AND_INSTALL,
(e: Electron.IpcMainInvokeEvent, args: string) => {
return updater.quitAndInstall();
},
);
}
10 changes: 4 additions & 6 deletions app/electron/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { fileURLToPath } from 'node:url';
import { sendAnalytics } from './analytics';
import { handleAuthCallback } from './auth';
import { listenForIpcMessages } from './events';
import AutoUpdateManager from './update';
import { updater } from './update';
import { APP_NAME, APP_SCHEMA } from '/common/constants';

export let mainWindow: BrowserWindow | null = null;
const require = createRequire(import.meta.url);
const __dirname = path.dirname(fileURLToPath(import.meta.url));

Expand All @@ -18,6 +19,7 @@ const RENDERER_DIST = path.join(__dirname, '../../dist');
const PRELOAD_PATH = path.join(__dirname, '../preload/index.js');
const INDEX_HTML = path.join(RENDERER_DIST, 'index.html');
const VITE_DEV_SERVER_URL = process.env.VITE_DEV_SERVER_URL;
const IS_DEV = process.env.NODE_ENV === 'development';

// Environment setup
const setupEnvironment = () => {
Expand Down Expand Up @@ -51,9 +53,6 @@ const setupProtocol = () => {
}
};

// Window management
export let mainWindow: BrowserWindow | null = null;

const createWindow = () => {
mainWindow = new BrowserWindow({
title: APP_NAME,
Expand All @@ -75,7 +74,6 @@ const initMainWindow = () => {
const win = createWindow();
win.maximize();
loadWindowContent(win);

win.webContents.setWindowOpenHandler(({ url }) => {
if (url.startsWith('https:')) {
shell.openExternal(url);
Expand All @@ -89,7 +87,7 @@ const setupAppEventListeners = () => {
app.whenReady().then(initMainWindow);

app.on('ready', () => {
new AutoUpdateManager();
updater.listen();
sendAnalytics('start app');
});

Expand Down
8 changes: 0 additions & 8 deletions app/electron/main/update.ts

This file was deleted.

70 changes: 70 additions & 0 deletions app/electron/main/update/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import pkg from 'electron-updater';
const { autoUpdater } = pkg;

import log from 'electron-log';
import { mainWindow } from '..';
import { MainChannels } from '/common/constants';

class AppUpdater {
static instance: AppUpdater | null = null;

static getInstance() {
if (!AppUpdater.instance) {
AppUpdater.instance = new AppUpdater();
}
return AppUpdater.instance;
}

private constructor() {
if (AppUpdater.instance) {
return AppUpdater.instance;
}

log.transports.file.level = 'info';
autoUpdater.logger = log;
autoUpdater.autoDownload = true;
AppUpdater.instance = this;
}

quitAndInstall() {
autoUpdater.quitAndInstall();
}

listen() {
const checkForUpdates = () => {
autoUpdater.checkForUpdates().catch((err) => {
log.error('Error checking for updates:', err);
});
};

checkForUpdates();
setInterval(checkForUpdates, 60 * 60 * 1000);

autoUpdater.on('update-available', () => {
log.info('Update available');
});

autoUpdater.on('update-not-available', () => {
log.info('Update not available');
mainWindow?.webContents.send(MainChannels.UPDATE_NOT_AVAILABLE);
});

autoUpdater.on('download-progress', (progress) => {
let log_message = 'Download speed: ' + progress.bytesPerSecond;
log_message = log_message + ' - Downloaded ' + progress.percent + '%';
log_message = log_message + ' (' + progress.transferred + '/' + progress.total + ')';
log.info(log_message);
});

autoUpdater.on('update-downloaded', () => {
log.info('Update downloaded');
mainWindow?.webContents.send(MainChannels.UPDATE_DOWNLOADED);
});

autoUpdater.on('error', (err) => {
log.error('AutoUpdater error:', err);
});
}
}

export const updater = AppUpdater.getInstance();
9 changes: 5 additions & 4 deletions app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"productName": "Onlook",
"name": "@onlook/browser",
"name": "@onlook/onlook",
"version": "0.0.24",
"homepage": "https://onlook.dev",
"main": "dist-electron/main/index.js",
Expand Down Expand Up @@ -57,7 +57,8 @@
"clsx": "^2.1.1",
"css-to-tailwind-translator": "^1.2.8",
"culori": "^4.0.1",
"electron-updater": "^6.2.1",
"electron-log": "^5.2.0",
"electron-updater": "^6.3.4",
"embla-carousel-react": "^8.3.0",
"embla-carousel-wheel-gestures": "^8.0.1",
"fflate": "^0.8.2",
Expand Down Expand Up @@ -101,8 +102,8 @@
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.19",
"css-tree": "^2.3.1",
"electron": "^32.0.1",
"electron-builder": "^24.13.3",
"electron": "^32.1.0",
"electron-builder": "^25.0.5",
"eslint": "8.x",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-react": "^7.34.3",
Expand Down
5 changes: 5 additions & 0 deletions app/src/components/AppBar/UpdateButton/UpdateProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { UpdateManager } from '@/lib/update';
import { createContext, useContext } from 'react';

const UpdateContext = createContext(new UpdateManager());
export const useUpdateManager = () => useContext(UpdateContext);
26 changes: 26 additions & 0 deletions app/src/components/AppBar/UpdateButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Button } from '@/components/ui/button';
import { DownloadIcon } from '@radix-ui/react-icons';
import { observer } from 'mobx-react-lite';
import { useUpdateManager } from './UpdateProvider';

const UpdateButton = observer(() => {
const updateManager = useUpdateManager();

return (
updateManager.updateAvailable && (
<Button
variant={'secondary'}
size={'sm'}
className="bg-red-500 hover:bg-red-600 h-6 rounded-sm gap-2 transition"
onClick={() => {
updateManager.quitAndInstall();
}}
>
<DownloadIcon />
<p>Install new Update</p>
</Button>
)
);
});

export default UpdateButton;
26 changes: 15 additions & 11 deletions app/src/components/AppBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Route } from '@/lib/routes';
import { DiscordLogoIcon, GitHubLogoIcon } from '@radix-ui/react-icons';
import { observer } from 'mobx-react-lite';
import { Button } from '../ui/button';
import UpdateButton from './UpdateButton';
import { Links } from '/common/constants';

const AppBar = observer(() => {
Expand Down Expand Up @@ -30,17 +31,20 @@ const AppBar = observer(() => {
>
<GitHubLogoIcon />
</Button>
<div className="flex ml-1 mr-2 rounded-sm bg-gradient-to-r p-[1px] from-[#6EE7B7] via-[#3B82F6] to-[#9333EA]">
<Button
size={'sm'}
variant={'ghost'}
className="h-6 relative bg-black text-white rounded-sm"
onClick={() => {
window.open(Links.OPEN_ISSUE, '_blank');
}}
>
Report Issue
</Button>
<div className="flex mr-2 gap-2">
<div className="flex ml-1 rounded-sm bg-gradient-to-r p-[1px] from-[#6EE7B7] via-[#3B82F6] to-[#9333EA]">
<Button
size={'sm'}
variant={'ghost'}
className="h-6 relative bg-black text-white rounded-sm"
onClick={() => {
window.open(Links.OPEN_ISSUE, '_blank');
}}
>
Report Issue
</Button>
</div>
<UpdateButton />
</div>
</div>
);
Expand Down
25 changes: 25 additions & 0 deletions app/src/lib/update/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { makeAutoObservable } from 'mobx';
import { MainChannels } from '/common/constants';

export class UpdateManager {
updateAvailable = false;

constructor() {
makeAutoObservable(this);
this.listen();
}

listen() {
window.api.on(MainChannels.UPDATE_DOWNLOADED, async (e, args) => {
this.updateAvailable = true;
});

window.api.on(MainChannels.UPDATE_NOT_AVAILABLE, async (e, args) => {
this.updateAvailable = false;
});
}

quitAndInstall() {
window.api.invoke(MainChannels.QUIT_AND_INSTALL);
}
}

0 comments on commit 3a9dafe

Please sign in to comment.