feat: 完成歌名透传

This commit is contained in:
sealday 2024-04-07 04:25:19 +08:00
parent c26d2b578c
commit ec1620462d
5 changed files with 160 additions and 53 deletions

View File

@ -0,0 +1,13 @@
"use client";
import { useContext } from "react";
import { DanmuContext } from "./provider";
export default function CurrentInput() {
const state = useContext(DanmuContext);
return (
<div className="input">
{state.songName ?? ""} {state.songId ? "-" : ""} {state.songArtist ?? ""}
</div>
);
}

34
app/danmu/live-check.tsx Normal file
View File

@ -0,0 +1,34 @@
"use client";
import { useContext } from "react";
import { DanmuContext } from "./provider";
export default function LiveCheck({ lives }: { lives: any[] }) {
const { dispatch, ...state } = useContext(DanmuContext);
return (
<ul className="divide-y divide-gray-300">
{lives.map((live, i) => (
<li key={i}>
<label>
{live.name} - {live.room_id}
<input
onChange={(e) => {
dispatch({
type: "lives",
payload: {
liveId: live.room_id,
liveName: live.name,
},
});
}}
className="raido radio-primary"
type="radio"
name="live"
checked={live.room_id === state.liveId}
/>
</label>
</li>
))}
</ul>
);
}

View File

@ -3,6 +3,10 @@ import Controls from "./controls";
import Danmu from "./danmu";
import { listLives } from "@/lib/actions/live";
import { listSongs } from "../songs/actions";
import DanmuProvider from "./provider";
import LiveCheck from "./live-check";
import SongCheck from "./song-check";
import CurrentInput from "./current-input";
export default async function Page() {
const token = await getToken();
@ -10,61 +14,37 @@ export default async function Page() {
const songs = await listSongs();
return (
<div className="flex flex-col md:flex-row">
<section className="basis-1/3 card">
<div className="h-[50vh] md:h-[80vh] overflow-auto card bg-base-100 card-bordered m-8">
<div className="card-body">
<div className="card-title"></div>
<ul>
{lives.map((live, i) => (
<li key={i}>
<label>
{live.name} - {live.room_id}
<input
className="raido radio-primary"
type="radio"
name="live"
/>
</label>
</li>
))}
</ul>
</div>
</div>
</section>
<section className="basis-1/3 card">
<div className="h-[50vh] md:h-[80vh] overflow-auto card bg-base-100 card-bordered m-8">
<div className="card-body">
<div className="card-title"></div>
<ul>
{songs.map((song, i) => (
<li key={i}>
<label>
{song.name} - {song.artist}
<input
className="raido radio-primary"
type="radio"
name="song"
/>
</label>
</li>
))}
</ul>
</div>
</div>
</section>
<section className="basis-1/3 card">
<div className="card-body">
<div className="mockup-browser border">
<div className="mockup-browser-toolbar">
<div className="input"></div>
</div>
<div className="divide-y divide-gray-300">
<Controls />
<Danmu token={token} />
<DanmuProvider>
<section className="basis-1/3 card">
<div className="h-[50vh] md:h-[80vh] overflow-auto card bg-base-100 card-bordered m-8">
<div className="card-body">
<div className="card-title"></div>
<LiveCheck lives={lives} />
</div>
</div>
</div>
</section>
</section>
<section className="basis-1/3 card">
<div className="h-[50vh] md:h-[80vh] overflow-auto card bg-base-100 card-bordered m-8">
<div className="card-body">
<div className="card-title"></div>
<SongCheck songs={songs} />
</div>
</div>
</section>
<section className="basis-1/3 card">
<div className="card-body">
<div className="mockup-browser border">
<div className="mockup-browser-toolbar">
<CurrentInput />
</div>
<div className="divide-y divide-gray-300">
<Controls />
<Danmu token={token} />
</div>
</div>
</div>
</section>
</DanmuProvider>
</div>
);
}

45
app/danmu/provider.tsx Normal file
View File

@ -0,0 +1,45 @@
"use client";
import { createContext, useReducer } from "react";
export interface DanmuPayload {
liveName?: string;
liveId?: string;
songId?: string;
songName?: string;
songArtist?: string;
}
export interface DanmuAction {
type: string;
payload: DanmuPayload;
}
export const DanmuContext = createContext<DanmuPayload & { dispatch?: any }>(
{}
);
const reducer = (state: DanmuPayload, action: DanmuAction): DanmuPayload => {
const payload = action.payload;
switch (action.type) {
case "songs":
return {
...state,
songId: payload.songId,
songName: payload.songName,
songArtist: payload.songArtist,
};
case "lives":
return { ...state, liveId: payload.liveId, liveName: payload.liveName };
default:
throw new Error("not support action");
}
};
export default function DanmuProvider(props: any) {
const [state, dispatch] = useReducer(reducer, {});
return (
<DanmuContext.Provider value={{ ...state, dispatch }}>
{props.children}
</DanmuContext.Provider>
);
}

35
app/danmu/song-check.tsx Normal file
View File

@ -0,0 +1,35 @@
"use client";
import { useContext } from "react";
import { DanmuContext } from "./provider";
export default function SongCheck({ songs }: { songs: any[] }) {
const { dispatch, ...state } = useContext(DanmuContext);
return (
<ul className="divide-y divide-gray-300">
{songs.map((song, i) => (
<li key={i}>
<label>
{song.name} - {song.artist}
<input
onChange={(e) => {
dispatch({
type: "songs",
payload: {
songId: song.source_id,
songName: song.name,
songArtist: song.artist,
},
});
}}
className="raido radio-primary"
type="radio"
name="songs"
checked={song.source_id === state.songId}
/>
</label>
</li>
))}
</ul>
);
}