Skip to content

Commit 0b6bd0c

Browse files
committed
feat: check for updates, show new version on home page
1 parent dc00f89 commit 0b6bd0c

File tree

6 files changed

+121
-5
lines changed

6 files changed

+121
-5
lines changed

src/main/index.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import {
6868
removeScreensaverImage,
6969
hasCustomScreensaverImage
7070
} from './lib/screensaver.js'
71+
import { getLatestVersion } from './lib/update.js'
7172

7273
let mainWindow: BrowserWindow | null = null
7374

@@ -230,7 +231,8 @@ enum IPCHandler {
230231
RemoveScreensaverImage = 'removeScreensaverImage',
231232
HasCustomScreensaverImage = 'hasCustomScreensaverImage',
232233
OpenDevTools = 'openDevTools',
233-
GetChannel = 'getChannel'
234+
GetChannel = 'getChannel',
235+
CheckUpdate = 'checkUpdate'
234236
}
235237

236238
async function setupIpcHandlers() {
@@ -476,6 +478,18 @@ async function setupIpcHandlers() {
476478
ipcMain.handle(IPCHandler.GetChannel, () => {
477479
return isNightly ? 'nightly' : 'stable'
478480
})
481+
482+
ipcMain.handle(IPCHandler.CheckUpdate, async () => {
483+
const currentVersion = 'v' + app.getVersion()
484+
const latestVersion = await getLatestVersion()
485+
if (!latestVersion) return null
486+
487+
return {
488+
currentVersion,
489+
latestVersion: latestVersion.version,
490+
downloadUrl: latestVersion.downloadUrl
491+
}
492+
})
479493
}
480494

481495
async function setupTray() {

src/main/lib/update.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import axios from 'axios'
2+
3+
export async function getLatestVersion() {
4+
const res = await axios.get(
5+
'https://api.github.com/repos/BluDood/GlanceThing/releases/latest'
6+
)
7+
8+
if (res.status !== 200) return null
9+
10+
return {
11+
version: res.data.tag_name,
12+
downloadUrl: res.data.html_url
13+
}
14+
}

src/preload/index.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ declare global {
6565
hasCustomScreensaverImage: () => Promise<boolean>
6666
openDevTools: () => void
6767
getChannel: () => Promise<'stable' | 'nightly'>
68+
checkUpdate: () => Promise<{
69+
currentVersion: string
70+
latestVersion: string
71+
downloadUrl: string
72+
} | null>
6873
}
6974
}
7075
}

src/preload/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ enum IPCHandler {
4242
DownloadLogs = 'downloadLogs',
4343
UploadScreensaverImage = 'uploadScreensaverImage',
4444
RemoveScreensaverImage = 'removeScreensaverImage',
45-
HasCustomScreensaverImage = 'hasCustomScreensaverImage'
45+
HasCustomScreensaverImage = 'hasCustomScreensaverImage',
46+
CheckUpdate = 'checkUpdate'
4647
}
4748

4849
// Custom APIs for renderer
@@ -116,7 +117,8 @@ const api = {
116117
removeScreensaverImage: () =>
117118
ipcRenderer.invoke(IPCHandler.RemoveScreensaverImage),
118119
openDevTools: () => ipcRenderer.invoke('openDevTools'),
119-
getChannel: () => ipcRenderer.invoke('getChannel')
120+
getChannel: () => ipcRenderer.invoke('getChannel'),
121+
checkUpdate: () => ipcRenderer.invoke(IPCHandler.CheckUpdate)
120122
}
121123

122124
// Use `contextBridge` APIs to expose Electron APIs to

src/renderer/src/pages/Home/Home.module.css

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,54 @@
6363
color: #ff9800;
6464
}
6565

66+
.update {
67+
position: absolute;
68+
bottom: 0;
69+
right: 0;
70+
margin: 20px;
71+
background: #111;
72+
padding: 12px;
73+
border-radius: 5px;
74+
display: flex;
75+
flex-direction: column;
76+
gap: 8px;
77+
animation: appear 500ms ease;
78+
}
79+
80+
.update .title {
81+
display: flex;
82+
align-items: center;
83+
gap: 8px;
84+
color: #fff;
85+
}
86+
87+
.update .title span {
88+
color: #0064ff;
89+
font-size: 22px;
90+
}
91+
92+
.update .content {
93+
display: flex;
94+
justify-content: space-between;
95+
gap: 15px;
96+
}
97+
98+
.update .content .version {
99+
display: flex;
100+
align-items: center;
101+
gap: 5px;
102+
color: #bbb;
103+
font-size: 14px;
104+
}
105+
106+
.update .content button {
107+
padding: 6px 8px;
108+
font-size: 14px;
109+
display: flex;
110+
align-items: center;
111+
gap: 5px;
112+
}
113+
66114
@keyframes appear {
67115
from {
68116
opacity: 0;

src/renderer/src/pages/Home/Home.tsx

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ const Home: React.FC = () => {
2828
const carThingStateRef = useRef(carThingState)
2929
const [needsPlaybackSetup, setNeedsPlaybackSetup] = useState(false)
3030

31+
const [updateInfo, setUpdateInfo] = useState<{
32+
currentVersion: string
33+
latestVersion: string
34+
downloadUrl: string
35+
} | null>(null)
36+
3137
useEffect(() => {
3238
window.api.getStorageValue('setupComplete').then(setupComplete => {
3339
if (!setupComplete) navigate('/setup')
@@ -40,7 +46,7 @@ const Home: React.FC = () => {
4046
carThingStateRef.current = state
4147
})
4248

43-
const timeout = setTimeout(() => {
49+
const stateTimeout = setTimeout(() => {
4450
if (carThingStateRef.current !== null) return
4551

4652
window.api.triggerCarThingStateUpdate()
@@ -50,9 +56,17 @@ const Home: React.FC = () => {
5056
if (handler === null) setNeedsPlaybackSetup(true)
5157
})
5258

59+
window.api.checkUpdate().then(setUpdateInfo)
60+
61+
const checkUpdateInterval = setInterval(
62+
() => window.api.checkUpdate().then(setUpdateInfo),
63+
1000 * 60 * 30
64+
)
65+
5366
return () => {
5467
removeListener()
55-
clearTimeout(timeout)
68+
clearTimeout(stateTimeout)
69+
clearInterval(checkUpdateInterval)
5670
}
5771
}, [])
5872

@@ -119,6 +133,25 @@ const Home: React.FC = () => {
119133
</button>
120134
</div>
121135
) : null}
136+
{updateInfo &&
137+
updateInfo.latestVersion !== updateInfo.currentVersion ? (
138+
<div className={styles.update}>
139+
<div className={styles.title}>
140+
<span className="material-icons">download</span>A new
141+
GlanceThing update is available!
142+
</div>
143+
<div className={styles.content}>
144+
<p className={styles.version}>
145+
{updateInfo.currentVersion}{' '}
146+
<span className="material-icons">arrow_forward</span>{' '}
147+
{updateInfo.latestVersion}
148+
</p>
149+
<button onClick={() => window.open(updateInfo.downloadUrl)}>
150+
Download <span className="material-icons">open_in_new</span>
151+
</button>
152+
</div>
153+
</div>
154+
) : null}
122155
</div>
123156
)
124157
}

0 commit comments

Comments
 (0)