Various fixes (#56)

* Add missing translation for progress synced toast

* Graceful shutdown after all books closed, closes #50

* Throttle app update check to once every day

* Avoid infinite loop to redirect to the login page, closes #54
This commit is contained in:
Huang Xin
2024-12-27 16:59:06 +01:00
committed by GitHub
parent cb2c7b5c89
commit 3dcab5a1ee
23 changed files with 73 additions and 17 deletions
@@ -26,5 +26,6 @@ module.exports = {
},
metadata: {},
allowDynamicKeys: true,
removeUnusedKeys: true,
},
};
@@ -74,6 +74,7 @@
"Parallel Read": "Paralleles Lesen",
"Published:": "Veröffentlicht:",
"Publisher:": "Verlag:",
"Reading progress synced": "Lesevorgang synchronisiert",
"Reload Page": "Seite neu laden",
"Reveal in File Explorer": "Im Datei-Explorer anzeigen",
"Reveal in Finder": "Im Finder anzeigen",
@@ -74,6 +74,7 @@
"Parallel Read": "Lectura paralela",
"Published:": "Publicado:",
"Publisher:": "Editorial:",
"Reading progress synced": "Progreso de lectura sincronizado",
"Reload Page": "Recargar página",
"Reveal in File Explorer": "Mostrar en el Explorador de archivos",
"Reveal in Finder": "Mostrar en Finder",
@@ -74,6 +74,7 @@
"Parallel Read": "Lecture parallèle",
"Published:": "Publié :",
"Publisher:": "Éditeur :",
"Reading progress synced": "Progression de lecture synchronisée",
"Reload Page": "Recharger la page",
"Reveal in File Explorer": "Afficher dans l'explorateur de fichiers",
"Reveal in Finder": "Afficher dans le Finder",
@@ -74,6 +74,7 @@
"Parallel Read": "Baca Paralel",
"Published:": "Diterbitkan:",
"Publisher:": "Penerbit:",
"Reading progress synced": "Progres membaca disinkronkan",
"Reload Page": "Muat Ulang Halaman",
"Reveal in File Explorer": "Tampilkan di File Explorer",
"Reveal in Finder": "Tampilkan di Finder",
@@ -74,6 +74,7 @@
"Parallel Read": "Lettura parallela",
"Published:": "Pubblicato:",
"Publisher:": "Editore:",
"Reading progress synced": "Progresso lettura sincronizzato",
"Reload Page": "Ricarica pagina",
"Reveal in File Explorer": "Mostra in Esplora file",
"Reveal in Finder": "Mostra nel Finder",
@@ -74,6 +74,7 @@
"Parallel Read": "並列読書",
"Published:": "出版日:",
"Publisher:": "出版社:",
"Reading progress synced": "読書進捗が同期されました",
"Reload Page": "ページを再読み込み",
"Reveal in File Explorer": "エクスプローラーで表示",
"Reveal in Finder": "Finderで表示",
@@ -74,6 +74,7 @@
"Parallel Read": "병렬 읽기",
"Published:": "출판일:",
"Publisher:": "출판사:",
"Reading progress synced": "읽기 진행 상황 동기화됨",
"Reload Page": "페이지 새로고침",
"Reveal in File Explorer": "파일 탐색기에서 표시",
"Reveal in Finder": "Finder에서 표시",
@@ -74,6 +74,7 @@
"Parallel Read": "Leitura Paralela",
"Published:": "Publicado:",
"Publisher:": "Editora:",
"Reading progress synced": "Progresso de leitura sincronizado",
"Reload Page": "Recarregar Página",
"Reveal in File Explorer": "Mostrar no Explorador de Arquivos",
"Reveal in Finder": "Mostrar no Finder",
@@ -74,6 +74,7 @@
"Parallel Read": "Параллельное чтение",
"Published:": "Опубликовано:",
"Publisher:": "Издатель:",
"Reading progress synced": "Синхронизирован прогресс чтения",
"Reload Page": "Перезагрузить страницу",
"Reveal in File Explorer": "Показать в проводнике",
"Reveal in Finder": "Показать в Finder",
@@ -74,6 +74,7 @@
"Parallel Read": "Paralel Okuma",
"Published:": "Yayınlanma:",
"Publisher:": "Yayıncı:",
"Reading progress synced": "Okuma ilerlemesi senkronize edildi",
"Reload Page": "Sayfayı Yenile",
"Reveal in File Explorer": "Dosya Gezgininde Göster",
"Reveal in Finder": "Finder'da Göster",
@@ -74,6 +74,7 @@
"Parallel Read": "Đọc song song",
"Published:": "Xuất bản:",
"Publisher:": "Nhà xuất bản:",
"Reading progress synced": "Tiến độ đọc đã được đồng bộ",
"Reload Page": "Tải lại trang",
"Reveal in File Explorer": "Hiển thị trong File Explorer",
"Reveal in Finder": "Hiển thị trong Finder",
@@ -74,6 +74,7 @@
"Parallel Read": "并排阅读",
"Published:": "出版日期",
"Publisher:": "出版商",
"Reading progress synced": "阅读进度已同步",
"Reload Page": "重新加载页面",
"Reveal in File Explorer": "在文件管理器中显示",
"Reveal in Finder": "在访达中显示",
@@ -74,6 +74,7 @@
"Parallel Read": "並排閱讀",
"Published:": "出版日期",
"Publisher:": "出版商",
"Reading progress synced": "閱讀進度已同步",
"Reload Page": "重新載入頁面",
"Reveal in File Explorer": "在檔案管理器中顯示",
"Reveal in Finder": "在訪達中顯示",
@@ -57,6 +57,7 @@
"shell:default",
"updater:default",
"process:default",
"process:allow-exit",
"process:allow-restart",
"cli:default",
"oauth:allow-start",
+7 -2
View File
@@ -73,6 +73,7 @@ async fn start_server(window: Window) -> Result<u16, String> {
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
let builder = tauri::Builder::default()
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_oauth::init())
.invoke_handler(tauri::generate_handler![start_server])
@@ -137,10 +138,14 @@ pub fn run() {
#[cfg(target_os = "macos")]
let win_builder = win_builder
.decorations(true)
.title_bar_style(TitleBarStyle::Overlay).title("");
.title_bar_style(TitleBarStyle::Overlay)
.title("");
#[cfg(not(target_os = "macos"))]
let win_builder = win_builder.decorations(false).transparent(true).title("Readest");
let win_builder = win_builder
.decorations(false)
.transparent(true)
.title("Readest");
win_builder.build().unwrap();
// let win = win_builder.build().unwrap();
+15 -3
View File
@@ -9,15 +9,17 @@ import { FcGoogle } from 'react-icons/fc';
import { FaApple } from 'react-icons/fa';
import { VscAzure } from 'react-icons/vsc';
import { FaGithub } from 'react-icons/fa';
import { IoArrowBack } from 'react-icons/io5';
import { useAuth } from '@/context/AuthContext';
import { supabase } from '@/utils/supabase';
import { useTheme } from '@/hooks/useTheme';
import { useEnv } from '@/context/EnvContext';
import { useSettingsStore } from '@/store/settingsStore';
import { isTauriAppPlatform } from '@/services/environment';
import { start, cancel, onUrl, onInvalidUrl } from '@fabianlars/tauri-plugin-oauth';
import { openUrl } from '@tauri-apps/plugin-opener';
import { handleAuthCallback } from '@/helpers/auth';
import { IoArrowBack } from 'react-icons/io5';
type OAuthProvider = 'google' | 'apple' | 'azure' | 'github';
@@ -46,7 +48,9 @@ const ProviderLogin: React.FC<ProviderLoginProp> = ({ provider, handleSignIn, Ic
export default function AuthPage() {
const router = useRouter();
const { login } = useAuth();
const { envConfig } = useEnv();
const { isDarkMode } = useTheme();
const { settings, setSettings, saveSettings } = useSettingsStore();
const [port, setPort] = useState<number | null>(null);
const isOAuthServerRunning = useRef(false);
const [isMounted, setIsMounted] = useState(false);
@@ -109,6 +113,14 @@ export default function AuthPage() {
}
};
const handleGoBack = () => {
// Keep login false to avoid infinite loop to redirect to the login page
settings.keepLogin = false;
setSettings(settings);
saveSettings(envConfig, settings);
router.back();
};
useEffect(() => {
if (!isTauriAppPlatform()) return;
if (isOAuthServerRunning.current) return;
@@ -147,7 +159,7 @@ export default function AuthPage() {
return isTauriAppPlatform() ? (
<div className='flex pt-11'>
<button
onClick={() => router.back()}
onClick={handleGoBack}
className='btn btn-ghost fixed left-3 top-11 h-8 min-h-8 w-8 p-0'
>
<IoArrowBack size={20} />
@@ -191,7 +203,7 @@ export default function AuthPage() {
) : (
<div style={{ maxWidth: '420px', margin: 'auto', padding: '2rem', paddingTop: '4rem' }}>
<button
onClick={() => router.back()}
onClick={handleGoBack}
className='btn btn-ghost fixed left-10 top-6 h-8 min-h-8 w-8 p-0'
>
<IoArrowBack size={20} />
@@ -11,7 +11,8 @@ import { useReaderStore } from '@/store/readerStore';
import { useSidebarStore } from '@/store/sidebarStore';
import { SystemSettings } from '@/types/settings';
import { parseOpenWithFiles } from '@/helpers/cli';
import { tauriHandleClose } from '@/utils/window';
import { tauriHandleClose, tauriHandleOnCloseWindow } from '@/utils/window';
import { isTauriAppPlatform } from '@/services/environment';
import { uniqueId } from '@/utils/misc';
import { navigateToLibrary } from '@/utils/nav';
import { BOOK_IDS_SEPARATOR } from '@/services/constants';
@@ -61,6 +62,7 @@ const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ i
}, []);
useEffect(() => {
if (isTauriAppPlatform()) tauriHandleOnCloseWindow(handleCloseBooks);
window.addEventListener('beforeunload', handleCloseBooks);
return () => {
window.removeEventListener('beforeunload', handleCloseBooks);
@@ -68,12 +70,12 @@ const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ i
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [bookKeys]);
const saveBookConfig = (bookKey: string) => {
const saveBookConfig = async (bookKey: string) => {
const config = getConfig(bookKey);
const { book } = getBookData(bookKey) || {};
const { isPrimary } = getViewState(bookKey) || {};
if (isPrimary && book && config) {
saveConfig(envConfig, bookKey, config, settings);
await saveConfig(envConfig, bookKey, config, settings);
}
};
@@ -81,7 +83,7 @@ const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ i
console.log('Closing book', bookKey);
getView(bookKey)?.close();
getView(bookKey)?.remove();
saveBookConfig(bookKey);
await saveBookConfig(bookKey);
clearViewState(bookKey);
};
@@ -90,11 +92,9 @@ const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ i
navigateToLibrary(router);
};
const handleCloseBooks = () => {
bookKeys.forEach((key) => {
saveConfigAndCloseBook(key);
});
saveSettings(envConfig, settings);
const handleCloseBooks = async () => {
await Promise.all(bookKeys.map((key) => saveConfigAndCloseBook(key)));
await saveSettings(envConfig, settings);
};
const handleCloseBooksToLibrary = () => {
@@ -5,6 +5,7 @@ import { BookConfig } from '@/types/book';
import { useBookDataStore } from '@/store/bookDataStore';
import { useReaderStore } from '@/store/readerStore';
import { useSettingsStore } from '@/store/settingsStore';
import { useTranslation } from '@/hooks/useTranslation';
import { deserializeConfig, serializeConfig } from '@/utils/serializer';
import { DEFAULT_BOOK_SEARCH_CONFIG, SYNC_PROGRESS_INTERVAL_SEC } from '@/services/constants';
@@ -12,6 +13,7 @@ export const useProgressSync = (
bookKey: string,
setToastMessage?: React.Dispatch<React.SetStateAction<string>>,
) => {
const _ = useTranslation();
const { getConfig, setConfig } = useBookDataStore();
const { getView } = useReaderStore();
const { settings } = useSettingsStore();
@@ -81,7 +83,7 @@ export const useProgressSync = (
const configFraction = config!.progress![0] / config!.progress![1];
if (syncedFraction > configFraction) {
view?.goToFraction(syncedFraction);
setToastMessage?.('Progress synced');
setToastMessage?.(_('Reading progress synced'));
}
}
}
+9
View File
@@ -1,9 +1,18 @@
import { check } from '@tauri-apps/plugin-updater';
import { ask } from '@tauri-apps/plugin-dialog';
import { relaunch } from '@tauri-apps/plugin-process';
import { CHECK_UPDATE_INTERVAL_SEC } from '@/services/constants';
const LAST_CHECK_KEY = 'lastAppUpdateCheck';
export const checkForAppUpdates = async () => {
const lastCheck = localStorage.getItem(LAST_CHECK_KEY);
const now = Date.now();
if (lastCheck && now - parseInt(lastCheck, 10) < CHECK_UPDATE_INTERVAL_SEC * 1000) return;
localStorage.setItem(LAST_CHECK_KEY, now.toString());
const update = await check();
console.log('update found', update);
if (update) {
const yes = await ask(
`
@@ -89,3 +89,4 @@ export const READEST_WEB_BASE_URL = 'https://web.readest.com';
export const SYNC_PROGRESS_INTERVAL_SEC = 60;
export const SYNC_NOTES_INTERVAL_SEC = 60;
export const CHECK_UPDATE_INTERVAL_SEC = 24 * 60 * 60;
+2 -2
View File
@@ -68,8 +68,8 @@ export const useBookDataStore = create<BookDataState>((set, get) => ({
library.unshift(book);
setLibrary(library);
config.updatedAt = Date.now();
appService.saveBookConfig(book, config, settings);
appService.saveLibraryBooks(library);
await appService.saveBookConfig(book, config, settings);
await appService.saveLibraryBooks(library);
},
updateBooknotes: (key: string, booknotes: BookNote[]) => {
let updatedConfig: BookConfig | undefined;
+12
View File
@@ -12,3 +12,15 @@ export const tauriHandleClose = async () => {
const { getCurrentWindow } = await import('@tauri-apps/api/window');
getCurrentWindow().close();
};
export const tauriHandleOnCloseWindow = async (callback: () => void) => {
const { TauriEvent } = await import('@tauri-apps/api/event');
const { getCurrentWindow } = await import('@tauri-apps/api/window');
const { exit } = await import('@tauri-apps/plugin-process');
const currentWindow = getCurrentWindow();
return currentWindow.listen(TauriEvent.WINDOW_CLOSE_REQUESTED, async () => {
await callback();
console.log('exit app');
await exit(0);
});
};