From 2dcb5d7c1ea498a38647f08f00078709390797d5 Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Fri, 20 Jun 2025 22:45:10 +0800 Subject: [PATCH] sync: add network timeout of sync to 5 sec (#1432) * sync: add network timeout of sync to 5 sec * css: minor tweaks on headings and list --- apps/readest-app/src/libs/sync.ts | 31 +++++++++++++++++++---------- apps/readest-app/src/utils/fetch.ts | 10 ++++++++++ apps/readest-app/src/utils/style.ts | 5 ++++- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/apps/readest-app/src/libs/sync.ts b/apps/readest-app/src/libs/sync.ts index 398ddb18..dc39cd1a 100644 --- a/apps/readest-app/src/libs/sync.ts +++ b/apps/readest-app/src/libs/sync.ts @@ -1,6 +1,7 @@ import { Book, BookConfig, BookNote, BookDataRecord } from '@/types/book'; import { getAPIBaseUrl } from '@/services/environment'; import { getAccessToken } from '@/utils/access'; +import { fetchWithTimeout } from '@/utils/fetch'; const SYNC_API_ENDPOINT = getAPIBaseUrl() + '/sync'; @@ -33,11 +34,15 @@ export class SyncClient { if (!token) throw new Error('Not authenticated'); const url = `${SYNC_API_ENDPOINT}?since=${encodeURIComponent(since)}&type=${type ?? ''}&book=${book ?? ''}`; - const res = await fetch(url, { - headers: { - Authorization: `Bearer ${token}`, + const res = await fetchWithTimeout( + url, + { + headers: { + Authorization: `Bearer ${token}`, + }, }, - }); + 5000, + ); if (!res.ok) { const error = await res.json(); @@ -55,14 +60,18 @@ export class SyncClient { const token = await getAccessToken(); if (!token) throw new Error('Not authenticated'); - const res = await fetch(SYNC_API_ENDPOINT, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${token}`, + const res = await fetchWithTimeout( + SYNC_API_ENDPOINT, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify(payload), }, - body: JSON.stringify(payload), - }); + 5000, + ); if (!res.ok) { const error = await res.json(); diff --git a/apps/readest-app/src/utils/fetch.ts b/apps/readest-app/src/utils/fetch.ts index 43670fed..94acb17a 100644 --- a/apps/readest-app/src/utils/fetch.ts +++ b/apps/readest-app/src/utils/fetch.ts @@ -1,5 +1,15 @@ import { getAccessToken } from './access'; +export const fetchWithTimeout = (url: string, options: RequestInit, timeout = 8000) => { + const controller = new AbortController(); + const id = setTimeout(() => controller.abort(), timeout); + + return fetch(url, { + ...options, + signal: controller.signal, + }).finally(() => clearTimeout(id)); +}; + export const fetchWithAuth = async (url: string, options: RequestInit) => { const token = await getAccessToken(); if (!token) { diff --git a/apps/readest-app/src/utils/style.ts b/apps/readest-app/src/utils/style.ts index 00c2f2f3..3df589e3 100644 --- a/apps/readest-app/src/utils/style.ts +++ b/apps/readest-app/src/utils/style.ts @@ -209,7 +209,7 @@ const getLayoutStyles = ( width: auto; background-color: transparent !important; } - p, li, blockquote, dd, div:not(:has(*:not(b, a, em, i, strong, u, span))) { + p, blockquote, dd, div:not(:has(*:not(b, a, em, i, strong, u, span))) { line-height: ${lineSpacing} ${overrideLayout ? '!important' : ''}; word-spacing: ${wordSpacing}px ${overrideLayout ? '!important' : ''}; letter-spacing: ${letterSpacing}px ${overrideLayout ? '!important' : ''}; @@ -240,6 +240,9 @@ const getLayoutStyles = ( ${!vertical && overrideLayout ? `margin-top: ${paragraphMargin}em !important;` : ''} ${!vertical && overrideLayout ? `margin-bottom: ${paragraphMargin}em !important;` : ''} } + h1, h2, h3, h4, h5, h6 { + text-align: initial; + } :lang(zh), :lang(ja), :lang(ko) { widows: 1;