Skip to content

Commit

Permalink
Merge pull request #34 from Videodock/feat/performance-updates
Browse files Browse the repository at this point in the history
Feat / skeletons and fewer shelves
  • Loading branch information
ChristiaanScheermeijer authored Jun 9, 2021
2 parents f4ab008 + bec5608 commit 64e9b92
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 44 deletions.
5 changes: 5 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
<meta property="og:image" content="/images/icon-256x256.png">
<link rel="icon" href="favicon.ico" type="image/x-icon" />

<!-- Pre-connect JW Player origins -->
<link rel="preconnect" href="https://content.jwplatform.com"/>
<link rel="preconnect" href="https://cdn.jwplayer.com"/>
<link rel="preconnect" href="https://jwpapp.com"/>

<!-- Safari web app -->
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-icon" href="/images/icon-152x152.png">
Expand Down
19 changes: 14 additions & 5 deletions src/components/Card/Card.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
.title {
font-size: 34px;
font-family: var(--body-font-family);
line-height: 36px;
height: 1em;
text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.14), 0px 4px 5px rgba(0, 0, 0, 0.12), 0px 1px 10px rgba(0, 0, 0, 0.2);

@include responsive.mobile-only {
font-size: 24px;
}
Expand All @@ -42,6 +46,7 @@
.meta {
padding: 16px;
background: linear-gradient(to top, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0));
justify-content: space-between;
}
}

Expand Down Expand Up @@ -88,34 +93,38 @@ $aspects: ((1, 1), (2, 1), (2, 3), (4, 3), (5, 3), (16, 9), (9, 16));
@include responsive.mobile-only {
font-size: 14px;
}
flex: 1;
color: var(--card-color);
font-family: var(--body-alt-font-family);
font-weight: 700;
font-size: 16px;
text-align: left;
overflow: hidden;
text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.14), 0px 3px 4px rgba(0, 0, 0, 0.12), 0px 1px 5px rgba(0, 0, 0, 0.2);
@supports (-webkit-line-clamp: 2) {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}

height: 2.3em;

&.loading {
background-color: var(--card-slider-loading-card-bg);
height: 16px;
border-radius: 5px;
width: 30%;
}
}

.meta {
position: absolute;
bottom: 0;
display: flex;
justify-content: flex-end;
align-items: center;
width: 100%;
padding: 8px;
color: var(--card-color);

.title {
flex: 1;
}
}

