fix(desktop): in-memory update progress polling (#5126)
Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
parent
936b0fff46
commit
754f076f18
3 changed files with 67 additions and 37 deletions
|
|
@ -31,8 +31,4 @@ export interface UpdateState {
|
|||
status: UpdateStatus;
|
||||
version?: string;
|
||||
message?: string;
|
||||
progress?: {
|
||||
downloaded: number;
|
||||
total?: number;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in a new issue