fix: system keyboard shortcuts conflicts with labelling shortcuts in labelling page
This commit is contained in:
parent
07571eb7b4
commit
e88d77d135
@ -21,7 +21,7 @@ const videoSchema = BiliVideoSchema.omit({ publishedAt: true })
|
||||
|
||||
export const getUnlabelledVideos = new Elysia({ prefix: "/videos" }).use(requireAuth).get(
|
||||
"/unlabelled",
|
||||
async () => {
|
||||
async ({ user }) => {
|
||||
return db.execute<z.infer<typeof videoSchema>>(sql`
|
||||
SELECT bm.*, ls.views, bu.username, bu.uid
|
||||
FROM (
|
||||
@ -44,7 +44,8 @@ export const getUnlabelledVideos = new Elysia({ prefix: "/videos" }).use(require
|
||||
SELECT aid
|
||||
FROM internal.video_type_label
|
||||
TABLESAMPLE SYSTEM (8)
|
||||
WHERE video_type_label."user" = 'bvZMWcgYL2dr6vsJ'
|
||||
WHERE video_type_label."user" != ${user!.unqId}
|
||||
AND video_type_label."user" = 'bvZMWcgYL2dr6vsJ'
|
||||
ORDER BY RANDOM()
|
||||
LIMIT 19
|
||||
)
|
||||
|
||||
@ -4,13 +4,12 @@ import { Check, ChevronLeft, ChevronRight, X } from "lucide-react";
|
||||
interface ControlBarProps {
|
||||
currentIndex: number;
|
||||
videosLength: number;
|
||||
hasMore: boolean;
|
||||
onPrevious: () => void;
|
||||
onNext: () => void;
|
||||
onLabel: (label: boolean) => void;
|
||||
}
|
||||
|
||||
export function ControlBar({ currentIndex, videosLength, hasMore, onPrevious, onNext, onLabel }: ControlBarProps) {
|
||||
export function ControlBar({ currentIndex, videosLength, onPrevious, onNext, onLabel }: ControlBarProps) {
|
||||
return (
|
||||
<div className="fixed bottom-0 left-0 right-0 bg-background border-t p-4 shadow-lg">
|
||||
<div className="max-w-4xl mx-auto flex items-center justify-between gap-4">
|
||||
@ -40,7 +39,7 @@ export function ControlBar({ currentIndex, videosLength, hasMore, onPrevious, on
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={onNext}
|
||||
disabled={currentIndex === videosLength - 1 && !hasMore}
|
||||
disabled={currentIndex === videosLength - 1}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
下一个
|
||||
|
||||
@ -18,24 +18,8 @@ export function VideoInfo({ video }: VideoInfoProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mb-24">
|
||||
<div className="mb-24 mt-2">
|
||||
<div className="flex flex-col sm:flex-row sm:gap-4">
|
||||
{video.cover_url && (
|
||||
<a
|
||||
href={`https://www.bilibili.com/video/${video.bvid}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="min-w-full sm:min-w-60 md:min-w-80 max-w-full
|
||||
sm:max-w-60 md:max-w-80 aspect-video"
|
||||
>
|
||||
<img
|
||||
src={video.cover_url}
|
||||
referrerPolicy="no-referrer"
|
||||
className="w-full h-full object-cover rounded-lg"
|
||||
alt="Video cover"
|
||||
/>
|
||||
</a>
|
||||
)}
|
||||
<div>
|
||||
<div className="max-sm:mt-6 flex items-center gap-2">
|
||||
<h1 className="text-2xl font-medium">
|
||||
|
||||
@ -24,10 +24,11 @@ export default function Home() {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<any>(null);
|
||||
const [hasMore, setHasMore] = useState(true);
|
||||
const [instructionsOpen, setInstructionsOpen] = useState(false);
|
||||
const [localLabel, setLocalLabel] = useState<(boolean|undefined)[]>([]);
|
||||
|
||||
const fetchVideos = useCallback(async () => {
|
||||
if (videos.length >= 30) return;
|
||||
try {
|
||||
setLoading(true);
|
||||
const { data, error } = await app.videos.unlabelled.get({
|
||||
@ -43,9 +44,6 @@ export default function Home() {
|
||||
|
||||
if (data && data.length > 0) {
|
||||
setVideos((prev) => [...prev, ...data]);
|
||||
setHasMore(data.length === 20);
|
||||
} else {
|
||||
setHasMore(false);
|
||||
}
|
||||
} catch (err) {
|
||||
setError({ status: 500, value: { message: "网络错误" } });
|
||||
@ -55,12 +53,12 @@ export default function Home() {
|
||||
}, []);
|
||||
|
||||
const loadMoreIfNeeded = useCallback(() => {
|
||||
if (hasMore && videos.length - currentIndex <= 6) {
|
||||
if (videos.length - currentIndex <= 6) {
|
||||
fetchVideos();
|
||||
}
|
||||
}, [hasMore, videos.length, currentIndex, fetchVideos]);
|
||||
}, [videos.length, currentIndex, fetchVideos]);
|
||||
|
||||
const labelVideo = async (videoId: string, label: boolean) => {
|
||||
const labelVideo = async (currentIndex: number, videoId: string, label: boolean) => {
|
||||
const maxRetries = 5;
|
||||
let retries = 0;
|
||||
|
||||
@ -95,14 +93,25 @@ export default function Home() {
|
||||
|
||||
if (!success) {
|
||||
toast.error(`标记失败,请稍后重试`);
|
||||
setLocalLabel((prev) => {
|
||||
const newLabel = [...prev];
|
||||
newLabel[currentIndex] = undefined;
|
||||
return newLabel;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleLabel = async (label: boolean) => {
|
||||
const currentVideo = videos[currentIndex];
|
||||
if (!currentVideo) return;
|
||||
setLocalLabel((prev) => {
|
||||
const newLabel = [...prev];
|
||||
newLabel[currentIndex] = label;
|
||||
console.log(newLabel);
|
||||
return newLabel;
|
||||
});
|
||||
|
||||
labelVideo(currentVideo.bvid!, label);
|
||||
labelVideo(currentIndex, currentVideo.bvid!, label);
|
||||
if (currentIndex < videos.length - 1) {
|
||||
setCurrentIndex((prev) => prev + 1);
|
||||
loadMoreIfNeeded();
|
||||
@ -135,6 +144,12 @@ export default function Home() {
|
||||
return;
|
||||
}
|
||||
|
||||
const hasModifier = e.ctrlKey || e.altKey || e.shiftKey || e.metaKey;
|
||||
|
||||
if (hasModifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
const key = e.key.toUpperCase();
|
||||
|
||||
if (leftKeys.includes(key)) {
|
||||
@ -173,6 +188,11 @@ export default function Home() {
|
||||
}
|
||||
|
||||
const currentVideo = videos[currentIndex];
|
||||
const currentLabel = (()=> {
|
||||
const l = localLabel[currentIndex];
|
||||
if (l === undefined) return "none";
|
||||
return l ? "true" : "false";
|
||||
})()
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
@ -181,11 +201,11 @@ export default function Home() {
|
||||
{currentVideo ? (
|
||||
<>
|
||||
<LabelInstructions open={instructionsOpen} onOpenChange={setInstructionsOpen} />
|
||||
<span className="font-mono">Buffer health: {currentIndex}/{videos.length}, currentLabel: {currentLabel}</span>
|
||||
<VideoInfo video={currentVideo} />
|
||||
<ControlBar
|
||||
currentIndex={currentIndex}
|
||||
videosLength={videos.length}
|
||||
hasMore={hasMore}
|
||||
onPrevious={() => navigateTo(currentIndex - 1)}
|
||||
onNext={() => navigateTo(currentIndex + 1)}
|
||||
onLabel={handleLabel}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user