diff --git a/enjoy/src/renderer/components/audios/audio-card.tsx b/enjoy/src/renderer/components/audios/audio-card.tsx index b61012e6..2304fb87 100644 --- a/enjoy/src/renderer/components/audios/audio-card.tsx +++ b/enjoy/src/renderer/components/audios/audio-card.tsx @@ -2,7 +2,7 @@ import { Link } from "react-router-dom"; import { cn } from "@renderer/lib/utils"; export const AudioCard = (props: { - audio: AudioType; + audio: Partial; className?: string; }) => { const { audio, className } = props; diff --git a/enjoy/src/renderer/components/audios/audios-component.tsx b/enjoy/src/renderer/components/audios/audios-component.tsx index 66ca2c24..0f6974bb 100644 --- a/enjoy/src/renderer/components/audios/audios-component.tsx +++ b/enjoy/src/renderer/components/audios/audios-component.tsx @@ -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 ; + return (
@@ -135,6 +167,14 @@ export const AudiosComponent = () => {
+ {offset > -1 && ( +
+ +
+ )} + { diff --git a/enjoy/src/renderer/components/videos/videos-component.tsx b/enjoy/src/renderer/components/videos/videos-component.tsx index 4d16115b..9516e82c 100644 --- a/enjoy/src/renderer/components/videos/videos-component.tsx +++ b/enjoy/src/renderer/components/videos/videos-component.tsx @@ -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 ; + return (
@@ -135,6 +167,14 @@ export const VideosComponent = () => {
+ {offset > -1 && ( +
+ +
+ )} + { diff --git a/enjoy/src/renderer/reducers/audios-reducer.ts b/enjoy/src/renderer/reducers/audios-reducer.ts index 6062c40a..f99a7d06 100644 --- a/enjoy/src/renderer/reducers/audios-reducer.ts +++ b/enjoy/src/renderer/reducers/audios-reducer.ts @@ -1,12 +1,19 @@ export const audiosReducer = ( audios: AudioType[], action: { - type: "create" | "update" | "destroy" | "set"; + type: "append" | "create" | "update" | "destroy" | "set"; record?: Partial; records?: Partial[]; } ) => { 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]; } diff --git a/enjoy/src/renderer/reducers/videos-reducer.ts b/enjoy/src/renderer/reducers/videos-reducer.ts index d4f61884..456099ff 100644 --- a/enjoy/src/renderer/reducers/videos-reducer.ts +++ b/enjoy/src/renderer/reducers/videos-reducer.ts @@ -1,12 +1,19 @@ export const videosReducer = ( videos: VideoType[], action: { - type: "create" | "update" | "destroy" | "set"; + type: "append" | "create" | "update" | "destroy" | "set"; record?: Partial; records?: Partial[]; } ) => { 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]; }