From 365f28fee50b1292ad4f975ae51507c9538acadf Mon Sep 17 00:00:00 2001 From: amr Date: Mon, 18 Apr 2022 10:26:36 +0200 Subject: [PATCH] added an update checker button for library (#172) * added an update checker button for library * fixed import path * fixed progress props to not be inline * added error handling * fixed linting issue --- src/components/library/UpdateChecker.tsx | 67 ++++++++++++++++++++++++ src/screens/Library.tsx | 2 + src/typings.d.ts | 9 ++++ 3 files changed, 78 insertions(+) create mode 100644 src/components/library/UpdateChecker.tsx diff --git a/src/components/library/UpdateChecker.tsx b/src/components/library/UpdateChecker.tsx new file mode 100644 index 00000000..678cb94a --- /dev/null +++ b/src/components/library/UpdateChecker.tsx @@ -0,0 +1,67 @@ +import React, { useEffect, useState } from 'react'; +import IconButton from '@mui/material/IconButton'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import CircularProgress from '@mui/material/CircularProgress'; +import { Box } from '@mui/system'; +import Typography from '@mui/material/Typography'; +import client from 'util/client'; +import makeToast from '../util/Toast'; + +interface IProgressProps { + progress: number +} + +function Progress({ progress }: IProgressProps) { + return ( + + + + + {`${Math.round(progress)}%`} + + + + + ); +} + +const baseWebsocketUrl = JSON.parse(window.localStorage.getItem('serverBaseURL')!).replace('http', 'ws'); + +function UpdateChecker() { + const [loading, setLoading] = useState(false); + const [progress, setProgress] = useState(0); + + const onClick = async () => { + try { + setLoading(true); + setProgress(0); + await client.post('/api/v1/update/fetch'); + } catch (e) { + makeToast('Checking for updates failed!', 'error'); + setLoading(false); + } + }; + + useEffect(() => { + const wsc = new WebSocket(`${baseWebsocketUrl}/api/v1/update`); + wsc.onmessage = (e) => { + const data = JSON.parse(e.data) as IUpdateStatus; + const { COMPLETE, RUNNING, PENDING } = data.statusMap; + + setLoading(data.running); + const currentProgress = 100 * (COMPLETE / (COMPLETE + RUNNING + PENDING)); + + setProgress(Number.isNaN(currentProgress) ? 0 : currentProgress); + }; + + return () => wsc.close(); + }, []); + + return ( + + {loading ? : } + + ); +} + +export default UpdateChecker; diff --git a/src/screens/Library.tsx b/src/screens/Library.tsx index baa2be63..f904c043 100644 --- a/src/screens/Library.tsx +++ b/src/screens/Library.tsx @@ -17,6 +17,7 @@ import LibraryOptions from 'components/library/LibraryOptions'; import LibraryMangaGrid from 'components/library/LibraryMangaGrid'; import AppbarSearch from 'components/util/AppbarSearch'; import { useQueryParam, NumberParam } from 'use-query-params'; +import UpdateChecker from '../components/library/UpdateChecker'; interface IMangaCategory { category: ICategory @@ -31,6 +32,7 @@ export default function Library() { <> + , ); }, []); diff --git a/src/typings.d.ts b/src/typings.d.ts index 327a7af3..0938eee6 100644 --- a/src/typings.d.ts +++ b/src/typings.d.ts @@ -187,6 +187,15 @@ interface IQueue { queue: IDownloadChapter[] } +interface IUpdateStatus { + running: boolean + statusMap: { + COMPLETE: number, + RUNNING: number, + PENDING: number + } +} + interface PreferenceProps { key: string title: string