watched filter split by channel and playlist

This commit is contained in:
Simon
2025-08-23 12:17:55 +07:00
parent ba44ab252e
commit a9264e348f
9 changed files with 48 additions and 12 deletions

View File

@@ -42,6 +42,8 @@ class UserMeConfigSerializer(serializers.Serializer):
) )
grid_items = serializers.IntegerField(max_value=7, min_value=3) grid_items = serializers.IntegerField(max_value=7, min_value=3)
hide_watched = serializers.BooleanField(allow_null=True) hide_watched = serializers.BooleanField(allow_null=True)
hide_watched_channel = serializers.BooleanField(allow_null=True)
hide_watched_playlist = serializers.BooleanField(allow_null=True)
file_size_unit = serializers.ChoiceField(choices=["binary", "metric"]) file_size_unit = serializers.ChoiceField(choices=["binary", "metric"])
show_ignored_only = serializers.BooleanField() show_ignored_only = serializers.BooleanField()
show_subed_only = serializers.BooleanField(allow_null=True) show_subed_only = serializers.BooleanField(allow_null=True)

View File

@@ -23,6 +23,8 @@ class UserConfigType(TypedDict, total=False):
vid_type_filter: str | None vid_type_filter: str | None
grid_items: int grid_items: int
hide_watched: bool | None hide_watched: bool | None
hide_watched_channel: bool | None
hide_watched_playlist: bool | None
file_size_unit: str file_size_unit: str
show_ignored_only: bool show_ignored_only: bool
show_subed_only: bool | None show_subed_only: bool | None
@@ -48,6 +50,8 @@ class UserConfig:
vid_type_filter=None, vid_type_filter=None,
grid_items=3, grid_items=3,
hide_watched=False, hide_watched=False,
hide_watched_channel=None,
hide_watched_playlist=None,
file_size_unit="binary", file_size_unit="binary",
show_ignored_only=False, show_ignored_only=False,
show_subed_only=None, show_subed_only=None,

View File

