mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
using the update syncBox injectables directly for status bar notifications
Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>
This commit is contained in:
parent
7cbcc184a0
commit
041141fe39
@ -10,7 +10,8 @@ export type ApplicationUpdateStatusEventId =
|
|||||||
| "checking-for-updates"
|
| "checking-for-updates"
|
||||||
| "no-updates-available"
|
| "no-updates-available"
|
||||||
| "download-for-update-started"
|
| "download-for-update-started"
|
||||||
| "download-for-update-failed";
|
| "download-for-update-failed"
|
||||||
|
| "download-for-update-succeeded";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||||
export type ApplicationUpdateStatusChannelMessage = { eventId: ApplicationUpdateStatusEventId; version?: string };
|
export type ApplicationUpdateStatusChannelMessage = { eventId: ApplicationUpdateStatusEventId; version?: string };
|
||||||
|
|||||||
@ -5,21 +5,21 @@
|
|||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import createSyncBoxInjectable from "../../utils/sync-box/create-sync-box.injectable";
|
import createSyncBoxInjectable from "../../utils/sync-box/create-sync-box.injectable";
|
||||||
import type { UpdateChannel } from "../update-channels";
|
import type { UpdateChannel } from "../update-channels";
|
||||||
|
import type { SyncBox } from "../../utils/sync-box/sync-box-injection-token";
|
||||||
import { syncBoxInjectionToken } from "../../utils/sync-box/sync-box-injection-token";
|
import { syncBoxInjectionToken } from "../../utils/sync-box/sync-box-injection-token";
|
||||||
|
|
||||||
|
export type DiscoveredUpdateVersion = SyncBox<{ version: string; updateChannel: UpdateChannel } | null>;
|
||||||
|
|
||||||
const discoveredUpdateVersionInjectable = getInjectable({
|
const discoveredUpdateVersionInjectable = getInjectable({
|
||||||
id: "discovered-update-version",
|
id: "discovered-update-version",
|
||||||
|
|
||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const createSyncBox = di.inject(createSyncBoxInjectable);
|
const createSyncBox = di.inject(createSyncBoxInjectable);
|
||||||
|
|
||||||
return createSyncBox<
|
return createSyncBox(
|
||||||
| { version: string; updateChannel: UpdateChannel }
|
|
||||||
| null
|
|
||||||
>(
|
|
||||||
"discovered-update-version",
|
"discovered-update-version",
|
||||||
null,
|
null,
|
||||||
);
|
) as DiscoveredUpdateVersion;
|
||||||
},
|
},
|
||||||
|
|
||||||
injectionToken: syncBoxInjectionToken,
|
injectionToken: syncBoxInjectionToken,
|
||||||
|
|||||||
@ -4,12 +4,15 @@
|
|||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import createSyncBoxInjectable from "../../utils/sync-box/create-sync-box.injectable";
|
import createSyncBoxInjectable from "../../utils/sync-box/create-sync-box.injectable";
|
||||||
|
import type { SyncBox } from "../../utils/sync-box/sync-box-injection-token";
|
||||||
import { syncBoxInjectionToken } from "../../utils/sync-box/sync-box-injection-token";
|
import { syncBoxInjectionToken } from "../../utils/sync-box/sync-box-injection-token";
|
||||||
|
|
||||||
export interface ProgressOfDownload {
|
export interface ProgressOfDownload {
|
||||||
percentage: number;
|
percentage: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ProgressOfUpdateDownload = SyncBox<ProgressOfDownload>;
|
||||||
|
|
||||||
const progressOfUpdateDownloadInjectable = getInjectable({
|
const progressOfUpdateDownloadInjectable = getInjectable({
|
||||||
id: "progress-of-update-download-state",
|
id: "progress-of-update-download-state",
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,11 @@
|
|||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import createSyncBoxInjectable from "../../utils/sync-box/create-sync-box.injectable";
|
import createSyncBoxInjectable from "../../utils/sync-box/create-sync-box.injectable";
|
||||||
|
import type { SyncBox } from "../../utils/sync-box/sync-box-injection-token";
|
||||||
import { syncBoxInjectionToken } from "../../utils/sync-box/sync-box-injection-token";
|
import { syncBoxInjectionToken } from "../../utils/sync-box/sync-box-injection-token";
|
||||||
|
|
||||||
|
export type UpdateIsBeingDownloaded = SyncBox<boolean>;
|
||||||
|
|
||||||
const updateIsBeingDownloadedInjectable = getInjectable({
|
const updateIsBeingDownloadedInjectable = getInjectable({
|
||||||
id: "update-is-being-downloaded",
|
id: "update-is-being-downloaded",
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,11 @@
|
|||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import createSyncBoxInjectable from "../../utils/sync-box/create-sync-box.injectable";
|
import createSyncBoxInjectable from "../../utils/sync-box/create-sync-box.injectable";
|
||||||
|
import type { SyncBox } from "../../utils/sync-box/sync-box-injection-token";
|
||||||
import { syncBoxInjectionToken } from "../../utils/sync-box/sync-box-injection-token";
|
import { syncBoxInjectionToken } from "../../utils/sync-box/sync-box-injection-token";
|
||||||
|
|
||||||
|
export type UpdatesAreBeingDiscovered = SyncBox<boolean>;
|
||||||
|
|
||||||
const updatesAreBeingDiscoveredInjectable = getInjectable({
|
const updatesAreBeingDiscoveredInjectable = getInjectable({
|
||||||
id: "updates-are-being-discovered",
|
id: "updates-are-being-discovered",
|
||||||
|
|
||||||
|
|||||||
@ -1,67 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
|
||||||
import { makeObservable, observable } from "mobx";
|
|
||||||
|
|
||||||
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;
|
|
||||||
@observable private _version: string | undefined = undefined;
|
|
||||||
|
|
||||||
constructor(state: AutoUpdateStateName = "idle") {
|
|
||||||
makeObservable(this);
|
|
||||||
|
|
||||||
this._state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
get name(): AutoUpdateStateName {
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
|
|
||||||
set name(state: AutoUpdateStateName) {
|
|
||||||
this._state = state;
|
|
||||||
|
|
||||||
this.triggerIdle();
|
|
||||||
}
|
|
||||||
|
|
||||||
get version(): string | undefined {
|
|
||||||
return this._version;
|
|
||||||
}
|
|
||||||
|
|
||||||
set version(version: string | undefined) {
|
|
||||||
this._version = version;
|
|
||||||
|
|
||||||
this.triggerIdle();
|
|
||||||
}
|
|
||||||
|
|
||||||
private triggerIdle(): void {
|
|
||||||
clearTimeout(timerId);
|
|
||||||
|
|
||||||
switch (this.name) {
|
|
||||||
case "checking":
|
|
||||||
case "available":
|
|
||||||
case "downloading":
|
|
||||||
case "idle":
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "done":
|
|
||||||
case "not-available":
|
|
||||||
case "download-failed":
|
|
||||||
case "download-succeeded":
|
|
||||||
timerId = setTimeout(() => this.name = "idle", 5000);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const AutoUpdateStateInjectable = getInjectable({
|
|
||||||
id: "auto-update-state",
|
|
||||||
instantiate: () => new AutoUpdateState("idle"),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default AutoUpdateStateInjectable;
|
|
||||||
@ -8,7 +8,6 @@ import applicationUpdateStatusChannelInjectable from "../../common/application-u
|
|||||||
//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 type { MessageChannelListener } from "../../common/utils/channel/message-channel-listener-injection-token";
|
||||||
import { messageChannelListenerInjectionToken } 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({
|
const applicationUpdateStatusListenerInjectable = getInjectable({
|
||||||
id: "application-update-status-listener",
|
id: "application-update-status-listener",
|
||||||
@ -16,35 +15,34 @@ const applicationUpdateStatusListenerInjectable = getInjectable({
|
|||||||
instantiate: (di): MessageChannelListener<ApplicationUpdateStatusChannel> => {
|
instantiate: (di): MessageChannelListener<ApplicationUpdateStatusChannel> => {
|
||||||
const channel = di.inject(applicationUpdateStatusChannelInjectable);
|
const channel = di.inject(applicationUpdateStatusChannelInjectable);
|
||||||
//const showInfoNotification = di.inject(showInfoNotificationInjectable);
|
//const showInfoNotification = di.inject(showInfoNotificationInjectable);
|
||||||
const autoUpdateState = di.inject(AutoUpdateStateInjectable);
|
|
||||||
|
|
||||||
const eventHandlers: Record<ApplicationUpdateStatusEventId, { handle: (version?: string) => void }> = {
|
const eventHandlers: Record<ApplicationUpdateStatusEventId, { handle: (version?: string) => void }> = {
|
||||||
"checking-for-updates": {
|
"checking-for-updates": {
|
||||||
handle: () => {
|
handle: () => {
|
||||||
//showInfoNotification("Checking for updates...");
|
//showInfoNotification("Checking for updates...");
|
||||||
autoUpdateState.name = "checking";
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
"no-updates-available": {
|
"no-updates-available": {
|
||||||
handle: () => {
|
handle: () => {
|
||||||
//showInfoNotification("No new updates available");
|
//showInfoNotification("No new updates available");
|
||||||
autoUpdateState.name = "not-available";
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
"download-for-update-started": {
|
"download-for-update-started": {
|
||||||
handle: (version) => {
|
handle: (/*version*/) => {
|
||||||
//showInfoNotification(`Download for version ${version} started...`);
|
//showInfoNotification(`Download for version ${version} started...`);
|
||||||
autoUpdateState.name = "downloading";
|
|
||||||
autoUpdateState.version = version;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
"download-for-update-failed": {
|
"download-for-update-failed": {
|
||||||
handle: () => {
|
handle: () => {
|
||||||
//showInfoNotification("Download of update failed");
|
//showInfoNotification("Download of update failed");
|
||||||
autoUpdateState.name = "download-failed";
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"download-for-update-succeeded": {
|
||||||
|
handle: () => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,30 +4,58 @@
|
|||||||
*/
|
*/
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import React from "react";
|
import assert from "assert";
|
||||||
import AutoUpdateStateInjectable from "../../../common/auto-update/auto-update-state.injectable";
|
import React, { useEffect, useState } from "react";
|
||||||
import type { AutoUpdateState } from "../../../common/auto-update/auto-update-state.injectable";
|
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
|
import type { ProgressOfUpdateDownload } from "../../../common/application-update/progress-of-update-download/progress-of-update-download.injectable";
|
||||||
import progressOfUpdateDownloadInjectable from "../../../common/application-update/progress-of-update-download/progress-of-update-download.injectable";
|
import progressOfUpdateDownloadInjectable from "../../../common/application-update/progress-of-update-download/progress-of-update-download.injectable";
|
||||||
import type { ProgressOfDownload } from "../../../common/application-update/progress-of-update-download/progress-of-update-download.injectable";
|
import type { DiscoveredUpdateVersion } from "../../../common/application-update/discovered-update-version/discovered-update-version.injectable";
|
||||||
import type { SyncBox } from "../../../common/utils/sync-box/sync-box-injection-token";
|
import discoveredUpdateVersionInjectable from "../../../common/application-update/discovered-update-version/discovered-update-version.injectable";
|
||||||
|
import type { UpdateIsBeingDownloaded } from "../../../common/application-update/update-is-being-downloaded/update-is-being-downloaded.injectable";
|
||||||
|
import updateIsBeingDownloadedInjectable from "../../../common/application-update/update-is-being-downloaded/update-is-being-downloaded.injectable";
|
||||||
|
import type { UpdatesAreBeingDiscovered } from "../../../common/application-update/updates-are-being-discovered/updates-are-being-discovered.injectable";
|
||||||
|
import updatesAreBeingDiscoveredInjectable from "../../../common/application-update/updates-are-being-discovered/updates-are-being-discovered.injectable";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
state: AutoUpdateState;
|
progressOfUpdateDownload: ProgressOfUpdateDownload;
|
||||||
progressOfUpdateDownload: SyncBox<ProgressOfDownload>;
|
discoveredVersionState: DiscoveredUpdateVersion;
|
||||||
|
downloadingUpdateState: UpdateIsBeingDownloaded;
|
||||||
|
checkingForUpdatesState: UpdatesAreBeingDiscovered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface EndNoteProps {
|
||||||
|
version?: string;
|
||||||
|
note: (version: string) => JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EndNote = ({ version, note }: EndNoteProps) => {
|
||||||
|
const [idling, setIdling] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timerId = setTimeout(() => setIdling(true), 5000);
|
||||||
|
|
||||||
|
return () => clearTimeout(timerId);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (idling) {
|
||||||
|
return idle();
|
||||||
|
}
|
||||||
|
|
||||||
|
return note(version ?? "");
|
||||||
|
};
|
||||||
|
|
||||||
const checking = () => (
|
const checking = () => (
|
||||||
<>
|
<>
|
||||||
<Spinner/>
|
<Spinner/>
|
||||||
<div>{"Checking for updates..."}</div>
|
<div>{"Checking for updates..."}</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
const available = () => <div>{"Update is available"}</div>;
|
|
||||||
const notAvailable = () => <div>{"No new updates available"}</div>;
|
|
||||||
const downloading = (state: AutoUpdateState, percentDone: number) => {
|
|
||||||
const { version } = state;
|
|
||||||
|
|
||||||
|
const available = (version: string) => <div>{`${version ?? "Update"} is available`}</div>;
|
||||||
|
|
||||||
|
const notAvailable = () => <div>{"No new updates available"}</div>;
|
||||||
|
|
||||||
|
const downloading = (version: string, percentDone: number) => {
|
||||||
if ( percentDone === 0 ) {
|
if ( percentDone === 0 ) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -37,57 +65,46 @@ const downloading = (state: AutoUpdateState, percentDone: number) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( percentDone < 100 ) {
|
|
||||||
return <div>{`Download for version ${version} ${percentDone}%...`}</div>;
|
return <div>{`Download for version ${version} ${percentDone}%...`}</div>;
|
||||||
}
|
|
||||||
|
|
||||||
state.name = "download-succeeded";
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const done = () => <div>{"Done checking for updates"}</div>;
|
const downloadSucceeded = (version: string) => <div>{`Download for version ${version} complete`}</div>;
|
||||||
const downloadFailed = (version: string | undefined) => <div>{`Download for version ${version} failed`}</div>;
|
|
||||||
const downloadSucceeded = (version: string | undefined) => <div>{`Download for version ${version} complete`}</div>;
|
|
||||||
const idle = () => <></>;
|
const idle = () => <></>;
|
||||||
|
|
||||||
export const NonInjectedAutoUpdateComponent = observer(({ state, progressOfUpdateDownload }: Dependencies) => {
|
export const NonInjectedAutoUpdateComponent = observer(({ progressOfUpdateDownload, discoveredVersionState, downloadingUpdateState, checkingForUpdatesState }: Dependencies) => {
|
||||||
|
const discoveredVersion = discoveredVersionState.value.get();
|
||||||
|
|
||||||
switch(state.name) {
|
if (downloadingUpdateState.value.get()) {
|
||||||
case "checking":
|
|
||||||
return checking();
|
|
||||||
|
|
||||||
case "available":
|
assert(discoveredVersion);
|
||||||
return available();
|
|
||||||
|
|
||||||
case "not-available":
|
|
||||||
return notAvailable();
|
|
||||||
|
|
||||||
case "downloading": {
|
|
||||||
const roundedPercentage = Math.round(progressOfUpdateDownload.value.get().percentage);
|
const roundedPercentage = Math.round(progressOfUpdateDownload.value.get().percentage);
|
||||||
|
|
||||||
return downloading(state, roundedPercentage);
|
if ( roundedPercentage > 99 ) {
|
||||||
|
return <EndNote note={downloadSucceeded} version={discoveredVersion.version} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "done":
|
return downloading(discoveredVersion.version, roundedPercentage);
|
||||||
return done();
|
|
||||||
|
|
||||||
case "download-failed":
|
|
||||||
return downloadFailed(state.version);
|
|
||||||
|
|
||||||
case "download-succeeded":
|
|
||||||
return downloadSucceeded(state.version);
|
|
||||||
|
|
||||||
case "idle":
|
|
||||||
return idle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (checkingForUpdatesState.value.get()) {
|
||||||
|
return checking();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( discoveredVersion) {
|
||||||
|
return <EndNote note={available} version={discoveredVersion.version} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <EndNote note={notAvailable} />;
|
||||||
});
|
});
|
||||||
|
|
||||||
export const AutoUpdateComponent = withInjectables<Dependencies>(NonInjectedAutoUpdateComponent, {
|
export const AutoUpdateComponent = withInjectables<Dependencies>(NonInjectedAutoUpdateComponent, {
|
||||||
getProps: (di, props) => ({
|
getProps: (di, props) => ({
|
||||||
state: di.inject(AutoUpdateStateInjectable),
|
|
||||||
progressOfUpdateDownload: di.inject(progressOfUpdateDownloadInjectable),
|
progressOfUpdateDownload: di.inject(progressOfUpdateDownloadInjectable),
|
||||||
|
discoveredVersionState: di.inject(discoveredUpdateVersionInjectable),
|
||||||
|
downloadingUpdateState: di.inject(updateIsBeingDownloadedInjectable),
|
||||||
|
checkingForUpdatesState: di.inject(updatesAreBeingDiscoveredInjectable),
|
||||||
...props,
|
...props,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user