Skip to content

Commit ac8a4ff

Browse files
committed
make queue work, can now deselect videos from selection show video
1 parent 6badae1 commit ac8a4ff

File tree

1 file changed

+103
-44
lines changed

1 file changed

+103
-44
lines changed

packages/react/src/components/layout/SelectionFooter.tsx

+103-44
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { Suspense, useState } from "react";
2-
import { useAtom, useAtomValue } from "jotai";
2+
import { useAtom, useAtomValue, useSetAtom } from "jotai";
33
import { Button } from "@/shadcn/ui/button";
44
import { Dialog, DialogContent } from "@/shadcn/ui/dialog";
55
import {
@@ -29,6 +29,8 @@ import { userAtom } from "@/store/auth";
2929
import { Link } from "react-router-dom";
3030
import { LazyNewPlaylistDialog } from "../video/LazyNewPlaylistDialog";
3131
import { useToast } from "@/shadcn/ui/use-toast";
32+
import { queueAtom } from "@/store/queue";
33+
3234
const SelectedVideosModal = ({
3335
isSmall,
3436
open,
@@ -38,7 +40,7 @@ const SelectedVideosModal = ({
3840
open: boolean;
3941
onOpenChange: (open: boolean) => void;
4042
}) => {
41-
const { selectedVideos } = useVideoSelection();
43+
const { selectedVideos, setSelectedVideos } = useVideoSelection();
4244

4345
const getThumbnailSrc = (video: PlaceholderVideo) => {
4446
const size = isSmall ? "sm" : "md";
@@ -47,16 +49,40 @@ const SelectedVideosModal = ({
4749

4850
return (
4951
<Dialog open={open} onOpenChange={onOpenChange}>
50-
<DialogContent>
51-
{selectedVideos.map((video) => (
52-
<div key={video.id} className="flex items-center space-x-4 p-2">
53-
<VideoThumbnail
54-
src={getThumbnailSrc(video)}
55-
alt={video.title}
56-
className="h-auto w-24 rounded"
57-
/>
58-
<div>
59-
<h3 className="font-semibold">{video.title}</h3>
52+
<DialogContent className="flex max-h-[50vh] min-w-min max-w-[min(500px,calc(100vw-40px))] flex-col gap-0 overflow-y-auto overflow-x-hidden px-0 py-6">
53+
{selectedVideos.map((video, idx) => (
54+
<div
55+
key={video.id}
56+
className={
57+
"flex items-center space-x-2 px-2 py-1 " +
58+
(idx % 2 === 0 ? "bg-base-3" : "")
59+
}
60+
>
61+
<Button
62+
variant="ghost"
63+
size="icon-lg"
64+
className="size-10 shrink-0"
65+
onClick={() =>
66+
setSelectedVideos((prev) =>
67+
prev.filter((v) => v.id !== video.id),
68+
)
69+
}
70+
>
71+
<div className="i-heroicons:x-mark" />
72+
<span className="sr-only">Remove</span>
73+
</Button>
74+
<Link
75+
to={`/watch/${video.id}`}
76+
className="block w-24 shrink-0 overflow-hidden rounded"
77+
>
78+
<VideoThumbnail
79+
src={getThumbnailSrc(video)}
80+
alt={video.title}
81+
className=""
82+
/>
83+
</Link>
84+
<div className="min-w-80">
85+
<h3 className="line-clamp-2 font-semibold">{video.title}</h3>
6086
<p className="text-sm text-gray-500">{}</p>
6187
{/* what was i doing here again why is this block empty ^ */}
6288
</div>
@@ -141,37 +167,7 @@ const SelectionFooter = () => {
141167
Open in Multiview
142168
</Button>
143169

144-
<DropdownMenu>
145-
<DropdownMenuTrigger asChild>
146-
<Button
147-
variant="base-outline"
148-
size="sm"
149-
disabled={!selectedVideos.length}
150-
className="flex items-center"
151-
>
152-
<span className="i-heroicons:folder-open mr-2" />
153-
{t("component.mainNav.playlist")}
154-
<div className="i-lucide:chevron-up ml-2 size-4"></div>
155-
</Button>
156-
</DropdownMenuTrigger>
157-
<DropdownMenuContent>
158-
<DropdownMenuItem onClick={() => setPage(1)}>
159-
<div className="i-heroicons:queue-list" />
160-
Add to Queue
161-
</DropdownMenuItem>
162-
<DropdownMenuGroup>
163-
<DropdownMenuSub>
164-
<DropdownMenuSubTrigger className="bg-base-1">
165-
<div className="i-solar:playlist-broken" />
166-
Add to Playlist
167-
</DropdownMenuSubTrigger>
168-
<DropdownMenuPortal>
169-
<PlaylistMenuItems />
170-
</DropdownMenuPortal>
171-
</DropdownMenuSub>
172-
</DropdownMenuGroup>
173-
</DropdownMenuContent>
174-
</DropdownMenu>
170+
<SelectionModifyPlaylistMenu disabled={!selectedVideos.length} />
175171

176172
<DropdownMenu>
177173
<DropdownMenuTrigger asChild>
@@ -263,14 +259,77 @@ const SelectionFooter = () => {
263259
);
264260
};
265261

266-
function PlaylistMenuItems() {
262+
function SelectionModifyPlaylistMenu({ disabled }: { disabled: boolean }) {
263+
const { t } = useTranslation();
264+
const { selectedVideos } = useVideoSelection();
265+
266+
const setQueue = useSetAtom(queueAtom);
267+
const { toast } = useToast();
268+
269+
return (
270+
<DropdownMenu>
271+
<DropdownMenuTrigger asChild>
272+
<Button
273+
variant="base-outline"
274+
size="sm"
275+
disabled={disabled}
276+
className="flex items-center"
277+
>
278+
<span className="i-heroicons:folder-open mr-2" />
279+
{t("component.mainNav.playlist")}
280+
<div className="i-lucide:chevron-up ml-2 size-4"></div>
281+
</Button>
282+
</DropdownMenuTrigger>
283+
<DropdownMenuContent>
284+
<DropdownMenuItem
285+
onClick={() => {
286+
setQueue((prev) => {
287+
return [
288+
...selectedVideos.filter(
289+
(v) => v.type === "stream" || v.type === "clip",
290+
),
291+
...prev.filter(
292+
(v) => !selectedVideos.find(({ id }) => id === v.id),
293+
),
294+
];
295+
});
296+
297+
toast({
298+
variant: "primary",
299+
title: "Added to queue",
300+
duration: 2000,
301+
});
302+
}}
303+
>
304+
<div className="i-heroicons:queue-list" />
305+
Add to Queue
306+
</DropdownMenuItem>
307+
<DropdownMenuGroup>
308+
<DropdownMenuSub>
309+
<DropdownMenuSubTrigger className="bg-base-1">
310+
<div className="i-solar:playlist-broken" />
311+
Add to Playlist
312+
</DropdownMenuSubTrigger>
313+
<DropdownMenuPortal>
314+
<SelectionModifyPlaylistSubmenu />
315+
</DropdownMenuPortal>
316+
</DropdownMenuSub>
317+
</DropdownMenuGroup>
318+
</DropdownMenuContent>
319+
</DropdownMenu>
320+
);
321+
}
322+
323+
function SelectionModifyPlaylistSubmenu() {
267324
const { t } = useTranslation();
268325
const { toast } = useToast();
269326

270327
const { mutate } = usePlaylistVideoMassAddMutation({
271328
onSuccess: () => {
272329
toast({
273330
title: "Added to playlist",
331+
duration: 2000,
332+
variant: "primary",
274333
});
275334
},
276335
});

0 commit comments

Comments
 (0)