fix(desktop): in-memory update progress polling (#5126)

Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
Shreyas 2025-06-13 11:11:37 +05:30 committed by GitHub
parent 936b0fff46
commit 754f076f18
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 67 additions and 37 deletions

View file

@ -31,8 +31,4 @@ export interface UpdateState {
status: UpdateStatus;
version?: string;
message?: string;
progress?: {
downloaded: number;
total?: number;
};
}

View file

@ -4,6 +4,8 @@ import { type LazyStore } from "@tauri-apps/plugin-store";
import { UpdateStatus, CheckResult, UpdateState } from "~/types";
export class UpdaterService {
private currentProgress: { downloaded: number; total?: number } = { downloaded: 0 };
constructor(private store: LazyStore) {}
async initialize(): Promise<void> {
@ -12,6 +14,10 @@ export class UpdaterService {
});
}
getCurrentProgress(): { downloaded: number; total?: number } {
return this.currentProgress;
}
async checkForUpdates(timeout = 5000): Promise<CheckResult> {
try {
await this.saveUpdateState({
@ -86,41 +92,36 @@ export class UpdaterService {
throw new Error("No update available to install");
}
await this.saveUpdateState({
status: UpdateStatus.DOWNLOADING,
progress: {
downloaded: 0,
total: undefined
}
});
let totalBytes: number | undefined;
let downloadedBytes = 0;
await this.saveUpdateState({
status: UpdateStatus.DOWNLOADING,
});
await updateResult.downloadAndInstall(
(event: DownloadEvent) => {
if (event.event === 'Started') {
totalBytes = event.data.contentLength;
this.saveUpdateState({
status: UpdateStatus.DOWNLOADING,
progress: {
downloaded: 0,
total: totalBytes
}
});
} else if (event.event === 'Progress') {
downloadedBytes += event.data.chunkLength;
this.saveUpdateState({
status: UpdateStatus.DOWNLOADING,
progress: {
try {
if (event.event === 'Started') {
totalBytes = event.data.contentLength;
downloadedBytes = 0;
console.log(`Download started, total size: ${totalBytes} bytes`);
} else if (event.event === 'Progress') {
downloadedBytes += event.data.chunkLength;
console.log(`Download progress: ${downloadedBytes}/${totalBytes} bytes`);
this.currentProgress = {
downloaded: downloadedBytes,
total: totalBytes
}
});
} else if (event.event === 'Finished') {
this.saveUpdateState({
status: UpdateStatus.INSTALLING
});
};
} else if (event.event === 'Finished') {
console.log("Download finished, starting installation");
this.saveUpdateState({
status: UpdateStatus.INSTALLING
});
}
} catch (error) {
console.warn('Progress tracking error:', error);
}
}
);

View file

@ -129,7 +129,7 @@
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue"
import { ref, onMounted, onUnmounted } from "vue"
import { LazyStore } from "@tauri-apps/plugin-store"
import { load } from "@hoppscotch/plugin-appload"
import { getVersion } from "@tauri-apps/api/app"
@ -183,6 +183,8 @@ const appVersion = ref("...")
const updaterService = new UpdaterService(appStore)
let progressPollingInterval: ReturnType<typeof setInterval> | undefined
const formatBytes = (bytes: number): string => {
if (bytes === 0) return "0 Bytes"
@ -211,22 +213,29 @@ const setupUpdateStateWatcher = async () => {
updateStatus.value = newValue.status
updateMessage.value = newValue.message || ""
if (newValue.progress) {
downloadProgress.value = newValue.progress
}
if (newValue.status === UpdateStatus.AVAILABLE) {
appState.value = AppState.UPDATE_AVAILABLE
} else if (newValue.status === UpdateStatus.ERROR) {
error.value = newValue.message || "Unknown error"
appState.value = AppState.ERROR
// Stop progress polling on error
stopProgressPolling()
} else if (
newValue.status === UpdateStatus.DOWNLOADING ||
newValue.status === UpdateStatus.INSTALLING
) {
appState.value = AppState.UPDATE_IN_PROGRESS
// Start progress polling when downloading
if (newValue.status === UpdateStatus.DOWNLOADING) {
startProgressPolling()
} else {
// Stop progress polling when installing
stopProgressPolling()
}
} else if (newValue.status === UpdateStatus.READY_TO_RESTART) {
appState.value = AppState.UPDATE_READY
// Stop progress polling when ready to restart
stopProgressPolling()
}
}
)
@ -234,6 +243,24 @@ const setupUpdateStateWatcher = async () => {
return unsubscribe
}
const startProgressPolling = () => {
if (progressPollingInterval) return
progressPollingInterval = setInterval(() => {
const currentProgress = updaterService.getCurrentProgress()
if (currentProgress.downloaded > downloadProgress.value.downloaded) {
downloadProgress.value = currentProgress
}
}, 100)
}
const stopProgressPolling = () => {
if (progressPollingInterval) {
clearInterval(progressPollingInterval)
progressPollingInterval = undefined
}
}
const installUpdate = async () => {
try {
appState.value = AppState.UPDATE_IN_PROGRESS
@ -244,6 +271,7 @@ const installUpdate = async () => {
const errorMessage = err instanceof Error ? err.message : String(err)
error.value = `Failed to install update: ${errorMessage}`
appState.value = AppState.ERROR
stopProgressPolling()
}
}
@ -332,6 +360,7 @@ const initialize = async () => {
appState.value = AppState.LOADING
error.value = ""
downloadProgress.value = { downloaded: 0 }
stopProgressPolling()
try {
try {
@ -368,4 +397,8 @@ const initialize = async () => {
onMounted(() => {
initialize()
})
onUnmounted(() => {
stopProgressPolling()
})
</script>