Skip to content

Commit

Permalink
refactor: viewitemcontainer
Browse files Browse the repository at this point in the history
  • Loading branch information
grafixeyehero committed Jul 8, 2023
1 parent 5598f49 commit 2b146f8
Show file tree
Hide file tree
Showing 44 changed files with 2,662 additions and 949 deletions.
Original file line number Diff line number Diff line change
@@ -1,38 +1,27 @@
import React, { FC, useCallback, useEffect, useRef, useState } from 'react';
import AlphaPicker from '../alphaPicker/alphaPicker';
import { ViewQuerySettings } from '../../types/interface';
import AlphaPicker from 'components/alphaPicker/alphaPicker';
import { LibraryViewSettings } from 'types/library';

interface AlphaPickerContainerProps {
viewQuerySettings: ViewQuerySettings;
setViewQuerySettings: React.Dispatch<React.SetStateAction<ViewQuerySettings>>;
libraryViewSettings: LibraryViewSettings;
setLibraryViewSettings: React.Dispatch<React.SetStateAction<LibraryViewSettings>>;
}

const AlphaPickerContainer: FC<AlphaPickerContainerProps> = ({ viewQuerySettings, setViewQuerySettings }) => {
const AlphaPickerContainer: FC<AlphaPickerContainerProps> = ({ libraryViewSettings, setLibraryViewSettings }) => {
const [ alphaPicker, setAlphaPicker ] = useState<AlphaPicker>();
const element = useRef<HTMLDivElement>(null);

alphaPicker?.updateControls(viewQuerySettings);
alphaPicker?.updateControls(libraryViewSettings);

const onAlphaPickerChange = useCallback((e) => {
const newValue = (e as CustomEvent).detail.value;
let updatedValue: React.SetStateAction<ViewQuerySettings>;
if (newValue === '#') {
updatedValue = {
NameLessThan: 'A',
NameStartsWith: undefined
};
} else {
updatedValue = {
NameLessThan: undefined,
NameStartsWith: newValue
};
}
setViewQuerySettings((prevState) => ({
setLibraryViewSettings((prevState) => ({
...prevState,
StartIndex: 0,
...updatedValue
NameLessThan: newValue === '#' ? 'A' : undefined,
NameStartsWith: newValue === '#' ? undefined : newValue
}));
}, [setViewQuerySettings]);
}, [setLibraryViewSettings]);

useEffect(() => {
const alphaPickerElement = element.current;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import GenresSectionContainer from './GenresSectionContainer';
import { CollectionType } from 'types/collectionType';

interface GenresItemsContainerProps {
parentId?: string | null;
parentId: string | null | undefined;
collectionType?: CollectionType;
itemType: BaseItemKind;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import SectionContainer from './SectionContainer';
import { CollectionType } from 'types/collectionType';

interface GenresSectionContainerProps {
parentId?: string | null;
parentId: string | null | undefined;
collectionType?: CollectionType;
itemType: BaseItemKind;
genre: BaseItemDto;
Expand Down
137 changes: 137 additions & 0 deletions src/apps/experimental/components/library/ItemsContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client';
import React, { FC, useEffect, useCallback, useRef } from 'react';
import globalize from 'scripts/globalize';
import cardBuilder from 'components/cardbuilder/cardBuilder';
import listview from 'components/listview/listview';
import imageLoader from 'components/images/imageLoader';
import ItemsContainerElement from 'elements/ItemsContainerElement';
import 'elements/emby-itemscontainer/emby-itemscontainer';
import { LibraryViewSettings } from 'types/library';
import { LibraryTab } from 'types/libraryTab';
import { CollectionType } from 'types/collectionType';
import { CardOptions } from 'types/cardOptions';

interface ItemsContainerI {
libraryViewSettings: LibraryViewSettings;
viewType: LibraryTab;
collectionType?: CollectionType;
noItemsMessage: string;
items: BaseItemDto[];
}

const ItemsContainer: FC<ItemsContainerI> = ({ libraryViewSettings, viewType, collectionType, noItemsMessage, items }) => {
const element = useRef<HTMLDivElement>(null);

const getCardOptions = useCallback(() => {
let shape;
let preferThumb;
let preferDisc;
let preferLogo;
let lines = libraryViewSettings.ShowTitle ? 2 : 0;

if (libraryViewSettings.ImageType === 'banner') {
shape = 'banner';
} else if (libraryViewSettings.ImageType === 'disc') {
shape = 'square';
preferDisc = true;
} else if (libraryViewSettings.ImageType === 'logo') {
shape = 'backdrop';
preferLogo = true;
} else if (libraryViewSettings.ImageType === 'thumb') {
shape = 'backdrop';
preferThumb = true;
} else {
shape = 'auto';
}

const cardOptions: CardOptions = {
shape: shape,
showTitle: libraryViewSettings.ShowTitle,
showYear: libraryViewSettings.ShowYear,
cardLayout: libraryViewSettings.CardLayout,
centerText: true,
context: collectionType,
coverImage: true,
preferThumb: preferThumb,
preferDisc: preferDisc,
preferLogo: preferLogo,
overlayPlayButton: false,
overlayMoreButton: true,
overlayText: !libraryViewSettings.ShowTitle
};

if (
viewType === LibraryTab.Songs
|| viewType === LibraryTab.Albums
|| viewType === LibraryTab.Episodes
) {
cardOptions.showParentTitle = libraryViewSettings.ShowTitle;
} else if (viewType === LibraryTab.Artists) {
cardOptions.showYear = false;
lines = 1;
}

cardOptions.lines = lines;
cardOptions.items = items;

return cardOptions;
}, [
viewType,
collectionType,
items,
libraryViewSettings.CardLayout,
libraryViewSettings.ImageType,
libraryViewSettings.ShowTitle,
libraryViewSettings.ShowYear
]);

const getItemsHtml = useCallback(() => {
let html = '';

if (libraryViewSettings.ImageType === 'list') {
html = listview.getListViewHtml({
items: items,
context: collectionType
});
} else {
html = cardBuilder.getCardsHtml(
items,
getCardOptions()
);
}

if (!items.length) {
html += '<div class="noItemsMessage centerMessage">';
html
+= '<h1>' + globalize.translate('MessageNothingHere') + '</h1>';
html += '<p>' + globalize.translate(noItemsMessage) + '</p>';
html += '</div>';
}

return html;
}, [
getCardOptions,
collectionType,
items,
noItemsMessage,
libraryViewSettings.ImageType
]);

useEffect(() => {
const itemsContainer = element.current?.querySelector('.itemsContainer') as HTMLDivElement;
itemsContainer.innerHTML = getItemsHtml();
imageLoader.lazyChildren(itemsContainer);
}, [getItemsHtml]);

const cssClass = libraryViewSettings.ImageType == 'list' ? 'vertical-list' : 'vertical-wrap';

return (
<div ref={element}>
<ItemsContainerElement
className={`itemsContainer ${cssClass} centered padded-left padded-right padded-right-withalphapicker`}
/>
</div>
);
};

export default ItemsContainer;
34 changes: 34 additions & 0 deletions src/apps/experimental/components/library/NewCollectionButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { FC, useCallback } from 'react';
import { IconButton } from '@mui/material';
import AddIcon from '@mui/icons-material/Add';
import globalize from 'scripts/globalize';

const NewCollectionButton: FC = () => {
const showCollectionEditor = useCallback(() => {
import('components/collectionEditor/collectionEditor').then(
({ default: CollectionEditor }) => {
const serverId = window.ApiClient.serverId();
const collectionEditor = new CollectionEditor();
collectionEditor.show({
items: [],
serverId: serverId
}).catch(() => {
// closed collection editor
});
}).catch(err => {
console.error('[NewCollection] failed to load collection editor', err);
});
}, []);

return (
<IconButton
title={globalize.translate('Add')}
className='paper-icon-button-light btnNewCollection autoSize'
onClick={showCollectionEditor}
>
<AddIcon />
</IconButton>
);
};

export default NewCollectionButton;
94 changes: 94 additions & 0 deletions src/apps/experimental/components/library/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React, { FC, useCallback } from 'react';
import Box from '@mui/material/Box';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import IconButton from '@mui/material/IconButton';

import globalize from 'scripts/globalize';
import * as userSettings from 'scripts/settings/userSettings';
import { LibraryViewSettings } from 'types/library';

interface PaginationProps {
libraryViewSettings: LibraryViewSettings;
setLibraryViewSettings: React.Dispatch<React.SetStateAction<LibraryViewSettings>>;
totalRecordCount: number;
}

const Pagination: FC<PaginationProps> = ({
libraryViewSettings,
setLibraryViewSettings,
totalRecordCount
}) => {
const limit = userSettings.libraryPageSize(undefined);
const startIndex = libraryViewSettings.StartIndex || 0;
const recordsStart = totalRecordCount ? startIndex + 1 : 0;
const recordsEnd = limit ?
Math.min(startIndex + limit, totalRecordCount) :
totalRecordCount;
const showControls = limit > 0 && limit < totalRecordCount;

const onNextPageClick = useCallback(() => {
if (limit > 0) {
const newIndex = startIndex + limit;
setLibraryViewSettings((prevState) => ({
...prevState,
StartIndex: newIndex
}));
}
}, [limit, setLibraryViewSettings, startIndex]);

const onPreviousPageClick = useCallback(() => {
if (limit > 0) {
const newIndex = Math.max(0, startIndex - limit);
setLibraryViewSettings((prevState) => ({
...prevState,
StartIndex: newIndex
}));
}
}, [limit, setLibraryViewSettings, startIndex]);

return (
<Box className='paging'>
<Box
className='listPaging'
style={{ display: 'flex', alignItems: 'center' }}
>
<span>
{globalize.translate(
'ListPaging',
recordsStart,
recordsEnd,
totalRecordCount
)}
</span>
{showControls && (
<>
<IconButton
title={globalize.translate('Previous')}
className='paper-icon-button-light btnPreviousPage autoSize'
disabled={startIndex ? false : true}
onClick={onPreviousPageClick}
>
<ArrowBackIcon />
</IconButton>

<IconButton
title={globalize.translate('Next')}
className='paper-icon-button-light btnNextPage autoSize'
disabled={
startIndex + limit >= totalRecordCount ?
true :
false
}
onClick={onNextPageClick}
>
<ArrowForwardIcon />
</IconButton>
</>
)}
</Box>
</Box>
);
};

export default Pagination;
32 changes: 32 additions & 0 deletions src/apps/experimental/components/library/PlayAllButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { FC, useCallback } from 'react';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import IconButton from '@mui/material/IconButton';
import { useGetItem } from 'hooks/useFetchItems';
import { playbackManager } from 'components/playback/playbackmanager';
import globalize from 'scripts/globalize';

interface PlayAllButtonProps {
parentId: string | null | undefined;
}

const PlayAllButton: FC<PlayAllButtonProps> = ({ parentId }) => {
const { data: item } = useGetItem(parentId);

const playAll = useCallback(() => {
playbackManager.play({
items: [item]
});
}, [item]);

return (
<IconButton
title={globalize.translate('HeaderPlayAll')}
className='paper-icon-button-light btnPlayAll autoSize'
onClick={playAll}
>
<PlayArrowIcon />
</IconButton>
);
};

export default PlayAllButton;
31 changes: 31 additions & 0 deletions src/apps/experimental/components/library/ShuffleButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { FC, useCallback } from 'react';
import { IconButton } from '@mui/material';
import ShuffleIcon from '@mui/icons-material/Shuffle';

import { useGetItem } from 'hooks/useFetchItems';
import { playbackManager } from 'components/playback/playbackmanager';
import globalize from 'scripts/globalize';

interface ShuffleButtonProps {
parentId: string | null | undefined;
}

const ShuffleButton: FC<ShuffleButtonProps> = ({ parentId }) => {
const { data: item } = useGetItem(parentId);

const shuffle = useCallback(() => {
playbackManager.shuffle(item);
}, [item]);

return (
<IconButton
title={globalize.translate('Shuffle')}
className='paper-icon-button-light btnShuffle autoSize'
onClick={shuffle}
>
<ShuffleIcon />
</IconButton>
);
};

export default ShuffleButton;
Loading

0 comments on commit 2b146f8

Please sign in to comment.