From 9c2e70c7e63d67cc2aee4fa779f2a938a08c7538 Mon Sep 17 00:00:00 2001 From: yanguoyu <841185308@qq.com> Date: Mon, 24 Jul 2023 10:29:34 +0800 Subject: [PATCH] refactor: Refactor update logic --- .../src/components/GeneralSetting/hooks.ts | 46 ++++++++ .../src/components/GeneralSetting/index.tsx | 105 +++++------------- .../neuron-ui/src/containers/Navbar/index.tsx | 21 ++-- packages/neuron-ui/src/locales/en.json | 2 +- packages/neuron-ui/src/locales/zh-tw.json | 2 +- packages/neuron-ui/src/locales/zh.json | 2 +- packages/neuron-wallet/src/controllers/api.ts | 2 +- .../neuron-wallet/src/controllers/update.ts | 61 +++++----- .../src/models/subjects/app-updater.ts | 6 +- 9 files changed, 124 insertions(+), 123 deletions(-) create mode 100644 packages/neuron-ui/src/components/GeneralSetting/hooks.ts diff --git a/packages/neuron-ui/src/components/GeneralSetting/hooks.ts b/packages/neuron-ui/src/components/GeneralSetting/hooks.ts new file mode 100644 index 0000000000..0551a62c5c --- /dev/null +++ b/packages/neuron-ui/src/components/GeneralSetting/hooks.ts @@ -0,0 +1,46 @@ +import { Dispatch, SetStateAction, useCallback, useMemo, useState } from 'react' +import { cancelCheckUpdates, cancelDownloadUpdate, checkForUpdates } from 'services/remote' + +export const useUpdateDownloadStatus = ({ + setShowCheckDialog, + downloadProgress, +}: { + setShowCheckDialog: Dispatch> + downloadProgress: number +}) => { + const [showUpdateDownloadStatus, setShowUpdateDownloadStatus] = useState(false) + const openShowUpdateDownloadStatus = useCallback(() => { + setShowUpdateDownloadStatus(true) + }, []) + const onCheckUpdate = useCallback(() => { + setShowCheckDialog(true) + checkForUpdates() + }, [setShowCheckDialog]) + const hasStartDownload = useMemo(() => downloadProgress >= 0, [downloadProgress]) + return { + showUpdateDownloadStatus, + openShowUpdateDownloadStatus, + onCheckUpdate, + onCancel: useCallback(() => { + if (hasStartDownload) { + cancelDownloadUpdate() + } + setShowUpdateDownloadStatus(false) + }, [hasStartDownload]), + } +} + +export const useCheckUpdate = () => { + const [showCheckDialog, setShowCheckDialog] = useState(false) + const onCancelCheckUpdates = useCallback(() => { + if (showCheckDialog) { + cancelCheckUpdates() + } + setShowCheckDialog(false) + }, [showCheckDialog]) + return { + showCheckDialog, + setShowCheckDialog, + onCancelCheckUpdates, + } +} diff --git a/packages/neuron-ui/src/components/GeneralSetting/index.tsx b/packages/neuron-ui/src/components/GeneralSetting/index.tsx index 8c53edc133..312bccca56 100644 --- a/packages/neuron-ui/src/components/GeneralSetting/index.tsx +++ b/packages/neuron-ui/src/components/GeneralSetting/index.tsx @@ -6,21 +6,15 @@ import LanguageDialog from 'components/LanguageDialog' import AlertDialog from 'widgets/AlertDialog' import { ReactComponent as VersionLogo } from 'widgets/Icons/VersionLogo.svg' import { ReactComponent as ArrowNext } from 'widgets/Icons/ArrowNext.svg' -import { - checkForUpdates, - cancelCheckUpdates, - downloadUpdate, - cancelDownloadUpdate, - installUpdate, - getVersion, -} from 'services/remote' +import { cancelCheckUpdates, downloadUpdate, installUpdate, getVersion } from 'services/remote' import { uniformTimeFormatter, bytesFormatter, clsx } from 'utils' import { LanguageSelect } from 'widgets/Icons/icon' import styles from './generalSetting.module.scss' +import { useCheckUpdate, useUpdateDownloadStatus } from './hooks' interface UpdateDownloadStatusProps { show: boolean - onCancel: (status?: string) => void + onCancel: () => void progress: number newVersion: string releaseDate: string @@ -69,7 +63,7 @@ const UpdateDownloadStatus = ({ onConfirm={handleConfirm} disabled={!available} confirmText={t('updates.install-update')} - onCancel={() => onCancel('checked')} + onCancel={onCancel} title={t('updates.update-available')} confirmProps={{ 'data-method': 'download', @@ -135,76 +129,45 @@ const GeneralSetting = ({ updater }: GeneralSettingProps) => { const [showLangDialog, setShowLangDialog] = useState(false) const [searchParams] = useSearchParams() const [errorMsg, setErrorMsg] = useState('') - const [dialogType, setDialogType] = useState<'' | 'checking' | 'checked' | 'updating' | 'updated'>('') - const [isFetchUpdateByClick, setIsFetchUpdateByClick] = useState(false) - const { version: newVersion } = updater + const { showCheckDialog, setShowCheckDialog, onCancelCheckUpdates } = useCheckUpdate() + const { version: newVersion, checking, downloadProgress } = updater + const { showUpdateDownloadStatus, openShowUpdateDownloadStatus, onCheckUpdate, onCancel } = useUpdateDownloadStatus({ + setShowCheckDialog, + downloadProgress, + }) - const version = useMemo(() => { + useEffect(() => { + if (showCheckDialog && newVersion) { + setShowCheckDialog(false) + openShowUpdateDownloadStatus() + } + }, [showCheckDialog, newVersion, openShowUpdateDownloadStatus, setShowCheckDialog]) + + const currentVersion = useMemo(() => { return getVersion() }, []) useEffect(() => { const checkUpdate = searchParams.get('checkUpdate') if (checkUpdate === '1') { - checkForUpdates() - setIsFetchUpdateByClick(true) + onCheckUpdate() } - return () => setIsFetchUpdateByClick(false) - }, [searchParams, checkForUpdates]) + }, [searchParams, onCheckUpdate]) useEffect(() => { if (updater.errorMsg) { setErrorMsg(updater.errorMsg) cancelCheckUpdates() - return - } - if (updater.isUpdated) { - setDialogType('updated') - return } - if (updater.checking) { - setDialogType('checking') - return - } - if (newVersion) { - setDialogType('checked') - return - } - if (updater.downloadProgress > 0) { - setDialogType('updating') - return - } - setDialogType('') - }, [updater, setDialogType, setErrorMsg]) - - const handleUpdate = useCallback( - (e: React.SyntheticEvent) => { - const { - dataset: { method }, - } = e.target as HTMLElement - - setIsFetchUpdateByClick(true) - if (newVersion) { - setDialogType('checked') - } else if (method === 'cancelCheck') { - if (dialogType === 'checking') { - cancelCheckUpdates() - } - setDialogType('') - } else if (method === 'check') { - checkForUpdates() - } - }, - [dialogType, setDialogType, cancelCheckUpdates, checkForUpdates] - ) + }, [updater.errorMsg, setErrorMsg]) return (

- {t('settings.general.version')} v{newVersion || version} + {t('settings.general.version')} v{newVersion || currentVersion}

-
@@ -228,37 +191,27 @@ const GeneralSetting = ({ updater }: GeneralSettingProps) => { message={errorMsg} type="failed" onCancel={() => { - setIsFetchUpdateByClick(false) setErrorMsg('') }} />
-

{t(dialogType === 'checking' ? 'updates.checking-updates' : 'updates.update-not-available')}

+

{t(checking || newVersion ? 'updates.checking-updates' : 'updates.update-not-available')}

{ - if (status !== 'checked') { - cancelDownloadUpdate() - } - setIsFetchUpdateByClick(false) - setDialogType('') - }} + show={showUpdateDownloadStatus} + onCancel={onCancel} progress={updater.downloadProgress} progressInfo={updater.progressInfo} newVersion={updater.version} diff --git a/packages/neuron-ui/src/containers/Navbar/index.tsx b/packages/neuron-ui/src/containers/Navbar/index.tsx index f765c0137c..443d0230aa 100644 --- a/packages/neuron-ui/src/containers/Navbar/index.tsx +++ b/packages/neuron-ui/src/containers/Navbar/index.tsx @@ -68,6 +68,8 @@ const MenuButton = ({ ) } +const ONE_DAY_MILLISECONDS = 24 * 3600 * 1000 + const Navbar = () => { const { pathname } = useLocation() const dispatch = useDispatch() @@ -94,21 +96,14 @@ const Navbar = () => { }, [dispatch]) useEffect(() => { - const now = new Date() - const nextTriggerTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59) - checkForUpdates() - if (nextTriggerTime) { - const timeDiff = nextTriggerTime.getTime() - now.getTime() - - setTimeout(() => { - checkForUpdates() - setInterval(() => { - checkForUpdates() - }, 24 * 60 * 60 * 1000) - }, timeDiff) + const interval = setInterval(() => { + checkForUpdates() + }, ONE_DAY_MILLISECONDS) + return () => { + clearInterval(interval) } - }, [checkForUpdates]) + }, []) useEffect(() => { if (pathname.includes(RoutePath.Settings)) { diff --git a/packages/neuron-ui/src/locales/en.json b/packages/neuron-ui/src/locales/en.json index 9450151e06..1c3cf8d443 100644 --- a/packages/neuron-ui/src/locales/en.json +++ b/packages/neuron-ui/src/locales/en.json @@ -740,7 +740,7 @@ "downloading-update": "Downloading update...", "update-not-available": "There are currently no updates available.", "updates-found-do-you-want-to-update": "An update ({{version}}) is available", - "install-update": "Install Update", + "install-update": "Immediate Update", "updates-downloaded-about-to-quit-and-install": "Update downloaded. Ready to install and relaunch.", "quit-and-install": "Install and relaunch" }, diff --git a/packages/neuron-ui/src/locales/zh-tw.json b/packages/neuron-ui/src/locales/zh-tw.json index 4a437feb2e..5aef09ccab 100644 --- a/packages/neuron-ui/src/locales/zh-tw.json +++ b/packages/neuron-ui/src/locales/zh-tw.json @@ -711,7 +711,7 @@ "downloading-update": "正在下載更新…", "update-not-available": "當前是最新版本", "updates-found-do-you-want-to-update": "新版本 {{version}} 可供下載", - "install-update": "安裝更新", + "install-update": "立即更新", "updates-downloaded-about-to-quit-and-install": "下載完成。請安裝新版本。", "quit-and-install": "安裝並重啓應用" }, diff --git a/packages/neuron-ui/src/locales/zh.json b/packages/neuron-ui/src/locales/zh.json index 2d00fcaf72..936882fae2 100644 --- a/packages/neuron-ui/src/locales/zh.json +++ b/packages/neuron-ui/src/locales/zh.json @@ -733,7 +733,7 @@ "downloading-update": "正在下载更新...", "update-not-available": "当前是最新版本", "updates-found-do-you-want-to-update": "新版本 {{version}} 可供下载", - "install-update": "安装更新", + "install-update": "立即更新", "updates-downloaded-about-to-quit-and-install": "下载完成。请安装新版本。", "quit-and-install": "安装并重启应用" }, diff --git a/packages/neuron-wallet/src/controllers/api.ts b/packages/neuron-wallet/src/controllers/api.ts index 8ccd7626ec..a169c79375 100644 --- a/packages/neuron-wallet/src/controllers/api.ts +++ b/packages/neuron-wallet/src/controllers/api.ts @@ -555,7 +555,7 @@ export default class ApiController { }) handle('download-update', async () => { - new UpdateController(false).downloadUpdate() + new UpdateController(true).downloadUpdate() }) handle('cancel-download-update', async () => { diff --git a/packages/neuron-wallet/src/controllers/update.ts b/packages/neuron-wallet/src/controllers/update.ts index d63301220c..e67a19d26d 100644 --- a/packages/neuron-wallet/src/controllers/update.ts +++ b/packages/neuron-wallet/src/controllers/update.ts @@ -1,11 +1,13 @@ import { autoUpdater, UpdateInfo, CancellationToken } from 'electron-updater' -import AppUpdaterSubject from '../models/subjects/app-updater' +import AppUpdaterSubject, { AppUpdater } from '../models/subjects/app-updater' export default class UpdateController { static isChecking = false // One instance is already running and checking static downCancellationToken = new CancellationToken() + static lastNotifyInfo: AppUpdater + constructor(check: boolean = true) { autoUpdater.autoDownload = false @@ -34,14 +36,14 @@ export default class UpdateController { } public downloadUpdate() { - this.notify(0) + this.notify({ ...UpdateController.lastNotifyInfo, progressInfo: null, downloadProgress: 0 }) UpdateController.downCancellationToken = new CancellationToken() autoUpdater.downloadUpdate(UpdateController.downCancellationToken) } public cancelDownloadUpdate() { UpdateController.downCancellationToken.cancel() - this.notify() + this.notify({ ...UpdateController.lastNotifyInfo, progressInfo: null, downloadProgress: -1 }) autoUpdater.removeAllListeners() } @@ -50,54 +52,57 @@ export default class UpdateController { autoUpdater.on('error', error => { UpdateController.isChecking = false - this.notify(-1, null, false, '', '', '', error == null ? 'unknown' : (error.stack || error).toString()) + this.notify({ + version: '', + releaseDate: '', + releaseNotes: '', + errorMsg: error == null ? 'unknown' : (error.stack || error).toString(), + }) }) autoUpdater.on('update-available', (info: UpdateInfo) => { if (UpdateController.isChecking) { UpdateController.isChecking = false - this.notify(-1, null, false, info.version, info.releaseDate, info.releaseNotes as string) + this.notify({ + version: info.version, + releaseDate: info.releaseDate, + releaseNotes: info.releaseNotes as string, + }) } }) autoUpdater.on('update-not-available', () => { if (UpdateController.isChecking) { UpdateController.isChecking = false - this.notify(-1, null, true) + this.notify({ isUpdated: true }) } }) - autoUpdater.on('download-progress', progress => { - const progressPercent = progress.percent / 100 + autoUpdater.on('download-progress', progressInfo => { + const progressPercent = progressInfo.percent / 100 if (progressPercent !== 1) { - this.notify(progressPercent, progress) + this.notify({ ...UpdateController.lastNotifyInfo, downloadProgress: progressPercent, progressInfo }) } }) autoUpdater.on('update-downloaded', () => { UpdateController.isChecking = false - this.notify(1) + this.notify({ ...UpdateController.lastNotifyInfo, downloadProgress: 1 }) }) } - private notify( - downloadProgress: number = -1, - progressInfo = null, - isUpdated = false, - version = '', - releaseDate = '', - releaseNotes = '', - errorMsg = '' - ) { - AppUpdaterSubject.next({ - downloadProgress, - progressInfo, - isUpdated, - version, - releaseDate, - releaseNotes, - errorMsg, + private notify(appUpdater?: Partial>) { + UpdateController.lastNotifyInfo = { + downloadProgress: -1, + progressInfo: null, + isUpdated: false, + version: '', + releaseDate: '', + releaseNotes: '', + errorMsg: '', + ...appUpdater, checking: UpdateController.isChecking, - }) + } + AppUpdaterSubject.next(UpdateController.lastNotifyInfo) } } diff --git a/packages/neuron-wallet/src/models/subjects/app-updater.ts b/packages/neuron-wallet/src/models/subjects/app-updater.ts index 11a5aadac3..dc7d3af22f 100644 --- a/packages/neuron-wallet/src/models/subjects/app-updater.ts +++ b/packages/neuron-wallet/src/models/subjects/app-updater.ts @@ -1,6 +1,6 @@ import { Subject } from 'rxjs' -const AppUpdaterSubject = new Subject<{ +export interface AppUpdater { checking: boolean isUpdated: boolean downloadProgress: number // -1: not started, 1: finished, 0~1: downloading @@ -13,6 +13,8 @@ const AppUpdaterSubject = new Subject<{ releaseDate: string releaseNotes: string errorMsg: string -}>() +} + +const AppUpdaterSubject = new Subject() export default AppUpdaterSubject