add video filter by height
This commit is contained in:
parent
445ef8ad05
commit
f2da730aa2
|
|
@ -120,6 +120,7 @@ class VideoListQuerySerializer(serializers.Serializer):
|
|||
choices=VideoTypeEnum.values_known(), required=False
|
||||
)
|
||||
page = serializers.IntegerField(required=False)
|
||||
height = serializers.IntegerField(required=False)
|
||||
|
||||
|
||||
class CommentThreadItemSerializer(serializers.Serializer):
|
||||
|
|
|
|||
|
|
@ -44,6 +44,11 @@ class QueryBuilder:
|
|||
type_list_list = self.parse_type(video_type)
|
||||
must_list.append(type_list_list)
|
||||
|
||||
height = self.request_params.get("height")
|
||||
if height:
|
||||
height_must = self.parse_height(height)
|
||||
must_list.append(height_must)
|
||||
|
||||
query = {"bool": {"must": must_list}}
|
||||
|
||||
return query
|
||||
|
|
@ -83,6 +88,11 @@ class QueryBuilder:
|
|||
|
||||
return {"match": {"vid_type": vid_type}}
|
||||
|
||||
def parse_height(self, height: str):
|
||||
"""parse height to int"""
|
||||
|
||||
return {"term": {"streams.height": {"value": height}}}
|
||||
|
||||
def parse_sort(self) -> dict | None:
|
||||
"""build sort key"""
|
||||
playlist = self.request_params.get("playlist")
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class VideoApiListView(ApiBaseView):
|
|||
- sort:enum=published|downloaded|views|likes|duration|filesize
|
||||
- order:enum=asc|desc
|
||||
- type:enum=videos|streams|shorts
|
||||
- height:int=px
|
||||
"""
|
||||
|
||||
search_base = "ta_video/_search/"
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ type FilterType = {
|
|||
sort?: SortByType;
|
||||
order?: SortOrderType;
|
||||
type?: VideoTypes;
|
||||
height?: string;
|
||||
};
|
||||
|
||||
const loadVideoListByFilter = async (filter: FilterType) => {
|
||||
|
|
@ -67,6 +68,7 @@ const loadVideoListByFilter = async (filter: FilterType) => {
|
|||
if (filter.sort) searchParams.append('sort', filter.sort);
|
||||
if (filter.order) searchParams.append('order', filter.order);
|
||||
if (filter.type) searchParams.append('type', filter.type);
|
||||
if (filter.height) searchParams.append('height', filter.height.toString());
|
||||
|
||||
const endpoint = `/api/video/${searchParams.toString() ? `?${searchParams.toString()}` : ''}`;
|
||||
return APIClient<VideoListByFilterResponseType>(endpoint);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
SortOrderType,
|
||||
VideoTypes,
|
||||
} from '../api/loader/loadVideoListByPage';
|
||||
import { useFilterBarTempConf } from '../stores/FilterbarTempConf';
|
||||
|
||||
type FilterbarProps = {
|
||||
viewStyle: ViewStyleNamesType;
|
||||
|
|
@ -26,6 +27,7 @@ const Filterbar = ({ viewStyle, showSort = true, showTypeFilter = false }: Filte
|
|||
const { userConfig, setUserConfig } = useUserConfigStore();
|
||||
|
||||
const [showHidden, setShowHidden] = useState(false);
|
||||
const { filterHeight, setFilterHeight } = useFilterBarTempConf();
|
||||
|
||||
const currentViewStyle = userConfig[viewStyle];
|
||||
const isGridView = currentViewStyle === ViewStylesEnum.Grid;
|
||||
|
|
@ -82,6 +84,11 @@ const Filterbar = ({ viewStyle, showSort = true, showTypeFilter = false }: Filte
|
|||
<option value="shorts">Shorts</option>
|
||||
</select>
|
||||
)}
|
||||
<input
|
||||
placeholder="height in px"
|
||||
value={filterHeight}
|
||||
onChange={e => setFilterHeight(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{showHidden && (
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import humanFileSize from '../functions/humanFileSize';
|
|||
import { useUserConfigStore } from '../stores/UserConfigStore';
|
||||
import { FileSizeUnits } from '../api/actions/updateUserConfig';
|
||||
import { ApiResponseType } from '../functions/APIClient';
|
||||
import { useFilterBarTempConf } from '../stores/FilterbarTempConf';
|
||||
|
||||
type ChannelParams = {
|
||||
channelId: string;
|
||||
|
|
@ -44,6 +45,7 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => {
|
|||
const videoId = searchParams.get('videoId');
|
||||
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
const { filterHeight } = useFilterBarTempConf();
|
||||
|
||||
const [channelResponse, setChannelResponse] = useState<ApiResponseType<ChannelResponseType>>();
|
||||
const [videoResponse, setVideoReponse] =
|
||||
|
|
@ -82,6 +84,7 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => {
|
|||
sort: userConfig.sort_by,
|
||||
order: userConfig.sort_order,
|
||||
type: videoType,
|
||||
height: filterHeight,
|
||||
});
|
||||
const channelAggs = await loadChannelAggs(channelId);
|
||||
|
||||
|
|
@ -95,6 +98,7 @@ const ChannelVideo = ({ videoType }: ChannelVideoProps) => {
|
|||
userConfig.sort_by,
|
||||
userConfig.sort_order,
|
||||
userConfig.hide_watched,
|
||||
filterHeight,
|
||||
currentPage,
|
||||
channelId,
|
||||
pagination?.current_page,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import EmbeddableVideoPlayer from '../components/EmbeddableVideoPlayer';
|
|||
import { SponsorBlockType } from './Video';
|
||||
import { useUserConfigStore } from '../stores/UserConfigStore';
|
||||
import { ApiResponseType } from '../functions/APIClient';
|
||||
import { useFilterBarTempConf } from '../stores/FilterbarTempConf';
|
||||
|
||||
export type PlayerType = {
|
||||
watched: boolean;
|
||||
|
|
@ -118,6 +119,8 @@ const Home = () => {
|
|||
const [continueVideoResponse, setContinueVideoResponse] =
|
||||
useState<ApiResponseType<VideoListByFilterResponseType>>();
|
||||
|
||||
const { filterHeight } = useFilterBarTempConf();
|
||||
|
||||
const { data: videoResponseData } = videoResponse ?? {};
|
||||
const { data: continueVideoResponseData } = continueVideoResponse ?? {};
|
||||
|
||||
|
|
@ -145,6 +148,7 @@ const Home = () => {
|
|||
type: userConfig.vid_type_filter as VideoTypes,
|
||||
sort: userConfig.sort_by,
|
||||
order: userConfig.sort_order,
|
||||
height: filterHeight,
|
||||
});
|
||||
|
||||
try {
|
||||
|
|
@ -165,6 +169,7 @@ const Home = () => {
|
|||
userConfig.sort_order,
|
||||
userConfig.hide_watched,
|
||||
userConfig.vid_type_filter,
|
||||
filterHeight,
|
||||
currentPage,
|
||||
pagination?.current_page,
|
||||
videoId,
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import { useUserConfigStore } from '../stores/UserConfigStore';
|
|||
import { ApiResponseType } from '../functions/APIClient';
|
||||
import NotFound from './NotFound';
|
||||
import updatePlaylistSortOrder from '../api/actions/updatePlaylistSortOrder';
|
||||
import { useFilterBarTempConf } from '../stores/FilterbarTempConf';
|
||||
|
||||
export type VideoResponseType = {
|
||||
data?: VideoType[];
|
||||
|
|
@ -46,6 +47,7 @@ const Playlist = () => {
|
|||
const videoId = searchParams.get('videoId');
|
||||
|
||||
const { userConfig } = useUserConfigStore();
|
||||
const { filterHeight } = useFilterBarTempConf();
|
||||
const { currentPage, setCurrentPage } = useOutletContext() as OutletContextType;
|
||||
const isAdmin = useIsAdmin();
|
||||
|
||||
|
|
@ -90,6 +92,7 @@ const Playlist = () => {
|
|||
? WatchTypesEnum.Watched
|
||||
: WatchTypesEnum.Unwatched) as WatchTypes),
|
||||
type: userConfig.vid_type_filter as VideoTypes,
|
||||
height: filterHeight,
|
||||
});
|
||||
|
||||
setPlaylistResponse(playlist);
|
||||
|
|
@ -109,6 +112,7 @@ const Playlist = () => {
|
|||
playlistId,
|
||||
userConfig.hide_watched,
|
||||
userConfig.vid_type_filter,
|
||||
filterHeight,
|
||||
refresh,
|
||||
currentPage,
|
||||
pagination?.current_page,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
// temporary values for filtering, not stored in backend
|
||||
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface FilterbarTempConfInterface {
|
||||
filterHeight: string;
|
||||
setFilterHeight: (filterHeight: string) => void;
|
||||
}
|
||||
|
||||
export const useFilterBarTempConf = create<FilterbarTempConfInterface>(set => ({
|
||||
filterHeight: '',
|
||||
setFilterHeight: (filterHeight: string) => set({ filterHeight }),
|
||||
}));
|
||||
Loading…
Reference in New Issue