Show last used source
This commit is contained in:
@@ -6,8 +6,11 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { SourceIdInfo } from '@/modules/source/Source.types.ts';
|
||||
|
||||
export type MetadataBrowseSettings = {
|
||||
hideLibraryEntries: boolean;
|
||||
extensionLanguages: string[];
|
||||
showNsfw: boolean;
|
||||
lastUsedSourceId: SourceIdInfo['id'] | null;
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ export enum DefaultLanguage {
|
||||
OTHER = 'other',
|
||||
LOCAL_SOURCE = 'localsourcelang',
|
||||
PINNED = 'pinned',
|
||||
LAST_USED_SOURCE = 'last_used_source',
|
||||
}
|
||||
|
||||
const DEFAULT_LANGUAGE_TO_TRANSLATION: Record<DefaultLanguage, TranslationKey> = {
|
||||
@@ -22,6 +23,7 @@ const DEFAULT_LANGUAGE_TO_TRANSLATION: Record<DefaultLanguage, TranslationKey> =
|
||||
[DefaultLanguage.OTHER]: 'extension.language.other',
|
||||
[DefaultLanguage.LOCAL_SOURCE]: 'extension.language.other',
|
||||
[DefaultLanguage.PINNED]: 'global.label.pinned',
|
||||
[DefaultLanguage.LAST_USED_SOURCE]: 'global.label.last_used',
|
||||
};
|
||||
|
||||
type LanguageObject = ISOLanguage & { orgCode: string; isoCode: string };
|
||||
|
||||
@@ -54,4 +54,5 @@ export const extensionLanguageToTranslationKey: { [state in ExtensionGroupState
|
||||
[DefaultLanguage.OTHER]: 'extension.language.other',
|
||||
[DefaultLanguage.LOCAL_SOURCE]: 'extension.language.other',
|
||||
[DefaultLanguage.PINNED]: 'global.label.pinned',
|
||||
[DefaultLanguage.LAST_USED_SOURCE]: 'global.label.last_used',
|
||||
};
|
||||
|
||||
@@ -49,9 +49,13 @@ export const isExtensionState = (value: string): boolean =>
|
||||
|
||||
export const isExtensionStateOrLanguage = (languageCode: string): boolean =>
|
||||
isExtensionState(languageCode) ||
|
||||
[DefaultLanguage.ALL, DefaultLanguage.OTHER, DefaultLanguage.LOCAL_SOURCE, DefaultLanguage.PINNED].includes(
|
||||
languageCode as DefaultLanguage,
|
||||
);
|
||||
[
|
||||
DefaultLanguage.ALL,
|
||||
DefaultLanguage.OTHER,
|
||||
DefaultLanguage.LOCAL_SOURCE,
|
||||
DefaultLanguage.PINNED,
|
||||
DefaultLanguage.LAST_USED_SOURCE,
|
||||
].includes(languageCode as DefaultLanguage);
|
||||
|
||||
export const translateExtensionLanguage = (languageCode: string): string =>
|
||||
isExtensionStateOrLanguage(languageCode)
|
||||
|
||||
@@ -96,6 +96,7 @@ export const APP_METADATA_KEY_TO_TYPE = {
|
||||
shouldUsePureBlackMode: 'boolean',
|
||||
mangaGridItemWidth: 'number',
|
||||
isPinned: 'boolean',
|
||||
lastUsedSourceId: 'string',
|
||||
} as const satisfies Record<AppMetadataKeys, 'auto' | 'string' | 'number' | 'boolean'>;
|
||||
|
||||
export const VALID_APP_METADATA_KEYS = Object.keys(APP_METADATA_KEY_TO_TYPE);
|
||||
@@ -147,6 +148,7 @@ export const GLOBAL_METADATA_KEYS: AppMetadataKeys[] = [
|
||||
'hideLibraryEntries',
|
||||
'extensionLanguages',
|
||||
'showNsfw',
|
||||
'lastUsedSourceId',
|
||||
|
||||
// history
|
||||
'hideHistory',
|
||||
|
||||
@@ -44,6 +44,7 @@ export const SERVER_SETTINGS_METADATA_DEFAULT: MetadataServerSettings = {
|
||||
hideLibraryEntries: false,
|
||||
extensionLanguages: getDefaultLanguages(),
|
||||
showNsfw: true,
|
||||
lastUsedSourceId: null,
|
||||
|
||||
// history
|
||||
hideHistory: false,
|
||||
|
||||
@@ -35,7 +35,10 @@ import {
|
||||
GetSourceMangasFetchMutation,
|
||||
GetSourceMangasFetchMutationVariables,
|
||||
} from '@/lib/graphql/generated/graphql.ts';
|
||||
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
|
||||
import {
|
||||
updateMetadataServerSettings,
|
||||
useMetadataServerSettings,
|
||||
} from '@/modules/settings/services/ServerSettingsMetadata.ts';
|
||||
import { useLocalStorage, useSessionStorage } from '@/modules/core/hooks/useStorage.tsx';
|
||||
import { AppStorage } from '@/lib/storage/AppStorage.ts';
|
||||
import { getGridSnapshotKey } from '@/modules/manga/components/MangaGrid.tsx';
|
||||
@@ -382,6 +385,12 @@ export function SourceMangas() {
|
||||
setFiltersToApply([]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
updateMetadataServerSettings('lastUsedSourceId', sourceId).catch(
|
||||
defaultPromiseErrorHandler('SourceMangas::setLastUsedSourceId'),
|
||||
);
|
||||
}, [sourceId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (filteredOutAllItemsOfFetchedPage && hasNextPage && !loading) {
|
||||
loadPage(lastPageNum + 1);
|
||||
|
||||
@@ -15,7 +15,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { CustomTooltip } from '@/modules/core/components/CustomTooltip.tsx';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { useLocalStorage } from '@/modules/core/hooks/useStorage.tsx';
|
||||
import { getDefaultLanguages } from '@/modules/core/utils/Languages.ts';
|
||||
import { DefaultLanguage, getDefaultLanguages } from '@/modules/core/utils/Languages.ts';
|
||||
import { LoadingPlaceholder } from '@/modules/core/components/feedback/LoadingPlaceholder.tsx';
|
||||
import { SourceCard } from '@/modules/source/components/SourceCard.tsx';
|
||||
import { LanguageSelect } from '@/modules/core/components/inputs/LanguageSelect.tsx';
|
||||
@@ -33,7 +33,7 @@ export function Sources() {
|
||||
|
||||
const [shownLangs, setShownLangs] = useLocalStorage<string[]>('shownSourceLangs', getDefaultLanguages());
|
||||
const {
|
||||
settings: { showNsfw },
|
||||
settings: { showNsfw, lastUsedSourceId },
|
||||
} = useMetadataServerSettings();
|
||||
|
||||
const {
|
||||
@@ -47,10 +47,19 @@ export function Sources() {
|
||||
() => SourceService.filter(sources ?? [], { showNsfw, languages: shownLangs, keepLocalSource: true }),
|
||||
[sources, shownLangs],
|
||||
);
|
||||
const sourcesByLanguageTuple = useMemo(
|
||||
() => Object.entries(SourceService.groupByLanguage(filteredSources)),
|
||||
[filteredSources],
|
||||
);
|
||||
const sourcesByLanguage = useMemo(() => {
|
||||
const lastUsedSource = SourceService.getLastUsedSource(lastUsedSourceId, filteredSources);
|
||||
const groupedByLanguageTuple = Object.entries(SourceService.groupByLanguage(filteredSources));
|
||||
|
||||
if (lastUsedSource) {
|
||||
return [
|
||||
[DefaultLanguage.LAST_USED_SOURCE, [lastUsedSource]],
|
||||
...groupedByLanguageTuple,
|
||||
] satisfies typeof groupedByLanguageTuple;
|
||||
}
|
||||
|
||||
return groupedByLanguageTuple;
|
||||
}, [filteredSources]);
|
||||
|
||||
const sourceLanguages = useMemo(() => SourceService.getLanguages(sources ?? []), [sources]);
|
||||
const areSourcesFromDifferentRepos = useMemo(
|
||||
@@ -94,10 +103,10 @@ export function Sources() {
|
||||
|
||||
return (
|
||||
<>
|
||||
{sourcesByLanguageTuple.map(([languages, sourcesOfLanguage]) => (
|
||||
<Fragment key={languages}>
|
||||
{sourcesByLanguage.map(([language, sourcesOfLanguage]) => (
|
||||
<Fragment key={language}>
|
||||
<Typography
|
||||
key={languages}
|
||||
key={language}
|
||||
variant="h5"
|
||||
component="h2"
|
||||
sx={{
|
||||
@@ -107,7 +116,7 @@ export function Sources() {
|
||||
fontWeight: 'bold',
|
||||
}}
|
||||
>
|
||||
{translateExtensionLanguage(languages)}
|
||||
{translateExtensionLanguage(language)}
|
||||
</Typography>
|
||||
{sourcesOfLanguage.map((source) => (
|
||||
<SourceCard key={source.id} source={source} showSourceRepo={areSourcesFromDifferentRepos} />
|
||||
|
||||
@@ -109,4 +109,11 @@ export class Sources {
|
||||
|
||||
return sources.some((source) => source.extension.repo !== repo && !Sources.isLocalSource(source));
|
||||
}
|
||||
|
||||
static getLastUsedSource<Source extends SourceIdInfo & SourceMetaInfo>(
|
||||
lastUsedSourceId: SourceIdInfo['id'] | null,
|
||||
sources: Source[],
|
||||
): Source | undefined {
|
||||
return sources.find((source) => source.id === lastUsedSourceId);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user