1
0

fix: system keyboard shortcuts conflicts with labelling shortcuts in labelling page

This commit is contained in:
alikia2x (寒寒) 2025-12-09 00:52:28 +08:00
parent 07571eb7b4
commit e88d77d135
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG Key ID: 56209E0CCD8420C6
4 changed files with 35 additions and 31 deletions

View File

@ -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
)

View File

@ -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"
>

View File

@ -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">

View File

@ -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}