Skip to content

Commit

Permalink
feat(home): add ignored flag to recent videos view
Browse files Browse the repository at this point in the history
  • Loading branch information
AXeL-dev committed Aug 28, 2022
1 parent 7df12ab commit 547efe5
Show file tree
Hide file tree
Showing 21 changed files with 401 additions and 64 deletions.
1 change: 1 addition & 0 deletions src/store/reducers/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const defaultSettings = {
recentViewFilters: {
viewed: true,
watchLater: true,
ignored: false,
others: true,
},
watchLaterViewFilters: {
Expand Down
71 changes: 43 additions & 28 deletions src/store/reducers/videos.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { VideoCache, Video, VideoFlags, VideoFlag } from 'types';

type VideoWithId = Pick<VideoCache, 'id'>;
type AddVideoPayload = Video | Omit<VideoCache, 'flags'>;
type RemoveVideoPayload = Video | Pick<VideoCache, 'id'>;
type RemoveVideoPayload = Video | VideoWithId;

interface VideosState {
list: VideoCache[];
Expand Down Expand Up @@ -67,39 +68,32 @@ export const videosSlice = createSlice({
...action.payload,
};
},
addViewedVideo: (state, action: PayloadAction<AddVideoPayload>) => {
const video = action.payload;
addVideo({
state,
video,
flags: { viewed: true },
});
},
removeViewedVideo: (state, action: PayloadAction<RemoveVideoPayload>) => {
const video = action.payload;
setVideoFlags({
state,
video,
flags: { viewed: false },
});
},
addWatchLaterVideo: (state, action: PayloadAction<AddVideoPayload>) => {
const video = action.payload;
addVideoFlag: (
state,
action: PayloadAction<{
video: AddVideoPayload;
flag: VideoFlag;
}>,
) => {
const { video, flag } = action.payload;
addVideo({
state,
video,
flags: { toWatchLater: true },
flags: { [flag]: true },
});
},
removeWatchLaterVideo: (
removeVideoFlag: (
state,
action: PayloadAction<RemoveVideoPayload>,
action: PayloadAction<{
video: RemoveVideoPayload;
flag: VideoFlag;
}>,
) => {
const video = action.payload;
const { video, flag } = action.payload;
setVideoFlags({
state,
video,
flags: { toWatchLater: false },
flags: { [flag]: false },
});
},
clearWatchLaterList: (
Expand Down Expand Up @@ -154,6 +148,28 @@ export const videosSlice = createSlice({
: video,
);
},
setVideosFlag: (
state,
action: PayloadAction<{
videos: VideoWithId[];
flag: VideoFlag;
value?: boolean;
}>,
) => {
const { videos, flag, value = true } = action.payload;
const targetIds = videos.map(({ id }) => id);
state.list = state.list.map((video) =>
targetIds.includes(video.id)
? {
...video,
flags: {
...video.flags,
[flag]: value,
},
}
: video,
);
},
saveVideos: (
state,
action: PayloadAction<{
Expand All @@ -175,14 +191,13 @@ export const videosSlice = createSlice({

export const {
setVideos,
addViewedVideo,
removeViewedVideo,
addWatchLaterVideo,
removeWatchLaterVideo,
addVideoFlag,
removeVideoFlag,
clearWatchLaterList,
archiveVideo,
unarchiveVideo,
archiveVideosByFlag,
setVideosFlag,
saveVideos,
} = videosSlice.actions;

Expand Down
18 changes: 15 additions & 3 deletions src/store/selectors/settings.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import type { RootState } from 'store';
import { createSelector } from 'reselect';
import { HomeView, ViewFilters } from 'types';
import {
HomeView,
ViewFilters,
RecentViewFilters,
WatchLaterViewFilters,
} from 'types';
import { defaultSettings } from 'store/reducers/settings';

export const selectSettings = (state: RootState) => state.settings;

Expand All @@ -12,9 +18,15 @@ export const selectViewFilters = (view: HomeView) =>
createSelector(selectSettings, (settings): ViewFilters => {
switch (view) {
case HomeView.Recent:
return settings.recentViewFilters;
return {
...defaultSettings.recentViewFilters,
...settings.recentViewFilters,
} as RecentViewFilters;
case HomeView.WatchLater:
return settings.watchLaterViewFilters;
return {
...defaultSettings.watchLaterViewFilters,
...settings.watchLaterViewFilters,
} as WatchLaterViewFilters;
default:
return {} as ViewFilters;
}
Expand Down
13 changes: 13 additions & 0 deletions src/store/selectors/videos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ export const selectRecentChannelVideos = (channel: Channel) =>
),
);

export const selectRecentOnlyVideos = (channel?: Channel) =>
createSelector(selectVideos, (videos) =>
videos.filter(
({ flags = {}, channelId }) =>
Object.keys(flags).every(
(key) =>
['recent', 'notified'].includes(key) || !flags[key as VideoFlag],
) &&
(!channel || channel.id === channelId),
),
);

export const selectViewedVideos = (channel?: Channel) =>
createSelector(selectVideos, (videos) =>
videos.filter(
Expand Down Expand Up @@ -135,5 +147,6 @@ export const selectVideoMeta = (video: Video) =>
isViewed: flags?.viewed || false,
isToWatchLater: flags?.toWatchLater || false,
isArchived: flags?.archived || false,
isIgnored: flags?.ignored || false,
};
});
2 changes: 1 addition & 1 deletion src/store/utils/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const removeOutdatedVideos = (videos: VideoCache[], settings: Settings) => {
({ flags, publishedAt }) =>
flags.viewed ||
flags.toWatchLater ||
(flags.recent &&
((flags.recent || flags.ignored) &&
elapsedDays(publishedAt) <= settings.recentVideosSeniority) ||
(flags.notified &&
elapsedDays(publishedAt) <= channelCheckerConfig.videosSeniority),
Expand Down
1 change: 1 addition & 0 deletions src/types/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface HomeDisplayOptions {
export interface RecentViewFilters {
viewed: boolean;
watchLater: boolean;
ignored: boolean;
others: boolean;
}

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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
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';

interface IgnoredBadgeProps {
video: Video;
view: HomeView;
}

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

return view === HomeView.Recent && isIgnored ? (
<Tooltip title="Ignored" aria-label="ignored">
<Box
sx={{
display: 'flex',
color: '#eee',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
padding: '3px 5px',
borderRadius: '2px',
'&:hover': {
color: '#fff',
},
}}
>
<DoDisturbOnIcon sx={{ fontSize: '1rem' }} />
</Box>
</Tooltip>
) : null;
}

export default IgnoredBadge;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Box } from '@mui/material';
import { HomeView, Video } from 'types';
import ViewedBadge from './ViewedBadge';
import ArchivedBadge from './ArchivedBadge';
import IgnoredBadge from './IgnoredBadge';

interface VideoBadgesProps {
video: Video;
Expand All @@ -24,6 +25,7 @@ function VideoBadges(props: VideoBadgesProps) {
}}
>
<ViewedBadge video={video} />
<IgnoredBadge video={video} view={view} />
<ArchivedBadge video={video} view={view} />
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from 'react';
import { IconButton, Tooltip } from '@mui/material';
import DoDisturbOnIcon from '@mui/icons-material/DoDisturbOn';
import DoNotDisturbOffIcon from '@mui/icons-material/DoNotDisturbOff';
import { HomeView, Video } from 'types';
import { useAppDispatch, useAppSelector } from 'store';
import { addVideoFlag, removeVideoFlag } from 'store/reducers/videos';
import { selectVideoMeta } from 'store/selectors/videos';

interface IgnoredActionProps {
video: Video;
view: HomeView;
}

function IgnoredAction(props: IgnoredActionProps) {
const { video, view } = props;
const { isIgnored } = useAppSelector(selectVideoMeta(video));
const dispatch = useAppDispatch();

return view === HomeView.Recent ? (
isIgnored ? (
<Tooltip title="Unignore" aria-label="unignore">
<IconButton
sx={{
display: 'flex',
color: '#eee',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
padding: '4px',
borderRadius: '2px',
'&:hover': {
color: '#fff',
},
}}
size="small"
onClick={() => {
dispatch(
removeVideoFlag({
video,
flag: 'ignored',
}),
);
}}
>
<DoNotDisturbOffIcon sx={{ fontSize: '1.125rem' }} />
</IconButton>
</Tooltip>
) : (
<Tooltip title="Ignore" aria-label="ignore">
<IconButton
sx={{
color: '#eee',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
padding: '4px',
borderRadius: '2px',
'&:hover': {
color: '#fff',
},
}}
size="small"
onClick={() => {
dispatch(
addVideoFlag({
video,
flag: 'ignored',
}),
);
}}
>
<DoDisturbOnIcon sx={{ fontSize: '1.125rem' }} />
</IconButton>
</Tooltip>
)
) : null;
}

export default IgnoredAction;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import VisibilityIcon from '@mui/icons-material/Visibility';
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
import { Video } from 'types';
import { useAppDispatch, useAppSelector } from 'store';
import { addViewedVideo, removeViewedVideo } from 'store/reducers/videos';
import { addVideoFlag, removeVideoFlag } from 'store/reducers/videos';
import { selectVideoMeta } from 'store/selectors/videos';

interface ViewedActionProps {
Expand All @@ -30,7 +30,12 @@ function ViewedAction(props: ViewedActionProps) {
}}
size="small"
onClick={() => {
dispatch(addViewedVideo(video));
dispatch(
addVideoFlag({
video,
flag: 'viewed',
}),
);
}}
>
<VisibilityIcon sx={{ fontSize: '1.125rem' }} />
Expand All @@ -51,7 +56,12 @@ function ViewedAction(props: ViewedActionProps) {
}}
size="small"
onClick={() => {
dispatch(removeViewedVideo(video));
dispatch(
removeVideoFlag({
video,
flag: 'viewed',
}),
);
}}
>
<VisibilityOffIcon sx={{ fontSize: '1.125rem' }} />
Expand Down
Loading

0 comments on commit 547efe5

Please sign in to comment.