Skip to content

Commit

Permalink
refactor: view filters
Browse files Browse the repository at this point in the history
  • Loading branch information
AXeL-dev committed Aug 22, 2022
1 parent 3bbeea8 commit 671c0ab
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 117 deletions.
45 changes: 24 additions & 21 deletions src/store/selectors/videos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {
Channel,
HomeView,
Video,
VideoCache,
VideoFlag,
VideoFlags,
ViewFilter,
ViewFilters,
} from 'types';
Expand All @@ -14,9 +14,13 @@ import { selectViewFilters } from './settings';

export const selectVideos = (state: RootState) => state.videos.list;

export const selectChannelVideos = (channel: Channel) =>
export const selectChannelVideos = (channel: Channel, filters?: ViewFilters) =>
createSelector(selectVideos, (videos) =>
videos.filter(({ channelId }) => channel.id === channelId),
videos.filter(
(video) =>
channel.id === video.channelId &&
(!filters || filterVideoByFlags(video, filters)),
),
);

export const selectViewedVideos = (channel?: Channel) =>
Expand Down Expand Up @@ -44,24 +48,23 @@ const filter2Flag = (key: ViewFilter): VideoFlag => {
}
};

export const filterVideoByFlags = (flags: VideoFlags, filters: ViewFilters) => {
export const filterVideoByFlags = (video: VideoCache, filters: ViewFilters) => {
const filterKeys = Object.keys(filters) as ViewFilter[];
const hasFlag = (key: ViewFilter) => {
const flag = filter2Flag(key);
return video.flags[flag];
};
return filterKeys.some((key) => {
switch (key) {
case 'uncategorised':
return (
filters.uncategorised &&
filterKeys
.filter((key) => key !== 'uncategorised')
.every((key) => {
const flag = filter2Flag(key);
return !flags[flag];
})
.filter((key) => !['uncategorised'].includes(key))
.every((key) => !hasFlag(key))
);
default: {
const flag = filter2Flag(key);
return filters[key] && flags[flag];
}
default:
return filters[key] && hasFlag(key);
}
});
};
Expand All @@ -73,10 +76,10 @@ export const selectWatchLaterVideos = (channel?: Channel) =>
(videos, filters) =>
videos
.filter(
({ flags, channelId }) =>
flags.toWatchLater &&
(!channel || channel.id === channelId) &&
filterVideoByFlags(flags, filters),
(video) =>
video.flags.toWatchLater &&
(!channel || channel.id === video.channelId) &&
filterVideoByFlags(video, filters),
)
.sort((a, b) => b.publishedAt - a.publishedAt),
);
Expand All @@ -88,10 +91,10 @@ export const selectWatchLaterVideosCount = createSelector(
(videos, filters, activeChannels) => {
const activeChannelsIds = activeChannels.map(({ id }) => id);
return videos.filter(
({ flags, channelId }) =>
flags.toWatchLater &&
activeChannelsIds.includes(channelId) &&
filterVideoByFlags(flags, filters),
(video) =>
video.flags.toWatchLater &&
activeChannelsIds.includes(video.channelId) &&
filterVideoByFlags(video, filters),
).length;
},
);
Expand Down
13 changes: 9 additions & 4 deletions src/store/services/youtube/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,14 @@ type GetVideosByIdResponse = {
};

type GetChannelVideosArgs = GetChannelActivitiesArgs & {
persistVideos?: boolean;
persistVideosFlags?: VideoFlags;
persistVideosOptions?: PersistVideosOptions;
};

export interface PersistVideosOptions {
enable: boolean;
flags?: VideoFlags;
}

export type GetChannelVideosResponse = GetVideosByIdResponse;