.tag {
Expand Down
14 changes: 9 additions & 5 deletions src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type CardProps = {
posterAspect?: '1:1' | '2:1' | '2:3' | '4:3' | '5:3' | '16:9' | '9:16';
featured?: boolean;
disabled?: boolean;
loading?: boolean;
};

function Card({
Expand All @@ -27,6 +28,7 @@ function Card({
posterAspect = '16:9',
featured = false,
disabled = false,
loading = false,
}: CardProps): JSX.Element {
const cardClassName = classNames(styles.card, { [styles.featured]: featured, [styles.disabled]: disabled });
const posterClassNames = classNames(styles.poster, styles[`aspect${posterAspect.replace(':', '')}`]);
Expand All @@ -51,14 +53,16 @@ function Card({
aria-label={`Play ${title}`}
>
<div className={posterClassNames} style={{ backgroundImage: posterSource ? `url(${posterSource})` : '' }}>
<div className={styles.meta}>
<div className={styles.title}>{featured ? title : ''}</div>
{metaData()}
</div>
{!loading && (
<div className={styles.meta}>
{featured && <div className={classNames(styles.title, { [styles.loading]: loading })}>{title}</div>}
{metaData()}
</div>
)}
</div>
{!featured && (
<div className={styles.titleContainer}>
<div className={styles.title}>{title}</div>
<div className={classNames(styles.title, { [styles.loading]: loading })}>{title}</div>
</div>
)}
</div>
Expand Down
5 changes: 5 additions & 0 deletions src/components/Shelf/Shelf.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

.title {
width: 100%;
min-height: 28px;
margin-bottom: 12px;
overflow: hidden;
color: var(--card-color);
Expand Down Expand Up @@ -47,3 +48,7 @@
}
}
}
.error {
color: var(--card-color);
font-family: var(--body-alt-font-family);
}
49 changes: 22 additions & 27 deletions src/components/Shelf/Shelf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@ export const featuredTileBreakpoints: Breakpoints = {
};

export type ShelfProps = {
playlist: Playlist | undefined;
playlist: Playlist;
onCardClick: (playlistItem: PlaylistItem) => void;
onCardHover: (playlistItem: PlaylistItem) => void;
featured?: boolean;
loading?: boolean;
error?: unknown;
};

const placeholderItems = new Array(15).fill({});

const Shelf: React.FC<ShelfProps> = ({
playlist,
onCardClick,
onCardHover,
featured = false,
loading = false,
error = null,
}: ShelfProps) => {
const breakpoint: Breakpoint = useBreakpoint();
const [didSlideBefore, setDidSlideBefore] = useState(false);
Expand All @@ -55,17 +55,17 @@ const Shelf: React.FC<ShelfProps> = ({
doSlide();
};

if (!playlist) return null;
if (error) return <h2 className={styles.error}>Could not load items</h2>;

return (
<div className={classNames(styles.shelf, { [styles.featured]: featured })}>
{!featured && <h2 className={styles['title']}>{loading ? '...' : playlist.title}</h2>}
<TileDock<PlaylistItem | number>
items={loading ? placeholderItems : playlist.playlist}
{!featured && <h2 className={classNames(styles.title, { [styles.loading]: loading })}>{playlist.title}</h2>}
<TileDock<PlaylistItem>
items={playlist.playlist}
tilesToShow={tilesToShow}
cycleMode={'restart'}
showControls={!matchMedia('(hover: none)').matches}
transitionTime={loading ? '0s' : '0.3s'}
showControls={!matchMedia('(hover: none)').matches && !loading}
transitionTime={'0.3s'}
spacing={8}
renderLeftControl={(doSlide) => (
<div
Expand Down Expand Up @@ -97,24 +97,19 @@ const Shelf: React.FC<ShelfProps> = ({
<ChevronRight />
</div>
)}
renderTile={(item, isInView) => {
if (loading || typeof item === 'number') {
return <Card title={'...'} duration={0} featured={featured} />;
}

return (
<Card
title={item.title}
duration={item.duration}
posterSource={findPlaylistImageForWidth(item, imageSourceWidth)}
seriesId={item.seriesId}
onClick={() => (isInView ? onCardClick(item) : null)}
onHover={() => onCardHover(item)}
featured={featured}
disabled={!isInView}
/>
);
}}
renderTile={(item, isInView) => (
<Card
title={item.title}
duration={item.duration}
posterSource={findPlaylistImageForWidth(item, imageSourceWidth)}
seriesId={item.seriesId}
onClick={() => (isInView ? onCardClick(item) : null)}
onHover={() => onCardHover(item)}
featured={featured}
disabled={!isInView}
loading={loading}
/>
)}
/>
</div>
);
Expand Down
9 changes: 6 additions & 3 deletions src/containers/Shelf/Shelf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ type ShelfProps = {
};

const Shelf = ({ playlistId, onCardClick, onCardHover, relatedMediaId, featured = false }: ShelfProps): JSX.Element => {
const { isLoading, error, data: playlist }: UsePlaylistResult = usePlaylist(playlistId, relatedMediaId);
const { isLoading, error, data: playlist = { title: '', playlist: [] } }: UsePlaylistResult = usePlaylist(
playlistId,
relatedMediaId,
);

if (!playlistId) return <p>No playlist</p>;
if (error) return <p>Error here {error}</p>;
if (!playlistId) return <p>No playlist id</p>;

return (
<ShelfComponent
loading={isLoading}
error={error}
playlist={playlist}
onCardClick={onCardClick}
onCardHover={onCardHover}
Expand Down
25 changes: 23 additions & 2 deletions src/hooks/usePlaylist.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
import { UseBaseQueryResult, useQuery } from 'react-query';
import type { Playlist } from 'types/playlist';
import type { Playlist, PlaylistItem } from 'types/playlist';

const baseUrl = 'https://content.jwplatform.com'; // temp data, till config arrives
const baseUrl = 'https://content.jwplatform.com';

const placeholderData: Playlist = {
title: '',
playlist: new Array(30).fill({
description: '',
duration: 0,
feedid: '',
image: '',
images: [],
link: '',
genre: '',
mediaid: '',
pubdate: 0,
rating: '',
sources: [],
tags: '',
title: '',
tracks: [],
} as PlaylistItem),
};

const getPlaylistById = (playlistId: string, relatedMediaId?: string) => {
const relatedQuery = relatedMediaId ? `?related_media_id=${relatedMediaId}` : '';
Expand All @@ -14,5 +34,6 @@ export type UsePlaylistResult<TData = Playlist, TError = unknown> = UseBaseQuery
export default function usePlaylist(playlistId: string, relatedMediaId?: string): UsePlaylistResult {
return useQuery(['playlist', playlistId, relatedMediaId], () => getPlaylistById(playlistId, relatedMediaId), {
enabled: !!playlistId,
placeholderData,
});
}
1 change: 1 addition & 0 deletions src/screens/Home/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ const Home = (): JSX.Element => {
scrollTop={scrollTop}
width={document.body.offsetWidth}
isScrollingOptOut
overscanRowCount={3}
/>
)}
</WindowScroller>
Expand Down
5 changes: 5 additions & 0 deletions src/screens/Playlist/Playlist.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,8 @@
.cell {
padding: 8px;
}

.error {
color: var(--primary-color);
margin: 20px;
}
5 changes: 3 additions & 2 deletions src/screens/Playlist/Playlist.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ function Playlist({
const { updateBlurImage } = useContext(UIStateContext);
const config: Config = useContext(ConfigContext);
const { isLoading, error, data: { title, playlist } = { title: '', playlist: [] } } = usePlaylist(id);

const [filter, setFilter] = useState<string>('');
const breakpoint: Breakpoint = useBreakpoint();
const isLargeScreen = breakpoint >= Breakpoint.md;
Expand All @@ -53,8 +54,7 @@ function Playlist({
if (filteredPlaylist.length) updateBlurImage(filteredPlaylist[0].image);
}, [filter, filteredPlaylist, updateBlurImage]);

if (isLoading) return <p>Loading...</p>;
if (error || !playlist) return <p>No playlist found...</p>;
if (error || !playlist) return <h2 className={styles.error}>Could not load items</h2>;

const cellRenderer = ({ columnIndex, rowIndex, style }: GridCellProps) => {
if (!playlistRows[rowIndex][columnIndex]) return;
Expand All @@ -72,6 +72,7 @@ function Playlist({
seriesId={seriesId}
onClick={() => onCardClick(playlistItem)}
onHover={() => onCardHover(playlistItem)}
loading={isLoading}
/>
</div>
);
Expand Down

0 comments on commit 64e9b92

Please sign in to comment.