forked from akai/readest
feat: apply custom fonts directly in custom font panel (#1870)
This commit is contained in:
@@ -532,5 +532,6 @@
|
||||
"Select Image": "حدد صورة",
|
||||
"Select Video": "حدد فيديو",
|
||||
"Select Audio": "حدد صوت",
|
||||
"Select Fonts": "حدد الخطوط"
|
||||
"Select Fonts": "حدد الخطوط",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "تنسيقات الخط المدعومة: .ttf، .odf، .woff، .woff2"
|
||||
}
|
||||
|
||||
@@ -512,5 +512,6 @@
|
||||
"Select Image": "རི་མོ་འདེམས་པ།",
|
||||
"Select Video": "བརྙན་ཟློས་འདེམས་པ།",
|
||||
"Select Audio": "སྒྲ་ཟློས་འདེམས་པ།",
|
||||
"Select Fonts": "ཡིག་གཟུགས་འདེམས་པ།"
|
||||
"Select Fonts": "ཡིག་གཟུགས་འདེམས་པ།",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "ཡིག་གཟུགས་འདེམས་པ་བྱས་ནས་བསྐྱར་བརྗེ་བ། ཡིག་གཟུགས་ཀྱི་སྒྲ་སྐད། .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -516,5 +516,6 @@
|
||||
"Select Image": "Bild auswählen",
|
||||
"Select Video": "Video auswählen",
|
||||
"Select Audio": "Audio auswählen",
|
||||
"Select Fonts": "Schriftarten auswählen"
|
||||
"Select Fonts": "Schriftarten auswählen",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Unterstützte Schriftartenformate: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -516,5 +516,6 @@
|
||||
"Select Image": "Επιλογή Εικόνας",
|
||||
"Select Video": "Επιλογή Βίντεο",
|
||||
"Select Audio": "Επιλογή Ήχου",
|
||||
"Select Fonts": "Επιλογή Γραμματοσειρών"
|
||||
"Select Fonts": "Επιλογή Γραμματοσειρών",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Υποστηριζόμενες μορφές γραμματοσειρών: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -520,5 +520,6 @@
|
||||
"Select Image": "Seleccionar Imagen",
|
||||
"Select Video": "Seleccionar Video",
|
||||
"Select Audio": "Seleccionar Audio",
|
||||
"Select Fonts": "Seleccionar Fuentes"
|
||||
"Select Fonts": "Seleccionar Fuentes",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Formatos de fuente compatibles: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -520,5 +520,6 @@
|
||||
"Select Image": "Sélectionner une Image",
|
||||
"Select Video": "Sélectionner une Vidéo",
|
||||
"Select Audio": "Sélectionner un Audio",
|
||||
"Select Fonts": "Sélectionner des Polices"
|
||||
"Select Fonts": "Sélectionner des Polices",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Formats de police pris en charge : .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -516,5 +516,6 @@
|
||||
"Select Image": "छवि चुनें",
|
||||
"Select Video": "वीडियो चुनें",
|
||||
"Select Audio": "ऑडियो चुनें",
|
||||
"Select Fonts": "फ़ॉन्ट चुनें"
|
||||
"Select Fonts": "फ़ॉन्ट चुनें",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "समर्थित फ़ॉन्ट प्रारूप: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -512,5 +512,6 @@
|
||||
"Select Image": "Pilih Gambar",
|
||||
"Select Video": "Pilih Video",
|
||||
"Select Audio": "Pilih Audio",
|
||||
"Select Fonts": "Pilih Font"
|
||||
"Select Fonts": "Pilih Font",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Format font yang didukung: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -520,5 +520,6 @@
|
||||
"Select Image": "Seleziona Immagine",
|
||||
"Select Video": "Seleziona Video",
|
||||
"Select Audio": "Seleziona Audio",
|
||||
"Select Fonts": "Seleziona Font"
|
||||
"Select Fonts": "Seleziona Font",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Formati di font supportati: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -512,5 +512,6 @@
|
||||
"Select Image": "画像を選択",
|
||||
"Select Video": "動画を選択",
|
||||
"Select Audio": "音声を選択",
|
||||
"Select Fonts": "フォントを選択"
|
||||
"Select Fonts": "フォントを選択",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "サポートされているフォント形式:.ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -512,5 +512,6 @@
|
||||
"Select Image": "이미지 선택",
|
||||
"Select Video": "동영상 선택",
|
||||
"Select Audio": "오디오 선택",
|
||||
"Select Fonts": "글꼴 선택"
|
||||
"Select Fonts": "글꼴 선택",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "지원되는 글꼴 형식: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -516,5 +516,6 @@
|
||||
"Select Image": "Afbeelding Selecteren",
|
||||
"Select Video": "Video Selecteren",
|
||||
"Select Audio": "Audio Selecteren",
|
||||
"Select Fonts": "Lettertypen Selecteren"
|
||||
"Select Fonts": "Lettertypen Selecteren",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Ondersteunde lettertypeformaten: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -524,5 +524,6 @@
|
||||
"Select Image": "Wybierz Obraz",
|
||||
"Select Video": "Wybierz Wideo",
|
||||
"Select Audio": "Wybierz Audio",
|
||||
"Select Fonts": "Wybierz Czcionki"
|
||||
"Select Fonts": "Wybierz Czcionki",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Obsługiwane formaty czcionek: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -520,5 +520,6 @@
|
||||
"Select Image": "Selecionar Imagem",
|
||||
"Select Video": "Selecionar Vídeo",
|
||||
"Select Audio": "Selecionar Áudio",
|
||||
"Select Fonts": "Selecionar Fontes"
|
||||
"Select Fonts": "Selecionar Fontes",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Formatos de fonte suportados: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -524,5 +524,6 @@
|
||||
"Select Image": "Выбрать Изображение",
|
||||
"Select Video": "Выбрать Видео",
|
||||
"Select Audio": "Выбрать Аудио",
|
||||
"Select Fonts": "Выбрать Шрифты"
|
||||
"Select Fonts": "Выбрать Шрифты",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Поддерживаемые форматы шрифтов: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -512,5 +512,6 @@
|
||||
"Select Image": "เลือกรูปภาพ",
|
||||
"Select Video": "เลือกวิดีโอ",
|
||||
"Select Audio": "เลือกเสียง",
|
||||
"Select Fonts": "เลือกฟอนต์"
|
||||
"Select Fonts": "เลือกฟอนต์",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "รูปแบบฟอนต์ที่รองรับ: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -516,5 +516,6 @@
|
||||
"Select Image": "Resim Seç",
|
||||
"Select Video": "Video Seç",
|
||||
"Select Audio": "Ses Seç",
|
||||
"Select Fonts": "Yazı Tiplerini Seç"
|
||||
"Select Fonts": "Yazı Tiplerini Seç",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Desteklenen yazı tipi formatları: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -524,5 +524,6 @@
|
||||
"Select Image": "Вибрати Зображення",
|
||||
"Select Video": "Вибрати Відео",
|
||||
"Select Audio": "Вибрати Аудіо",
|
||||
"Select Fonts": "Вибрати Шрифти"
|
||||
"Select Fonts": "Вибрати Шрифти",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Підтримувані формати шрифтів: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -512,5 +512,6 @@
|
||||
"Select Image": "Chọn Hình Ảnh",
|
||||
"Select Video": "Chọn Video",
|
||||
"Select Audio": "Chọn Âm Thanh",
|
||||
"Select Fonts": "Chọn Phông Chữ"
|
||||
"Select Fonts": "Chọn Phông Chữ",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "Định dạng phông chữ được hỗ trợ: .ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -512,5 +512,6 @@
|
||||
"Select Image": "选择图片",
|
||||
"Select Video": "选择视频",
|
||||
"Select Audio": "选择音频",
|
||||
"Select Fonts": "选择字体"
|
||||
"Select Fonts": "选择字体",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "支持的字体格式:.ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -512,5 +512,6 @@
|
||||
"Select Image": "選擇圖片",
|
||||
"Select Video": "選擇影片",
|
||||
"Select Audio": "選擇音訊",
|
||||
"Select Fonts": "選擇字型"
|
||||
"Select Fonts": "選擇字型",
|
||||
"Supported font formats: .ttf, .odf, .woff, .woff2": "支援的字型格式:.ttf, .odf, .woff, .woff2"
|
||||
}
|
||||
|
||||
@@ -176,9 +176,12 @@ const TranslatorPopup: React.FC<TranslatorPopupProps> = ({
|
||||
className='bg-gray-600 text-white/75'
|
||||
value={targetLang}
|
||||
onChange={handleTargetLangChange}
|
||||
options={Object.entries(translatorLangs)
|
||||
.sort((a, b) => a[1].localeCompare(b[1]))
|
||||
.map(([code, name]) => ({ value: code, label: name }))}
|
||||
options={[
|
||||
{ value: '', label: _('System Language') },
|
||||
...Object.entries(translatorLangs)
|
||||
.sort((a, b) => a[1].localeCompare(b[1]))
|
||||
.map(([code, name]) => ({ value: code, label: name })),
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
{loading ? (
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
import clsx from 'clsx';
|
||||
import React, { useState } from 'react';
|
||||
import { MdAdd, MdDelete } from 'react-icons/md';
|
||||
import { IoMdCloseCircleOutline } from 'react-icons/io';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useCustomFontStore } from '@/store/customFontStore';
|
||||
import { FILE_SELECTION_PRESETS, useFileSelector } from '@/hooks/useFileSelector';
|
||||
import { mountCustomFont } from '@/styles/fonts';
|
||||
import { parseFontFamily } from '@/utils/font';
|
||||
import { getFilename } from '@/utils/path';
|
||||
import { saveViewSettings } from '../../utils/viewSettingsHelper';
|
||||
|
||||
interface CustomFontsProps {
|
||||
bookKey: string;
|
||||
onBack: () => void;
|
||||
}
|
||||
|
||||
const CustomFonts: React.FC<CustomFontsProps> = ({ onBack }) => {
|
||||
const CustomFonts: React.FC<CustomFontsProps> = ({ bookKey, onBack }) => {
|
||||
const _ = useTranslation();
|
||||
const { appService, envConfig } = useEnv();
|
||||
const {
|
||||
@@ -24,10 +28,18 @@ const CustomFonts: React.FC<CustomFontsProps> = ({ onBack }) => {
|
||||
getAvailableFonts,
|
||||
saveCustomFonts,
|
||||
} = useCustomFontStore();
|
||||
const { getViewSettings } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const [isDeleteMode, setIsDeleteMode] = useState(false);
|
||||
|
||||
const { selectFiles } = useFileSelector(appService, _);
|
||||
|
||||
const currentDefaultFont =
|
||||
viewSettings.defaultFont.toLowerCase() === 'serif' ? 'serif' : 'sans-serif';
|
||||
|
||||
const currentFontFamily =
|
||||
currentDefaultFont === 'serif' ? viewSettings.serifFont : viewSettings.sansSerifFont;
|
||||
|
||||
const handleImportFont = () => {
|
||||
selectFiles({ ...FILE_SELECTION_PRESETS.fonts, multiple: true }).then(async (result) => {
|
||||
if (result.error || result.files.length === 0) return;
|
||||
@@ -76,6 +88,17 @@ const CustomFonts: React.FC<CustomFontsProps> = ({ onBack }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectFont = (fontId: string) => {
|
||||
const font = customFonts.find((f) => f.id === fontId);
|
||||
if (font) {
|
||||
if (currentDefaultFont === 'serif') {
|
||||
saveViewSettings(envConfig, bookKey, 'serifFont', font.name);
|
||||
} else {
|
||||
saveViewSettings(envConfig, bookKey, 'sansSerifFont', font.name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const toggleDeleteMode = () => {
|
||||
setIsDeleteMode(!isDeleteMode);
|
||||
};
|
||||
@@ -87,12 +110,14 @@ const CustomFonts: React.FC<CustomFontsProps> = ({ onBack }) => {
|
||||
return (
|
||||
<div className='w-full'>
|
||||
<div className='mb-6 flex h-8 items-center justify-between'>
|
||||
<div className='breadcrumbs py-1 text-sm font-medium'>
|
||||
<div className='breadcrumbs py-1'>
|
||||
<ul>
|
||||
<li>
|
||||
<a onClick={onBack}>{_('Font')}</a>
|
||||
<a className='font-semibold' onClick={onBack}>
|
||||
{_('Font')}
|
||||
</a>
|
||||
</li>
|
||||
<li>{_('Custom Fonts')}</li>
|
||||
<li className='font-medium'>{_('Custom Fonts')}</li>
|
||||
</ul>
|
||||
</div>
|
||||
{availableFonts.length > 0 && (
|
||||
@@ -131,11 +156,20 @@ const CustomFonts: React.FC<CustomFontsProps> = ({ onBack }) => {
|
||||
</div>
|
||||
|
||||
{availableFonts.map((font) => (
|
||||
<div key={font.id} className='card border-base-200 bg-base-200 h-12 border shadow-sm'>
|
||||
<div
|
||||
key={font.id}
|
||||
className={clsx(
|
||||
'card h-12 border shadow-sm',
|
||||
currentFontFamily === font.name
|
||||
? 'border-primary/50 bg-primary/50'
|
||||
: 'border-base-200 bg-base-200 cursor-pointer',
|
||||
)}
|
||||
onClick={() => handleSelectFont(font.id)}
|
||||
>
|
||||
<div className='card-body flex items-center justify-center p-2'>
|
||||
<div
|
||||
style={{
|
||||
fontFamily: font.loaded ? `"${font.name}", serif` : 'serif',
|
||||
fontFamily: font.loaded ? `"${font.name}", sans-serif` : 'sans-serif',
|
||||
fontWeight: 400,
|
||||
}}
|
||||
className='text-base-content line-clamp-1 max-w-[90%]'
|
||||
@@ -159,7 +193,8 @@ const CustomFonts: React.FC<CustomFontsProps> = ({ onBack }) => {
|
||||
<div className='bg-base-200/30 my-8 rounded-lg p-4'>
|
||||
<div className='text-base-content/70'>
|
||||
<div className='mb-1 text-xs font-medium'>{_('Tips')}:</div>
|
||||
<ul className='list-inside list-disc space-y-1 text-xs'>
|
||||
<ul className='list-inside list-disc space-y-1 text-sm sm:text-xs'>
|
||||
<li>{_('Supported font formats: .ttf, .odf, .woff, .woff2')}</li>
|
||||
<li>{_('Custom fonts can be selected from the Font Face menu')}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -22,6 +22,7 @@ import { useReaderStore } from '@/store/readerStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useCustomFontStore } from '@/store/customFontStore';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
import { getOSPlatform, isCJKEnv } from '@/utils/misc';
|
||||
import { getSysFontsList } from '@/utils/bridge';
|
||||
import { isCJKStr } from '@/utils/lang';
|
||||
@@ -32,7 +33,6 @@ import { SettingsPanelPanelProp } from './SettingsDialog';
|
||||
import NumberInput from './NumberInput';
|
||||
import FontDropdown from './FontDropDown';
|
||||
import CustomFonts from './CustomFonts';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
|
||||
const genCJKFontsList = (sysFonts: string[]) => {
|
||||
return Array.from(new Set([...sysFonts, ...CJK_SERIF_FONTS, ...CJK_SANS_SERIF_FONTS]))
|
||||
@@ -185,6 +185,12 @@ const FontPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
|
||||
setCustomFonts(getFontFamilies());
|
||||
}, [allCustomFonts, getFontFamilies]);
|
||||
|
||||
useEffect(() => {
|
||||
setSerifFont(viewSettings.serifFont);
|
||||
setSansSerifFont(viewSettings.sansSerifFont);
|
||||
setMonospaceFont(viewSettings.monospaceFont);
|
||||
}, [viewSettings.serifFont, viewSettings.sansSerifFont, viewSettings.monospaceFont]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isTauriAppPlatform()) {
|
||||
getSysFontsList().then((res) => {
|
||||
@@ -273,7 +279,7 @@ const FontPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
|
||||
if (fontPanelView === 'custom-fonts') {
|
||||
return (
|
||||
<div className='my-4 w-full'>
|
||||
<CustomFonts onBack={handleBackToMain} />
|
||||
<CustomFonts bookKey={bookKey} onBack={handleBackToMain} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ const SettingsDialog: React.FC<{ bookKey: string; config: BookConfig }> = ({ boo
|
||||
const [isRtl] = useState(() => getDirFromUILanguage() === 'rtl');
|
||||
const tabsRef = useRef<HTMLDivElement | null>(null);
|
||||
const [showAllTabLabels, setShowAllTabLabels] = useState(false);
|
||||
const { setFontLayoutSettingsDialogOpen } = useSettingsStore();
|
||||
const { setFontPanelView, setFontLayoutSettingsDialogOpen } = useSettingsStore();
|
||||
|
||||
const tabConfig = [
|
||||
{
|
||||
@@ -85,6 +85,7 @@ const SettingsDialog: React.FC<{ bookKey: string; config: BookConfig }> = ({ boo
|
||||
|
||||
const handleSetActivePanel = (tab: SettingsPanelType) => {
|
||||
setActivePanel(tab);
|
||||
setFontPanelView('main-fonts');
|
||||
localStorage.setItem('lastConfigPanel', tab);
|
||||
};
|
||||
|
||||
@@ -115,6 +116,8 @@ const SettingsDialog: React.FC<{ bookKey: string; config: BookConfig }> = ({ boo
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setFontPanelView('main-fonts');
|
||||
|
||||
const container = tabsRef.current;
|
||||
if (!container) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user