feature/share-libs
tsx 89 lines 2.53 KB
Raw
1 "use client";
2
3 import { invoke } from "@tauri-apps/api/tauri";
4 import { useContext, useEffect, useState } from "react";
5 import { TAURI_PLAYER_PREPARE } from "../../lib/tauri-handler";
6 import { useRouter, useSearchParams } from "next/navigation";
7 import { useLogger } from "@/lib/logger";
8 import { IconSpinner } from "../../components/icons";
9 import { PlayerPrepareResponse } from "@/models/content";
10 import { TauriResponse } from "@/models/shared";
11 import Player from "./_components/player";
12 import { UserContext } from "../../lib/current-user-context";
13
14 enum State {
15 LOADING,
16 LOADED,
17 ERROR,
18 }
19
20 export default function Page() {
21 const log = useLogger("Play");
22 const searchParams = useSearchParams();
23 const audioFileId = searchParams.get("audioFileId");
24 const [title, setTitle] = useState("Loading song...");
25 const [state, setState] = useState(State.LOADING);
26 const user = useContext(UserContext);
27 const userId = user.user?.user.id;
28 const router = useRouter();
29
30 useEffect(() => {
31 log.debug("Play page loaded.");
32 async function fetchData() {
33 try {
34 const result: PlayerPrepareResponse = await invoke(
35 TAURI_PLAYER_PREPARE,
36 { audioFileId }
37 );
38 log.debug("PreparePlayerResponse", result);
39 switch (result.status) {
40 case TauriResponse.SUCCESS:
41 if (result.audio_file_name) setTitle(result.audio_file_name);
42
43 setState(State.LOADED);
44 break;
45 case TauriResponse.ERROR:
46 setState(State.ERROR);
47 break;
48 }
49 } catch (error) {
50 log.error(error);
51 setState(State.ERROR);
52 }
53 }
54 fetchData();
55 // eslint-disable-next-line react-hooks/exhaustive-deps
56 }, []);
57
58 // Sanity check
59 if (!userId) {
60 log.error("No user context");
61 return router.push("/login");
62 }
63
64 if (!audioFileId) {
65 log.error("Missing audio file ID or user ID");
66 return <div>Missing audio file ID</div>;
67 }
68
69 return (
70 <>
71 <div className="flex justify-between">
72 <div className="self-start">
73 <h1 className="text-3xl font-bold">{title}</h1>
74 </div>
75 </div>
76 <div className="prose prose-sm prose-invert max-w-none">
77 {state === State.LOADING && (
78 <IconSpinner className="w-10 h-10 animate-spin" />
79 )}
80 {state === State.ERROR && (
81 <div className="text-red-500">Failed to load song</div>
82 )}
83 {state === State.LOADED && (
84 <Player audioId={audioFileId} userId={userId} />
85 )}
86 </div>
87 </>
88 );
89 }