Skip to content

Commit

Permalink
Notify for updates (#25)
Browse files Browse the repository at this point in the history
* on open, show an update dialog if available
* show downloading dialog and version in dialog
* don't allow prerelease to trigger update notify
* bump to 0.7.0
  • Loading branch information
jgresham authored Apr 25, 2022
1 parent b0044d4 commit 5ae4e22
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 19 deletions.
3 changes: 3 additions & 0 deletions dev-app-update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
provider: github
owner: jgresham
repo: nice-node
4 changes: 2 additions & 2 deletions release/app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion release/app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nice-node",
"version": "0.5.2-alpha",
"version": "0.7.0-alpha",
"description": "An app to easily run an Ethereum node",
"productName": "NiceNode",
"main": "./dist/main/main.js",
Expand Down
4 changes: 2 additions & 2 deletions src/main/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default function getDebugInfo() {
let niceNodeVersion = app.getVersion();

if (process.env.NODE_ENV === 'development') {
niceNodeVersion = `dev-${niceNodeVersion}`;
niceNodeVersion = `Dev-${niceNodeVersion}`;
}

return {
Expand All @@ -28,7 +28,7 @@ const getDebugInfoShort = () => {
let niceNodeVersion = app.getVersion();

if (process.env.NODE_ENV === 'development') {
niceNodeVersion = `dev-${niceNodeVersion}`;
niceNodeVersion = `Dev-${niceNodeVersion}`;
}

return {
Expand Down
25 changes: 24 additions & 1 deletion src/main/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const logger = winston.createLogger({
transports: [
//
// - Write all logs with importance level of `error` or less to `error.log`
// - Write all logs with importance level of `info` or less to `combined.log`
// - Write all logs with importance level of `info` or less to `application.log`
//
new winston.transports.File({
filename: path.join(app.getPath('logs'), 'application.log'),
Expand All @@ -41,6 +41,24 @@ const logger = winston.createLogger({
],
});

export const autoUpdateLogger = winston.createLogger({
level: 'info',
format: winston.format.json(),
defaultMeta: { service: 'auto-updater-service' },
transports: [
new winston.transports.File({
filename: path.join(app.getPath('logs'), 'auto-updater-application.log'),
level: 'info',
maxsize: 10000000, // 50 MB
}),
new winston.transports.File({
filename: path.join(app.getPath('logs'), 'auto-updater-error.log'),
level: 'error',
maxsize: 10000000, // 50 MB
}),
],
});

// const gethRotateTransport: DailyRotateFile = new DailyRotateFile({
// // filename: path.join(app.getPath('logs'), 'geth', 'application-%DATE%.log'),
// filename: path.join(app.getPath('logs'), 'geth', 'application.log'),
Expand Down Expand Up @@ -92,6 +110,11 @@ if (process.env.NODE_ENV !== 'production') {
format: winston.format.simple(),
})
);
autoUpdateLogger.add(
new winston.transports.Console({
format: winston.format.simple(),
})
);
gethLogger.add(
new winston.transports.Console({
format: winston.format.simple(),
Expand Down
85 changes: 73 additions & 12 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@
* `./src/main.js` using webpack. This gives us some performance wins.
*/
import path from 'path';
import { app, BrowserWindow, shell } from 'electron';
import { app, BrowserWindow, dialog, shell } from 'electron';

// import { autoUpdater } from 'electron-updater';
import { autoUpdater, UpdateInfo } from 'electron-updater';
// import log from 'electron-log';
// import debug from 'electron-debug';
import * as Sentry from '@sentry/electron/main';
import sleep from 'await-sleep';
// import { CaptureConsole } from '@sentry/integrations';

import logger from './logger';
import logger, { autoUpdateLogger } from './logger';
import MenuBuilder from './menu';
import { resolveHtmlPath } from './util';
import { setWindow } from './messenger';
Expand All @@ -43,13 +44,19 @@ Sentry.init({
});

// If your app does uses auto updates
// export default class AppUpdater {
// constructor() {
// log.transports.file.level = 'info';
// autoUpdater.logger = log;
// autoUpdater.checkForUpdatesAndNotify();
// }
// }
export default class AppUpdater {
constructor() {
autoUpdater.logger = autoUpdateLogger;
autoUpdater.autoDownload = false;
autoUpdater.autoInstallOnAppQuit = false;
// Github allows releases to be marked as "pre-release" for
// testing purposes. Devs can set this to true and create
// a "pre-release" to test the auto update functionality.
// https://www.electron.build/auto-update#appupdater-moduleeventseventemitter
autoUpdater.allowPrerelease = false;
autoUpdater.checkForUpdatesAndNotify();
}
}

let mainWindow: BrowserWindow | null = null;

Expand Down Expand Up @@ -132,8 +139,10 @@ const createWindow = async () => {
});

// Remove this if your app does not use auto updates
// eslint-disable-next-line
// new AppUpdater();
// eslint-disable-next-line @typescript-eslint/no-use-before-define
intiUpdateHandlers(mainWindow);
// eslint-disable-next-line no-new
new AppUpdater();

// [Start] Modifies the renderer's Origin header for all outgoing web requests.
// This is done to simplify the allowed origins set for geth
Expand Down Expand Up @@ -193,6 +202,58 @@ app
})
.catch(logger.info);

const intiUpdateHandlers = (browserWindow: BrowserWindow) => {
autoUpdater.on('error', (error) => {
logger.error('autoUpdater:::::::::error', error);
});

autoUpdater.on('checking-for-update', () => {
logger.info('autoUpdater:::::::::checking-for-update');
});
autoUpdater.on('download-progress', (info) => {
logger.info(`autoUpdater:::::::::download-progress: `, info);
});
autoUpdater.on('update-available', async (info: UpdateInfo) => {
logger.info('autoUpdater:::::::::update-available: ', info);
// Quick fix to wait for window load before showing update prompt
await sleep(5000);
dialog
.showMessageBox(browserWindow, {
type: 'info',
title: 'Updates for NiceNode available',
message: `Do you want update NiceNode now? NiceNode will restart after downloading the update. Update to version ${info.version}.`,
buttons: ['Yes', 'No'],
})
.then(async (buttonIndex) => {
if (buttonIndex.response === 0) {
console.log('update accepted by user');
console.log('starting download');
autoUpdater.downloadUpdate();
dialog.showMessageBox(browserWindow, {
type: 'info',
title: 'Updates for NiceNode available',
message: `Downloading NiceNode update...`,
});
} else {
console.log('update checkbox not checked');
}
})
.catch((err) => {
console.error('error in update available diaglog: ', err);
});
});

autoUpdater.on('update-not-available', () => {
logger.info('autoUpdater:::::::::update-not-available');
});

autoUpdater.on('update-downloaded', () => {
logger.info('autoUpdater:::::::::update-downloaded');
logger.info('Calling autoUpdater.quitAndInstall()');
autoUpdater.quitAndInstall();
});
};

// no blocking work
const initialize = () => {
logger.info('Initializing main process work...');
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const Footer = () => {
<VscDebugConsole />
</IconButton>
<div style={{ position: 'fixed', right: 10, fontSize: 14 }}>
<span>version {sNiceNodeVersion}</span>
<span>v{sNiceNodeVersion}</span>
</div>

<Debugging
Expand Down
67 changes: 67 additions & 0 deletions src/renderer/Footer/NiceNodeSettings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useEffect, useState } from 'react';
import electron from '../electronGlobal';

const NiceNodeSettings = () => {
const [sShouldCheckForUpdates, setShouldCheckForUpdates] =
useState<boolean>();

const getShouldCheckForUpdates = async () => {
const shouldCheckForUpdates = await electron.getStoreValue(
'settings.shouldCheckForUpdates'
);
setShouldCheckForUpdates(shouldCheckForUpdates);
};

const saveShouldCheckForUpdates = async (value: boolean) => {
await electron.setStoreValue('settings.shouldCheckForUpdates', value);
// todo: if fails, show user
setShouldCheckForUpdates(value);
};

useEffect(() => {
getShouldCheckForUpdates();
}, []);

return (
<>
<h2>NiceNode</h2>
<h3>Updates</h3>
<div
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'start',
marginBottom: 10,
}}
>
<form>
<label htmlFor="shouldCheckForUpdates">
<input
id="shouldCheckForUpdates"
type="checkbox"
name="shouldCheckForUpdates"
checked={sShouldCheckForUpdates}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
saveShouldCheckForUpdates(e.target.checked)
}
/>
Check for updates
</label>
{/* <label htmlFor="shouldAutoInstallUpdates">
<input
id="shouldAutoInstallUpdates"
type="checkbox"
name="shouldAutoInstallUpdates"
checked={sShouldCheckForUpdates}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
saveShouldCheckForUpdates(e.target.checked)
}
/>
Automatically install updates (restarts NiceNode)
</label> */}
</form>
</div>
</>
);
};
export default NiceNodeSettings;
2 changes: 2 additions & 0 deletions src/renderer/Footer/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import electron from '../electronGlobal';
import MenuDrawer from './MenuDrawer';
import { useGetExecutionNodeInfoQuery } from '../state/services';
import NodeConfig from './NodeConfig';
import NiceNodeSettings from './NiceNodeSettings';

type Props = {
isOpen: boolean | undefined;
Expand All @@ -23,6 +24,7 @@ const Settings = ({ isOpen, onClickCloseButton }: Props) => {
onClickCloseButton={onClickCloseButton}
>
<NodeConfig />
<NiceNodeSettings />
{qNodeInfo?.currentData && !qNodeInfo?.isError && (
<h4>Running: {qNodeInfo.currentData}</h4>
)}
Expand Down

0 comments on commit 5ae4e22

Please sign in to comment.