forked from akai/readest
This commit is contained in:
@@ -660,5 +660,7 @@
|
||||
"Outline": "مخطط",
|
||||
"Save Current Color": "حفظ اللون الحالي",
|
||||
"Quick Colors": "ألوان سريعة",
|
||||
"Highlighter": "محدد النص"
|
||||
"Highlighter": "محدد النص",
|
||||
"Save Book Cover": "حفظ غلاف الكتاب",
|
||||
"Auto-save last book cover": "حفظ غلاف الكتاب الأخير تلقائيًا"
|
||||
}
|
||||
|
||||
@@ -644,5 +644,7 @@
|
||||
"Outline": "বাহিরের রেখা",
|
||||
"Save Current Color": "বর্তমান রঙ সংরক্ষণ করুন",
|
||||
"Quick Colors": "দ্রুত রংসমূহ",
|
||||
"Highlighter": "হাইলাইটার"
|
||||
"Highlighter": "হাইলাইটার",
|
||||
"Save Book Cover": "বইয়ের মলাট সংরক্ষণ করুন",
|
||||
"Auto-save last book cover": "শেষ বইয়ের মলাট স্বয়ংক্রিয়ভাবে সংরক্ষণ করুন"
|
||||
}
|
||||
|
||||
@@ -640,5 +640,7 @@
|
||||
"Outline": "མཐའ་ཐིག",
|
||||
"Save Current Color": "མིག་སྔའི་ཚོན་གཏན་འཁེལ་བྱེད།",
|
||||
"Quick Colors": "མྱུར་ཚོན།",
|
||||
"Highlighter": "མདོག་ཚད་ཀྱི་བསྡུར་བ།"
|
||||
"Highlighter": "མདོག་ཚད་ཀྱི་བསྡུར་བ།",
|
||||
"Save Book Cover": "དེབ་གནས་བཅས་པའི་སྤྱོད་བྱས་མ་ཐུབ།",
|
||||
"Auto-save last book cover": "དེབ་གནས་བཅས་པའི་སྤྱོད་བྱས་མ་ཐུབ།"
|
||||
}
|
||||
|
||||
@@ -644,5 +644,7 @@
|
||||
"Outline": "Umriss",
|
||||
"Save Current Color": "Aktuelle Farbe speichern",
|
||||
"Quick Colors": "Schnellfarben",
|
||||
"Highlighter": "Textmarker"
|
||||
"Highlighter": "Textmarker",
|
||||
"Save Book Cover": "Buchcover speichern",
|
||||
"Auto-save last book cover": "Letztes Buchcover automatisch speichern"
|
||||
}
|
||||
|
||||
@@ -644,5 +644,7 @@
|
||||
"Outline": "Περίγραμμα",
|
||||
"Save Current Color": "Αποθήκευση τρέχουσας χρώματος",
|
||||
"Quick Colors": "Γρήγορα χρώματα",
|
||||
"Highlighter": "Υπογραμμιστής"
|
||||
"Highlighter": "Υπογραμμιστής",
|
||||
"Save Book Cover": "Αποθήκευση εξωφύλλου βιβλίου",
|
||||
"Auto-save last book cover": "Αυτόματη αποθήκευση τελευταίου εξωφύλλου βιβλίου"
|
||||
}
|
||||
|
||||
@@ -648,5 +648,7 @@
|
||||
"Outline": "Contorno",
|
||||
"Save Current Color": "Guardar Color Actual",
|
||||
"Quick Colors": "Colores Rápidos",
|
||||
"Highlighter": "Resaltador"
|
||||
"Highlighter": "Resaltador",
|
||||
"Save Book Cover": "Guardar Portada del Libro",
|
||||
"Auto-save last book cover": "Guardar automáticamente la última portada del libro"
|
||||
}
|
||||
|
||||
@@ -644,5 +644,7 @@
|
||||
"Outline": "خطکشی",
|
||||
"Save Current Color": "ذخیره رنگ فعلی",
|
||||
"Quick Colors": "رنگهای سریع",
|
||||
"Highlighter": "ماژیک هایلایت"
|
||||
"Highlighter": "ماژیک هایلایت",
|
||||
"Save Book Cover": "ذخیره جلد کتاب",
|
||||
"Auto-save last book cover": "ذخیره خودکار آخرین جلد کتاب"
|
||||
}
|
||||
|
||||
@@ -648,5 +648,7 @@
|
||||
"Outline": "Contour",
|
||||
"Save Current Color": "Enregistrer la Couleur Actuelle",
|
||||
"Quick Colors": "Couleurs Rapides",
|
||||
"Highlighter": "Surligneur"
|
||||
"Highlighter": "Surligneur",
|
||||
"Save Book Cover": "Enregistrer la Couverture du Livre",
|
||||
"Auto-save last book cover": "Enregistrer automatiquement la dernière couverture du livre"
|
||||
}
|
||||
|
||||
@@ -644,5 +644,7 @@
|
||||
"Outline": "आउटलाइन",
|
||||
"Save Current Color": "वर्तमान रंग सहेजें",
|
||||
"Quick Colors": "त्वरित रंग",
|
||||
"Highlighter": "हाइलाइटर"
|
||||
"Highlighter": "हाइलाइटर",
|
||||
"Save Book Cover": "बुक कवर सहेजें",
|
||||
"Auto-save last book cover": "अंतिम पुस्तक कवर को स्वचालित रूप से सहेजें"
|
||||
}
|
||||
|
||||
@@ -640,5 +640,7 @@
|
||||
"Outline": "Garis Besar",
|
||||
"Save Current Color": "Simpan Warna Saat Ini",
|
||||
"Quick Colors": "Warna Cepat",
|
||||
"Highlighter": "Penyorot"
|
||||
"Highlighter": "Penyorot",
|
||||
"Save Book Cover": "Simpan Sampul Buku",
|
||||
"Auto-save last book cover": "Simpan otomatis sampul buku terakhir"
|
||||
}
|
||||
|
||||
@@ -648,5 +648,7 @@
|
||||
"Outline": "Contorno",
|
||||
"Save Current Color": "Salva Colore Corrente",
|
||||
"Quick Colors": "Colori Veloci",
|
||||
"Highlighter": "Evidenziatore"
|
||||
"Highlighter": "Evidenziatore",
|
||||
"Save Book Cover": "Salva Copertina del Libro",
|
||||
"Auto-save last book cover": "Salva automaticamente l'ultima copertina del libro"
|
||||
}
|
||||
|
||||
@@ -640,5 +640,7 @@
|
||||
"Outline": "アウトライン",
|
||||
"Save Current Color": "現在の色を保存",
|
||||
"Quick Colors": "クイックカラー",
|
||||
"Highlighter": "蛍光ペン"
|
||||
"Highlighter": "蛍光ペン",
|
||||
"Save Book Cover": "本のカバーを保存",
|
||||
"Auto-save last book cover": "最後の本のカバーを自動保存"
|
||||
}
|
||||
|
||||
@@ -640,5 +640,7 @@
|
||||
"Outline": "윤곽선",
|
||||
"Save Current Color": "현재 색상 저장",
|
||||
"Quick Colors": "빠른 색상",
|
||||
"Highlighter": "형광펜"
|
||||
"Highlighter": "형광펜",
|
||||
"Save Book Cover": "책 표지 저장",
|
||||
"Auto-save last book cover": "마지막 책 표지 자동 저장"
|
||||
}
|
||||
|
||||
@@ -644,5 +644,7 @@
|
||||
"Outline": "Omtrek",
|
||||
"Save Current Color": "Huidige kleur opslaan",
|
||||
"Quick Colors": "Snelle kleuren",
|
||||
"Highlighter": "Marker"
|
||||
"Highlighter": "Marker",
|
||||
"Save Book Cover": "Opslaan boekomslag",
|
||||
"Auto-save last book cover": "Automatisch opslaan laatste boekomslag"
|
||||
}
|
||||
|
||||
@@ -652,5 +652,7 @@
|
||||
"Outline": "Obrys",
|
||||
"Save Current Color": "Zapisz bieżący kolor",
|
||||
"Quick Colors": "Szybkie kolory",
|
||||
"Highlighter": "Zakreślacz"
|
||||
"Highlighter": "Zakreślacz",
|
||||
"Save Book Cover": "Zapisz okładkę książki",
|
||||
"Auto-save last book cover": "Automatyczne zapisywanie ostatniej okładki książki"
|
||||
}
|
||||
|
||||
@@ -648,5 +648,7 @@
|
||||
"Outline": "Contorno",
|
||||
"Save Current Color": "Salvar cor atual",
|
||||
"Quick Colors": "Cores rápidas",
|
||||
"Highlighter": "Marcador"
|
||||
"Highlighter": "Marcador",
|
||||
"Save Book Cover": "Salvar Capa do Livro",
|
||||
"Auto-save last book cover": "Salvar automaticamente a última capa do livro"
|
||||
}
|
||||
|
||||
@@ -652,5 +652,7 @@
|
||||
"Outline": "Контур",
|
||||
"Save Current Color": "Сохранить текущий цвет",
|
||||
"Quick Colors": "Быстрые цвета",
|
||||
"Highlighter": "Маркер"
|
||||
"Highlighter": "Маркер",
|
||||
"Save Book Cover": "Сохранить обложку книги",
|
||||
"Auto-save last book cover": "Автоматически сохранять последнюю обложку книги"
|
||||
}
|
||||
|
||||
@@ -644,5 +644,7 @@
|
||||
"Outline": "පරිසීමාව",
|
||||
"Save Current Color": "දැන් ඇති වර්ණය සුරකින්න",
|
||||
"Quick Colors": "ක්ෂණික වර්ණ",
|
||||
"Highlighter": "ඉස්මතු කරන්නා"
|
||||
"Highlighter": "ඉස්මතු කරන්නා",
|
||||
"Save Book Cover": "පොත් ආවරණය සුරකින්න",
|
||||
"Auto-save last book cover": "අවසන් පොත් ආවරණය ස්වයංක්රීයව සුරකින්න"
|
||||
}
|
||||
|
||||
@@ -644,5 +644,7 @@
|
||||
"Outline": "Kontur",
|
||||
"Save Current Color": "Spara aktuell färg",
|
||||
"Quick Colors": "Snabba färger",
|
||||
"Highlighter": "Markeringspenna"
|
||||
"Highlighter": "Markeringspenna",
|
||||
"Save Book Cover": "Spara bokomslag",
|
||||
"Auto-save last book cover": "Automatiskt spara senaste bokomslag"
|
||||
}
|
||||
|
||||
@@ -644,5 +644,7 @@
|
||||
"Outline": "வட்டம்",
|
||||
"Save Current Color": "தற்போதைய நிறத்தை சேமிக்கவும்",
|
||||
"Quick Colors": "விரைவு நிறங்கள்",
|
||||
"Highlighter": "ஹைலைட்டர்"
|
||||
"Highlighter": "ஹைலைட்டர்",
|
||||
"Save Book Cover": "புத்தகக் கோப்பைச் சேமிக்கவும்",
|
||||
"Auto-save last book cover": "அවසන් புத்தகக் கோப்பு காலியாக உள்ளது"
|
||||
}
|
||||
|
||||
@@ -640,5 +640,7 @@
|
||||
"Outline": "เส้นขอบ",
|
||||
"Save Current Color": "บันทึกสีปัจจุบัน",
|
||||
"Quick Colors": "สีด่วน",
|
||||
"Highlighter": "ปากกาเน้นข้อความ"
|
||||
"Highlighter": "ปากกาเน้นข้อความ",
|
||||
"Save Book Cover": "บันทึกปกหนังสือ",
|
||||
"Auto-save last book cover": "บันทึกปกหนังสือสุดท้ายโดยอัตโนมัติ"
|
||||
}
|
||||
|
||||
@@ -644,5 +644,7 @@
|
||||
"Outline": "Kontur",
|
||||
"Save Current Color": "Mevcut Rengi Kaydet",
|
||||
"Quick Colors": "Hızlı Renkler",
|
||||
"Highlighter": "Vurgulayıcı"
|
||||
"Highlighter": "Vurgulayıcı",
|
||||
"Save Book Cover": "Kitap Kapağını Kaydet",
|
||||
"Auto-save last book cover": "Son kitap kapağını otomatik olarak kaydet"
|
||||
}
|
||||
|
||||
@@ -652,5 +652,7 @@
|
||||
"Outline": "Контур",
|
||||
"Save Current Color": "Зберегти поточний колір",
|
||||
"Quick Colors": "Швидкі кольори",
|
||||
"Highlighter": "Маркер"
|
||||
"Highlighter": "Маркер",
|
||||
"Save Book Cover": "Зберегти обкладинку книги",
|
||||
"Auto-save last book cover": "Автоматично зберегти останню обкладинку книги"
|
||||
}
|
||||
|
||||
@@ -640,5 +640,7 @@
|
||||
"Outline": "Đường viền",
|
||||
"Save Current Color": "Lưu màu hiện tại",
|
||||
"Quick Colors": "Màu nhanh",
|
||||
"Highlighter": "Bút đánh dấu"
|
||||
"Highlighter": "Bút đánh dấu",
|
||||
"Save Book Cover": "Lưu bìa sách",
|
||||
"Auto-save last book cover": "Tự động lưu bìa sách cuối cùng"
|
||||
}
|
||||
|
||||
@@ -640,5 +640,7 @@
|
||||
"Outline": "轮廓",
|
||||
"Save Current Color": "保存当前颜色",
|
||||
"Quick Colors": "快速颜色",
|
||||
"Highlighter": "荧光笔"
|
||||
"Highlighter": "荧光笔",
|
||||
"Save Book Cover": "保存书籍封面",
|
||||
"Auto-save last book cover": "自动保存最后一本书的封面"
|
||||
}
|
||||
|
||||
@@ -640,5 +640,7 @@
|
||||
"Outline": "輪廓",
|
||||
"Save Current Color": "儲存目前顏色",
|
||||
"Quick Colors": "快速顏色",
|
||||
"Highlighter": "螢光筆"
|
||||
"Highlighter": "螢光筆",
|
||||
"Save Book Cover": "保存書籍封面",
|
||||
"Auto-save last book cover": "自動保存最後一本書的封面"
|
||||
}
|
||||
|
||||
@@ -53,6 +53,9 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ setIsDropdownOpen }) => {
|
||||
);
|
||||
const [isTelemetryEnabled, setIsTelemetryEnabled] = useState(settings.telemetryEnabled);
|
||||
const [alwaysInForeground, setAlwaysInForeground] = useState(settings.alwaysInForeground);
|
||||
const [savedBookCoverForLockScreen, setSavedBookCoverForLockScreen] = useState(
|
||||
settings.savedBookCoverForLockScreen || '',
|
||||
);
|
||||
const iconSize = useResponsiveSize(16);
|
||||
|
||||
const showAboutReadest = () => {
|
||||
@@ -169,6 +172,12 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ setIsDropdownOpen }) => {
|
||||
setSettingsDialogOpen(true);
|
||||
};
|
||||
|
||||
const handleSetSavedBookCoverForLockScreen = () => {
|
||||
const newValue = settings.savedBookCoverForLockScreen ? '' : 'default';
|
||||
saveSysSettings(envConfig, 'savedBookCoverForLockScreen', newValue);
|
||||
setSavedBookCoverForLockScreen(newValue);
|
||||
};
|
||||
|
||||
const toggleAlwaysInForeground = async () => {
|
||||
const requestAlwaysInForeground = !settings.alwaysInForeground;
|
||||
|
||||
@@ -299,7 +308,20 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ setIsDropdownOpen }) => {
|
||||
<hr aria-hidden='true' className='border-base-200 my-1' />
|
||||
<MenuItem label={_('Advanced Settings')}>
|
||||
<ul className='flex flex-col'>
|
||||
<MenuItem label={_('Change Data Location')} noIcon onClick={handleSetRootDir} />
|
||||
<MenuItem
|
||||
label={_('Change Data Location')}
|
||||
noIcon={!appService?.isAndroidApp}
|
||||
onClick={handleSetRootDir}
|
||||
/>
|
||||
{appService?.isAndroidApp && (
|
||||
<MenuItem
|
||||
label={_('Save Book Cover')}
|
||||
tooltip={_('Auto-save last book cover')}
|
||||
description={'💾 Images/last-book-cover.png'}
|
||||
toggled={!!savedBookCoverForLockScreen}
|
||||
onClick={handleSetSavedBookCoverForLockScreen}
|
||||
/>
|
||||
)}
|
||||
</ul>
|
||||
</MenuItem>
|
||||
</>
|
||||
|
||||
@@ -50,6 +50,7 @@ import { TransformContext } from '@/services/transformers/types';
|
||||
import { transformContent } from '@/services/transformService';
|
||||
import { lockScreenOrientation } from '@/utils/bridge';
|
||||
import { useTextTranslation } from '../hooks/useTextTranslation';
|
||||
import { useBookCoverAutoSave } from '../hooks/useAutoSaveBookCover';
|
||||
import { manageSyntaxHighlighting } from '@/utils/highlightjs';
|
||||
import { getViewInsets } from '@/utils/insets';
|
||||
import { removeTabIndex } from '@/utils/a11y';
|
||||
@@ -101,6 +102,7 @@ const FoliateViewer: React.FC<{
|
||||
useUICSS(bookKey);
|
||||
useProgressSync(bookKey);
|
||||
useProgressAutoSave(bookKey);
|
||||
useBookCoverAutoSave(bookKey);
|
||||
const { syncState, conflictDetails, resolveWithLocal, resolveWithRemote } = useKOSync(bookKey);
|
||||
useTextTranslation(bookKey, viewRef.current);
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useBookDataStore } from '@/store/bookDataStore';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { throttle } from '@/utils/throttle';
|
||||
import { getCoverFilename } from '@/utils/book';
|
||||
|
||||
export const useBookCoverAutoSave = (bookKey: string) => {
|
||||
const { envConfig, appService } = useEnv();
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const saveBookCover = useCallback(
|
||||
throttle(
|
||||
() => {
|
||||
setTimeout(async () => {
|
||||
const settings = useSettingsStore.getState().settings;
|
||||
const bookData = useBookDataStore.getState().getBookData(bookKey);
|
||||
const book = bookData?.book;
|
||||
const savedBookHash = settings.savedBookCoverForLockScreen;
|
||||
if (appService && book && savedBookHash && savedBookHash !== book?.hash) {
|
||||
const coverPath = await appService.resolveFilePath(getCoverFilename(book), 'Books');
|
||||
try {
|
||||
await appService.copyFile(coverPath, 'last-book-cover.png', 'Images');
|
||||
settings.savedBookCoverForLockScreen = book.hash;
|
||||
useSettingsStore.getState().setSettings(settings);
|
||||
useSettingsStore.getState().saveSettings(envConfig, settings);
|
||||
} catch (error) {
|
||||
console.error('Failed to auto-save book cover for lock screen:', error);
|
||||
}
|
||||
}
|
||||
}, 5000);
|
||||
},
|
||||
5000,
|
||||
{ emitLast: false },
|
||||
),
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
saveBookCover();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
};
|
||||
@@ -38,6 +38,7 @@ import { getOSPlatform, isContentURI, isValidURL } from '@/utils/misc';
|
||||
import { getDirPath, getFilename } from '@/utils/path';
|
||||
import { NativeFile, RemoteFile } from '@/utils/file';
|
||||
import { copyURIToPath } from '@/utils/bridge';
|
||||
import { copyFiles } from '@/utils/files';
|
||||
|
||||
import { BaseAppService } from './appService';
|
||||
import {
|
||||
@@ -78,7 +79,8 @@ const getPathResolver = ({
|
||||
const getCustomBasePrefixSync = isCustomBaseDir
|
||||
? (baseDir: BaseDir) => {
|
||||
return () => {
|
||||
const leafDir = ['Settings', 'Data', 'Books', 'Fonts'].includes(baseDir) ? '' : baseDir;
|
||||
const dataDirs = ['Settings', 'Data', 'Books', 'Fonts', 'Images'];
|
||||
const leafDir = dataDirs.includes(baseDir) ? '' : baseDir;
|
||||
return leafDir ? `${customRootDir}/${leafDir}` : customRootDir!;
|
||||
};
|
||||
}
|
||||
@@ -392,6 +394,33 @@ export class NativeAppService extends BaseAppService {
|
||||
});
|
||||
}
|
||||
await this.prepareBooksDir();
|
||||
await this.runMigrations();
|
||||
}
|
||||
|
||||
private CURRENT_MIGRATION_VERSION = 20251029;
|
||||
|
||||
private async runMigrations() {
|
||||
try {
|
||||
const settings = await this.loadSettings();
|
||||
const lastMigrationVersion = settings.migrationVersion || 0;
|
||||
|
||||
if (lastMigrationVersion < 20251029) {
|
||||
try {
|
||||
await this.migrate20251029();
|
||||
} catch (error) {
|
||||
console.error('Error migrating to version 20251029:', error);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastMigrationVersion < this.CURRENT_MIGRATION_VERSION) {
|
||||
await this.saveSettings({
|
||||
...settings,
|
||||
migrationVersion: this.CURRENT_MIGRATION_VERSION,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to run migrations:', error);
|
||||
}
|
||||
}
|
||||
|
||||
override resolvePath(fp: string, base: BaseDir): ResolvedPath {
|
||||
@@ -422,4 +451,16 @@ export class NativeAppService extends BaseAppService {
|
||||
});
|
||||
return Array.isArray(selected) ? selected : selected ? [selected] : [];
|
||||
}
|
||||
|
||||
async migrate20251029() {
|
||||
console.log('Running migration 20251029 to update paths in Images dir...');
|
||||
const rootPath = await this.resolveFilePath('..', 'Data');
|
||||
const newDir = await this.fs.getPrefix('Images');
|
||||
const oldDir = await join(rootPath, 'Images', 'Readest', 'Images');
|
||||
|
||||
await copyFiles(this, oldDir, newDir);
|
||||
|
||||
const dirToDelete = await join(rootPath, 'Images', 'Readest');
|
||||
await this.deleteDir(dirToDelete, 'None', true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ export interface SystemSettings {
|
||||
openLastBooks: boolean;
|
||||
lastOpenBooks: string[];
|
||||
autoImportBooksOnOpen: boolean;
|
||||
savedBookCoverForLockScreen: string;
|
||||
telemetryEnabled: boolean;
|
||||
libraryViewMode: LibraryViewModeType;
|
||||
librarySortBy: LibrarySortByType;
|
||||
@@ -70,6 +71,8 @@ export interface SystemSettings {
|
||||
lastSyncedAtConfigs: number;
|
||||
lastSyncedAtNotes: number;
|
||||
|
||||
migrationVersion: number;
|
||||
|
||||
globalReadSettings: ReadSettings;
|
||||
globalViewSettings: ViewSettings;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { AppService, FileItem } from '@/types/system';
|
||||
|
||||
export const copyFiles = async (appService: AppService, srcDir: string, dstDir: string) => {
|
||||
let filesToCopy: FileItem[] = [];
|
||||
try {
|
||||
filesToCopy = await appService.readDirectory(srcDir, 'None');
|
||||
} catch (error) {
|
||||
throw new Error(`Dir ${srcDir} failed to read.`);
|
||||
}
|
||||
|
||||
for (let i = 0; i < filesToCopy.length; i++) {
|
||||
const file = filesToCopy[i]!;
|
||||
const srcPath = `${srcDir}/${file.path}`;
|
||||
const destPath = `${dstDir}/${file.path}`;
|
||||
await appService.copyFile(srcPath, destPath, 'None');
|
||||
}
|
||||
|
||||
const filesCopied = await appService.readDirectory(dstDir, 'None');
|
||||
for (const file of filesToCopy) {
|
||||
if (!filesCopied.find((f) => f.path === file.path && f.size === file.size)) {
|
||||
throw new Error(`File ${file.path} failed to copy.`);
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user