Skip to content

Commit

Permalink
Merge pull request #2637 from ever-co/feat/server-web-updater
Browse files Browse the repository at this point in the history
[Feat] server web updater
  • Loading branch information
evereq authored Jun 16, 2024
2 parents 3ad5444 + 4e476f3 commit 62c66eb
Show file tree
Hide file tree
Showing 15 changed files with 814 additions and 163 deletions.
15 changes: 4 additions & 11 deletions apps/server-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
"build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.prod.ts",
"postinstall": "ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && npm run build:dll",
"lint": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx",
"pack:mac": "electron-builder build --mac --publish never && npm run build:dll",
"pack:win": "electron-builder build --win --publish never && npm run build:dll",
"pack:linux": "electron-builder build --linux --publish never && npm run build:dll",
"pack:mac": "electron-builder build --mac --publish always && npm run build:dll",
"pack:win": "electron-builder build --win --publish always && npm run build:dll",
"pack:linux": "electron-builder build --linux --publish always && npm run build:dll",
"package": "electron-builder build --publish never && npm run build:dll",
"rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir release/app",
"start": "ts-node ./.erb/scripts/check-port-in-use.js && npm run start:renderer",
Expand Down Expand Up @@ -239,15 +239,8 @@
"publish": [
{
"provider": "github",
"repo": "ever-teams-web-server",
"repo": "ever-teams",
"releaseType": "release"
},
{
"provider": "spaces",
"name": "ever",
"region": "sfo3",
"path": "/ever-teams-web-server",
"acl": "public-read"
}
]
},
Expand Down
22 changes: 21 additions & 1 deletion apps/server-web/src/main/helpers/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,25 @@ export const EventLists = {
webServerStopped: 'WEB_SERVER_STOPPED',
webServerStart: 'WEB_SERVER_START',
webServerStop: 'WEB_SERVER_STOP',
gotoSetting: 'GO_TO_SETTING'
gotoSetting: 'GO_TO_SETTING',
UPDATE_AVAILABLE: 'UPDATE_AVAILABLE',
UPDATE_ERROR: 'UPDATE_ERROR',
UPDATE_NOT_AVAILABLE: 'UPDATE_NOT_AVAILABLE',
UPDATE_PROGRESS: 'UPDATE_PROGRESS',
UPDATE_DOWNLOADED: 'UPDATE_DOWNLOADED',
UPDATE_CANCELLED: 'UPDATE_CANCELLED'
}

export const SettingPageTypeMessage = {
loadSetting: 'load-setting',
checkUpdate: 'check-for-update',
updateAvailable: 'update-available',
downloadingUpdate: 'downloading-update',
downloaded: 'downloaded-update',
installUpdate: 'install-update',
saveSetting: 'save-setting',
updateError: 'update-error',
upToDate: 'uptodate',
mainResponse: 'main-response',
showVersion: 'show-version'
}
94 changes: 75 additions & 19 deletions apps/server-web/src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import { DesktopServer } from './helpers/desktop-server';
import { LocalStore } from './helpers/services/libs/desktop-store';
import { EventEmitter } from 'events';
import { defaultTrayMenuItem, _initTray, updateTrayMenu } from './tray';
import { EventLists } from './helpers/constant';
import { EventLists, SettingPageTypeMessage } from './helpers/constant';
import { resolveHtmlPath } from './util';
import Updater from './updater';

const eventEmiter = new EventEmitter();
const eventEmitter = new EventEmitter();

const controller = new AbortController();
const { signal } = controller;
const isPack = app.isPackaged;
const desktopServer = new DesktopServer(false, eventEmiter);
const desktopServer = new DesktopServer(false, eventEmitter);
const isProd = process.env.NODE_ENV === 'production';

// const appPath = app.getAppPath();
Expand All @@ -21,8 +22,9 @@ let isServerRun: boolean;

let tray:Tray;
let settingWindow: BrowserWindow | null = null;
const updater = new Updater(eventEmitter);

const trayMenuItems = defaultTrayMenuItem(eventEmiter);
const trayMenuItems = defaultTrayMenuItem(eventEmitter);

const RESOURCES_PATH = app.isPackaged
? path.join(process.resourcesPath, 'assets/icons/gauzy')
Expand Down Expand Up @@ -138,47 +140,83 @@ const getEnvApi = () => {
return setting;
};

const SendMessageToSettingWindow = (type: string, data: any) => {
settingWindow?.webContents.send('setting-page', {
type,
data
});
}

