From 90e46860a5a80d744312878e5a5840dff965fff5 Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Thu, 30 Jan 2025 16:46:17 +0100 Subject: [PATCH] ux: make toast info and hint info less disturbing (#272) --- .../src/app/library/hooks/useBooksSync.ts | 8 ++- apps/readest-app/src/app/library/page.tsx | 11 ++-- .../src/app/reader/components/BooksGrid.tsx | 2 + .../src/app/reader/components/HintInfo.tsx | 58 +++++++++++++++++++ .../src/app/reader/components/SectionInfo.tsx | 4 +- .../src/app/reader/hooks/useProgressSync.ts | 4 +- apps/readest-app/src/components/Toast.tsx | 14 ++++- 7 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 apps/readest-app/src/app/reader/components/HintInfo.tsx diff --git a/apps/readest-app/src/app/library/hooks/useBooksSync.ts b/apps/readest-app/src/app/library/hooks/useBooksSync.ts index 39184a59..4af4c679 100644 --- a/apps/readest-app/src/app/library/hooks/useBooksSync.ts +++ b/apps/readest-app/src/app/library/hooks/useBooksSync.ts @@ -18,6 +18,12 @@ export const useBooksSync = () => { syncBooks([], 'pull'); }; + const pushLibrary = async () => { + if (!user) return; + const newBooks = getNewBooks(); + syncBooks(newBooks, 'push'); + }; + useEffect(() => { if (!user) return; if (syncBooksPullingRef.current) return; @@ -104,5 +110,5 @@ export const useBooksSync = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [syncedBooks]); - return { pullLibrary }; + return { pullLibrary, pushLibrary }; }; diff --git a/apps/readest-app/src/app/library/page.tsx b/apps/readest-app/src/app/library/page.tsx index 38b9f4df..634c5323 100644 --- a/apps/readest-app/src/app/library/page.tsx +++ b/apps/readest-app/src/app/library/page.tsx @@ -52,7 +52,7 @@ const LibraryPage = () => { const demoBooks = useDemoBooks(); const containerRef = useRef(null); - const { pullLibrary } = useBooksSync(); + const { pullLibrary, pushLibrary } = useBooksSync(); usePullToRefresh(containerRef, pullLibrary); @@ -216,9 +216,11 @@ const LibraryPage = () => { setLoading(true); try { await appService?.uploadBook(book); - updateBook(envConfig, book); + await updateBook(envConfig, book); + pushLibrary(); eventDispatcher.dispatch('toast', { - type: 'success', + type: 'info', + timeout: 2000, message: _('Book uploaded: {{title}}', { title: book.title, }), @@ -241,7 +243,8 @@ const LibraryPage = () => { await appService?.downloadBook(book); updateBook(envConfig, book); eventDispatcher.dispatch('toast', { - type: 'success', + type: 'info', + timeout: 2000, message: _('Book downloaded: {{title}}', { title: book.title, }), diff --git a/apps/readest-app/src/app/reader/components/BooksGrid.tsx b/apps/readest-app/src/app/reader/components/BooksGrid.tsx index 27caaf4f..ec88e8dc 100644 --- a/apps/readest-app/src/app/reader/components/BooksGrid.tsx +++ b/apps/readest-app/src/app/reader/components/BooksGrid.tsx @@ -15,6 +15,7 @@ import Ribbon from './Ribbon'; import SettingsDialog from './settings/SettingsDialog'; import Annotator from './annotator/Annotator'; import FootnotePopup from './FootnotePopup'; +import HintInfo from './HintInfo'; interface BooksGridProps { bookKeys: string[]; @@ -76,6 +77,7 @@ const BooksGrid: React.FC = ({ bookKeys, onCloseBook }) => { {viewSettings.scrolled ? null : ( <> + = ({ bookKey, gapRight }) => { + const { isSideBarVisible } = useSidebarStore(); + const { isTrafficLightVisible } = useTrafficLight(); + const [hintMessage, setHintMessage] = React.useState(null); + const hintTimeout = useRef(2000); + const dismissTimeout = useRef | null>(null); + + const handleShowHint = (event: CustomEvent) => { + const { message, bookKey: hintBookKey, timeout = 2000 } = event.detail; + if (hintBookKey !== bookKey) return; + setHintMessage(message); + hintTimeout.current = timeout; + }; + + useEffect(() => { + eventDispatcher.on('hint', handleShowHint); + return () => { + eventDispatcher.off('hint', handleShowHint); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + if (dismissTimeout.current) clearTimeout(dismissTimeout.current); + dismissTimeout.current = setTimeout(() => setHintMessage(''), hintTimeout.current); + return () => { + if (dismissTimeout.current) clearTimeout(dismissTimeout.current); + }; + }, [hintMessage]); + + return ( +
+

+ {hintMessage || ''} +

+
+ ); +}; + +export default HintInfo; diff --git a/apps/readest-app/src/app/reader/components/SectionInfo.tsx b/apps/readest-app/src/app/reader/components/SectionInfo.tsx index 1f5ddcd9..b64c5739 100644 --- a/apps/readest-app/src/app/reader/components/SectionInfo.tsx +++ b/apps/readest-app/src/app/reader/components/SectionInfo.tsx @@ -15,12 +15,12 @@ const SectionInfo: React.FC = ({ section, gapLeft }) => { return (
-

+

{section || ''}

diff --git a/apps/readest-app/src/app/reader/hooks/useProgressSync.ts b/apps/readest-app/src/app/reader/hooks/useProgressSync.ts index 8925758a..f80e125d 100644 --- a/apps/readest-app/src/app/reader/hooks/useProgressSync.ts +++ b/apps/readest-app/src/app/reader/hooks/useProgressSync.ts @@ -118,8 +118,8 @@ export const useProgressSync = (bookKey: string) => { if (CFI.compare(configCFI, syncedCFI) < 0) { if (view) { view.goTo(syncedCFI); - eventDispatcher.dispatch('toast', { - type: 'success', + eventDispatcher.dispatch('hint', { + bookKey, message: _('Reading Progress Synced'), }); } diff --git a/apps/readest-app/src/components/Toast.tsx b/apps/readest-app/src/components/Toast.tsx index 5dfcd9a2..6d41cb02 100644 --- a/apps/readest-app/src/components/Toast.tsx +++ b/apps/readest-app/src/components/Toast.tsx @@ -48,14 +48,24 @@ export const Toast = () => { return ( toastMessage && ( -
+
- + {toastMessage}