forked from akai/readest
@@ -57,7 +57,6 @@
|
||||
"Layout": "التخطيط",
|
||||
"Light Mode": "الوضع الفاتح",
|
||||
"Loading...": "جارٍ التحميل...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "الصفحة {{currentPage}} \\ {{totalPage}}",
|
||||
"Logged in": "تم تسجيل الدخول",
|
||||
"Logged in as {{userDisplayName}}": "تم تسجيل الدخول باسم {{userDisplayName}}",
|
||||
"Match Case": "مطابقة حالة الأحرف",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "لون الخلفية",
|
||||
"Preview": "معاينة",
|
||||
"Contrast": "التباين",
|
||||
"Sunset": "غروب الشمس"
|
||||
"Sunset": "غروب الشمس",
|
||||
"Double Border": "حدود مزدوجة",
|
||||
"Border Color": "لون الحدود"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Layout",
|
||||
"Light Mode": "Hellmodus",
|
||||
"Loading...": "Wird geladen...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Pos. {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Angemeldet",
|
||||
"Logged in as {{userDisplayName}}": "Angemeldet als {{userDisplayName}}",
|
||||
"Match Case": "Groß-/Kleinschreibung beachten",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Hintergrundfarbe",
|
||||
"Preview": "Vorschau",
|
||||
"Contrast": "Kontrast",
|
||||
"Sunset": "Sonnenuntergang"
|
||||
"Sunset": "Sonnenuntergang",
|
||||
"Double Border": "Doppelter Rand",
|
||||
"Border Color": "Randfarbe"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Διάταξη",
|
||||
"Light Mode": "Φωτεινή λειτουργία",
|
||||
"Loading...": "Φόρτωση...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Θέση {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Συνδεδεμένος",
|
||||
"Logged in as {{userDisplayName}}": "Συνδεδεμένος ως {{userDisplayName}}",
|
||||
"Match Case": "Ταίριασμα πεζών-κεφαλαίων",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Χρώμα φόντου",
|
||||
"Preview": "Προεπισκόπηση",
|
||||
"Contrast": "Αντίθεση",
|
||||
"Sunset": "Ηλιοβασίλεμα"
|
||||
"Sunset": "Ηλιοβασίλεμα",
|
||||
"Double Border": "Διπλό περιθώριο",
|
||||
"Border Color": "Χρώμα περιγράμματος"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Diseño",
|
||||
"Light Mode": "Modo claro",
|
||||
"Loading...": "Cargando...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Pos. {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Sesión iniciada",
|
||||
"Logged in as {{userDisplayName}}": "Sesión iniciada como {{userDisplayName}}",
|
||||
"Match Case": "Coincidir mayúsculas y minúsculas",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Color de fondo",
|
||||
"Preview": "Vista previa",
|
||||
"Contrast": "Contraste",
|
||||
"Sunset": "Atardecer"
|
||||
"Sunset": "Atardecer",
|
||||
"Double Border": "Doble borde",
|
||||
"Border Color": "Color del borde"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Mise en page",
|
||||
"Light Mode": "Mode clair",
|
||||
"Loading...": "Chargement...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Pos. {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Connecté",
|
||||
"Logged in as {{userDisplayName}}": "Connecté en tant que {{userDisplayName}}",
|
||||
"Match Case": "Respecter la casse",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Couleur de fond",
|
||||
"Preview": "Aperçu",
|
||||
"Contrast": "Contraste",
|
||||
"Sunset": "Coucher de soleil"
|
||||
"Sunset": "Coucher de soleil",
|
||||
"Double Border": "Double bordure",
|
||||
"Border Color": "Couleur de la bordure"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "लेआउट",
|
||||
"Light Mode": "लाइट मोड",
|
||||
"Loading...": "लोड हो रहा है...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "स्थान {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "लॉग इन किया",
|
||||
"Logged in as {{userDisplayName}}": "{{userDisplayName}} के रूप में लॉग इन किया",
|
||||
"Match Case": "केस मैच करें",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "पृष्ठभूमि रंग",
|
||||
"Preview": "पूर्वावलोकन",
|
||||
"Contrast": "विरोधाभास",
|
||||
"Sunset": "सनसेट"
|
||||
"Sunset": "सनसेट",
|
||||
"Double Border": "डबल बॉर्डर",
|
||||
"Border Color": "बॉर्डर रंग"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Tata Letak",
|
||||
"Light Mode": "Mode Terang",
|
||||
"Loading...": "Memuat...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Lok. {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Sudah Masuk",
|
||||
"Logged in as {{userDisplayName}}": "Masuk sebagai {{userDisplayName}}",
|
||||
"Match Case": "Cocokkan Huruf Besar/Kecil",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Warna Latar Belakang",
|
||||
"Preview": "Pratinjau",
|
||||
"Contrast": "Kontras",
|
||||
"Sunset": "Senja"
|
||||
"Sunset": "Senja",
|
||||
"Double Border": "Garis Ganda",
|
||||
"Border Color": "Warna Garis"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Layout",
|
||||
"Light Mode": "Modalità chiara",
|
||||
"Loading...": "Caricamento...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Pos. {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Accesso effettuato",
|
||||
"Logged in as {{userDisplayName}}": "Accesso effettuato come {{userDisplayName}}",
|
||||
"Match Case": "Maiuscole/minuscole",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Colore sfondo",
|
||||
"Preview": "Anteprima",
|
||||
"Contrast": "Contrasto",
|
||||
"Sunset": "Tramonto"
|
||||
"Sunset": "Tramonto",
|
||||
"Double Border": "Doppio bordo",
|
||||
"Border Color": "Colore bordo"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "レイアウト",
|
||||
"Light Mode": "ライトモード",
|
||||
"Loading...": "読み込み中...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "位置 {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "ログイン済み",
|
||||
"Logged in as {{userDisplayName}}": "{{userDisplayName}}としてログイン中",
|
||||
"Match Case": "大文字・小文字を区別",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "背景色",
|
||||
"Preview": "プレビュー",
|
||||
"Contrast": "コントラスト",
|
||||
"Sunset": "サンセット"
|
||||
"Sunset": "サンセット",
|
||||
"Double Border": "二重枠",
|
||||
"Border Color": "ボーダーカラー"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "레이아웃",
|
||||
"Light Mode": "라이트 모드",
|
||||
"Loading...": "로딩 중...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "위치 {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "로그인됨",
|
||||
"Logged in as {{userDisplayName}}": "{{userDisplayName}}(으)로 로그인됨",
|
||||
"Match Case": "대소문자 구분",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "배경 색상",
|
||||
"Preview": "미리보기",
|
||||
"Contrast": "대비",
|
||||
"Sunset": "일몰"
|
||||
"Sunset": "일몰",
|
||||
"Double Border": "이중 테두리",
|
||||
"Border Color": "테두리 색상"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Układ",
|
||||
"Light Mode": "Tryb jasny",
|
||||
"Loading...": "Ładowanie...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Poz. {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Zalogowano",
|
||||
"Logged in as {{userDisplayName}}": "Zalogowano jako {{userDisplayName}}",
|
||||
"Match Case": "Uwzględnij wielkość liter",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Kolor tła",
|
||||
"Preview": "Podgląd",
|
||||
"Contrast": "Kontrast",
|
||||
"Sunset": "Zachód słońca"
|
||||
"Sunset": "Zachód słońca",
|
||||
"Double Border": "Podwójna ramka",
|
||||
"Border Color": "Kolor ramki"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Layout",
|
||||
"Light Mode": "Modo Claro",
|
||||
"Loading...": "Carregando...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Loc. {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Conectado",
|
||||
"Logged in as {{userDisplayName}}": "Conectado como {{userDisplayName}}",
|
||||
"Match Case": "Diferenciar Maiúsculas e Minúsculas",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Cor de Fundo",
|
||||
"Preview": "Visualizar",
|
||||
"Contrast": "Contraste",
|
||||
"Sunset": "Pôr do Sol"
|
||||
"Sunset": "Pôr do Sol",
|
||||
"Double Border": "Borda Dupla",
|
||||
"Border Color": "Cor da Borda"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Макет",
|
||||
"Light Mode": "Светлая тема",
|
||||
"Loading...": "Загрузка...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Поз. {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Выполнен вход",
|
||||
"Logged in as {{userDisplayName}}": "Вход выполнен как {{userDisplayName}}",
|
||||
"Match Case": "Учитывать регистр",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Цвет фона",
|
||||
"Preview": "Предпросмотр",
|
||||
"Contrast": "Контраст",
|
||||
"Sunset": "Закат"
|
||||
"Sunset": "Закат",
|
||||
"Double Border": "Двойная граница",
|
||||
"Border Color": "Цвет границы"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Düzen",
|
||||
"Light Mode": "Aydınlık Mod",
|
||||
"Loading...": "Yükleniyor...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Konum {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Giriş Yapıldı",
|
||||
"Logged in as {{userDisplayName}}": "{{userDisplayName}} olarak giriş yapıldı",
|
||||
"Match Case": "Büyük/Küçük Harf Eşleştir",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Arka Plan Rengi",
|
||||
"Preview": "Önizleme",
|
||||
"Contrast": "Kontrast",
|
||||
"Sunset": "Gün Batımı"
|
||||
"Sunset": "Gün Batımı",
|
||||
"Double Border": "Çift Sınır",
|
||||
"Border Color": "Sınır Rengi"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Макет",
|
||||
"Light Mode": "Світлий режим",
|
||||
"Loading...": "Завантаження...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Поз. {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Увійшли",
|
||||
"Logged in as {{userDisplayName}}": "Увійшли як {{userDisplayName}}",
|
||||
"Match Case": "Враховувати регістр",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Колір фону",
|
||||
"Preview": "Попередній перегляд",
|
||||
"Contrast": "Контраст",
|
||||
"Sunset": "Захід сонця"
|
||||
"Sunset": "Захід сонця",
|
||||
"Double Border": "Подвійна рамка",
|
||||
"Border Color": "Колір рамки"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "Bố cục",
|
||||
"Light Mode": "Chế độ sáng",
|
||||
"Loading...": "Đang tải...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "Vị trí {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "Đã đăng nhập",
|
||||
"Logged in as {{userDisplayName}}": "Đăng nhập với tên {{userDisplayName}}",
|
||||
"Match Case": "Phân biệt chữ hoa/thường",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "Màu nền",
|
||||
"Preview": "Xem trước",
|
||||
"Contrast": "Tương phản",
|
||||
"Sunset": "Hoàng hôn"
|
||||
"Sunset": "Hoàng hôn",
|
||||
"Double Border": "Đôi viền",
|
||||
"Border Color": "Màu viền"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "布局",
|
||||
"Light Mode": "浅色主题",
|
||||
"Loading...": "加载中...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "位置 {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "已登录",
|
||||
"Logged in as {{userDisplayName}}": "{{userDisplayName}} 已登录",
|
||||
"Match Case": "匹配大小写",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "背景颜色",
|
||||
"Preview": "预览",
|
||||
"Contrast": "对比",
|
||||
"Sunset": "日落"
|
||||
"Sunset": "日落",
|
||||
"Double Border": "页面版框",
|
||||
"Border Color": "版框颜色"
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Layout": "版面",
|
||||
"Light Mode": "淺色主題",
|
||||
"Loading...": "載入中...",
|
||||
"Loc. {{currentPage}} / {{totalPage}}": "位置 {{currentPage}} / {{totalPage}}",
|
||||
"Logged in": "已登入",
|
||||
"Logged in as {{userDisplayName}}": "{{userDisplayName}} 已登入",
|
||||
"Match Case": "匹配大小寫",
|
||||
@@ -243,5 +242,7 @@
|
||||
"Background Color": "背景顏色",
|
||||
"Preview": "預覽",
|
||||
"Contrast": "對比",
|
||||
"Sunset": "日落"
|
||||
"Sunset": "日落",
|
||||
"Double Border": "頁面邊框",
|
||||
"Border Color": "邊框顏色"
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import SettingsDialog from './settings/SettingsDialog';
|
||||
import Annotator from './annotator/Annotator';
|
||||
import FootnotePopup from './FootnotePopup';
|
||||
import HintInfo from './HintInfo';
|
||||
import DoubleBorder from './DoubleBorder';
|
||||
|
||||
interface BooksGridProps {
|
||||
bookKeys: string[];
|
||||
@@ -60,7 +61,8 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
|
||||
|
||||
const { section, pageinfo, sectionLabel } = progress || {};
|
||||
const isBookmarked = getViewState(bookKey)?.ribbonVisible;
|
||||
const marginGap = `${viewSettings.gapPercent}%`;
|
||||
const horizontalGapPercent = viewSettings.gapPercent;
|
||||
const verticalMarginPixels = viewSettings.marginPx;
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -68,7 +70,7 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
|
||||
key={bookKey}
|
||||
className={`${appService?.hasRoundedWindow ? 'rounded-window' : ''} relative h-full w-full overflow-hidden`}
|
||||
>
|
||||
{isBookmarked && <Ribbon width={marginGap} />}
|
||||
{isBookmarked && <Ribbon width={`${horizontalGapPercent}%`} />}
|
||||
<HeaderBar
|
||||
bookKey={bookKey}
|
||||
bookTitle={book.title}
|
||||
@@ -81,13 +83,32 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
|
||||
<FootnotePopup bookKey={bookKey} bookDoc={bookDoc} />
|
||||
{viewSettings.scrolled ? null : (
|
||||
<>
|
||||
<SectionInfo section={sectionLabel} gapLeft={marginGap} />
|
||||
<HintInfo bookKey={bookKey} gapRight={marginGap} />
|
||||
{viewSettings.vertical && viewSettings.doubleBorder && (
|
||||
<DoubleBorder
|
||||
borderColor={viewSettings.borderColor}
|
||||
horizontalGap={horizontalGapPercent}
|
||||
verticalMargin={verticalMarginPixels}
|
||||
/>
|
||||
)}
|
||||
<SectionInfo
|
||||
section={sectionLabel}
|
||||
isVertical={viewSettings.vertical}
|
||||
horizontalGap={horizontalGapPercent}
|
||||
verticalMargin={verticalMarginPixels}
|
||||
/>
|
||||
<HintInfo
|
||||
bookKey={bookKey}
|
||||
isVertical={viewSettings.vertical}
|
||||
horizontalGap={horizontalGapPercent}
|
||||
verticalMargin={verticalMarginPixels}
|
||||
/>
|
||||
<PageInfoView
|
||||
bookFormat={book.format}
|
||||
section={section}
|
||||
pageinfo={pageinfo}
|
||||
gapRight={marginGap}
|
||||
isVertical={viewSettings.vertical}
|
||||
horizontalGap={horizontalGapPercent}
|
||||
verticalMargin={verticalMarginPixels}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
interface DoubleBorderProps {
|
||||
borderColor: string;
|
||||
horizontalGap: number;
|
||||
verticalMargin: number;
|
||||
}
|
||||
|
||||
const paddingPx = 10;
|
||||
|
||||
const DoubleBorder: React.FC<DoubleBorderProps> = ({
|
||||
borderColor,
|
||||
horizontalGap,
|
||||
verticalMargin,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={'borderframe pointer-events-none absolute'}
|
||||
style={{
|
||||
border: `4px solid ${borderColor}`,
|
||||
height: `calc(100% - ${verticalMargin * 2}px + ${paddingPx * 2}px)`,
|
||||
top: `calc(${verticalMargin}px - ${paddingPx}px)`,
|
||||
left: `calc(${horizontalGap * 2}% - 32px - ${paddingPx}px)`,
|
||||
right: `calc(${horizontalGap * 2}% - 32px - ${paddingPx}px)`,
|
||||
}}
|
||||
></div>
|
||||
<div
|
||||
className={'borderframe pointer-events-none absolute'}
|
||||
style={{
|
||||
border: `1px solid ${borderColor}`,
|
||||
height: `calc(100% - ${verticalMargin * 2}px)`,
|
||||
top: `${verticalMargin}px`,
|
||||
left: `${horizontalGap * 2}%`,
|
||||
right: `${horizontalGap * 2}%`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={'borderframe pointer-events-none absolute'}
|
||||
style={{
|
||||
border: `1px solid ${borderColor}`,
|
||||
width: '32px',
|
||||
height: `calc(100% - ${verticalMargin * 2}px)`,
|
||||
top: `${verticalMargin}px`,
|
||||
left: `calc(${horizontalGap * 2}% - 32px)`,
|
||||
borderRight: 'none',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={'borderframe pointer-events-none absolute'}
|
||||
style={{
|
||||
border: `1px solid ${borderColor}`,
|
||||
width: '32px',
|
||||
height: `calc(100% - ${verticalMargin * 2}px)`,
|
||||
top: `${verticalMargin}px`,
|
||||
left: `calc(100% - ${horizontalGap * 2}%)`,
|
||||
borderLeft: 'none',
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DoubleBorder;
|
||||
@@ -6,10 +6,17 @@ import { eventDispatcher } from '@/utils/event';
|
||||
|
||||
interface SectionInfoProps {
|
||||
bookKey: string;
|
||||
gapRight: string;
|
||||
isVertical: boolean;
|
||||
horizontalGap: number;
|
||||
verticalMargin: number;
|
||||
}
|
||||
|
||||
const HintInfo: React.FC<SectionInfoProps> = ({ bookKey, gapRight }) => {
|
||||
const HintInfo: React.FC<SectionInfoProps> = ({
|
||||
bookKey,
|
||||
isVertical,
|
||||
horizontalGap,
|
||||
verticalMargin,
|
||||
}) => {
|
||||
const { isSideBarVisible } = useSidebarStore();
|
||||
const { isTrafficLightVisible } = useTrafficLightStore();
|
||||
const [hintMessage, setHintMessage] = React.useState<string | null>(null);
|
||||
@@ -42,13 +49,26 @@ const HintInfo: React.FC<SectionInfoProps> = ({ bookKey, gapRight }) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'pageinfo absolute right-0 top-0 flex max-w-[50%] items-end',
|
||||
isTrafficLightVisible && !isSideBarVisible ? 'h-[44px]' : 'h-[30px]',
|
||||
hintMessage ? '' : '',
|
||||
'sectioninfo absolute flex justify-end overflow-hidden',
|
||||
!isVertical && (isTrafficLightVisible && !isSideBarVisible ? 'h-[44px]' : 'h-[30px]'),
|
||||
isVertical ? 'writing-vertical-rl w-[32px] items-center' : 'top-0 items-end',
|
||||
isVertical ? 'max-h-[50%]' : 'max-w-[50%]',
|
||||
)}
|
||||
style={{ right: gapRight }}
|
||||
style={
|
||||
isVertical
|
||||
? {
|
||||
bottom: `calc(${horizontalGap / 2}% + ${verticalMargin}px)`,
|
||||
left: `calc(100% - ${horizontalGap * 2}%)`,
|
||||
height: `calc(100% - ${verticalMargin * 2}px)`,
|
||||
}
|
||||
: { right: `${horizontalGap}%` }
|
||||
}
|
||||
>
|
||||
<h2 className='text-neutral-content line-clamp-1 text-center font-sans text-xs font-light'>
|
||||
<h2
|
||||
className={clsx(
|
||||
'text-neutral-content line-clamp-1 text-center font-sans text-xs font-light',
|
||||
)}
|
||||
>
|
||||
{hintMessage || ''}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { PageInfo } from '@/types/book';
|
||||
@@ -6,27 +7,53 @@ interface PageInfoProps {
|
||||
bookFormat: string;
|
||||
section?: PageInfo;
|
||||
pageinfo?: PageInfo;
|
||||
gapRight: string;
|
||||
isVertical: boolean;
|
||||
horizontalGap: number;
|
||||
verticalMargin: number;
|
||||
}
|
||||
|
||||
const PageInfoView: React.FC<PageInfoProps> = ({ bookFormat, section, pageinfo, gapRight }) => {
|
||||
const PageInfoView: React.FC<PageInfoProps> = ({
|
||||
bookFormat,
|
||||
section,
|
||||
pageinfo,
|
||||
isVertical,
|
||||
horizontalGap,
|
||||
verticalMargin,
|
||||
}) => {
|
||||
const _ = useTranslation();
|
||||
const pageInfo =
|
||||
bookFormat === 'PDF'
|
||||
? section
|
||||
? `${section.current + 1} / ${section.total}`
|
||||
? isVertical
|
||||
? `${section.current + 1} · ${section.total}`
|
||||
: `${section.current + 1} / ${section.total}`
|
||||
: ''
|
||||
: pageinfo
|
||||
? _('Loc. {{currentPage}} / {{totalPage}}', {
|
||||
currentPage: pageinfo.current + 1,
|
||||
totalPage: pageinfo.total,
|
||||
})
|
||||
? _(
|
||||
isVertical ? '{{currentPage}} · {{totalPage}}' : 'Loc. {{currentPage}} / {{totalPage}}',
|
||||
{
|
||||
currentPage: pageinfo.current + 1,
|
||||
totalPage: pageinfo.total,
|
||||
},
|
||||
)
|
||||
: '';
|
||||
|
||||
return (
|
||||
<div
|
||||
className='pageinfo absolute bottom-0 left-0 right-0 flex h-12 items-center justify-end'
|
||||
style={{ paddingRight: gapRight }}
|
||||
className={clsx(
|
||||
'pageinfo absolute bottom-0 flex items-center justify-end',
|
||||
isVertical ? 'left-0' : 'right-0',
|
||||
isVertical ? 'writing-vertical-rl w-[32px]' : 'h-12',
|
||||
)}
|
||||
style={
|
||||
isVertical
|
||||
? {
|
||||
bottom: `calc(${horizontalGap / 2}% + ${verticalMargin}px)`,
|
||||
left: `calc(${horizontalGap * 2}% - 32px)`,
|
||||
height: `calc(100% - ${verticalMargin * 2}px)`,
|
||||
}
|
||||
: { paddingRight: `${horizontalGap}%` }
|
||||
}
|
||||
>
|
||||
<h2 className='text-neutral-content text-right font-sans text-xs font-extralight'>
|
||||
{pageInfo}
|
||||
|
||||
@@ -6,21 +6,42 @@ import { useTrafficLightStore } from '@/store/trafficLightStore';
|
||||
|
||||
interface SectionInfoProps {
|
||||
section?: string;
|
||||
gapLeft: string;
|
||||
isVertical: boolean;
|
||||
horizontalGap: number;
|
||||
verticalMargin: number;
|
||||
}
|
||||
|
||||
const SectionInfo: React.FC<SectionInfoProps> = ({ section, gapLeft }) => {
|
||||
const SectionInfo: React.FC<SectionInfoProps> = ({
|
||||
section,
|
||||
isVertical,
|
||||
horizontalGap,
|
||||
verticalMargin,
|
||||
}) => {
|
||||
const { isSideBarVisible } = useSidebarStore();
|
||||
const { isTrafficLightVisible } = useTrafficLightStore();
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'pageinfo absolute right-0 top-0 flex max-w-[50%] items-end',
|
||||
isTrafficLightVisible && !isSideBarVisible ? 'h-[44px]' : 'h-[30px]',
|
||||
'sectioninfo absolute flex overflow-hidden',
|
||||
!isVertical && (isTrafficLightVisible && !isSideBarVisible ? 'h-[44px]' : 'h-[30px]'),
|
||||
isVertical ? 'writing-vertical-rl w-[32px] items-center' : 'top-0 items-end',
|
||||
isVertical ? 'max-h-[50%]' : 'max-w-[50%]',
|
||||
)}
|
||||
style={{ left: gapLeft }}
|
||||
style={
|
||||
isVertical
|
||||
? {
|
||||
top: `calc(${horizontalGap / 2}% + ${verticalMargin}px)`,
|
||||
left: `calc(100% - ${horizontalGap * 2}%)`,
|
||||
height: `calc(100% - ${verticalMargin * 2}px)`,
|
||||
}
|
||||
: { left: `${horizontalGap}%` }
|
||||
}
|
||||
>
|
||||
<h2 className='text-neutral-content line-clamp-1 text-center font-sans text-xs font-light'>
|
||||
<h2
|
||||
className={clsx(
|
||||
'text-neutral-content line-clamp-1 text-center font-sans text-xs font-light',
|
||||
)}
|
||||
>
|
||||
{section || ''}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
@@ -36,6 +36,8 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
const [writingMode, setWritingMode] = useState(viewSettings.writingMode!);
|
||||
const [overrideLayout, setOverrideLayout] = useState(viewSettings.overrideLayout!);
|
||||
const [isScrolledMode, setScrolledMode] = useState(viewSettings.scrolled!);
|
||||
const [doubleBorder, setDoubleBorder] = useState(viewSettings.doubleBorder!);
|
||||
const [borderColor, setBorderColor] = useState(viewSettings.borderColor!);
|
||||
|
||||
useEffect(() => {
|
||||
viewSettings.paragraphMargin = paragraphMargin;
|
||||
@@ -177,6 +179,9 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
// global settings are not supported for writing mode
|
||||
const prevWritingMode = viewSettings.writingMode;
|
||||
viewSettings.writingMode = writingMode;
|
||||
if (writingMode.includes('vertical')) {
|
||||
viewSettings.vertical = true;
|
||||
}
|
||||
setViewSettings(bookKey, viewSettings);
|
||||
if (view) {
|
||||
view.renderer.setStyles?.(getStyles(viewSettings));
|
||||
@@ -218,6 +223,26 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isScrolledMode]);
|
||||
|
||||
useEffect(() => {
|
||||
viewSettings.doubleBorder = doubleBorder;
|
||||
setViewSettings(bookKey, viewSettings);
|
||||
if (isFontLayoutSettingsGlobal) {
|
||||
settings.globalViewSettings.doubleBorder = doubleBorder;
|
||||
setSettings(settings);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [doubleBorder]);
|
||||
|
||||
useEffect(() => {
|
||||
viewSettings.borderColor = borderColor;
|
||||
setViewSettings(bookKey, viewSettings);
|
||||
if (isFontLayoutSettingsGlobal) {
|
||||
settings.globalViewSettings.borderColor = borderColor;
|
||||
setSettings(settings);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [borderColor]);
|
||||
|
||||
const langCode = getBookLangCode(bookData.bookDoc?.metadata?.language);
|
||||
const mightBeRTLBook =
|
||||
langCode === 'zh' || langCode === 'ja' || langCode === 'ko' || langCode === '';
|
||||
@@ -281,6 +306,39 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{viewSettings.vertical && (
|
||||
<>
|
||||
<div className='w-full'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<h2 className='font-medium'>{_('Double Border')}</h2>
|
||||
<input
|
||||
type='checkbox'
|
||||
className='toggle'
|
||||
checked={doubleBorder}
|
||||
onChange={() => setDoubleBorder(!doubleBorder)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='w-full'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<h2 className='font-medium'>{_('Border Color')}</h2>
|
||||
<div className='flex gap-4'>
|
||||
<button
|
||||
className={`btn btn-circle btn-sm bg-red-300 hover:bg-red-500 ${borderColor === 'red' ? 'btn-active !bg-red-500' : ''}`}
|
||||
onClick={() => setBorderColor('red')}
|
||||
></button>
|
||||
|
||||
<button
|
||||
className={`btn btn-circle btn-sm bg-black/50 hover:bg-black ${borderColor === 'black' ? 'btn-active !bg-black' : ''}`}
|
||||
onClick={() => setBorderColor('black')}
|
||||
></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className='w-full'>
|
||||
<h2 className='mb-2 font-medium'>{_('Paragraph')}</h2>
|
||||
<div className='card bg-base-100 border-base-200 border shadow'>
|
||||
@@ -374,7 +432,7 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
label={_('Horizontal Margins (%)')}
|
||||
value={gapPercent}
|
||||
onChange={setGapPercent}
|
||||
min={0}
|
||||
min={viewSettings.vertical ? 2 : 0}
|
||||
max={30}
|
||||
/>
|
||||
<NumberInput
|
||||
|
||||
@@ -71,6 +71,8 @@ export const DEFAULT_BOOK_LAYOUT: BookLayout = {
|
||||
writingMode: 'auto',
|
||||
vertical: false,
|
||||
rtl: false,
|
||||
doubleBorder: true,
|
||||
borderColor: 'red',
|
||||
};
|
||||
|
||||
export const DEFAULT_BOOK_STYLE: BookStyle = {
|
||||
|
||||
@@ -278,6 +278,10 @@ foliate-view {
|
||||
line-height: 1em !important;
|
||||
}
|
||||
|
||||
.writing-vertical-rl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
|
||||
.direction-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,8 @@ export interface BookLayout {
|
||||
writingMode: WritingMode;
|
||||
vertical: boolean;
|
||||
rtl: boolean;
|
||||
doubleBorder: boolean;
|
||||
borderColor: string;
|
||||
}
|
||||
|
||||
export interface BookStyle {
|
||||
|
||||
@@ -133,6 +133,7 @@ const getLayoutStyles = (
|
||||
hyphenate: boolean,
|
||||
zoomLevel: number,
|
||||
writingMode: string,
|
||||
vertical: boolean,
|
||||
bg: string,
|
||||
fg: string,
|
||||
primary: string,
|
||||
@@ -181,6 +182,7 @@ const getLayoutStyles = (
|
||||
color: ${fg};
|
||||
${writingMode === 'auto' ? '' : `writing-mode: ${writingMode};`}
|
||||
text-align: var(--default-text-align);
|
||||
max-height: unset;
|
||||
background-color: var(--theme-bg-color, transparent);
|
||||
background: var(--background-set, none);
|
||||
}
|
||||
@@ -195,7 +197,7 @@ const getLayoutStyles = (
|
||||
background-color: transparent !important;
|
||||
}
|
||||
p, li, blockquote, dd {
|
||||
margin: ${paragraphMargin}em 0;
|
||||
margin: ${vertical ? `0 ${paragraphMargin}em` : `${paragraphMargin}em 0`};
|
||||
line-height: ${lineSpacing} ${overrideLayout ? '!important' : ''};
|
||||
word-spacing: ${wordSpacing}px ${overrideLayout ? '!important' : ''};
|
||||
letter-spacing: ${letterSpacing}px ${overrideLayout ? '!important' : ''};
|
||||
@@ -314,6 +316,7 @@ export const getStyles = (viewSettings: ViewSettings, themeCode?: ThemeCode) =>
|
||||
viewSettings.hyphenation!,
|
||||
viewSettings.zoomLevel! / 100.0,
|
||||
viewSettings.writingMode!,
|
||||
viewSettings.vertical!,
|
||||
themeCode.bg,
|
||||
themeCode.fg,
|
||||
themeCode.primary,
|
||||
|
||||
+1
-1
Submodule packages/foliate-js updated: a4480cfa93...c50960743b
Reference in New Issue
Block a user