const queries = {
Expand Down Expand Up @@ -277,9 +281,10 @@ export const extendedApi = youtubeApi.injectEndpoints({
};
},
onQueryStarted: async (arg, { dispatch, queryFulfilled }) => {
const { persistVideos, persistVideosFlags: flags = {} } = arg;
const { persistVideosOptions } = arg;
try {
if (persistVideos) {
if (persistVideosOptions?.enable) {
const { flags = {} } = persistVideosOptions;
const { data } = await queryFulfilled;
dispatch(
saveVideos({
Expand Down
16 changes: 8 additions & 8 deletions src/ui/components/pages/Home/ChannelRenderer/DefaultRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React, { useState, useEffect } from 'react';
import { Channel, HomeView, Video, VideoFlags } from 'types';
import { useGetChannelVideosQuery } from 'store/services/youtube';
import { Channel, HomeView, Video } from 'types';
import {
PersistVideosOptions,
useGetChannelVideosQuery,
} from 'store/services/youtube';
import ChannelRenderer from './ChannelRenderer';
import config from './ChannelVideos/config';
import { useGrid } from 'hooks';
Expand All @@ -9,8 +12,7 @@ export interface DefaultRendererProps {
channel: Channel;
view: HomeView;
publishedAfter?: string;
persistVideos?: boolean;
persistVideosFlags?: VideoFlags;
persistVideosOptions?: PersistVideosOptions;
filter?: (video: Video) => boolean;
onError?: (error: any) => void;
onChange?: (data: any) => void;
Expand All @@ -21,8 +23,7 @@ function DefaultRenderer(props: DefaultRendererProps) {
const {
channel,
publishedAfter,
persistVideos = false,
persistVideosFlags,
persistVideosOptions,
filter = () => true,
onError,
onChange,
Expand All @@ -36,8 +37,7 @@ function DefaultRenderer(props: DefaultRendererProps) {
channel,
publishedAfter,
maxResults,
persistVideos,
persistVideosFlags,
persistVideosOptions,
},
{
skip: itemsPerRow === 0,
Expand Down
37 changes: 10 additions & 27 deletions src/ui/components/pages/Home/ChannelRenderer/RecentViewRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import { useAppSelector } from 'store';
import { selectSettings } from 'store/selectors/settings';
import { getDateBefore } from 'helpers/utils';
import DefaultRenderer, { DefaultRendererProps } from './DefaultRenderer';
import {
filterVideoByFlags,
selectChannelVideos,
} from 'store/selectors/videos';
import { selectChannelVideos } from 'store/selectors/videos';
import { isWebExtension } from 'helpers/webext';
import { Video } from 'types';

Expand All @@ -16,28 +13,12 @@ export interface RecentViewRendererProps
function RecentViewRenderer(props: RecentViewRendererProps) {
const { channel } = props;
const settings = useAppSelector(selectSettings);
const videos = useAppSelector(selectChannelVideos(channel));
const filters = settings.recentViewFilters;
const { exclusionList, inclusionList } = useMemo(
() => ({
exclusionList: videos
.filter(({ flags }) => !filterVideoByFlags(flags, filters))
.map(({ id }) => id),
inclusionList: videos
.filter(({ flags }) => filterVideoByFlags(flags, filters))
.map(({ id }) => id),
}),
[videos, filters],
);
const videos = useAppSelector(
selectChannelVideos(channel, settings.recentViewFilters),
).map(({ id }) => id);
const filterCallback = useCallback(
(video: Video) => {
if (filters.uncategorised) {
return !exclusionList.includes(video.id);
} else {
return inclusionList.includes(video.id);
}
},
[filters.uncategorised, exclusionList, inclusionList],
(video: Video) => videos.includes(video.id),
[videos],
);
const publishedAfter = useMemo(
() => getDateBefore(settings.recentVideosSeniority).toISOString(),
Expand All @@ -47,8 +28,10 @@ function RecentViewRenderer(props: RecentViewRendererProps) {
return (
<DefaultRenderer
publishedAfter={publishedAfter}
persistVideos={isWebExtension}
persistVideosFlags={{ recent: true }}
persistVideosOptions={{
enable: isWebExtension,
flags: { recent: true },
}}
filter={filterCallback}
{...props}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ function RecentVideosSeniority(props: RecentVideosSeniorityProps) {
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
>
{options.map(({ label, value }) => (
{options.map(({ label, value }, index) => (
<CheckableMenuItem
key={index}
checked={seniority === value}
onClick={() => handleChange(value)}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useAppDispatch, useAppSelector } from 'store';
import FilterListIcon from '@mui/icons-material/FilterList';
import { selectViewFilters } from 'store/selectors/settings';
import { setViewFilters } from 'store/reducers/settings';
import { HomeView, Nullable } from 'types';
import { HomeView, Nullable, RecentViewFilters as Filters } from 'types';

interface RecentViewFiltersProps {}

Expand All @@ -23,34 +23,12 @@ function RecentViewFilters(props: RecentViewFiltersProps) {
setAnchorEl(null);
};

const handleUncategorisedFilterToggle = () => {
const handleFilterToggle = (key: keyof Filters) => {
dispatch(
setViewFilters({
view: HomeView.Recent,
filters: {
uncategorised: !filters.uncategorised,
},
}),
);
};

const handleViewedFilterToggle = () => {
dispatch(
setViewFilters({
view: HomeView.Recent,
filters: {
viewed: !filters.viewed,
},
}),
);
};

const handleWatchLaterFilterToggle = () => {
dispatch(
setViewFilters({
view: HomeView.Recent,
filters: {
watchLater: !filters.watchLater,
[key]: !filters[key],
},
}),
);
Expand Down Expand Up @@ -82,19 +60,19 @@ function RecentViewFilters(props: RecentViewFiltersProps) {
>
<CheckableMenuItem
checked={filters.uncategorised}
onClick={handleUncategorisedFilterToggle}
onClick={() => handleFilterToggle('uncategorised')}
>
Uncategorised
</CheckableMenuItem>
<CheckableMenuItem
checked={filters.viewed}
onClick={handleViewedFilterToggle}
onClick={() => handleFilterToggle('viewed')}
>
Viewed
</CheckableMenuItem>
<CheckableMenuItem
checked={filters.watchLater!}
onClick={handleWatchLaterFilterToggle}
onClick={() => handleFilterToggle('watchLater')}
>
Watch later
</CheckableMenuItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { IconButton } from '@mui/material';
import { StyledMenu, CheckableMenuItem } from 'ui/components/shared';
import { useAppDispatch, useAppSelector } from 'store';
import FilterListIcon from '@mui/icons-material/FilterList';
import { HomeView, Nullable } from 'types';
import { HomeView, Nullable, WatchLaterViewFilters as Filters } from 'types';
import { selectViewFilters } from 'store/selectors/settings';
import { setViewFilters } from 'store/reducers/settings';

Expand All @@ -23,34 +23,12 @@ function WatchLaterViewFilters(props: WatchLaterViewFiltersProps) {
setAnchorEl(null);
};

const handleUncategorisedFilterToggle = () => {
const handleFilterToggle = (key: keyof Filters) => {
dispatch(
setViewFilters({
view: HomeView.WatchLater,
filters: {
uncategorised: !filters.uncategorised,
},
}),
);
};

const handleViewedFilterToggle = () => {
dispatch(
setViewFilters({
view: HomeView.WatchLater,
filters: {
viewed: !filters.viewed,
},
}),
);
};

const handleArchivedFilterToggle = () => {
dispatch(
setViewFilters({
view: HomeView.WatchLater,
filters: {
archived: !filters.archived,
[key]: !filters[key],
},
}),
);
Expand Down Expand Up @@ -82,19 +60,19 @@ function WatchLaterViewFilters(props: WatchLaterViewFiltersProps) {
>
<CheckableMenuItem
checked={filters.uncategorised}
onClick={handleUncategorisedFilterToggle}
onClick={() => handleFilterToggle('uncategorised')}
>
Uncategorised
</CheckableMenuItem>
<CheckableMenuItem
checked={filters.viewed}
onClick={handleViewedFilterToggle}
onClick={() => handleFilterToggle('viewed')}
>
Viewed
</CheckableMenuItem>
<CheckableMenuItem
checked={filters.archived!}
onClick={handleArchivedFilterToggle}
onClick={() => handleFilterToggle('archived')}
>
Archived
</CheckableMenuItem>
Expand Down

0 comments on commit 671c0ab

Please sign in to comment.