diff --git a/src/common/application-update/progress-of-update-download/progress-of-update-download.injectable.ts b/src/common/application-update/progress-of-update-download/progress-of-update-download.injectable.ts index 26ecd1d618..fe7a5d2f3f 100644 --- a/src/common/application-update/progress-of-update-download/progress-of-update-download.injectable.ts +++ b/src/common/application-update/progress-of-update-download/progress-of-update-download.injectable.ts @@ -3,10 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; +import type { JsonObject } from "type-fest"; import createSyncBoxInjectable from "../../utils/sync-box/create-sync-box.injectable"; import { syncBoxInjectionToken } from "../../utils/sync-box/sync-box-injection-token"; -export interface ProgressOfDownload { +export interface ProgressOfDownload extends JsonObject { percentage: number; } diff --git a/src/common/auto-update/auto-update-state.injectable.ts b/src/common/auto-update/auto-update-state.injectable.ts index c250aa72b3..f5a6c59de9 100644 --- a/src/common/auto-update/auto-update-state.injectable.ts +++ b/src/common/auto-update/auto-update-state.injectable.ts @@ -5,16 +5,18 @@ import { getInjectable } from "@ogre-tools/injectable"; import { makeObservable, observable } from "mobx"; -export type AutoUpdateStateName = "checking" | "available" | "not-available" | "done" | "downloading" | "idle"; +export type AutoUpdateStateName = "checking" | "available" | "not-available" | "done" | "downloading" | "download-failed" | "download-succeeded" | "idle"; + +let timerId: NodeJS.Timeout; export class AutoUpdateState { @observable private _state: AutoUpdateStateName; - private timerId: NodeJS.Timeout; + @observable private _version: string | undefined = undefined; constructor(state: AutoUpdateStateName = "idle") { makeObservable(this); - this.name = state; + this._state = state; } get name() : AutoUpdateStateName { @@ -27,9 +29,18 @@ export class AutoUpdateState { this.triggerIdle(); } + get version() : string | undefined { + return this._version; + } + + set version(version: string | undefined ) { + this._version = version; + + this.triggerIdle(); + } + private triggerIdle(): void { - clearTimeout(this.timerId); - this.timerId = null; + clearTimeout(timerId); switch(this.name) { case "checking": @@ -40,7 +51,9 @@ export class AutoUpdateState { case "done": case "not-available": - this.timerId = setTimeout(() => this.name = "idle", 5000); + case "download-failed": + case "download-succeeded": + timerId = setTimeout(() => this.name = "idle", 5000); break; } } diff --git a/src/renderer/application-update/application-update-status-listener.injectable.ts b/src/renderer/application-update/application-update-status-listener.injectable.ts index 69ba23608c..9c5332c386 100644 --- a/src/renderer/application-update/application-update-status-listener.injectable.ts +++ b/src/renderer/application-update/application-update-status-listener.injectable.ts @@ -5,39 +5,46 @@ import { getInjectable } from "@ogre-tools/injectable"; import type { ApplicationUpdateStatusChannel, ApplicationUpdateStatusEventId } from "../../common/application-update/application-update-status-channel.injectable"; import applicationUpdateStatusChannelInjectable from "../../common/application-update/application-update-status-channel.injectable"; -import showInfoNotificationInjectable from "../components/notifications/show-info-notification.injectable"; +//import showInfoNotificationInjectable from "../components/notifications/show-info-notification.injectable"; import type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token"; import { messageChannelListenerInjectionToken } from "../../common/utils/channel/message-channel-listener-injection-token"; +import AutoUpdateStateInjectable from "../../common/auto-update/auto-update-state.injectable"; const applicationUpdateStatusListenerInjectable = getInjectable({ id: "application-update-status-listener", instantiate: (di): MessageChannelListener => { const channel = di.inject(applicationUpdateStatusChannelInjectable); - const showInfoNotification = di.inject(showInfoNotificationInjectable); + //const showInfoNotification = di.inject(showInfoNotificationInjectable); + const autoUpdateState = di.inject(AutoUpdateStateInjectable); const eventHandlers: Record void }> = { "checking-for-updates": { handle: () => { - showInfoNotification("Checking for updates..."); + //showInfoNotification("Checking for updates..."); + autoUpdateState.name = "checking"; }, }, "no-updates-available": { handle: () => { - showInfoNotification("No new updates available"); + //showInfoNotification("No new updates available"); + autoUpdateState.name = "not-available"; }, }, "download-for-update-started": { handle: (version) => { - showInfoNotification(`Download for version ${version} started...`); + //showInfoNotification(`Download for version ${version} started...`); + autoUpdateState.name = "downloading"; + autoUpdateState.version = version; }, }, "download-for-update-failed": { handle: () => { - showInfoNotification("Download of update failed"); + //showInfoNotification("Download of update failed"); + autoUpdateState.name = "download-failed"; }, }, }; diff --git a/src/renderer/components/status-bar/auto-update-status-bar-item.tsx b/src/renderer/components/status-bar/auto-update-status-bar-item.tsx index 80c89364f3..ffa082da35 100644 --- a/src/renderer/components/status-bar/auto-update-status-bar-item.tsx +++ b/src/renderer/components/status-bar/auto-update-status-bar-item.tsx @@ -8,25 +8,39 @@ import React from "react"; import AutoUpdateStateInjectable from "../../../common/auto-update/auto-update-state.injectable"; import type { AutoUpdateState } from "../../../common/auto-update/auto-update-state.injectable"; import { Spinner } from "../spinner"; +import progressOfUpdateDownloadInjectable, { ProgressOfDownload } from "../../../common/application-update/progress-of-update-download/progress-of-update-download.injectable"; +import type { SyncBox } from "../../../common/utils/sync-box/sync-box-injection-token"; interface Dependencies { state: AutoUpdateState; + progressOfUpdateDownload: SyncBox; } -const checking = () => <>
{"Checking for updates"}
; +const checking = () => <>
{"Checking for updates..."}
; const available = () =>
{"Update is available"}
; +const notAvailable = () =>
{"No new updates available"}
; +const downloading = (state: AutoUpdateState, percentDone: number) => { + const {version } = state; -const notAvailable = () => { + if ( percentDone === 0 ) { + return <>
{`Download for version ${version} started `}
; + } - return
{"Update is currently not available"}
; + if ( percentDone < 100 ) { + return
{`Download for version ${version} ${percentDone}%...`}
; + } + + state.name = "download-succeeded"; + + return null; }; -const downloading = () =>
{"Downloading update"}
; const done = () =>
{"Done checking for updates"}
; - +const downloadFailed = (version: string | undefined) =>
{`Download for version ${version} failed`}
; +const downloadSucceeded = (version: string | undefined) =>
{`Download for version ${version} complete`}
; const idle = () => <>; -export const NonInjectedAutoUpdateComponent = observer(({ state }: Dependencies) => { +export const NonInjectedAutoUpdateComponent = observer(({ state, progressOfUpdateDownload }: Dependencies) => { switch(state.name) { case "checking": @@ -39,13 +53,19 @@ export const NonInjectedAutoUpdateComponent = observer(({ state }: Dependencies) return notAvailable(); case "downloading": - return downloading(); + const roundedPercentage = Math.round(progressOfUpdateDownload.value.get().percentage); + return downloading(state, roundedPercentage); case "done": return done(); - default: - case "idle": + case "download-failed": + return downloadFailed(state.version); + + case "download-succeeded": + return downloadSucceeded(state.version); + + case "idle": return idle(); } @@ -54,6 +74,7 @@ export const NonInjectedAutoUpdateComponent = observer(({ state }: Dependencies) export const AutoUpdateComponent = withInjectables(NonInjectedAutoUpdateComponent, { getProps: (di, props) => ({ state: di.inject(AutoUpdateStateInjectable), + progressOfUpdateDownload: di.inject(progressOfUpdateDownloadInjectable), ...props, }), }); diff --git a/src/renderer/ipc/register-ipc-listeners.injectable.ts b/src/renderer/ipc/register-ipc-listeners.injectable.ts index 6868943a56..a37f983769 100644 --- a/src/renderer/ipc/register-ipc-listeners.injectable.ts +++ b/src/renderer/ipc/register-ipc-listeners.injectable.ts @@ -5,14 +5,12 @@ import { getInjectable } from "@ogre-tools/injectable"; import { registerIpcListeners } from "./register-listeners"; import listNamespacesForbiddenHandlerInjectable from "./list-namespaces-forbidden-handler.injectable"; -import AutoUpdateStateInjectable from "../../common/auto-update/auto-update-state.injectable"; const registerIpcListenersInjectable = getInjectable({ id: "register-ipc-listeners", instantiate: (di) => registerIpcListeners({ listNamespacesForbiddenHandler: di.inject(listNamespacesForbiddenHandlerInjectable), - updateState: di.inject(AutoUpdateStateInjectable), }), });