Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

save view type in recently imported panel #1076

Merged
merged 1 commit into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/core/react-query/settings/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { merge } from 'lodash';
import semver from 'semver';

import { webuiSettingsPatches } from '@/core/patches';
Expand Down Expand Up @@ -308,6 +309,7 @@ export const initialSettings: SettingsType = {
shokoNewsPostsCount: 5,
recentlyImportedEpisodesCount: 30,
recentlyImportedSeriesCount: 20,
recentlyImportedView: 'episodes',
},
},
FirstRun: false,
Expand Down Expand Up @@ -427,6 +429,13 @@ export const transformSettings = (response: SettingsServerType) => {
let webuiSettings = JSON.parse(
response.WebUI_Settings === '' ? '{}' : response.WebUI_Settings,
) as WebUISettingsType;

// Settings aren't fetched yet, transform is running on initialData
// Return without any operatations
if (webuiSettings.settingsRevision === 0) {
return { ...response, WebUI_Settings: webuiSettings };
}

const currentSettingsRevision = webuiSettings.settingsRevision ?? 0;
const versionedInitialSettings: WebUISettingsType = {
...initialSettings.WebUI_Settings,
Expand All @@ -444,7 +453,7 @@ export const transformSettings = (response: SettingsServerType) => {
.forEach((key) => {
webuiSettings = webuiSettingsPatches[key](webuiSettings);
});
webuiSettings = Object.assign({}, initialSettings.WebUI_Settings, webuiSettings);
webuiSettings = merge({}, initialSettings.WebUI_Settings, webuiSettings);
} catch {
webuiSettings = versionedInitialSettings;
}
Expand Down
1 change: 1 addition & 0 deletions src/core/types/api/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ export type WebUISettingsType = {
shokoNewsPostsCount: number;
recentlyImportedEpisodesCount: number;
recentlyImportedSeriesCount: number;
recentlyImportedView: 'episodes' | 'series';
};
};

Expand Down
24 changes: 1 addition & 23 deletions src/core/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import calendar from 'dayjs/plugin/calendar';
import durationPlugin from 'dayjs/plugin/duration';
import formatThousands from 'format-thousands';
import { enableMapSet } from 'immer';
import { isObject, toNumber } from 'lodash';
import { toNumber } from 'lodash';
import semver from 'semver';

import toast from '@/components/Toast';
Expand Down Expand Up @@ -42,28 +42,6 @@ export const parseServerVersion = (version: string) => {

export const getParsedSupportedServerVersion = () => parseServerVersion(minimumSupportedServerVersion)!;

export function mergeDeep(...objects: object[]) {
return objects.reduce((prev, obj) => {
Object.keys(obj).forEach((key) => {
const pVal: unknown = prev[key];
const oVal: unknown = obj[key];

if (Array.isArray(pVal) && Array.isArray(oVal)) {
// eslint-disable-next-line no-param-reassign
prev[key] = Array.from(new Set(pVal.concat(...oVal as [])));
} else if (isObject(pVal) && isObject(oVal)) {
// eslint-disable-next-line no-param-reassign
prev[key] = mergeDeep(pVal, oVal);
} else {
// eslint-disable-next-line no-param-reassign
prev[key] = oVal;
}
});

return prev;
}, {});
}

export const formatThousand = (num: number) => formatThousands(num, ',');

export const copyToClipboard = async (text: string, entityName?: string) => {
Expand Down
44 changes: 32 additions & 12 deletions src/pages/dashboard/panels/RecentlyImported.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { produce } from 'immer';

import MultiStateButton from '@/components/Input/MultiStateButton';
import ShokoPanel from '@/components/Panels/ShokoPanel';
Expand All @@ -8,27 +9,30 @@ import {
useDashboardRecentlyAddedEpisodesQuery,
useDashboardRecentlyAddedSeriesQuery,
} from '@/core/react-query/dashboard/queries';
import { usePatchSettingsMutation } from '@/core/react-query/settings/mutations';
import { useSettingsQuery } from '@/core/react-query/settings/queries';
import useEventCallback from '@/hooks/useEventCallback';
import EpisodeDetails from '@/pages/dashboard/components/EpisodeDetails';
import SeriesDetails from '@/pages/dashboard/components/SeriesDetails';

import type { RootState } from '@/core/store';

type TabType = 'Series' | 'Episodes';
const tabStates: { label?: string, value: TabType }[] = [
{ value: 'Episodes' },
{ value: 'Series' },
const tabStates: { label?: string, value: string }[] = [
{ label: 'Episodes', value: 'episodes' },
{ label: 'Series', value: 'series' },
];

const RecentlyImported = () => {
const layoutEditMode = useSelector((state: RootState) => state.mainpage.layoutEditMode);

const settings = useSettingsQuery().data;
const {
hideR18Content,
recentlyImportedEpisodesCount,
recentlyImportedSeriesCount,
} = useSettingsQuery().data.WebUI_Settings.dashboard;
recentlyImportedView,
} = settings.WebUI_Settings.dashboard;
const { mutate: patchSettings } = usePatchSettingsMutation();

const recentSeriesQuery = useDashboardRecentlyAddedSeriesQuery({
includeRestricted: !hideR18Content,
Expand All @@ -39,27 +43,43 @@ const RecentlyImported = () => {
pageSize: recentlyImportedEpisodesCount,
});

const [currentTab, setCurrentTab] = useState<TabType>(tabStates[0].value);
const handleTabChange = useEventCallback((newTab: TabType) => setCurrentTab(newTab));
const [viewMode, setViewMode] = useState<'episodes' | 'series'>('episodes');

useEffect(() => {
setViewMode(recentlyImportedView);
}, [recentlyImportedView]);

const handleTabChange = useEventCallback((newTab: 'episodes' | 'series') => {
setViewMode(newTab);
const newSettings = produce(settings, (draftState) => {
draftState.WebUI_Settings.dashboard.recentlyImportedView = newTab;
});
patchSettings({ newSettings });
});

return (
<ShokoPanel
title="Recently Imported"
editMode={layoutEditMode}
isFetching={currentTab === 'Series' ? recentSeriesQuery.isPending : recentEpisodesQuery.isPending}
isFetching={viewMode === 'series' ? recentSeriesQuery.isPending : recentEpisodesQuery.isPending}
options={
<MultiStateButton activeState={currentTab} states={tabStates} onStateChange={handleTabChange} alternateColor />
<MultiStateButton
activeState={viewMode}
states={tabStates}
onStateChange={handleTabChange}
alternateColor
/>
}
>
<div className="shoko-scrollbar relative flex">
<TransitionDiv show={currentTab !== 'Series'} className="absolute flex w-full">
<TransitionDiv show={viewMode !== 'series'} className="absolute flex w-full">
{(recentEpisodesQuery.data?.length ?? 0) > 0
? recentEpisodesQuery.data?.map(item => (
<EpisodeDetails episode={item} key={`${item.IDs.ShokoEpisode}-${item.IDs.ShokoFile}`} />
))
: <div className="flex w-full justify-center font-semibold">No Recently Imported Episodes!</div>}
</TransitionDiv>
<TransitionDiv show={currentTab === 'Series'} className="absolute flex w-full">
<TransitionDiv show={viewMode === 'series'} className="absolute flex w-full">
{(recentSeriesQuery.data?.length ?? 0) > 0
? recentSeriesQuery.data?.map(item => <SeriesDetails series={item} key={item.IDs.ID} />)
: <div className="flex w-full justify-center font-semibold">No Recently Imported Series!</div>}
Expand Down