@@ -34,6 +34,8 @@ export type UserConfigType = {
vid_type_filter: VideoTypes | null; vid_type_filter: VideoTypes | null;
grid_items: number; grid_items: number;
hide_watched: boolean | null; hide_watched: boolean | null;
hide_watched_channel: boolean | null;
hide_watched_playlist: boolean | null;
file_size_unit: 'binary' | 'metric'; file_size_unit: 'binary' | 'metric';
show_ignored_only: boolean; show_ignored_only: boolean;
show_subed_only: boolean | null; show_subed_only: boolean | null;

View File

@@ -21,14 +21,21 @@ import { useFilterBarTempConf } from '../stores/FilterbarTempConf';
import { useVideoSelectionStore } from '../stores/VideoSelectionStore'; import { useVideoSelectionStore } from '../stores/VideoSelectionStore';
import Button from './Button'; import Button from './Button';
import updateDownloadQueue from '../api/actions/updateDownloadQueue'; import updateDownloadQueue from '../api/actions/updateDownloadQueue';
import { HideWatchedType } from '../configuration/constants/HideWatched';
type FilterbarProps = { type FilterbarProps = {
viewStyle: ViewStyleNamesType; viewStyle: ViewStyleNamesType;
hideWatched: HideWatchedType;
showSort?: boolean; showSort?: boolean;
showTypeFilter?: boolean; showTypeFilter?: boolean;
}; };
const Filterbar = ({ viewStyle, showSort = true, showTypeFilter = false }: FilterbarProps) => { const Filterbar = ({
viewStyle,
hideWatched,
showSort = true,
showTypeFilter = false,
}: FilterbarProps) => {
const { userConfig, setUserConfig } = useUserConfigStore(); const { userConfig, setUserConfig } = useUserConfigStore();
const { const {
selectedVideoIds, selectedVideoIds,
@@ -44,6 +51,7 @@ const Filterbar = ({ viewStyle, showSort = true, showTypeFilter = false }: Filte
useFilterBarTempConf(); useFilterBarTempConf();
const currentViewStyle = userConfig[viewStyle]; const currentViewStyle = userConfig[viewStyle];
const currentHideWatched = userConfig[hideWatched];
const isGridView = currentViewStyle === ViewStylesEnum.Grid; const isGridView = currentViewStyle === ViewStylesEnum.Grid;
useEffect(() => { useEffect(() => {
@@ -114,10 +122,10 @@ const Filterbar = ({ viewStyle, showSort = true, showTypeFilter = false }: Filte
<div> <div>
<span>Filter:</span> <span>Filter:</span>
<select <select
value={userConfig.hide_watched === null ? '' : userConfig.hide_watched.toString()} value={currentHideWatched === null ? '' : currentHideWatched.toString()}
onChange={event => { onChange={event => {
handleUserConfigUpdate({ handleUserConfigUpdate({
hide_watched: event.target.value === '' ? null : event.target.value === 'true', [hideWatched]: event.target.value === '' ? null : event.target.value === 'true',
}); });
}} }}
> >

View File

@@ -0,0 +1,7 @@
export type HideWatchedType = 'hide_watched' | 'hide_watched_channel' | 'hide_watched_playlist';
export const HideWatchedName = {
Home: 'hide_watched',
Channel: 'hide_watched_channel',
Playlist: 'hide_watched_playlist',
};

View File

@@ -28,6 +28,7 @@ import { useUserConfigStore } from '../stores/UserConfigStore';
import { FileSizeUnits } from '../api/actions/updateUserConfig'; import { FileSizeUnits } from '../api/actions/updateUserConfig';
import { ApiResponseType } from '../functions/APIClient'; import { ApiResponseType } from '../functions/APIClient';
import { useFilterBarTempConf } from '../stores/FilterbarTempConf'; import { useFilterBarTempConf } from '../stores/FilterbarTempConf';
import { HideWatchedName, HideWatchedType } from '../configuration/constants/HideWatched';
type ChannelParams = { type ChannelParams = {
channelId: string; channelId: string;
@@ -76,9 +77,9 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => {
channel: channelId, channel: channelId,
page: currentPage, page: currentPage,
watch: watch:
userConfig.hide_watched === null userConfig.hide_watched_channel === null
? null ? null
: ((userConfig.hide_watched : ((userConfig.hide_watched_channel
? WatchTypesEnum.Watched ? WatchTypesEnum.Watched
: WatchTypesEnum.Unwatched) as WatchTypes), : WatchTypesEnum.Unwatched) as WatchTypes),
sort: userConfig.sort_by, sort: userConfig.sort_by,
@@ -97,7 +98,7 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => {
refresh, refresh,
userConfig.sort_by, userConfig.sort_by,
userConfig.sort_order, userConfig.sort_order,
userConfig.hide_watched, userConfig.hide_watched_channel,
filterHeight, filterHeight,
currentPage, currentPage,
channelId, channelId,
@@ -167,7 +168,10 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => {
</div> </div>
<div className={`boxed-content ${gridView}`}> <div className={`boxed-content ${gridView}`}>
<Filterbar viewStyle={ViewStyleNames.Home as ViewStyleNamesType} /> <Filterbar
viewStyle={ViewStyleNames.Home as ViewStyleNamesType}
hideWatched={HideWatchedName.Channel as HideWatchedType}
/>
</div> </div>
<EmbeddableVideoPlayer videoId={videoId} /> <EmbeddableVideoPlayer videoId={videoId} />

View File

@@ -23,6 +23,7 @@ import { SponsorBlockType } from './Video';
import { useUserConfigStore } from '../stores/UserConfigStore'; import { useUserConfigStore } from '../stores/UserConfigStore';
import { ApiResponseType } from '../functions/APIClient'; import { ApiResponseType } from '../functions/APIClient';
import { useFilterBarTempConf } from '../stores/FilterbarTempConf'; import { useFilterBarTempConf } from '../stores/FilterbarTempConf';
import { HideWatchedName, HideWatchedType } from '../configuration/constants/HideWatched';
export type PlayerType = { export type PlayerType = {
watched: boolean; watched: boolean;
@@ -202,7 +203,11 @@ const Home = () => {
<h1>Recent Videos</h1> <h1>Recent Videos</h1>
</div> </div>
<Filterbar viewStyle={ViewStyleNames.Home as ViewStyleNamesType} showTypeFilter={true} /> <Filterbar
viewStyle={ViewStyleNames.Home as ViewStyleNamesType}
hideWatched={HideWatchedName.Home as HideWatchedType}
showTypeFilter={true}
/>
</div> </div>
<div className={`boxed-content ${gridView}`}> <div className={`boxed-content ${gridView}`}>

View File

@@ -34,6 +34,7 @@ import { ApiResponseType } from '../functions/APIClient';
import NotFound from './NotFound'; import NotFound from './NotFound';
import updatePlaylistSortOrder from '../api/actions/updatePlaylistSortOrder'; import updatePlaylistSortOrder from '../api/actions/updatePlaylistSortOrder';
import { useFilterBarTempConf } from '../stores/FilterbarTempConf'; import { useFilterBarTempConf } from '../stores/FilterbarTempConf';
import { HideWatchedType, HideWatchedName } from '../configuration/constants/HideWatched';
export type VideoResponseType = { export type VideoResponseType = {
data?: VideoType[]; data?: VideoType[];
@@ -86,9 +87,9 @@ const Playlist = () => {
playlist: playlistId, playlist: playlistId,
page: currentPage, page: currentPage,
watch: watch:
userConfig.hide_watched === null userConfig.hide_watched_playlist === null
? null ? null
: ((userConfig.hide_watched : ((userConfig.hide_watched_playlist
? WatchTypesEnum.Watched ? WatchTypesEnum.Watched
: WatchTypesEnum.Unwatched) as WatchTypes), : WatchTypesEnum.Unwatched) as WatchTypes),
type: userConfig.vid_type_filter as VideoTypes, type: userConfig.vid_type_filter as VideoTypes,
@@ -110,7 +111,7 @@ const Playlist = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ }, [
playlistId, playlistId,
userConfig.hide_watched, userConfig.hide_watched_playlist,
userConfig.vid_type_filter, userConfig.vid_type_filter,
filterHeight, filterHeight,
refresh, refresh,
@@ -351,6 +352,7 @@ const Playlist = () => {
<div className={`boxed-content ${gridView}`}> <div className={`boxed-content ${gridView}`}>
<Filterbar <Filterbar
viewStyle={ViewStyleNames.Home as ViewStyleNamesType} // its a list of videos, so ViewStyleNames.Home viewStyle={ViewStyleNames.Home as ViewStyleNamesType} // its a list of videos, so ViewStyleNames.Home
hideWatched={HideWatchedName.Playlist as HideWatchedType}
showSort={false} showSort={false}
showTypeFilter={true} showTypeFilter={true}
/> />

View File

@@ -20,7 +20,9 @@ export const useUserConfigStore = create<UserConfigState>(set => ({
view_style_playlist: ViewStylesEnum.Grid as ViewStylesType, view_style_playlist: ViewStylesEnum.Grid as ViewStylesType,
vid_type_filter: null, vid_type_filter: null,
grid_items: 3, grid_items: 3,
hide_watched: false, hide_watched: null,
hide_watched_channel: null,
hide_watched_playlist: null,
file_size_unit: 'binary', file_size_unit: 'binary',
show_ignored_only: false, show_ignored_only: false,
show_subed_only: null, show_subed_only: null,