const onInitApplication = () => {
LocalStore.setDefaultServerConfig(); // check and set default config
tray = _initTray(trayMenuItems, getAssetPath('icon.png'));
eventEmiter.on(EventLists.webServerStart, async () => {
updateTrayMenu('SERVER_START', { enabled: false }, eventEmiter, tray, trayMenuItems);
eventEmitter.on(EventLists.webServerStart, async () => {
updateTrayMenu('SERVER_START', { enabled: false }, eventEmitter, tray, trayMenuItems);
isServerRun = true;
await runServer();
})

eventEmiter.on(EventLists.webServerStop, async () => {
eventEmitter.on(EventLists.webServerStop, async () => {
isServerRun = false;
await stopServer();
})

eventEmiter.on(EventLists.webServerStarted, () => {
eventEmitter.on(EventLists.webServerStarted, () => {
console.log(EventLists.webServerStarted)
updateTrayMenu('SERVER_START', { enabled: false }, eventEmiter, tray, trayMenuItems);
updateTrayMenu('SERVER_STOP', { enabled: true }, eventEmiter, tray, trayMenuItems);
updateTrayMenu('SERVER_STATUS', { label: 'Status: Started' }, eventEmiter, tray, trayMenuItems);
updateTrayMenu('SERVER_START', { enabled: false }, eventEmitter, tray, trayMenuItems);
updateTrayMenu('SERVER_STOP', { enabled: true }, eventEmitter, tray, trayMenuItems);
updateTrayMenu('SERVER_STATUS', { label: 'Status: Started' }, eventEmitter, tray, trayMenuItems);
isServerRun = true;
})

eventEmiter.on(EventLists.webServerStopped, () => {
eventEmitter.on(EventLists.webServerStopped, () => {
console.log(EventLists.webServerStopped);
updateTrayMenu('SERVER_STOP', { enabled: false }, eventEmiter, tray, trayMenuItems);
updateTrayMenu('SERVER_START', { enabled: true }, eventEmiter, tray, trayMenuItems);
updateTrayMenu('SERVER_STATUS', { label: 'Status: Stopped' }, eventEmiter, tray, trayMenuItems);
updateTrayMenu('SERVER_STOP', { enabled: false }, eventEmitter, tray, trayMenuItems);
updateTrayMenu('SERVER_START', { enabled: true }, eventEmitter, tray, trayMenuItems);
updateTrayMenu('SERVER_STATUS', { label: 'Status: Stopped' }, eventEmitter, tray, trayMenuItems);
isServerRun = false;
})

eventEmiter.on(EventLists.gotoSetting, async () => {
eventEmitter.on(EventLists.gotoSetting, async () => {
if (!settingWindow) {
await createWindow()
}
const serverSetting = LocalStore.getStore('config');
console.log('setting data', serverSetting);
settingWindow?.show();
settingWindow?.webContents.once('did-finish-load', () => {
settingWindow?.webContents.send('load_setting', serverSetting);
SendMessageToSettingWindow(SettingPageTypeMessage.loadSetting, serverSetting);
})
})

eventEmitter.on(EventLists.UPDATE_AVAILABLE, (data)=> {
console.log('UPDATE_AVAILABLE', data);
SendMessageToSettingWindow(SettingPageTypeMessage.updateAvailable, data);
})

eventEmitter.on(EventLists.UPDATE_ERROR, (data)=> {
console.log('UPDATE_ERROR', data);
SendMessageToSettingWindow(SettingPageTypeMessage.updateError, {message: JSON.stringify(data)});
})

eventEmitter.on(EventLists.UPDATE_NOT_AVAILABLE, (data)=> {
console.log('UPDATE_NOT_AVAILABLE', data);
SendMessageToSettingWindow(SettingPageTypeMessage.upToDate, data);
})

eventEmitter.on(EventLists.UPDATE_PROGRESS, (data)=> {
console.log('UPDATE_PROGRESS', data.percent);
SendMessageToSettingWindow(SettingPageTypeMessage.downloadingUpdate, {percent: Math.floor(data.percent || 0)});
})

eventEmitter.on(EventLists.UPDATE_DOWNLOADED, (data)=> {
console.log('UPDATE_DOWNLOADED', data);
SendMessageToSettingWindow(SettingPageTypeMessage.downloaded, data);
})

eventEmitter.on(EventLists.UPDATE_CANCELLED, (data)=> {
console.log('UPDATE_CANCELLED', data);
})
}

(async () => {
Expand All @@ -195,8 +233,26 @@ ipcMain.on('message', async (event, arg) => {
event.reply('message', `${arg} World!`)
})

ipcMain.on('save_setting', (event, arg) => {
LocalStore.updateConfigSetting(arg);
ipcMain.on('setting-page', (event, arg) => {
console.log('main setting page', arg);
switch (arg.type) {
case SettingPageTypeMessage.saveSetting:
LocalStore.updateConfigSetting(arg.data);
event.sender.send('setting-page', { type: SettingPageTypeMessage.mainResponse, data: true });
break;
case SettingPageTypeMessage.checkUpdate:
updater.checkUpdate();
break;
case SettingPageTypeMessage.installUpdate:
updater.installUpdate();
break;
case SettingPageTypeMessage.showVersion:
const currentVersion = app.getVersion();
event.sender.send('setting-page', { type: SettingPageTypeMessage.showVersion, data: currentVersion})
break;
default:
break;
}
})

app.on('before-quit', async (e) => {
Expand Down
5 changes: 4 additions & 1 deletion apps/server-web/src/main/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
/* eslint no-unused-vars: off */
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';

export type Channels = 'ipc-example';
export type Channels = 'setting-page' | 'ipc-renderer';

const electronHandler = {
ipcRenderer: {
sendMessage(channel: Channels, ...args: unknown[]) {
ipcRenderer.send(channel, ...args);
},
sendMessageSync(channel: Channels, ...args: unknown[]) {
ipcRenderer.sendSync(channel, ...args);
},
on(channel: Channels, func: (...args: unknown[]) => void) {
const subscription = (_event: IpcRendererEvent, ...args: unknown[]) =>
func(...args);
Expand Down
45 changes: 45 additions & 0 deletions apps/server-web/src/main/updater.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { autoUpdater, } from 'electron-updater';
import log from 'electron-log';
import EventEmitter from 'events';
import { EventLists } from './helpers/constant';

class AppUpdater {
constructor(eventEmitter: EventEmitter) {
log.transports.file.level = 'info';
autoUpdater.logger = log;
autoUpdater.on('update-available', () => {
eventEmitter.emit(EventLists.UPDATE_AVAILABLE);
})

autoUpdater.on('error', (message) => {
eventEmitter.emit(EventLists.UPDATE_ERROR, message);
})

autoUpdater.on('update-not-available', (info) => {
eventEmitter.emit(EventLists.UPDATE_NOT_AVAILABLE, info);
})

autoUpdater.on('download-progress', (info) => {
eventEmitter.emit(EventLists.UPDATE_PROGRESS, info);
})

autoUpdater.on('update-downloaded', (data) => {
eventEmitter.emit(EventLists.UPDATE_DOWNLOADED, data);
})

autoUpdater.on('update-cancelled', (info) => {
eventEmitter.emit(EventLists.UPDATE_CANCELLED, info);
})
// autoUpdater.checkForUpdatesAndNotify();
}

checkUpdate() {
autoUpdater.checkForUpdates();
}

installUpdate() {
autoUpdater.quitAndInstall();
}
}

export default AppUpdater;
18 changes: 18 additions & 0 deletions apps/server-web/src/renderer/components/About.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { EverTeamsLogo } from './svgs';
type Props = {
version: string;
};
export const AboutComponent = (props: Props) => {
return (
<div className="flex min-h-screen items-center justify-center bg-gray-100">
<div className="rounded-lg bg-gray-50 px-16 py-14">
<div className="flex justify-center">
<EverTeamsLogo />
</div>
<h2 className="w-[230px] text-center text-gray-600 mt-10">
V {props.version}
</h2>
</div>
</div>
);
};
99 changes: 99 additions & 0 deletions apps/server-web/src/renderer/components/Popup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
type Props = {
isShowPopup: boolean;
modalAction: () => void;
type: 'success' | 'error' | 'none';
message: string;
};
export function Popup(props: Props) {
return (
<div
className={`fixed z-10 inset-0 overflow-y-auto ${props.isShowPopup ? '' : 'hidden'}`}
id="my-modal"
>
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div className="fixed inset-0 transition-opacity" aria-hidden="true">
<div className="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span
className="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true"
>
&#8203;
</span>
<div
className="inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-1/3"
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline"
>
<div>
<div className="mx-auto flex items-center justify-center h-32 w-12 rounded-full">
{props.type === 'success' && (
<div className="rounded-full bg-green-200 p-6">
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-green-500 p-4">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
className="h-8 w-8 text-white"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M4.5 12.75l6 6 9-13.5"
/>
</svg>
</div>
</div>
)}
{props.type === 'error' && (
<div className="rounded-full bg-red-200 p-6">
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-red-500 p-4">
<svg
className="h-8 w-8 text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</div>
</div>
)}
</div>
<div className="mt-3 text-center sm:mt-5">
<h3
className="text-lg leading-6 font-medium text-gray-900"
id="modal-headline"
>
{props.type == 'success' ? 'Success' : 'Error'}
</h3>
<div className="mt-2">
<p className="text-sm text-gray-500 text-pretty break-words">
{props.message}
</p>
</div>
</div>
</div>
<div className="mt-5 sm:mt-6">
<button
className="mx-auto mt-10 block rounded-xl border-4 border-transparent bg-blue-400 px-6 py-3 text-center text-base font-medium text-blue-100 outline-8 hover:outline hover:duration-300"
onClick={props.modalAction}
>
OK
</button>
</div>
</div>
</div>
</div>
);
}
Loading

0 comments on commit 62c66eb

Please sign in to comment.