Skip to content

Commit 97c233c

Browse files
committed
updater
1 parent 1dec554 commit 97c233c

5 files changed

Lines changed: 78 additions & 22 deletions

File tree

backend/updater/component_updater.go

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -178,20 +178,14 @@ func (u *Updater) UpdateComponent(update ComponentUpdate) error {
178178
}
179179
exeDir := filepath.Dir(ex)
180180

181-
if update.Type == "theme" {
182-
url = fmt.Sprintf("%s/themes/%s.css", BaseRepoURL, update.Name)
183-
filename = filepath.Join(exeDir, "themes", update.Name+".json") // Note: User changed extension to .json in previous step, assuming themes are JSON now?
184-
// Wait, themes are JSON in this project (theming.go loads .json).
185-
// But in component_updater.go line 178 it says .css in URL.
186-
// Let's check theming.go again. It loads .json.
187-
// So URL should probably be .json too?
188-
// The user manually changed .css to .json in step 2423.
189-
// So I should respect that.
181+
switch update.Type {
182+
case "theme":
183+
filename = filepath.Join(exeDir, "themes", update.Name+".json")
190184
url = fmt.Sprintf("%s/themes/%s.json", BaseRepoURL, update.Name)
191-
} else if update.Type == "locale" {
185+
case "locale":
192186
url = fmt.Sprintf("%s/locales/%s.json", BaseRepoURL, update.Name)
193187
filename = filepath.Join(exeDir, "locales", update.Name+".json")
194-
} else {
188+
default:
195189
return fmt.Errorf("unknown component type: %s", update.Type)
196190
}
197191

backend/updater/updater.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"path/filepath"
1212
"runtime"
1313
"strings"
14-
"sync"
1514

1615
"github.com/wailsapp/wails/v3/pkg/application"
1716
)
@@ -22,8 +21,8 @@ const (
2221
)
2322

2423
type Updater struct {
25-
app *application.App
26-
lock sync.Mutex
24+
app *application.App
25+
newExePath string
2726
}
2827

2928
type ReleaseInfo struct {
@@ -85,6 +84,9 @@ func (u *Updater) CheckForUpdates() UpdateCheckResult {
8584
// DoUpdate downloads the new version side-by-side and launches it
8685
func (u *Updater) DoUpdate(version string) error {
8786
// 1. Fetch release info
87+
// url := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/tags/%s", RepoOwner, RepoName, version)
88+
// Actually we need to fetch the release info to get the assets.
89+
// The previous code was:
8890
url := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/tags/%s", RepoOwner, RepoName, version)
8991
resp, err := http.Get(url)
9092
if err != nil {
@@ -160,14 +162,24 @@ func (u *Updater) DoUpdate(version string) error {
160162
}
161163

162164
// 5. Launch new executable and quit
163-
u.app.Event.Emit("update:progress", map[string]interface{}{"status": "installing", "percent": 100})
165+
u.app.Event.Emit("update:progress", map[string]interface{}{"status": "ready", "percent": 100})
164166

165-
cmd := exec.Command(newExePath)
167+
// Store path for restart
168+
u.newExePath = newExePath
169+
return nil
170+
}
171+
172+
// RestartApp launches the new executable and quits the current one
173+
func (u *Updater) RestartApp() error {
174+
if u.newExePath == "" {
175+
return fmt.Errorf("no update ready to install")
176+
}
177+
178+
cmd := exec.Command(u.newExePath)
166179
if err := cmd.Start(); err != nil {
167180
return fmt.Errorf("failed to start new version: %w", err)
168181
}
169182

170-
// Quit current app
171183
u.app.Quit()
172184
return nil
173185
}

frontend/bindings/lce/backend/updater/updater.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ export function LoadLocalVersions() {
4949
}));
5050
}
5151

52+
/**
53+
* RestartApp launches the new executable and quits the current one
54+
* @returns {$CancellablePromise<void>}
55+
*/
56+
export function RestartApp() {
57+
return $Call.ByID(4288405115);
58+
}
59+
5260
/**
5361
* SaveLocalVersions saves versions to versions.json
5462
* @param {$models.ComponentVersions} versions

frontend/src/App/footer/UpdaterNotification.svelte

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
<script>
22
import { onMount } from 'svelte';
33
import { slide } from 'svelte/transition';
4-
import { updaterStore, checkForUpdates, doUpdate, updateComponent } from '../lib/store/updater';
4+
import {
5+
updaterStore,
6+
checkForUpdates,
7+
doUpdate,
8+
updateComponent,
9+
restartApp
10+
} from '../lib/store/updater';
511
import { t } from 'svelte-i18n';
612
713
onMount(() => {
@@ -14,6 +20,10 @@
1420
}
1521
}
1622
23+
function handleRestart() {
24+
restartApp();
25+
}
26+
1727
function handleComponentUpdate(component) {
1828
updateComponent(component);
1929
}
@@ -32,6 +42,11 @@
3242
<div class="fill" style="width: {$updaterStore.progress}%"></div>
3343
</div>
3444
<span class="status">Downloading... {Math.round($updaterStore.progress)}%</span>
45+
{:else if $updaterStore.readyToRestart}
46+
<div class="success-msg">{$t('update_ready', { default: 'Download Complete!' })}</div>
47+
<button class="update-btn restart-btn" on:click={handleRestart}>
48+
{$t('restart_now', { default: 'Restart Now' })}
49+
</button>
3550
{:else}
3651
<button class="update-btn" on:click={handleUpdate}>
3752
{$t('update_now', { default: 'Update Now' })}
@@ -111,6 +126,22 @@
111126
transform: translateY(-1px);
112127
}
113128
129+
.restart-btn {
130+
background: #4caf50;
131+
color: white;
132+
}
133+
134+
.restart-btn:hover {
135+
background: #45a049;
136+
}
137+
138+
.success-msg {
139+
color: #4caf50;
140+
font-size: 12px;
141+
font-weight: bold;
142+
margin-bottom: 5px;
143+
}
144+
114145
.progress-bar {
115146
height: 6px;
116147
background: rgba(255, 255, 255, 0.1);

frontend/src/App/lib/store/updater.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export const updaterStore = writable({
1515
downloading: false,
1616
progress: 0,
1717
error: null,
18-
componentUpdates: [] // Array of {type, name, version, changelog}
18+
componentUpdates: [], // Array of {type, name, version, changelog}
19+
readyToRestart: false
1920
});
2021

2122
export async function checkForUpdates() {
@@ -47,14 +48,24 @@ export async function doUpdate(version) {
4748

4849
try {
4950
await DoUpdate(version);
50-
// Success - usually the app restarts or closes, but we can show a message
51-
updaterStore.update((s) => ({ ...s, downloading: false, progress: 100 }));
52-
alert('Update downloaded! Please restart the application.');
51+
// Update downloaded, ready to restart
52+
updaterStore.update((s) => ({ ...s, downloading: false, progress: 100, readyToRestart: true }));
5353
} catch (err) {
5454
updaterStore.update((s) => ({ ...s, downloading: false, error: err.message }));
5555
}
5656
}
5757

58+
export async function restartApp() {
59+
try {
60+
// We need to import RestartApp from bindings, but it might not be generated yet.
61+
// Assuming wails generates it.
62+
const { RestartApp } = await import('/bindings/lce/backend/updater/updater');
63+
await RestartApp();
64+
} catch (err) {
65+
updaterStore.update((s) => ({ ...s, error: err.message }));
66+
}
67+
}
68+
5869
export async function updateComponent(component) {
5970
updaterStore.update((s) => ({ ...s, downloading: true, error: null }));
6071

0 commit comments

Comments
 (0)