Use stable array/object constants II
This commit is contained in:
@@ -20,6 +20,7 @@ import { VersionUpdateInfoDialog } from '@/features/app-updates/components/Versi
|
||||
import { useMetadataServerSettings } from '@/features/settings/services/ServerSettingsMetadata.ts';
|
||||
import { useLocalStorage } from '@/base/hooks/useStorage.tsx';
|
||||
import { AppRoutes } from '@/base/AppRoute.constants.ts';
|
||||
import { STABLE_EMPTY_OBJECT } from '@/base/Base.constants.ts';
|
||||
|
||||
const disabledUpdateCheck = () => Promise.resolve();
|
||||
|
||||
@@ -45,7 +46,7 @@ export const ServerUpdateChecker = () => {
|
||||
});
|
||||
|
||||
const { data } = requestManager.useGetAbout();
|
||||
const { aboutServer } = data ?? {};
|
||||
const { aboutServer } = data ?? STABLE_EMPTY_OBJECT;
|
||||
|
||||
const selectedServerChannelInfo = serverUpdateCheckData?.checkForServerUpdates?.find(
|
||||
(channel) => channel.channel === aboutServer?.buildType,
|
||||
|
||||
@@ -27,6 +27,7 @@ import { useMetadataServerSettings } from '@/features/settings/services/ServerSe
|
||||
import { getErrorMessage, noOp } from '@/lib/HelperFunctions.ts';
|
||||
import { AppStorage } from '@/lib/storage/AppStorage.ts';
|
||||
import { BrowserUtil } from '@/lib/BrowserUtil.ts';
|
||||
import { STABLE_EMPTY_OBJECT } from '@/base/Base.constants.ts';
|
||||
|
||||
const disabledUpdateCheck = () => Promise.resolve();
|
||||
|
||||
@@ -53,7 +54,7 @@ export const WebUIUpdateChecker = () => {
|
||||
const shouldCheckForUpdate = !isAutoUpdateEnabled && webUIInformAvailableUpdate;
|
||||
|
||||
const { data: aboutData } = requestManager.useGetAbout();
|
||||
const { aboutWebUI } = aboutData ?? {};
|
||||
const { aboutWebUI } = aboutData ?? STABLE_EMPTY_OBJECT;
|
||||
|
||||
const { data: webUIUpdateData, refetch: checkForUpdate } = requestManager.useCheckForWebUIUpdate({
|
||||
notifyOnNetworkStatusChange: true,
|
||||
|
||||
@@ -41,6 +41,7 @@ import { ExtensionAction, ExtensionGroupState, ExtensionState } from '@/features
|
||||
import { EXTENSION_ACTION_TO_FAILURE_TRANSLATION_MAP } from '@/features/extension/Extensions.constants.ts';
|
||||
import { AppRoutes } from '@/base/AppRoute.constants.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
||||
import {
|
||||
createUpdateMetadataServerSettings,
|
||||
useMetadataServerSettings,
|
||||
@@ -142,11 +143,11 @@ export function Extensions({ tabsMenuHeight }: { tabsMenuHeight: number }) {
|
||||
const areReposDefined = !!serverSettingsData?.settings.extensionRepos.length;
|
||||
const areMultipleReposInUse = (serverSettingsData?.settings.extensionRepos.length ?? 0) > 1;
|
||||
|
||||
const allExtensions = data?.fetchExtensions?.extensions;
|
||||
const allLangs = useMemo(() => getLanguagesFromExtensions(allExtensions ?? []), [allExtensions]);
|
||||
const allExtensions = data?.fetchExtensions?.extensions ?? STABLE_EMPTY_ARRAY;
|
||||
const allLangs = useMemo(() => getLanguagesFromExtensions(allExtensions), [allExtensions]);
|
||||
|
||||
const filteredExtensions = useMemo(
|
||||
() => filterExtensions(allExtensions ?? [], { selectedLanguages: shownLangs, showNsfw, query }),
|
||||
() => filterExtensions(allExtensions, { selectedLanguages: shownLangs, showNsfw, query }),
|
||||
[allExtensions, shownLangs, showNsfw, query],
|
||||
);
|
||||
const groupedExtensions = useMemo(() => groupExtensionsByLanguage(filteredExtensions), [filteredExtensions]);
|
||||
|
||||
@@ -30,6 +30,7 @@ import { VirtuosoUtil } from '@/lib/virtuoso/Virtuoso.util.tsx';
|
||||
import { StyledGroupHeader } from '@/base/components/virtuoso/StyledGroupHeader.tsx';
|
||||
import { StyledGroupItemWrapper } from '@/base/components/virtuoso/StyledGroupItemWrapper.tsx';
|
||||
import { SourceLanguageSelect } from '@/features/source/components/SourceLanguageSelect.tsx';
|
||||
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
||||
|
||||
export function Sources({ tabsMenuHeight }: { tabsMenuHeight: number }) {
|
||||
const { t } = useLingui();
|
||||
@@ -45,10 +46,10 @@ export function Sources({ tabsMenuHeight }: { tabsMenuHeight: number }) {
|
||||
error,
|
||||
refetch,
|
||||
} = requestManager.useGetSourceList({ notifyOnNetworkStatusChange: true });
|
||||
const sources = data?.sources.nodes;
|
||||
const sources = data?.sources.nodes ?? STABLE_EMPTY_ARRAY;
|
||||
const filteredSources = useMemo(
|
||||
() =>
|
||||
SourceService.filter(sources ?? [], {
|
||||
SourceService.filter(sources, {
|
||||
isNsfw: showNsfw ? undefined : true,
|
||||
languages: shownLangs,
|
||||
keepLocalSource: true,
|
||||
@@ -58,7 +59,7 @@ export function Sources({ tabsMenuHeight }: { tabsMenuHeight: number }) {
|
||||
);
|
||||
const sourcesForLanguageFilter = useMemo(
|
||||
() =>
|
||||
SourceService.filter(sources ?? [], {
|
||||
SourceService.filter(sources, {
|
||||
isNsfw: showNsfw ? undefined : true,
|
||||
removeLocalSource: true,
|
||||
}),
|
||||
|
||||
@@ -26,6 +26,7 @@ import { CheckboxInput } from '@/base/components/inputs/CheckboxInput.tsx';
|
||||
import { makeToast } from '@/base/utils/Toast.ts';
|
||||
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||
import { updateMetadataServerSettings } from '@/features/settings/services/ServerSettingsMetadata.ts';
|
||||
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
||||
import type {
|
||||
GetCategoriesBaseQuery,
|
||||
GetCategoriesBaseQueryVariables,
|
||||
@@ -112,9 +113,9 @@ export function CategorySelect(props: CategorySelectProps) {
|
||||
const { data } = requestManager.useGetCategories<GetCategoriesBaseQuery, GetCategoriesBaseQueryVariables>(
|
||||
GET_CATEGORIES_BASE,
|
||||
);
|
||||
const categoriesData = data?.categories.nodes;
|
||||
const categoriesData = data?.categories.nodes ?? STABLE_EMPTY_ARRAY;
|
||||
|
||||
const allCategories = useMemo(() => Categories.getUserCreated(categoriesData ?? []), [categoriesData]);
|
||||
const allCategories = useMemo(() => Categories.getUserCreated(categoriesData), [categoriesData]);
|
||||
|
||||
const defaultCategoryIds = useMemo(
|
||||
() => (addToLibrary ? Categories.getIds(Categories.getDefaults(allCategories)) : []),
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
||||
import { STABLE_EMPTY_ARRAY, STABLE_EMPTY_OBJECT } from '@/base/Base.constants.ts';
|
||||
import CheckBoxOutlineBlank from '@mui/icons-material/CheckBoxOutlineBlank';
|
||||
import Delete from '@mui/icons-material/Delete';
|
||||
import Download from '@mui/icons-material/Download';
|
||||
@@ -79,7 +79,7 @@ export const ChapterActionMenuItems = ({
|
||||
const { t } = useLingui();
|
||||
|
||||
const isSingleMode = !!chapter;
|
||||
const { isDownloaded, isRead, isBookmarked } = chapter ?? {};
|
||||
const { isDownloaded, isRead, isBookmarked } = chapter ?? STABLE_EMPTY_OBJECT;
|
||||
|
||||
const mangaChaptersResponse = requestManager.useGetMangaChapters<GetChaptersMangaQuery>(
|
||||
GET_CHAPTERS_MANGA,
|
||||
@@ -89,7 +89,7 @@ export const ChapterActionMenuItems = ({
|
||||
fetchPolicy: 'cache-only',
|
||||
},
|
||||
);
|
||||
const allChapters = mangaChaptersResponse.data?.chapters.nodes ?? [];
|
||||
const allChapters = mangaChaptersResponse.data?.chapters.nodes ?? STABLE_EMPTY_ARRAY;
|
||||
|
||||
const {
|
||||
settings: { deleteChaptersWithBookmark },
|
||||
|
||||
@@ -24,6 +24,7 @@ import { Header } from '@/features/extension/info/components/Header.tsx';
|
||||
import { Meta } from '@/features/extension/info/components/Meta.tsx';
|
||||
import { ActionButton } from '@/features/extension/info/components/ActionButton.tsx';
|
||||
import { SourceCard } from '@/features/extension/info/components/SourceCard.tsx';
|
||||
import { STABLE_EMPTY_OBJECT } from '@/base/Base.constants.ts';
|
||||
|
||||
export const ExtensionInfo = () => {
|
||||
const { t } = useLingui();
|
||||
@@ -34,7 +35,7 @@ export const ExtensionInfo = () => {
|
||||
const extensionResponse = requestManager.useGetExtension(pkgName);
|
||||
const sourcesResponse = requestManager.useGetSourceList();
|
||||
|
||||
const { extension } = extensionResponse.data ?? {};
|
||||
const { extension } = extensionResponse.data ?? STABLE_EMPTY_OBJECT;
|
||||
const sources = useMemo(() => {
|
||||
if (!sourcesResponse.data?.sources) {
|
||||
return [];
|
||||
|
||||
@@ -150,7 +150,7 @@ const SourceSearchPreview = React.memo(
|
||||
const { data: searchResult, isLoading, error, abortRequest } = results[0]!;
|
||||
currentAbortRequest.current = abortRequest;
|
||||
|
||||
const mangas = searchResult?.fetchSourceManga?.mangas ?? [];
|
||||
const mangas = searchResult?.fetchSourceManga?.mangas ?? STABLE_EMPTY_ARRAY;
|
||||
const noMangasFound = !error && !isLoading && !mangas.length;
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -21,6 +21,7 @@ import { Trackers } from '@/features/tracker/services/Trackers.ts';
|
||||
import type { GetTrackersSettingsQuery } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { MangaStatus } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { GET_TRACKERS_SETTINGS } from '@/lib/graphql/tracker/TrackerQuery.ts';
|
||||
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
||||
import { createUpdateCategoryMetadata, useGetCategoryMetadata } from '@/features/category/services/CategoryMetadata.ts';
|
||||
import { makeToast } from '@/base/utils/Toast.ts';
|
||||
import {
|
||||
@@ -62,7 +63,7 @@ export const LibraryOptionsPanel = ({
|
||||
const { t } = useLingui();
|
||||
|
||||
const trackerList = requestManager.useGetTrackerList<GetTrackersSettingsQuery>(GET_TRACKERS_SETTINGS);
|
||||
const loggedInTrackers = Trackers.getLoggedIn(trackerList.data?.trackers.nodes ?? []);
|
||||
const loggedInTrackers = Trackers.getLoggedIn(trackerList.data?.trackers.nodes ?? STABLE_EMPTY_ARRAY);
|
||||
|
||||
const categoryLibraryOptions = useGetCategoryMetadata(category);
|
||||
const updateCategoryLibraryOptions = createUpdateCategoryMetadata(category, (e) =>
|
||||
|
||||
@@ -23,6 +23,7 @@ import { GET_TRACKERS_SETTINGS } from '@/lib/graphql/tracker/TrackerQuery.ts';
|
||||
import type { MangaTrackRecordInfo } from '@/features/manga/Manga.types.ts';
|
||||
import { AppRoutes } from '@/base/AppRoute.constants.ts';
|
||||
import { MediaQuery } from '@/base/utils/MediaQuery.tsx';
|
||||
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
||||
|
||||
export const TrackMangaButton = ({ manga }: { manga: MangaTrackRecordInfo & Pick<MangaType, 'title'> }) => {
|
||||
const { t } = useLingui();
|
||||
@@ -30,7 +31,7 @@ export const TrackMangaButton = ({ manga }: { manga: MangaTrackRecordInfo & Pick
|
||||
const isMobileWidth = MediaQuery.useIsMobileWidth();
|
||||
|
||||
const trackerList = requestManager.useGetTrackerList<GetTrackersSettingsQuery>(GET_TRACKERS_SETTINGS);
|
||||
const trackers = trackerList.data?.trackers.nodes ?? [];
|
||||
const trackers = trackerList.data?.trackers.nodes ?? STABLE_EMPTY_ARRAY;
|
||||
const mangaTrackers = manga.trackRecords.nodes;
|
||||
|
||||
const loggedInTrackers = Trackers.getLoggedIn(trackers);
|
||||
|
||||
@@ -26,13 +26,14 @@ import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholde
|
||||
import type { GetMangaScreenQuery } from '@/lib/graphql/generated/graphql.ts';
|
||||
import { GET_MANGA_SCREEN } from '@/lib/graphql/manga/MangaQuery.ts';
|
||||
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
||||
import { STABLE_EMPTY_OBJECT } from '@/base/Base.constants.ts';
|
||||
import { useAppTitleAndAction } from '@/features/navigation-bar/hooks/useAppTitleAndAction.ts';
|
||||
import type { MangaLocationState } from '@/features/manga/Manga.types.ts';
|
||||
|
||||
export const Manga: React.FC = () => {
|
||||
const { t } = useLingui();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const { mode } = useLocation<MangaLocationState>().state ?? {};
|
||||
const { mode } = useLocation<MangaLocationState>().state ?? STABLE_EMPTY_OBJECT;
|
||||
|
||||
const autofetchedRef = useRef(false);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import type { NavbarItem } from '@/features/navigation-bar/NavigationBar.types.t
|
||||
import { NavBarItemMoreGroup } from '@/features/navigation-bar/NavigationBar.types.ts';
|
||||
import { AppRoutes } from '@/base/AppRoute.constants.ts';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
||||
import { DownloaderState } from '@/lib/graphql/generated/graphql.ts';
|
||||
|
||||
type RestrictedNavBarItem<Show extends NavbarItem['show']> = Omit<NavbarItem, 'show'> & { show: Show };
|
||||
@@ -64,7 +65,7 @@ const NAVIGATION_BAR_BASE_ITEMS = [
|
||||
useBadge: () => {
|
||||
const { data } = requestManager.useGetExtensionList({ fetchPolicy: 'cache-only' });
|
||||
|
||||
const extensions = data?.extensions.nodes ?? [];
|
||||
const extensions = data?.extensions.nodes ?? STABLE_EMPTY_ARRAY;
|
||||
const availableUpdates = extensions.filter((extension) => extension.hasUpdate).length;
|
||||
|
||||
if (!availableUpdates) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import type { ChapterListOptions } from '@/features/chapter/Chapter.types.ts';
|
||||
import { getReaderChapterFromCache } from '@/features/reader/Reader.utils.ts';
|
||||
import { DirectionOffset } from '@/base/Base.types.ts';
|
||||
import { getReaderChaptersStore } from '@/features/reader/stores/ReaderStore.ts';
|
||||
import { STABLE_EMPTY_OBJECT } from '@/base/Base.constants.ts';
|
||||
|
||||
import { READER_DEFAULT_CHAPTERS_STATE } from '@/features/reader/stores/ReaderChaptersStore.ts';
|
||||
|
||||
@@ -37,7 +38,7 @@ export const useReaderSetChaptersState = (
|
||||
const navigate = useNavigate();
|
||||
const locationState = useLocation<ReaderOpenChapterLocationState>().state;
|
||||
|
||||
const { updateInitialChapter } = locationState ?? {};
|
||||
const { updateInitialChapter } = locationState ?? STABLE_EMPTY_OBJECT;
|
||||
const finalInitialChapter = updateInitialChapter ? undefined : initialChapter;
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
toValidServerConversions,
|
||||
} from '@/features/settings/ImageProcessing.utils.ts';
|
||||
import { Processing } from '@/features/settings/components/images/Processing.tsx';
|
||||
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
||||
|
||||
export const ImageProcessingSetting = ({ type }: { type: ImageProcessingType }) => {
|
||||
const { t } = useLingui();
|
||||
@@ -46,7 +47,7 @@ export const ImageProcessingSetting = ({ type }: { type: ImageProcessingType })
|
||||
|
||||
const settingKey = IMAGE_PROCESSING_TYPE_TO_SETTING[type];
|
||||
|
||||
const conversions = data?.settings?.[settingKey] ?? [];
|
||||
const conversions = data?.settings?.[settingKey] ?? STABLE_EMPTY_ARRAY;
|
||||
|
||||
const [tmpConversions, setTmpConversions] = useState(
|
||||
normalizeConversions(maybeAddDefault(addStableIdToConversions(conversions))),
|
||||
|
||||
@@ -23,6 +23,7 @@ import { useMetadataServerSettings } from '@/features/settings/services/ServerSe
|
||||
import type { NavbarItem } from '@/features/navigation-bar/NavigationBar.types.ts';
|
||||
import { NavBarItemMoreGroup } from '@/features/navigation-bar/NavigationBar.types.ts';
|
||||
import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts';
|
||||
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
||||
|
||||
export const More = () => {
|
||||
const { t } = useLingui();
|
||||
@@ -45,7 +46,7 @@ export const More = () => {
|
||||
const hiddenNavBarItemsByMoreGroup = Object.groupBy(hiddenNavBarItems, (item) => item.moreGroup);
|
||||
|
||||
const hiddenItemsMoreGroup = [
|
||||
...(hiddenNavBarItemsByMoreGroup[NavBarItemMoreGroup.HIDDEN_ITEM] ?? []),
|
||||
...(hiddenNavBarItemsByMoreGroup[NavBarItemMoreGroup.HIDDEN_ITEM] ?? STABLE_EMPTY_ARRAY),
|
||||
{
|
||||
path: AppRoutes.settings.childRoutes.categories.path,
|
||||
title: msg`Categories`,
|
||||
|
||||
@@ -234,7 +234,7 @@ export function SourceMangas() {
|
||||
);
|
||||
const [filtersToApply, setLocationFiltersToApply] = useSessionStorage<IPos[]>(
|
||||
`source-mangas-location-${locationKey}-${sourceId}-filters`,
|
||||
currentFiltersToApply ?? [],
|
||||
currentFiltersToApply ?? STABLE_EMPTY_ARRAY,
|
||||
);
|
||||
const [dialogFiltersToApply, setDialogFiltersToApply] = useState<IPos[]>(filtersToApply);
|
||||
const [currentContentType, setCurrentContentType] = useSessionStorage<SourceContentType | undefined>(
|
||||
|
||||
@@ -40,6 +40,7 @@ import type { TrackerIdInfo, TTrackerBind } from '@/features/tracker/Tracker.typ
|
||||
import { Tracker } from '@/features/tracker/Tracker.types.ts';
|
||||
import { CustomButtonIcon } from '@/base/components/buttons/CustomButtonIcon.tsx';
|
||||
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
|
||||
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
||||
|
||||
const TrackButton = ({
|
||||
mangaId,
|
||||
@@ -133,7 +134,7 @@ export const TrackerSearch = ({
|
||||
const trackerSearch = requestManager.useTrackerSearch(tracker.id, searchString, {
|
||||
notifyOnNetworkStatusChange: true,
|
||||
});
|
||||
const searchResults = trackerSearch.data?.searchTracker.trackSearches ?? [];
|
||||
const searchResults = trackerSearch.data?.searchTracker.trackSearches ?? STABLE_EMPTY_ARRAY;
|
||||
|
||||
const hasResults = !!searchResults.length;
|
||||
const hasNoResults = !trackerSearch.loading && !trackerSearch.error && !hasResults;
|
||||
|
||||
Reference in New Issue
Block a user