Skip to content

Commit 7bcdf30

Browse files
committed
check latest version on startup and show tooltip when a new version is available
1 parent 94c6dc7 commit 7bcdf30

4 files changed

Lines changed: 72 additions & 1 deletion

File tree

packages/flowtest-electron/electron-main.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const template = require('./electron-menu');
66
const Watcher = require('./src/app/watcher');
77
const registerRendererEventHandlers = require('./src/ipc/collection');
88
const registerSettingsEventHandlers = require('./src/ipc/settings');
9+
const packageJson = require('./package.json'); // app's package.json
10+
const https = require('https');
911

1012
let mainWindow;
1113
let watcher;
@@ -20,6 +22,41 @@ if (process.env.NODE_ENV === 'production') {
2022
console.trace = noop;
2123
}
2224

25+
const version = {
26+
current: packageJson.version,
27+
latest: packageJson.version,
28+
};
29+
30+
function checkForUpdates() {
31+
const url = `https://raw.githubusercontent.com/FlowTestAI/FlowTest/main/packages/flowtest-electron/package.json`;
32+
33+
https
34+
.get(url, (res) => {
35+
let data = '';
36+
37+
res.on('data', (chunk) => {
38+
data += chunk;
39+
});
40+
41+
res.on('end', () => {
42+
try {
43+
const remotePackageJson = JSON.parse(data);
44+
const latestVersion = remotePackageJson.version;
45+
46+
if (latestVersion !== version.current) {
47+
version.latest = latestVersion;
48+
//shell.openExternal(`https://github.com/${username}/${repo}/releases`);
49+
}
50+
} catch (error) {
51+
console.error('Error parsing JSON:', error);
52+
}
53+
});
54+
})
55+
.on('error', (err) => {
56+
console.error('Error fetching package.json:', err);
57+
});
58+
}
59+
2360
app.on('ready', async () => {
2461
const menu = Menu.buildFromTemplate(template);
2562
Menu.setApplicationMenu(menu);
@@ -59,6 +96,12 @@ app.on('ready', async () => {
5996

6097
watcher = new Watcher();
6198

99+
checkForUpdates();
100+
mainWindow.webContents.on('did-finish-load', () => {
101+
// Send a message to the renderer process
102+
mainWindow.webContents.send('main:app-version', version);
103+
});
104+
62105
registerRendererEventHandlers(mainWindow, watcher);
63106
registerSettingsEventHandlers(mainWindow);
64107
});

src/components/molecules/headers/MainHeader.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,35 @@
11
import React from 'react';
22
import ThemeController from 'components/atoms/ThemeController';
33
import AppLogo from 'components/atoms/Logo';
4+
import useSettingsStore from 'stores/SettingsStore';
5+
import { ExclamationCircleIcon } from '@heroicons/react/24/outline';
6+
import Tippy from '@tippyjs/react';
7+
import 'tippy.js/dist/tippy.css';
48

59
const MainHeader = () => {
10+
const appVersion = useSettingsStore((state) => state.appVersion);
11+
612
return (
713
// <header className='flex items-center justify-between px-4 py-3 font-semibold tracking-widest dark:bg-slate-800 dark:text-white'>
814
<header className='flex items-center justify-between px-4 py-3 font-semibold tracking-widest'>
915
<div className='flex items-center gap-3'>
1016
<AppLogo styleClasses='w-6 h-6' />
1117
<div className='flex items-baseline gap-1'>
1218
<h2>FlowTestAI</h2>
13-
<span className='text-xs font-normal'>v1.1.0</span>
19+
<span className='text-xs font-normal'>
20+
<a href='https://github.com/FlowTestAI/FlowTest/releases' target='_blank' rel='noreferrer' className='link'>
21+
{`v${appVersion.current}`}
22+
</a>
23+
</span>
24+
{appVersion.current != appVersion.latest ? (
25+
<span className='text-xs font-normal'>
26+
<Tippy content={`v${appVersion.latest} available`} placement='top'>
27+
<ExclamationCircleIcon className='w-5 h-5' />
28+
</Tippy>
29+
</span>
30+
) : (
31+
<></>
32+
)}
1433
</div>
1534
</div>
1635
<ThemeController />

src/ipc/settings.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import useSettingsStore from 'stores/SettingsStore';
44
const registerSettingsEventHandlers = () => {
55
const _addLogSyncConfig = useSettingsStore((state) => state.addLogSyncConfig);
66
const _addGenAIUsageDisclaimer = useSettingsStore((state) => state.addGenAIUsageDisclaimer);
7+
const _updateAppVersion = useSettingsStore((state) => state.updateAppVersion);
78

89
useEffect(() => {
910
const { ipcRenderer } = window;
@@ -19,6 +20,10 @@ const registerSettingsEventHandlers = () => {
1920
}
2021
});
2122

23+
ipcRenderer.on('main:app-version', (version) => {
24+
_updateAppVersion(version);
25+
});
26+
2227
ipcRenderer.invoke('renderer:settings-window-ready');
2328
}, []);
2429
};

src/stores/SettingsStore.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ import { create } from 'zustand';
33
const useSettingsStore = create((set, get) => ({
44
logSyncConfig: {},
55
genAIUsageDisclaimer: false,
6+
appVersion: {},
67
addLogSyncConfig: (enabled, hostUrl, accessId, accessKey) => {
78
set((state) => ({ logSyncConfig: { ...state.logSyncConfig, ...{ enabled, hostUrl, accessId, accessKey } } }));
89
},
910
addGenAIUsageDisclaimer: (accepted) => {
1011
set((state) => ({ genAIUsageDisclaimer: accepted }));
1112
},
13+
updateAppVersion: (version) => {
14+
set((state) => ({ appVersion: version }));
15+
},
1216
}));
1317

1418
export default useSettingsStore;

0 commit comments

Comments
 (0)