Skip to content

Commit

Permalink
feat(home): add Bookmarks view
Browse files Browse the repository at this point in the history
  • Loading branch information
AXeL-dev committed Oct 2, 2022
1 parent c675ca8 commit f35b006
Show file tree
Hide file tree
Showing 32 changed files with 681 additions and 203 deletions.
28 changes: 27 additions & 1 deletion src/store/reducers/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,21 @@ export const defaultSettings = {
recentViewFilters: {
seen: true,
watchLater: true,
bookmarked: true,
ignored: false,
others: true,
},
watchLaterViewFilters: {
seen: true,
bookmarked: true,
archived: true,
others: true,
},
bookmarksViewFilters: {
seen: true,
watchLater: true,
others: true,
},
allViewSorting: {
publishDate: false,
},
Expand All @@ -36,8 +43,11 @@ export const defaultSettings = {
watchLaterViewSorting: {
publishDate: false,
},
bookmarksViewSorting: {
publishDate: false,
},
homeDisplayOptions: {
hiddenViews: [],
hiddenViews: [HomeView.Bookmarks],
extraVideoActions: [],
},
enableNotifications: true,
Expand Down Expand Up @@ -93,6 +103,14 @@ export const settingsSlice = createSlice({
...filters,
},
};
case HomeView.Bookmarks:
return {
...state,
bookmarksViewFilters: {
...state.bookmarksViewFilters,
...filters,
},
};
default:
return state;
}
Expand Down Expand Up @@ -130,6 +148,14 @@ export const settingsSlice = createSlice({
...sorting,
},
};
case HomeView.Bookmarks:
return {
...state,
bookmarksViewSorting: {
...state.bookmarksViewSorting,
...sorting,
},
};
default:
return state;
}
Expand Down
14 changes: 14 additions & 0 deletions src/store/reducers/videos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,19 @@ export const videosSlice = createSlice({
: video,
);
},
clearBookmarksList: (state) => {
state.list = state.list.map((video) =>
video.flags.bookmarked
? {
...video,
flags: {
...video.flags,
bookmarked: false,
},
}
: video,
);
},
archiveVideo: (state, action: PayloadAction<AddVideoPayload>) => {
const video = action.payload;
setVideoFlags({
Expand Down Expand Up @@ -209,6 +222,7 @@ export const {
addVideoFlag,
removeVideoFlag,
clearWatchLaterList,
clearBookmarksList,
archiveVideo,
unarchiveVideo,
archiveVideosByFlag,
Expand Down
31 changes: 20 additions & 11 deletions src/store/selectors/settings.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import type { RootState } from 'store';
import { createSelector } from 'reselect';
import {
HomeView,
ViewFilters,
RecentViewFilters,
WatchLaterViewFilters,
ExtraVideoAction,
} from 'types';
import { HomeView, ViewFilters, ExtraVideoAction } from 'types';
import { defaultSettings } from 'store/reducers/settings';

export const selectSettings = (state: RootState) => state.settings;
Expand All @@ -22,12 +16,17 @@ export const selectViewFilters = (view: HomeView) =>
return {
...defaultSettings.recentViewFilters,
...settings.recentViewFilters,
} as RecentViewFilters;
} as ViewFilters;
case HomeView.WatchLater:
return {
...defaultSettings.watchLaterViewFilters,
...settings.watchLaterViewFilters,
} as WatchLaterViewFilters;
} as ViewFilters;
case HomeView.Bookmarks:
return {
...defaultSettings.bookmarksViewFilters,
...settings.bookmarksViewFilters,
} as ViewFilters;
default:
return {} as ViewFilters;
}
Expand All @@ -52,6 +51,11 @@ export const selectViewSorting = (view: HomeView) =>
...defaultSettings.watchLaterViewSorting,
...settings.watchLaterViewSorting,
};
case HomeView.Bookmarks:
return {
...defaultSettings.bookmarksViewSorting,
...settings.bookmarksViewSorting,
};
case HomeView.All:
default:
return {
Expand All @@ -74,14 +78,19 @@ export const selectHiddenViews = createSelector(
(options) => options.hiddenViews,
);

export const selectHasHiddenView = (view: HomeView) =>
createSelector(selectHiddenViews, (hiddenViews) =>
hiddenViews.includes(view),
);

export const selectExtraVideoActions = createSelector(
selectHomeDisplayOptions,
(options) => options.extraVideoActions,
);

export const selectHasExtraVideoAction = (action: ExtraVideoAction) =>
createSelector(selectHomeDisplayOptions, (options) =>
options.extraVideoActions.includes(action),
createSelector(selectExtraVideoActions, (extraVideoActions) =>
extraVideoActions.includes(action),
);

export const selectRecentVideosSeniority = createSelector(
Expand Down
39 changes: 32 additions & 7 deletions src/store/selectors/videos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,36 @@ export const selectWatchLaterVideos = (channel?: Channel) =>
.sort((a, b) => b.publishedAt - a.publishedAt),
);

export const selectBookmarkedVideos = (channel?: Channel) =>
createSelector(
selectVideos,
selectViewFilters(HomeView.Bookmarks),
(videos, filters) =>
videos
.filter(
(video) =>
video.flags.bookmarked &&
(!channel || channel.id === video.channelId) &&
filterVideoByFlags(video, filters),
)
.sort((a, b) => b.publishedAt - a.publishedAt),
);

export const selectBookmarkedVideosCount = createSelector(
selectVideos,
selectViewFilters(HomeView.Bookmarks),
selectActiveChannels,
(videos, filters, activeChannels) => {
const activeChannelsIds = activeChannels.map(({ id }) => id);
return videos.filter(
(video) =>
video.flags.bookmarked &&
activeChannelsIds.includes(video.channelId) &&
filterVideoByFlags(video, filters),
).length;
},
);

export const selectWatchLaterVideosCount = createSelector(
selectVideos,
selectViewFilters(HomeView.WatchLater),
Expand Down Expand Up @@ -142,13 +172,8 @@ export const selectSeenWatchLaterVideosCount = createSelector(
},
);

export const selectVideoMeta = (video: Video) =>
export const selectVideoFlag = (video: Video, flag: VideoFlag) =>
createSelector(selectVideos, (videos) => {
const { flags } = videos.find(({ id }) => id === video.id) || {};
return {
isSeen: flags?.seen || false,
isToWatchLater: flags?.toWatchLater || false,
isArchived: flags?.archived || false,
isIgnored: flags?.ignored || false,
};
return flags?.[flag] || false;
});
1 change: 1 addition & 0 deletions src/store/utils/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const removeOutdatedVideos = (videos: VideoCache[], settings: Settings) => {
return videos.filter(
({ flags, publishedAt }) =>
flags.toWatchLater ||
flags.bookmarked ||
((flags.seen || flags.ignored) &&
elapsedDays(publishedAt) <= VideosSeniority.OneMonth) ||
(flags.recent &&
Expand Down
18 changes: 15 additions & 3 deletions src/types/Settings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { Either } from './common';

export interface Settings {
defaultView: HomeView | null;
apiKey: string;
Expand All @@ -8,9 +6,11 @@ export interface Settings {
recentVideosSeniority: VideosSeniority;
recentViewFilters: RecentViewFilters;
watchLaterViewFilters: WatchLaterViewFilters;
bookmarksViewFilters: BookmarksViewFilters;
allViewSorting: ViewSorting;
recentViewSorting: ViewSorting;
watchLaterViewSorting: ViewSorting;
bookmarksViewSorting: ViewSorting;
homeDisplayOptions: HomeDisplayOptions;
enableNotifications: boolean;
queryTimeout: number;
Expand All @@ -32,24 +32,36 @@ export interface ViewSorting {
export interface RecentViewFilters {
seen: boolean;
watchLater: boolean;
bookmarked: boolean;
ignored: boolean;
others: boolean;
}

export interface WatchLaterViewFilters {
seen: boolean;
bookmarked: boolean;
archived: boolean;
others: boolean;
}

export type ViewFilters = Either<RecentViewFilters, WatchLaterViewFilters>;
export interface BookmarksViewFilters {
seen: boolean;
watchLater: boolean;
others: boolean;
}

export interface ViewFilters
extends RecentViewFilters,
WatchLaterViewFilters,
BookmarksViewFilters {}

export type ViewFilter = keyof ViewFilters;

export enum HomeView {
All = 'all',
Recent = 'recent',
WatchLater = 'watch-later',
Bookmarks = 'bookmarks',
}

export enum VideosSeniority {
Expand Down
1 change: 1 addition & 0 deletions src/types/Video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type VideoFlags = Partial<{
archived: boolean;
ignored: boolean;
recent: boolean;
bookmarked: boolean;
}>;

export type VideoFlag = keyof VideoFlags;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import { useAppSelector } from 'store';
import { selectBookmarkedVideos } from 'store/selectors/videos';
import StaticRenderer, { StaticRendererProps } from './StaticRenderer';

export interface BookmarksViewRendererProps
extends Omit<StaticRendererProps, 'videos'> {}

function BookmarksViewRenderer(props: BookmarksViewRendererProps) {
const { channel, ...rest } = props;
const videos = useAppSelector(selectBookmarkedVideos(channel));

return <StaticRenderer channel={channel} videos={videos} {...rest} />;
}

export default BookmarksViewRenderer;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Box, Tooltip } from '@mui/material';
import ArchiveIcon from '@mui/icons-material/Archive';
import { HomeView, Video } from 'types';
import { useAppSelector } from 'store';
import { selectVideoMeta } from 'store/selectors/videos';
import { selectVideoFlag } from 'store/selectors/videos';

interface ArchivedBadgeProps {
video: Video;
Expand All @@ -12,7 +12,7 @@ interface ArchivedBadgeProps {

function ArchivedBadge(props: ArchivedBadgeProps) {
const { video, view } = props;
const { isArchived } = useAppSelector(selectVideoMeta(video));
const isArchived = useAppSelector(selectVideoFlag(video, 'archived'));

return view === HomeView.WatchLater && isArchived ? (
<Tooltip title="Archived" aria-label="archived">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Box, Tooltip } from '@mui/material';
import DoDisturbOnIcon from '@mui/icons-material/DoDisturbOn';
import { HomeView, Video } from 'types';
import { useAppSelector } from 'store';
import { selectVideoMeta } from 'store/selectors/videos';
import { selectVideoFlag } from 'store/selectors/videos';

interface IgnoredBadgeProps {
video: Video;
Expand All @@ -12,7 +12,7 @@ interface IgnoredBadgeProps {

function IgnoredBadge(props: IgnoredBadgeProps) {
const { video, view } = props;
const { isIgnored } = useAppSelector(selectVideoMeta(video));
const isIgnored = useAppSelector(selectVideoFlag(video, 'ignored'));

return view === HomeView.Recent && isIgnored ? (
<Tooltip title="Ignored" aria-label="ignored">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { Box, Tooltip } from '@mui/material';
import VisibilityIcon from '@mui/icons-material/Visibility';
import { Video } from 'types';
import { useAppSelector } from 'store';
import { selectVideoMeta } from 'store/selectors/videos';
import { selectVideoFlag } from 'store/selectors/videos';

interface SeenBadgeProps {
video: Video;
}

function SeenBadge(props: SeenBadgeProps) {
const { video } = props;
const { isSeen } = useAppSelector(selectVideoMeta(video));
const isSeen = useAppSelector(selectVideoFlag(video, 'seen'));

return isSeen ? (
<Tooltip title="Seen" aria-label="seen">
Expand Down
Loading

0 comments on commit f35b006

Please sign in to comment.