Introduce "koration" duration api

This commit is contained in:
schroda
2025-10-11 00:39:44 +02:00
parent f961e734bc
commit f539afb404
19 changed files with 77 additions and 43 deletions

View File

@@ -7,11 +7,12 @@
*/
import { useCallback, useEffect, useMemo } from 'react';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { d } from 'koration';
import { useLocalStorage } from '@/base/hooks/useStorage.tsx';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
const UPDATE_CHECK_INTERVAL = 1000 * 60 * 60; // 1 hour
const UPDATE_REMINDER_THRESHOLD = 1000 * 60 * 60; // 1 hour
const UPDATE_CHECK_INTERVAL = d(1).hours.inWholeMilliseconds;
const UPDATE_REMINDER_THRESHOLD = d(1).hours.inWholeMilliseconds;
export const useUpdateChecker = (
storageKey: string,

View File

@@ -27,6 +27,12 @@ export const BACKUP_FLAG_GROUP_TO_TRANSLATION: Record<BackupFlagGroup, Translati
export const BACKUP_FLAGS = Object.keys(BACKUP_FLAGS_TO_TRANSLATION) as readonly BackupFlag[];
export const BACKUP_FLAGS_BY_GROUP: Record<BackupFlagGroup, BackupFlag[]> = {
[BackupFlagGroup.LIBRARY]: ['includeManga', 'includeChapters', 'includeTracking', 'includeHistory', 'includeCategories'],
[BackupFlagGroup.LIBRARY]: [
'includeManga',
'includeChapters',
'includeTracking',
'includeHistory',
'includeCategories',
],
[BackupFlagGroup.SETTINGS]: ['includeClientData', 'includeServerSettings'],
};

View File

@@ -20,8 +20,9 @@ import PushPinIcon from '@mui/icons-material/PushPin';
import DoneAllIcon from '@mui/icons-material/DoneAll';
import FilterListIcon from '@mui/icons-material/FilterList';
import { useElementSize } from '@mantine/hooks';
import IconButton from '@mui/material/IconButton'; // ms
import IconButton from '@mui/material/IconButton';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import { d } from 'koration';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { AppbarSearch } from '@/base/components/AppbarSearch.tsx';
import { useDebounce } from '@/base/hooks/useDebounce.ts';
@@ -110,7 +111,7 @@ const compareSourcesBySearchResult = (
return 0;
};
const TRIGGER_SEARCH_THRESHOLD = 1000; // ms
const TRIGGER_SEARCH_THRESHOLD = d(1).seconds.inWholeMilliseconds;
const SourceSearchPreview = React.memo(
({

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { LongPressPointerHandlers, LongPressResult } from 'use-long-press/lib/use-long-press.types';
import { LongPressPointerHandlers, LongPressResult } from 'node_modules/use-long-press/lib/use-long-press.types';
import { PopupState } from 'material-ui-popup-state/hooks';
import type { JSX } from 'react';
import { SelectableCollectionReturnType } from '@/base/collection/hooks/useSelectableCollection.ts';

View File

@@ -14,6 +14,7 @@ import Stack from '@mui/material/Stack';
import TextField from '@mui/material/TextField';
import InputAdornment from '@mui/material/InputAdornment';
import { useRef } from 'react';
import { d } from 'koration';
import { IReaderSettings } from '@/features/reader/Reader.types.ts';
import { AUTO_SCROLL_SPEED } from '@/features/reader/settings/ReaderSettings.constants.tsx';
import { coerceIn } from '@/lib/HelperFunctions.ts';
@@ -62,7 +63,10 @@ export const ReaderNavBarDesktopAutoScroll = ({
setAutoScroll({ ...autoScroll, value }, false);
clearTimeout(updateTimeout.current);
updateTimeout.current = setTimeout(() => setAutoScroll({ ...autoScroll, value }, true), 1000);
updateTimeout.current = setTimeout(
() => setAutoScroll({ ...autoScroll, value }, true),
d(1).seconds.inWholeMilliseconds,
);
}}
slotProps={{
input: {

View File

@@ -8,13 +8,14 @@
import { useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { d } from 'koration';
import { IReaderSettings, IReaderSettingsWithDefaultFlag } from '@/features/reader/Reader.types.ts';
import { makeToast } from '@/base/utils/Toast.ts';
import { READING_MODE_VALUE_TO_DISPLAY_DATA } from '@/features/reader/settings/ReaderSettings.constants.tsx';
import { TReaderTapZoneContext } from '@/features/reader/tap-zones/TapZoneLayout.types.ts';
import { TranslationKey } from '@/base/Base.types.ts';
const HIDE_PREVIEW_TIMEOUT = 5000;
const HIDE_PREVIEW_TIMEOUT = d(5).seconds.inWholeMilliseconds;
export const useReaderShowSettingPreviewOnChange = (
isLoading: boolean,

View File

@@ -9,6 +9,7 @@
import { MutableRefObject, RefObject, useCallback, useEffect } from 'react';
import { Direction } from '@mui/material/styles';
import { t as translate } from 'i18next';
import { d } from 'koration';
import {
getNextIndexFromPage,
getNextPageIndex,
@@ -473,7 +474,10 @@ export class ReaderControls {
clearTimeout(ReaderControls.updateCurrentPageTimeout);
if (debounceChapterUpdate) {
ReaderControls.updateCurrentPageTimeout = setTimeout(handleCurrentPageIndexChange, 1000);
ReaderControls.updateCurrentPageTimeout = setTimeout(
handleCurrentPageIndexChange,
d(1).seconds.inWholeMilliseconds,
);
return;
}

View File

@@ -7,6 +7,7 @@
*/
import { MutableRefObject, useEffect, useRef } from 'react';
import { d } from 'koration';
export const useReaderHideCursorOnInactivity = (scrollElementRef: MutableRefObject<HTMLDivElement | null>) => {
const mouseInactiveTimeout = useRef<NodeJS.Timeout>(undefined);
@@ -26,7 +27,7 @@ export const useReaderHideCursorOnInactivity = (scrollElementRef: MutableRefObje
clearTimeout(mouseInactiveTimeout.current);
mouseInactiveTimeout.current = setTimeout(() => {
setCursorVisibility(false);
}, 5000);
}, d(5).seconds.inWholeMilliseconds);
};
handleMouseMove();

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import dayjs from 'dayjs';
import { d } from 'koration';
import { DEFAULT_DEVICE } from '@/features/device/services/Device.ts';
import { DEFAULT_SORT_SETTINGS } from '@/features/migration/Migration.constants.ts';
import { GlobalUpdateSkipEntriesSettings, MetadataServerSettings } from '@/features/settings/Settings.types.ts';
@@ -170,9 +170,9 @@ export const WEB_UI_INTERFACE_SELECT_VALUES: SelectSettingValue<WebUiInterface>[
);
export const GLOBAL_UPDATE_INTERVAL = {
default: 12,
min: 6,
max: 24 * 7 * 4, // 1 month
default: d(12).hours.inWholeHours,
min: d(6).hours.inWholeHours,
max: d(1).months.inWholeHours,
};
export const GLOBAL_UPDATE_SKIP_ENTRIES_TO_TRANSLATION: {
@@ -184,21 +184,21 @@ export const GLOBAL_UPDATE_SKIP_ENTRIES_TO_TRANSLATION: {
};
export const WEB_UI_UPDATE_INTERVAL = {
default: 23,
min: 1,
max: 23,
default: d(23).hours.inWholeHours,
min: d(1).hours.inWholeHours,
max: d(23).hours.inWholeHours,
};
export const JWT_ACCESS_TOKEN_EXPIRY = {
default: dayjs.duration(5, 'minute').asMinutes(),
min: dayjs.duration(1, 'minute').asMinutes(),
max: dayjs.duration(4, 'hour').asMinutes(),
default: d(5).minutes.inWholeMinutes,
min: d(1).minutes.inWholeMinutes,
max: d(4).hours.inWholeMinutes,
};
export const JWT_REFRESH_TOKEN_EXPIRY = {
default: dayjs.duration(60, 'day').asDays(),
min: dayjs.duration(1, 'day').asDays(),
max: dayjs.duration(1, 'year').asDays(),
default: d(60).days.inWholeDays,
min: d(1).days.inWholeDays,
max: d(1).years.inWholeDays,
};
export const KOREADER_SYNC_PERCENTAGE_TOLERANCE = {

View File

@@ -15,7 +15,7 @@ import ListItemText from '@mui/material/ListItemText';
import Switch from '@mui/material/Switch';
import ListSubheader from '@mui/material/ListSubheader';
import { t as translate } from 'i18next';
import dayjs from 'dayjs';
import { d } from 'koration';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { TextSetting } from '@/base/components/settings/text/TextSetting.tsx';
import { NumberSetting } from '@/base/components/settings/NumberSetting.tsx';
@@ -279,28 +279,24 @@ export const ServerSettings = () => {
/>
<NumberSetting
settingTitle={t('settings.server.auth.jwt.access_token_expiry')}
settingValue={dayjs.duration(serverSettings.jwtTokenExpiry).humanize()}
value={dayjs.duration(serverSettings.jwtTokenExpiry).asMinutes()}
settingValue={d(serverSettings.jwtTokenExpiry).minutes.humanize()}
value={d(serverSettings.jwtTokenExpiry).minutes.inWholeMinutes}
valueUnit={t('global.time.minutes.minute_other')}
defaultValue={JWT_ACCESS_TOKEN_EXPIRY.default}
minValue={JWT_ACCESS_TOKEN_EXPIRY.min}
maxValue={JWT_ACCESS_TOKEN_EXPIRY.max}
handleUpdate={(expiry) =>
updateSetting('jwtTokenExpiry', dayjs.duration(expiry, 'minute').toISOString())
}
handleUpdate={(expiry) => updateSetting('jwtTokenExpiry', d(expiry).minutes.toISOString())}
showSlider
/>
<NumberSetting
settingTitle={t('settings.server.auth.jwt.refresh_token_expiry')}
settingValue={dayjs.duration(serverSettings.jwtRefreshExpiry).humanize()}
value={dayjs.duration(serverSettings.jwtRefreshExpiry).asDays()}
settingValue={d(serverSettings.jwtRefreshExpiry).days.humanize()}
value={d(serverSettings.jwtRefreshExpiry).days.inWholeDays}
valueUnit={t('global.time.days.day_other')}
defaultValue={JWT_REFRESH_TOKEN_EXPIRY.default}
minValue={JWT_REFRESH_TOKEN_EXPIRY.min}
maxValue={JWT_REFRESH_TOKEN_EXPIRY.max}
handleUpdate={(expiry) =>
updateSetting('jwtRefreshExpiry', dayjs.duration(expiry, 'day').toISOString())
}
handleUpdate={(expiry) => updateSetting('jwtRefreshExpiry', d(expiry).days.toISOString())}
showSlider
/>
</>

View File

@@ -20,8 +20,8 @@ import { useCallback } from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies,no-restricted-imports
import { deepmerge } from '@mui/utils';
// eslint-disable-next-line no-restricted-imports
import { PaletteBackgroundChannel } from '@mui/material/styles/createThemeWithVars';
import { Palette } from '@vibrant/color';
import { PaletteBackgroundChannel } from 'node_modules/@mui/material/esm/styles/createThemeWithVars';
import { MediaQuery } from '@/base/utils/MediaQuery.tsx';
import { AppTheme } from '@/features/theme/services/AppThemes.ts';
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';