add pagy for audios/videos

This commit is contained in:
an-lee
2024-01-13 17:20:18 +08:00
parent 09b7ca40f4
commit 29e12106a2
5 changed files with 118 additions and 24 deletions

View File

@@ -2,7 +2,7 @@ import { Link } from "react-router-dom";
import { cn } from "@renderer/lib/utils";
export const AudioCard = (props: {
audio: AudioType;
audio: Partial<AudioType>;
className?: string;
}) => {
const { audio, className } = props;

View File

@@ -4,9 +4,11 @@ import {
AddMediaButton,
AudiosTable,
AudioEditForm,
LoaderSpin,
} from "@renderer/components";
import { t } from "i18next";
import {
Button,
Tabs,
TabsContent,
TabsList,
@@ -23,6 +25,7 @@ import {
DialogContent,
DialogHeader,
DialogTitle,
useToast,
} from "@renderer/components/ui";
import {
DbProviderContext,
@@ -43,28 +46,55 @@ export const AudiosComponent = () => {
const { addDblistener, removeDbListener } = useContext(DbProviderContext);
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const [offset, setOffest] = useState(0);
const [loading, setLoading] = useState(false);
const { toast } = useToast();
const navigate = useNavigate();
useEffect(() => {
fetchResources();
}, []);
useEffect(() => {
addDblistener(onAudiosUpdate);
fetchResources();
fetchAudios();
return () => {
removeDbListener(onAudiosUpdate);
};
}, []);
const fetchResources = async () => {
const audios = await EnjoyApp.audios.findAll({
limit: 10,
});
if (!audios) return;
const fetchAudios = async () => {
if (loading) return;
if (offset === -1) return;
dispatchAudios({ type: "set", records: audios });
setLoading(true);
const limit = 10;
EnjoyApp.audios
.findAll({
offset,
limit,
})
.then((_audios) => {
if (_audios.length === 0) {
setOffest(-1);
return;
}
if (_audios.length < limit) {
setOffest(-1);
} else {
setOffest(offset + _audios.length);
}
dispatchAudios({ type: "append", records: _audios });
})
.catch((err) => {
toast({
description: err.message,
variant: "destructive",
});
})
.finally(() => {
setLoading(false);
});
};
const onAudiosUpdate = (event: CustomEvent) => {
@@ -79,7 +109,7 @@ export const AudiosComponent = () => {
dispatchAudios({ type: "destroy", record });
}
} else if (model === "Video" && action === "create") {
navigate(`/videos/${record.id}`);
navigate(`/videos/${record.id}`);
} else if (model === "Transcription" && action === "update") {
dispatchAudios({
type: "update",
@@ -93,6 +123,8 @@ export const AudiosComponent = () => {
};
if (audios.length === 0) {
if (loading) return <LoaderSpin />;
return (
<div className="flex items-center justify-center h-48 border border-dashed rounded-lg">
<AddMediaButton />
@@ -135,6 +167,14 @@ export const AudiosComponent = () => {
</Tabs>
</div>
{offset > -1 && (
<div className="flex items-center justify-center my-4">
<Button variant="link" onClick={fetchAudios}>
{t("loadMore")}
</Button>
</div>
)}
<Dialog
open={!!editing}
onOpenChange={(value) => {

View File

@@ -4,6 +4,7 @@ import {
VideosTable,
VideoEditForm,
AddMediaButton,
LoaderSpin,
} from "@renderer/components";
import { t } from "i18next";
import {
@@ -19,10 +20,12 @@ import {
AlertDialogDescription,
AlertDialogCancel,
AlertDialogAction,
Button,
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
useToast,
} from "@renderer/components/ui";
import {
DbProviderContext,
@@ -43,11 +46,11 @@ export const VideosComponent = () => {
const { addDblistener, removeDbListener } = useContext(DbProviderContext);
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const navigate = useNavigate();
const [offset, setOffest] = useState(0);
const [loading, setLoading] = useState(false);
const { toast } = useToast();
useEffect(() => {
fetchVideos();
}, []);
const navigate = useNavigate();
useEffect(() => {
addDblistener(onVideosUpdate);
@@ -59,12 +62,39 @@ export const VideosComponent = () => {
}, []);
const fetchVideos = async () => {
const videos = await EnjoyApp.videos.findAll({
limit: 10,
});
if (!videos) return;
if (loading) return;
if (offset === -1) return;
dispatchVideos({ type: "set", records: videos });
setLoading(true);
const limit = 10;
EnjoyApp.videos
.findAll({
offset,
limit,
})
.then((_videos) => {
if (_videos.length === 0) {
setOffest(-1);
return;
}
if (_videos.length < limit) {
setOffest(-1);
} else {
setOffest(offset + _videos.length);
}
dispatchVideos({ type: "append", records: _videos });
})
.catch((err) => {
toast({
description: err.message,
variant: "destructive",
});
})
.finally(() => {
setLoading(false);
});
};
const onVideosUpdate = (event: CustomEvent) => {
@@ -93,6 +123,8 @@ export const VideosComponent = () => {
};
if (videos.length === 0) {
if (loading) return <LoaderSpin />;
return (
<div className="flex items-center justify-center h-48 border border-dashed rounded-lg">
<AddMediaButton />
@@ -135,6 +167,14 @@ export const VideosComponent = () => {
</Tabs>
</div>
{offset > -1 && (
<div className="flex items-center justify-center my-4">
<Button variant="link" onClick={fetchVideos}>
{t("loadMore")}
</Button>
</div>
)}
<Dialog
open={!!editing}
onOpenChange={(value) => {

View File

@@ -1,12 +1,19 @@
export const audiosReducer = (
audios: AudioType[],
action: {
type: "create" | "update" | "destroy" | "set";
type: "append" | "create" | "update" | "destroy" | "set";
record?: Partial<AudioType>;
records?: Partial<AudioType>[];
}
) => {
switch (action.type) {
case "append": {
if (action.record) {
return [...audios, action.record];
} else if (action.records) {
return [...audios, ...action.records];
}
}
case "create": {
return [action.record, ...audios];
}

View File

@@ -1,12 +1,19 @@
export const videosReducer = (
videos: VideoType[],
action: {
type: "create" | "update" | "destroy" | "set";
type: "append" | "create" | "update" | "destroy" | "set";
record?: Partial<VideoType>;
records?: Partial<VideoType>[];
}
) => {
switch (action.type) {
case "append": {
if (action.record) {
return [...videos, action.record];
} else if (action.records) {
return [...videos, ...action.records];
}
}
case "create": {
return [action.record, ...videos];
}