Skip to content

Commit

Permalink
Bring back collection selection in the program selector (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbenincasa authored Feb 23, 2024
1 parent 3e87426 commit 66bcae6
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 18 deletions.
3 changes: 2 additions & 1 deletion server/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"declaration": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"esModuleInterop": true
"esModuleInterop": true,
"noErrorTruncation": true
},
"files": [
"./types/fastify.d.ts"
Expand Down
90 changes: 73 additions & 17 deletions web2/src/components/channel_config/ProgrammingSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
import { Clear } from '@mui/icons-material';
import { Clear, ExpandLess, ExpandMore } from '@mui/icons-material';
import {
Collapse,
Divider,
FormControl,
IconButton,
InputAdornment,
InputLabel,
LinearProgress,
List,
ListItemButton,
ListItemIcon,
ListItemText,
MenuItem,
Select,
TextField,
Typography,
} from '@mui/material';
import { DataTag, useInfiniteQuery } from '@tanstack/react-query';
import { DataTag, useInfiniteQuery, useQuery } from '@tanstack/react-query';
import {
PlexLibraryCollections,
PlexLibraryMovies,
PlexLibraryShows,
PlexMedia,
PlexMovie,
PlexTvShow,
isPlexDirectory,
} from '@tunarr/types/plex';
import { chain, first, isEmpty, isNil, isUndefined } from 'lodash-es';
import React, { useCallback, useEffect, useState } from 'react';
import { chain, first, isEmpty, isNil, isUndefined, map } from 'lodash-es';
import React, { Fragment, useCallback, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useIntersectionObserver } from 'usehooks-ts';
import { toggle } from '../../helpers/util.ts';
import { fetchPlexPath, usePlex } from '../../hooks/plexHooks.ts';
import { usePlexServerSettings } from '../../hooks/settingsHooks.ts';
import useDebouncedState from '../../hooks/useDebouncedState.ts';
Expand All @@ -51,10 +57,9 @@ export default function ProgrammingSelector() {
const { data: plexServers } = usePlexServerSettings();
const selectedServer = useStore((s) => s.currentServer);
const selectedLibrary = useStore((s) => s.currentLibrary);
// const listingsByServer = useStore((s) => s.listingsByServer);
const knownMedia = useStore((s) => s.knownMediaByServer);
// const hierarchyByServer = useStore((s) => s.contentHierarchyByServer);
const navigate = useNavigate();
const [collectionsOpen, setCollectionsOpen] = useState(false);

useEffect(() => {
const server =
Expand Down Expand Up @@ -83,6 +88,7 @@ export default function ProgrammingSelector() {
...directoryChildren.Directory,
]);
}
setCollectionsOpen(false);
}, [selectedServer, directoryChildren]);

const { isLoading: searchLoading, data: searchData } = useInfiniteQuery({
Expand Down Expand Up @@ -121,6 +127,22 @@ export default function ProgrammingSelector() {
},
});

const { isLoading: collectionsLoading, data: collectionsData } = useQuery({
queryKey: [
'plex',
selectedServer?.name,
selectedLibrary?.key,
'collections',
],
queryFn: () => {
return fetchPlexPath<PlexLibraryCollections>(
selectedServer!.name,
`/library/sections/${selectedLibrary!.key}/collections?`,
)();
},
enabled: !isNil(selectedServer) && !isNil(selectedLibrary),
});

useEffect(() => {
if (searchData) {
// We're using this as an analogue for detecting the start of a new 'query'
Expand All @@ -144,6 +166,12 @@ export default function ProgrammingSelector() {
}
}, [selectedServer, searchData, setScrollParams]);

useEffect(() => {
if (selectedServer?.name && collectionsData && collectionsData.Metadata) {
addKnownMediaForServer(selectedServer.name, collectionsData.Metadata);
}
}, [selectedServer?.name, collectionsData]);

const onLibraryChange = useCallback(
(libraryUuid: string) => {
if (selectedServer) {
Expand Down Expand Up @@ -174,19 +202,47 @@ export default function ProgrammingSelector() {
}, [setSearch]);

const renderListItems = () => {
if (!searchData) {
return null;
const elements: JSX.Element[] = [];
if (collectionsData && collectionsData.size > 0) {
elements.push(
<Fragment key="collections">
<ListItemButton onClick={() => setCollectionsOpen(toggle)} dense>
<ListItemIcon>
{collectionsOpen ? <ExpandLess /> : <ExpandMore />}
</ListItemIcon>
<ListItemText
primary="Collections"
secondary={`${collectionsData.size} Collection${
collectionsData.size === 1 ? '' : 's'
}`}
/>
{/* <Button>Add All</Button> */}
</ListItemButton>
<Collapse in={collectionsOpen} timeout="auto">
{map(collectionsData.Metadata, (item) => (
<PlexListItem key={item.guid} item={item} />
))}
</Collapse>
<Divider variant="fullWidth" />
</Fragment>,
);
}

if (searchData) {
const items = chain(searchData.pages)
.reject((page) => page.size === 0)
.map((page) => page.Metadata)
.flatten()
.take(scrollParams.limit)
.value();
elements.push(
...map(items, (item: PlexMovie | PlexTvShow) => {
return <PlexListItem key={item.guid} item={item} />;
}),
);
}

return chain(searchData.pages)
.reject((page) => page.size === 0)
.map((page) => page.Metadata)
.flatten()
.take(scrollParams.limit)
.map((item: PlexMovie | PlexTvShow) => {
return <PlexListItem key={item.guid} item={item} />;
})
.value();
return elements;
};

return (
Expand Down
3 changes: 3 additions & 0 deletions web2/src/helpers/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,6 @@ export const zipWithIndex = <T extends object>(
originalIndex: i,
}));
};

// Useful for toggling state
export const toggle = (b: boolean) => !b;

0 comments on commit 66bcae6

Please sign in to comment.