From ccd467ebcf0dc920aadb0df581573f0eab44e321 Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Fri, 11 Apr 2025 09:40:26 +0800 Subject: [PATCH] feat: support separate header/footer visibility for paginated and scrolled modes (#859) --- .../public/locales/ar/translation.json | 4 +- .../public/locales/de/translation.json | 4 +- .../public/locales/el/translation.json | 4 +- .../public/locales/es/translation.json | 4 +- .../public/locales/fr/translation.json | 4 +- .../public/locales/hi/translation.json | 4 +- .../public/locales/id/translation.json | 4 +- .../public/locales/it/translation.json | 4 +- .../public/locales/ja/translation.json | 4 +- .../public/locales/ko/translation.json | 4 +- .../public/locales/pl/translation.json | 4 +- .../public/locales/pt/translation.json | 4 +- .../public/locales/ru/translation.json | 4 +- .../public/locales/tr/translation.json | 4 +- .../public/locales/uk/translation.json | 4 +- .../public/locales/vi/translation.json | 4 +- .../public/locales/zh-CN/translation.json | 4 +- .../public/locales/zh-TW/translation.json | 4 +- .../src/app/reader/components/BooksGrid.tsx | 53 +++++---- .../src/app/reader/components/FooterBar.tsx | 2 +- .../src/app/reader/components/HeaderBar.tsx | 106 +++++++++++------- .../src/app/reader/components/HintInfo.tsx | 49 ++++---- .../src/app/reader/components/PageInfo.tsx | 4 +- .../src/app/reader/components/SectionInfo.tsx | 55 +++++---- .../components/settings/LayoutPanel.tsx | 59 +++++++--- .../src/app/reader/hooks/useIframeEvents.ts | 6 +- apps/readest-app/src/services/constants.ts | 1 + apps/readest-app/src/types/book.ts | 1 + apps/readest-app/src/utils/config.ts | 3 +- 29 files changed, 264 insertions(+), 147 deletions(-) diff --git a/apps/readest-app/public/locales/ar/translation.json b/apps/readest-app/public/locales/ar/translation.json index 7d973df1..6ec0673b 100644 --- a/apps/readest-app/public/locales/ar/translation.json +++ b/apps/readest-app/public/locales/ar/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} ساعة", "{{value}} hours": "{{value}} ساعات", "CJK Font": "خط CJK", - "Clear Search": "مسح البحث" + "Clear Search": "مسح البحث", + "Header & Footer": "الرأس والتذييل", + "Apply also in Scrolled Mode": "تطبيق أيضًا في وضع التمرير" } diff --git a/apps/readest-app/public/locales/de/translation.json b/apps/readest-app/public/locales/de/translation.json index 5bcba975..6f2dfc5b 100644 --- a/apps/readest-app/public/locales/de/translation.json +++ b/apps/readest-app/public/locales/de/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} Stunde", "{{value}} hours": "{{value}} Stunden", "CJK Font": "CJK-Schriftart", - "Clear Search": "Suche löschen" + "Clear Search": "Suche löschen", + "Header & Footer": "Kopf- & Fußzeile", + "Apply also in Scrolled Mode": "Auch im Scroll-Modus anwenden" } diff --git a/apps/readest-app/public/locales/el/translation.json b/apps/readest-app/public/locales/el/translation.json index 62352924..edb2d1d5 100644 --- a/apps/readest-app/public/locales/el/translation.json +++ b/apps/readest-app/public/locales/el/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} ώρα", "{{value}} hours": "{{value}} ώρες", "CJK Font": "Γραμματοσειρά CJK", - "Clear Search": "Καθαρισμός αναζήτησης" + "Clear Search": "Καθαρισμός αναζήτησης", + "Header & Footer": "Κεφαλίδα & Υποσέλιδο", + "Apply also in Scrolled Mode": "Εφαρμογή και σε λειτουργία κύλισης" } diff --git a/apps/readest-app/public/locales/es/translation.json b/apps/readest-app/public/locales/es/translation.json index 05745a39..091baef8 100644 --- a/apps/readest-app/public/locales/es/translation.json +++ b/apps/readest-app/public/locales/es/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} hora", "{{value}} hours": "{{value}} horas", "CJK Font": "Fuente CJK", - "Clear Search": "Limpiar búsqueda" + "Clear Search": "Limpiar búsqueda", + "Header & Footer": "Encabezado y pie de página", + "Apply also in Scrolled Mode": "Aplicar también en modo desplazamiento" } diff --git a/apps/readest-app/public/locales/fr/translation.json b/apps/readest-app/public/locales/fr/translation.json index 8258e094..ed979381 100644 --- a/apps/readest-app/public/locales/fr/translation.json +++ b/apps/readest-app/public/locales/fr/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} heure", "{{value}} hours": "{{value}} heures", "CJK Font": "Police CJK", - "Clear Search": "Effacer la recherche" + "Clear Search": "Effacer la recherche", + "Header & Footer": "En-tête et pied de page", + "Apply also in Scrolled Mode": "Appliquer également en mode défilement" } diff --git a/apps/readest-app/public/locales/hi/translation.json b/apps/readest-app/public/locales/hi/translation.json index 0e426f3b..34c167d6 100644 --- a/apps/readest-app/public/locales/hi/translation.json +++ b/apps/readest-app/public/locales/hi/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} घंटा", "{{value}} hours": "{{value}} घंटे", "CJK Font": "CJK फ़ॉन्ट", - "Clear Search": "खोज साफ करें" + "Clear Search": "खोज साफ करें", + "Header & Footer": "हेडर और फ़ुटर", + "Apply also in Scrolled Mode": "स्क्रॉल मोड में भी लागू करें" } diff --git a/apps/readest-app/public/locales/id/translation.json b/apps/readest-app/public/locales/id/translation.json index 278418f9..ca68a7e0 100644 --- a/apps/readest-app/public/locales/id/translation.json +++ b/apps/readest-app/public/locales/id/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} jam", "{{value}} hours": "{{value}} jam", "CJK Font": "Font CJK", - "Clear Search": "Hapus Pencarian" + "Clear Search": "Hapus Pencarian", + "Header & Footer": "Header & Footer", + "Apply also in Scrolled Mode": "Terapkan juga di Mode Gulir" } diff --git a/apps/readest-app/public/locales/it/translation.json b/apps/readest-app/public/locales/it/translation.json index 6cb29f2e..7787557f 100644 --- a/apps/readest-app/public/locales/it/translation.json +++ b/apps/readest-app/public/locales/it/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} ora", "{{value}} hours": "{{value}} ore", "CJK Font": "Font CJK", - "Clear Search": "Cancella ricerca" + "Clear Search": "Cancella ricerca", + "Header & Footer": "Intestazione e piè di pagina", + "Apply also in Scrolled Mode": "Applica anche in modalità scorrimento" } diff --git a/apps/readest-app/public/locales/ja/translation.json b/apps/readest-app/public/locales/ja/translation.json index bb6ec3ff..8b3492cb 100644 --- a/apps/readest-app/public/locales/ja/translation.json +++ b/apps/readest-app/public/locales/ja/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}}時間", "{{value}} hours": "{{value}}時間", "CJK Font": "CJKフォント", - "Clear Search": "検索をクリア" + "Clear Search": "検索をクリア", + "Header & Footer": "ヘッダーとフッター", + "Apply also in Scrolled Mode": "スクロールモードでも適用" } diff --git a/apps/readest-app/public/locales/ko/translation.json b/apps/readest-app/public/locales/ko/translation.json index bbb8a534..881cf94d 100644 --- a/apps/readest-app/public/locales/ko/translation.json +++ b/apps/readest-app/public/locales/ko/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} 시간", "{{value}} hours": "{{value}} 시간", "CJK Font": "CJK 글꼴", - "Clear Search": "검색 지우기" + "Clear Search": "검색 지우기", + "Header & Footer": "헤더 및 푸터", + "Apply also in Scrolled Mode": "스크롤 모드에서도 적용" } diff --git a/apps/readest-app/public/locales/pl/translation.json b/apps/readest-app/public/locales/pl/translation.json index f93cfe36..2769697c 100644 --- a/apps/readest-app/public/locales/pl/translation.json +++ b/apps/readest-app/public/locales/pl/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} godzina", "{{value}} hours": "{{value}} godziny", "CJK Font": "Czcionka CJK", - "Clear Search": "Wyczyść wyszukiwanie" + "Clear Search": "Wyczyść wyszukiwanie", + "Header & Footer": "Nagłówek i stopka", + "Apply also in Scrolled Mode": "Zastosuj również w trybie przewijania" } diff --git a/apps/readest-app/public/locales/pt/translation.json b/apps/readest-app/public/locales/pt/translation.json index d69b8cc8..491efac8 100644 --- a/apps/readest-app/public/locales/pt/translation.json +++ b/apps/readest-app/public/locales/pt/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} hora", "{{value}} hours": "{{value}} horas", "CJK Font": "Fonte CJK", - "Clear Search": "Limpar Pesquisa" + "Clear Search": "Limpar Pesquisa", + "Header & Footer": "Cabeçalho e Rodapé", + "Apply also in Scrolled Mode": "Aplicar também no Modo Rolado" } diff --git a/apps/readest-app/public/locales/ru/translation.json b/apps/readest-app/public/locales/ru/translation.json index c2b6f1d5..a24409c0 100644 --- a/apps/readest-app/public/locales/ru/translation.json +++ b/apps/readest-app/public/locales/ru/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} час", "{{value}} hours": "{{value}} часа", "CJK Font": "CJK Шрифт", - "Clear Search": "Очистить поиск" + "Clear Search": "Очистить поиск", + "Header & Footer": "Заголовок и нижний колонтитул", + "Apply also in Scrolled Mode": "Применить также в прокручиваемом режиме" } diff --git a/apps/readest-app/public/locales/tr/translation.json b/apps/readest-app/public/locales/tr/translation.json index 2e8899c3..9489b1c0 100644 --- a/apps/readest-app/public/locales/tr/translation.json +++ b/apps/readest-app/public/locales/tr/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} saat", "{{value}} hours": "{{value}} saat", "CJK Font": "CJK Yazı Tipi", - "Clear Search": "Aramayı Temizle" + "Clear Search": "Aramayı Temizle", + "Header & Footer": "Başlık ve Altbilgi", + "Apply also in Scrolled Mode": "Kaydırılmış Modda da Uygula" } diff --git a/apps/readest-app/public/locales/uk/translation.json b/apps/readest-app/public/locales/uk/translation.json index 92b71e7a..9e4e9aa5 100644 --- a/apps/readest-app/public/locales/uk/translation.json +++ b/apps/readest-app/public/locales/uk/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} година", "{{value}} hours": "{{value}} години", "CJK Font": "CJK шрифт", - "Clear Search": "Очистити пошук" + "Clear Search": "Очистити пошук", + "Header & Footer": "Заголовок і нижній колонтитул", + "Apply also in Scrolled Mode": "Застосувати також у прокрученому режимі" } diff --git a/apps/readest-app/public/locales/vi/translation.json b/apps/readest-app/public/locales/vi/translation.json index d16bca53..f390ddc6 100644 --- a/apps/readest-app/public/locales/vi/translation.json +++ b/apps/readest-app/public/locales/vi/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}} giờ", "{{value}} hours": "{{value}} giờ", "CJK Font": "Phông chữ CJK", - "Clear Search": "Xóa tìm kiếm" + "Clear Search": "Xóa tìm kiếm", + "Header & Footer": "Đầu trang & Chân trang", + "Apply also in Scrolled Mode": "Áp dụng cũng trong chế độ cuộn" } diff --git a/apps/readest-app/public/locales/zh-CN/translation.json b/apps/readest-app/public/locales/zh-CN/translation.json index ff5411b3..a10144f5 100644 --- a/apps/readest-app/public/locales/zh-CN/translation.json +++ b/apps/readest-app/public/locales/zh-CN/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}}小时", "{{value}} hours": "{{value}}小时", "CJK Font": "中文字体", - "Clear Search": "清除搜索" + "Clear Search": "清除搜索", + "Header & Footer": "页眉页脚", + "Apply also in Scrolled Mode": "应用到滚动模式" } diff --git a/apps/readest-app/public/locales/zh-TW/translation.json b/apps/readest-app/public/locales/zh-TW/translation.json index 86629af7..6ac61d2f 100644 --- a/apps/readest-app/public/locales/zh-TW/translation.json +++ b/apps/readest-app/public/locales/zh-TW/translation.json @@ -274,5 +274,7 @@ "{{value}} hour": "{{value}}小時", "{{value}} hours": "{{value}}小時", "CJK Font": "中文字體", - "Clear Search": "清除搜索" + "Clear Search": "清除搜索", + "Header & Footer": "頁眉頁腳", + "Apply also in Scrolled Mode": "滾動模式同樣適用" } diff --git a/apps/readest-app/src/app/reader/components/BooksGrid.tsx b/apps/readest-app/src/app/reader/components/BooksGrid.tsx index 6516ea72..a1548eed 100644 --- a/apps/readest-app/src/app/reader/components/BooksGrid.tsx +++ b/apps/readest-app/src/app/reader/components/BooksGrid.tsx @@ -42,10 +42,7 @@ const BooksGrid: React.FC = ({ bookKeys, onCloseBook }) => { return (
= ({ bookKeys, onCloseBook }) => { const isBookmarked = getViewState(bookKey)?.ribbonVisible; const horizontalGapPercent = viewSettings.gapPercent; const verticalMarginPixels = viewSettings.marginPx; + const scrolled = viewSettings.scrolled; + const showBarsOnScroll = viewSettings.showBarsOnScroll; + const showHeader = viewSettings.showHeader && (scrolled ? showBarsOnScroll : true); + const showFooter = viewSettings.showFooter && (scrolled ? showBarsOnScroll : true); return (
= ({ bookKeys, onCloseBook }) => { key={bookKey} className={clsx( 'relative h-full w-full overflow-hidden', + index === 0 && + !viewSettings?.scrolled && + appService?.hasSafeAreaInset && + 'pt-[env(safe-area-inset-top)]', !isSideBarVisible && appService?.hasRoundedWindow && 'rounded-window', )} > @@ -85,32 +90,36 @@ const BooksGrid: React.FC = ({ bookKeys, onCloseBook }) => { {viewSettings.vertical && viewSettings.scrolled && ( <> -
-
+ {(showFooter || viewSettings.doubleBorder) && ( +
+ )} + {(showHeader || viewSettings.doubleBorder) && ( +
+ )} )} {viewSettings.vertical && viewSettings.doubleBorder && ( )} - {viewSettings.showHeader && ( + {showHeader && ( = ({ bookKeys, onCloseBook }) => { horizontalGap={horizontalGapPercent} verticalMargin={verticalMarginPixels} /> - {viewSettings.showFooter && ( + {showFooter && ( = ({ className={clsx( 'footer-bar shadow-xs absolute bottom-0 z-50 flex w-full flex-col', 'sm:h-[52px] sm:justify-center', - 'sm:bg-base-100 border-base-300/50 border sm:border-none', + 'sm:bg-base-100 border-base-300/50 border-t sm:border-none', 'transition-[opacity,transform] duration-300', appService?.hasRoundedWindow && 'rounded-window-bottom-right', !isSideBarVisible && appService?.hasRoundedWindow && 'rounded-window-bottom-left', diff --git a/apps/readest-app/src/app/reader/components/HeaderBar.tsx b/apps/readest-app/src/app/reader/components/HeaderBar.tsx index e2002a9a..1912b4f6 100644 --- a/apps/readest-app/src/app/reader/components/HeaderBar.tsx +++ b/apps/readest-app/src/app/reader/components/HeaderBar.tsx @@ -42,7 +42,7 @@ const HeaderBar: React.FC = ({ cleanupTrafficLightListeners, } = useTrafficLightStore(); const [isDropdownOpen, setIsDropdownOpen] = useState(false); - const { hoveredBookKey, setHoveredBookKey, bookKeys } = useReaderStore(); + const { bookKeys, hoveredBookKey, setHoveredBookKey } = useReaderStore(); const { isSideBarVisible } = useSidebarStore(); const iconSize16 = useResponsiveSize(16); @@ -70,56 +70,78 @@ const HeaderBar: React.FC = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [isSideBarVisible]); + const isVisible = hoveredBookKey === bookKey || isDropdownOpen; + return (
setHoveredBookKey(bookKey)} - onMouseLeave={() => setHoveredBookKey('')} > -
-
- + + +
+

{_('Header & Footer')}

+
+
+
+ {_('Show Header')} + setShowHeader(!showHeader)} + /> +
+
+ {_('Show Footer')} + setShowFooter(!showFooter)} + /> +
+
+ {_('Apply also in Scrolled Mode')} + setShowBarsOnScroll(!showBarsOnScroll)} + /> +
+
+
+
); }; diff --git a/apps/readest-app/src/app/reader/hooks/useIframeEvents.ts b/apps/readest-app/src/app/reader/hooks/useIframeEvents.ts index 4ca80189..6af604be 100644 --- a/apps/readest-app/src/app/reader/hooks/useIframeEvents.ts +++ b/apps/readest-app/src/app/reader/hooks/useIframeEvents.ts @@ -31,7 +31,10 @@ export const useClickEvent = ( if (appService?.isMobile) { windowStartX = 0; } else { - const windowPosition = await tauriGetWindowLogicalPosition(); + const windowPosition = (await tauriGetWindowLogicalPosition()) as { + x: number; + y: number; + }; windowStartX = windowPosition.x; } } else { @@ -52,6 +55,7 @@ export const useClickEvent = ( } else { if (hoveredBookKey) { setHoveredBookKey(null); + return; } if (!viewSettings.disableClick! && screenX >= viewCenterX) { if (viewSettings.swapClickArea) { diff --git a/apps/readest-app/src/services/constants.ts b/apps/readest-app/src/services/constants.ts index 91464ae8..d6038b48 100644 --- a/apps/readest-app/src/services/constants.ts +++ b/apps/readest-app/src/services/constants.ts @@ -90,6 +90,7 @@ export const DEFAULT_BOOK_LAYOUT: BookLayout = { borderColor: 'red', showHeader: true, showFooter: true, + showBarsOnScroll: false, }; export const DEFAULT_BOOK_STYLE: BookStyle = { diff --git a/apps/readest-app/src/types/book.ts b/apps/readest-app/src/types/book.ts index 7195a594..9b214aa9 100644 --- a/apps/readest-app/src/types/book.ts +++ b/apps/readest-app/src/types/book.ts @@ -82,6 +82,7 @@ export interface BookLayout { borderColor: string; showHeader: boolean; showFooter: boolean; + showBarsOnScroll: boolean; } export interface BookStyle { diff --git a/apps/readest-app/src/utils/config.ts b/apps/readest-app/src/utils/config.ts index c394f399..01940d4a 100644 --- a/apps/readest-app/src/utils/config.ts +++ b/apps/readest-app/src/utils/config.ts @@ -2,11 +2,12 @@ import { ViewSettings } from '@/types/book'; export const getMaxInlineSize = (viewSettings: ViewSettings) => { const isScrolled = viewSettings.scrolled!; + const isVertical = viewSettings.vertical!; const maxColumnCount = viewSettings.maxColumnCount!; const screenWidth = window.innerWidth; const screenHeight = window.innerHeight; - return maxColumnCount === 1 || isScrolled + return maxColumnCount === 1 || isScrolled || isVertical ? Math.max(screenWidth, screenHeight, 720) : viewSettings.maxInlineSize!; };