Force update after thirty days since update was downloaded (#5776)

This commit is contained in:
Janne Savolainen authored and GitHub committed 2022-07-06 09:48:00 -04:00
1 parent eb6cc70143
commit 6e5c8e0427
12 files changed
+1280

No files matched your search

@@ -0,0 +1,36 @@
/**
* 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 { computed } from "mobx";
import { rootFrameChildComponentInjectionToken } from "../../frames/root-frame/root-frame-child-component-injection-token";
import { ForceUpdateModal } from "./force-update-modal";
import timeSinceUpdateWasDownloadedInjectable from "./time-since-update-was-downloaded.injectable";
import updateDownloadedDateTimeInjectable from "../../../common/application-update/update-downloaded-date-time/update-downloaded-date-time.injectable";
import timeAfterUpdateMustBeInstalledInjectable from "./time-after-update-must-be-installed.injectable";
const forceUpdateModalRootFrameComponentInjectable = getInjectable({
id: "force-update-modal-root-frame-component",
instantiate: (di) => {
const timeSinceUpdateWasDownloaded = di.inject(timeSinceUpdateWasDownloadedInjectable);
const updateDownloadedDateTime = di.inject(updateDownloadedDateTimeInjectable);
const timeWhenUpdateMustBeInstalled = di.inject(timeAfterUpdateMustBeInstalledInjectable);
return {
id: "force-update-modal",
Component: ForceUpdateModal,
shouldRender: computed(
() =>
!!updateDownloadedDateTime.value.get() &&
timeSinceUpdateWasDownloaded.get() >= timeWhenUpdateMustBeInstalled,
),
};
},
injectionToken: rootFrameChildComponentInjectionToken,
});
export default forceUpdateModalRootFrameComponentInjectable;
@@ -0,0 +1,25 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
$baseline: 8px;
.ForceUpdateModal {
background-color: white;
border-radius: 1 * $baseline;
padding: 3 * $baseline;
width: 50 * $baseline;
.header {
margin-bottom: 2 * $baseline;
}
.content {
margin-bottom: 2 * $baseline;
}
.footer {
display: flex;
justify-content: center;
}
}
@@ -0,0 +1,69 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { withInjectables } from "@ogre-tools/injectable-react";
import React from "react";
import restartAndInstallUpdateInjectable from "../../components/update-button/restart-and-install-update.injectable";
import { Countdown } from "../../components/countdown/countdown";
import type { IComputedValue } from "mobx";
import { observer } from "mobx-react";
import installUpdateCountdownInjectable from "./install-update-countdown.injectable";
import { Dialog } from "../../components/dialog";
import { Button } from "../../components/button";
import styles from "./force-update-modal.module.scss";
interface Dependencies {
restartAndInstallUpdate: () => void;
secondsTill: IComputedValue<number>;
}
const NonInjectedForceUpdateModal = observer(
({ restartAndInstallUpdate, secondsTill }: Dependencies) => (
<Dialog isOpen={true} pinned>
<div
data-testid="must-update-immediately"
className={styles.ForceUpdateModal}
>
<div className={styles.header}>
<h2>Please update</h2>
</div>
<div className={styles.content}>
<p>
An update to Lens Desktop is required to continue using the application.
</p>
</div>
<div className={styles.footer}>
<Button
primary
data-testid="update-now-from-must-update-immediately-modal"
onClick={restartAndInstallUpdate}
label="Update"
>
{" "}
(
<Countdown
secondsTill={secondsTill}
data-testid="countdown-to-automatic-update"
/>
)
</Button>
</div>
</div>
</Dialog>
),
);
export const ForceUpdateModal = withInjectables<Dependencies>(
NonInjectedForceUpdateModal,
{
getProps: (di, props) => ({
restartAndInstallUpdate: di.inject(restartAndInstallUpdateInjectable),
secondsTill: di.inject(installUpdateCountdownInjectable),
...props,
}),
},
);
@@ -0,0 +1,27 @@
/**
* 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 countdownStateInjectable from "../../components/countdown/countdown-state.injectable";
import secondsAfterInstallStartsInjectable from "./seconds-after-install-starts.injectable";
import restartAndInstallUpdateInjectable from "../../components/update-button/restart-and-install-update.injectable";
const installUpdateCountdownInjectable = getInjectable({
id: "install-update-countdown",
instantiate: (di) => {
const secondsAfterInstallStarts = di.inject(secondsAfterInstallStartsInjectable);
const restartAndInstallUpdate = di.inject(restartAndInstallUpdateInjectable);
return di.inject(countdownStateInjectable, {
startFrom: secondsAfterInstallStarts,
onZero: () => {
restartAndInstallUpdate();
},
});
},
});
export default installUpdateCountdownInjectable;
@@ -0,0 +1,12 @@
/**
* 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";
const secondsAfterInstallStartsInjectable = getInjectable({
id: "seconds-after-install-starts",
instantiate: () => 90,
});
export default secondsAfterInstallStartsInjectable;
@@ -0,0 +1,14 @@
/**
* 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";
const THIRTY_DAYS = 30 * 24 * 60 * 60 * 1000;
const timeAfterUpdateMustBeInstalledInjectable = getInjectable({
id: "time-after-update-must-be-installed",
instantiate: () => THIRTY_DAYS,
});
export default timeAfterUpdateMustBeInstalledInjectable;
@@ -0,0 +1,30 @@
/**
* 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 assert from "assert";
import { computed } from "mobx";
import moment from "moment";
import updateDownloadedDateTimeInjectable from "../../../common/application-update/update-downloaded-date-time/update-downloaded-date-time.injectable";
import { reactiveNow } from "../../../common/utils/reactive-now/reactive-now";
const timeSinceUpdateWasDownloadedInjectable = getInjectable({
id: "time-since-update-was-downloaded",
instantiate: (di) => {
const updateDownloadedDateTime = di.inject(updateDownloadedDateTimeInjectable);
return computed(() => {
const currentTimestamp = reactiveNow();
const downloadedAt = updateDownloadedDateTime.value.get();
assert(downloadedAt);
return currentTimestamp - (moment(downloadedAt).unix() * 1000);
});
},
});
export default timeSinceUpdateWasDownloadedInjectable;