diff --git a/apps/web/src/dialogs/settings/other-settings.ts b/apps/web/src/dialogs/settings/other-settings.ts index 90c6e9ea2..d6724211c 100644 --- a/apps/web/src/dialogs/settings/other-settings.ts +++ b/apps/web/src/dialogs/settings/other-settings.ts @@ -21,10 +21,11 @@ import { SettingsGroup } from "./types"; import { appVersion } from "../../utils/version"; import { writeText } from "clipboard-polyfill"; import { showToast } from "../../utils/toast"; -import { checkForUpdate } from "../../utils/updater"; +import { checkForUpdate, downloadUpdate } from "../../utils/updater"; import { isMacStoreApp } from "../../utils/platform"; import { showIssueDialog } from "../../common/dialog-controller"; import { clearLogs, downloadLogs } from "../../utils/logger"; +import { useAutoUpdateStore } from "../../hooks/use-auto-updater"; export const AboutSettings: SettingsGroup[] = [ { @@ -35,24 +36,41 @@ export const AboutSettings: SettingsGroup[] = [ { key: "version", title: "Version", - description: appVersion.formatted, - components: [ - { - type: "button", - action: checkForUpdate, - title: "Check for updates", - variant: "secondary" - }, - { - type: "button", - action: async () => { - await writeText(appVersion.formatted); - showToast("info", "Copied to clipboard!"); - }, - title: "Copy", - variant: "secondary" - } - ] + description: () => { + const status = useAutoUpdateStore.getState().status; + if (status?.type === "available") + return `New version (v${status.version}) is available for download.`; + return appVersion.formatted; + }, + onStateChange: (listener) => + useAutoUpdateStore.subscribe((s) => s.status, listener), + components: () => { + const status = useAutoUpdateStore.getState().status; + return [ + status?.type === "available" + ? { + type: "button", + action: downloadUpdate, + title: `Install update`, + variant: "secondary" + } + : { + type: "button", + action: checkForUpdate, + title: "Check for updates", + variant: "secondary" + }, + { + type: "button", + action: async () => { + await writeText(appVersion.formatted); + showToast("info", "Copied to clipboard!"); + }, + title: "Copy", + variant: "secondary" + } + ]; + } }, { key: "roadmap", @@ -119,7 +137,8 @@ export const AboutSettings: SettingsGroup[] = [ components: [ { type: "button", - action: () => void window.open("https://fosstodon.org/@notesnook", "_blank"), + action: () => + void window.open("https://fosstodon.org/@notesnook", "_blank"), title: "Follow", variant: "secondary" } diff --git a/apps/web/src/hooks/use-auto-updater.ts b/apps/web/src/hooks/use-auto-updater.ts index 28fa374e2..b1088a089 100644 --- a/apps/web/src/hooks/use-auto-updater.ts +++ b/apps/web/src/hooks/use-auto-updater.ts @@ -17,10 +17,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import { checkForUpdate } from "../utils/updater"; import { AppEventManager, AppEvents } from "../common/app-events"; +import BaseStore from "../stores"; +import createStore from "../common/store"; type CompletedUpdateStatus = { type: "completed"; version: string }; type DownloadingUpdateStatus = { type: "downloading"; progress: number }; @@ -32,9 +34,18 @@ export type UpdateStatus = | DownloadingUpdateStatus | GenericUpdateStatus; +class AutoUpdateStore extends BaseStore { + status?: UpdateStatus; + setStatus = (status?: UpdateStatus) => { + this.set({ status }); + }; +} + +const [useAutoUpdateStore] = createStore(AutoUpdateStore); + let checkingForUpdateTimeout = 0; export function useAutoUpdater() { - const [status, setStatus] = useState(); + const { status, setStatus } = useAutoUpdateStore(); useEffect(() => { function changeStatus(status?: UpdateStatus) { @@ -104,3 +115,5 @@ export function useAutoUpdater() { return status; } + +export { useAutoUpdateStore };