refactor: 调整目录结构

This commit is contained in:
sealday 2024-04-06 02:35:31 +08:00
parent 28d86317c6
commit 8e2682e7c2
11 changed files with 118 additions and 93 deletions

View File

@ -1,7 +1,7 @@
/* eslint-disable no-console -- debug */ /* eslint-disable no-console -- debug */
"use client"; "use client";
import { useRef, useState, useEffect } from "react"; import { useRef, useState, useEffect } from "react";
import { query } from "@/app/lib/actions/lyrics"; import { query } from "@/lib/actions/lyrics";
const useLyricsRunner = (runner: (lyric: string) => void, interval: number) => { const useLyricsRunner = (runner: (lyric: string) => void, interval: number) => {
const [lyrics, setLyrics] = useState<string[]>([]); const [lyrics, setLyrics] = useState<string[]>([]);

View File

@ -3,6 +3,7 @@ import { Inter } from "next/font/google";
import "./globals.css"; import "./globals.css";
import SignoutButton from "./components/signout-button"; import SignoutButton from "./components/signout-button";
import Logo from "./components/logo"; import Logo from "./components/logo";
import BackButton from "./components/back-button";
const inter = Inter({ subsets: ["latin"] }); const inter = Inter({ subsets: ["latin"] });
@ -42,7 +43,10 @@ export default function RootLayout({
</a> </a>
</nav> </nav>
<SignoutButton className="inline-flex items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-base mt-4 md:mt-0" /> <div className="join">
<BackButton className="btn join-item" />
<SignoutButton className="btn join-item" />
</div>
</div> </div>
</header> </header>
<main>{children}</main> <main>{children}</main>
@ -56,9 +60,7 @@ export default function RootLayout({
<Logo /> <Logo />
<span className="ml-3 text-xl"></span> <span className="ml-3 text-xl"></span>
</a> </a>
<p className="mt-2 text-sm text-gray-500"> <p className="mt-2 text-sm text-gray-500"></p>
</p>
</div> </div>
<div className="flex-grow flex flex-wrap md:pl-20 -mb-10 md:mt-0 mt-10 md:text-left text-center"> <div className="flex-grow flex flex-wrap md:pl-20 -mb-10 md:mt-0 mt-10 md:text-left text-center">
<div className="lg:w-1/4 md:w-1/2 w-full px-4"> <div className="lg:w-1/4 md:w-1/2 w-full px-4">

View File

@ -1,96 +1,100 @@
'use client'; "use client";
import { useState, useEffect, useCallback } from "react"; import { useState, useEffect, useCallback } from "react";
import useWebSocket, { ReadyState } from 'react-use-websocket'; import useWebSocket, { ReadyState } from "react-use-websocket";
const MOMO_IM_URL = 'wss://live-ws.immomo.com/ws/im' const MOMO_IM_URL = "wss://live-ws.immomo.com/ws/im";
export const Danmu: React.FC = () => { export const Danmu: React.FC = () => {
//Public API that will echo messages sent to it back to the client //Public API that will echo messages sent to it back to the client
const [socketUrl, setSocketUrl] = useState(MOMO_IM_URL); const [socketUrl, setSocketUrl] = useState(MOMO_IM_URL);
const [messageHistory, setMessageHistory] = useState<MessageEvent<any>[]>([]); const [messageHistory, setMessageHistory] = useState<MessageEvent<any>[]>([]);
// { "msg_id": 1, "client_time": 1712305590234, "type": "Sauth", "data": { "momoid": "404821828", "roomid": "14515460054", "role": 6, "isVisitor": false, "token": "97e721d0bd3bf2e63a9797f9daf50919", "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" } } // { "msg_id": 1, "client_time": 1712305590234, "type": "Sauth", "data": { "momoid": "404821828", "roomid": "14515460054", "role": 6, "isVisitor": false, "token": "97e721d0bd3bf2e63a9797f9daf50919", "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" } }
const { sendMessage, lastMessage, readyState } = useWebSocket(socketUrl, { const { sendMessage, lastMessage, readyState } = useWebSocket(socketUrl, {
heartbeat: heartbeat: {
{ message: () => {
message: () => { const pingMessage = {
const pingMessage = { "msg_id": 2, "client_time": Date.now(), "type": "Ping", "data": {} } msg_id: 2,
return JSON.stringify(pingMessage); client_time: Date.now(),
}, type: "Ping",
interval: 5000, data: {},
} };
}); return JSON.stringify(pingMessage);
},
interval: 5000,
},
});
const momoId = "404821828" const momoId = "404821828";
const roomId = "14515460054" const roomId = "14515460054";
const momoToken = "97e721d0bd3bf2e63a9797f9daf50919" const momoToken = "97e721d0bd3bf2e63a9797f9daf50919";
const clientTime = Date.now() const clientTime = Date.now();
const data = { const data = {
"msg_id": 1, msg_id: 1,
"client_time": clientTime, client_time: clientTime,
"type": "Sauth", type: "Sauth",
"data": { data: {
"momoid": momoId, "roomid": roomId, momoid: momoId,
"role": 6, "isVisitor": false, roomid: roomId,
"token": momoToken role: 6,
}, isVisitor: false,
token: momoToken,
},
};
useEffect(() => {
if (ReadyState.OPEN === readyState) {
sendMessage(JSON.stringify(data));
} }
}, [readyState]);
useEffect(() => { useEffect(() => {
if (ReadyState.OPEN === readyState) { if (lastMessage !== null) {
sendMessage(JSON.stringify(data)); if (lastMessage.data) {
const message = JSON.parse(lastMessage.data);
if (message.type === "pong") {
return;
} }
}, [readyState]) setMessageHistory((prev) => prev.concat(message));
}
}
}, [lastMessage]);
const connectionStatus = {
[ReadyState.CONNECTING]: "Connecting",
[ReadyState.OPEN]: "Open",
[ReadyState.CLOSING]: "Closing",
[ReadyState.CLOSED]: "Closed",
[ReadyState.UNINSTANTIATED]: "Uninstantiated",
}[readyState];
return (
useEffect(() => { <div>
if (lastMessage !== null) { {messageHistory.map((message, idx) => (
if (lastMessage.data) { <MessageDispatcher key={idx} message={message} />
const message = JSON.parse(lastMessage.data); ))}
if (message.type === 'pong') { <div className="chat chat-end">
return; <div className="chat-bubble">You underestimate my power!</div>
} </div>
setMessageHistory((prev) => prev.concat(message)); </div>
} );
}
}, [lastMessage]);
const connectionStatus = {
[ReadyState.CONNECTING]: 'Connecting',
[ReadyState.OPEN]: 'Open',
[ReadyState.CLOSING]: 'Closing',
[ReadyState.CLOSED]: 'Closed',
[ReadyState.UNINSTANTIATED]: 'Uninstantiated',
}[readyState];
return (
<div>
{messageHistory.map((message, idx) => (
<MessageDispatcher key={idx} message={message} />
))}
<div className="chat chat-end">
<div className="chat-bubble">You underestimate my power!</div>
</div>
</div>
);
}; };
// TODO const MessageDispatcher: React.FC<{ message: any }> = ({ message }) => {
const MessageDispatcher: React.FC = ({ message }) => { const messageType = message?.groups?.[0]?.units?.[0]?.type;
let nick = "wait";
const messageType = message?.groups?.[0]?.units?.[0]?.type let content = "wait";
let nick = 'wait';
let content = 'wait';
if (messageType === 'Message') {
nick = message?.groups?.[0]?.nick;
content = message?.groups?.[0]?.units?.[0]?.['Msg.Message.data']?.text
}
return (<div className="chat chat-start">
<div className="chat-bubble">{nick}: {content}</div>
</div>)
if (messageType === "Message") {
nick = message?.groups?.[0]?.nick;
content = message?.groups?.[0]?.units?.[0]?.["Msg.Message.data"]?.text;
}
return (
<div className="chat chat-start">
<div className="chat-bubble">
{nick}: {content}
</div>
</div>
);
}; };

View File

@ -1,7 +1,5 @@
import { Danmu } from "./danmu"; import { Danmu } from "./danmu";
export default function Page() { export default function Page() {
return <main>hello world return <Danmu />;
<Danmu />
</main>
} }

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import { signin } from "@/app/lib/actions/auth"; import { signin } from "@/lib/actions/auth";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import { useFormState, useFormStatus } from "react-dom"; import { useFormState, useFormStatus } from "react-dom";

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import { signup } from "@/app/lib/actions/auth"; import { signup } from "@/lib/actions/auth";
import Link from "next/link"; import Link from "next/link";
import { useFormState, useFormStatus } from "react-dom"; import { useFormState, useFormStatus } from "react-dom";
import signupSvg from "@/app/signup/signup.svg"; import signupSvg from "@/app/signup/signup.svg";

View File

@ -0,0 +1,21 @@
"use client";
import { useRouter } from "next/navigation";
export default function BackButton({
className,
}: {
className?: string | undefined;
}) {
const router = useRouter();
return (
<button
className={className}
onClick={() => {
router.back();
}}
>
退
</button>
);
}

View File

@ -1,5 +1,5 @@
"use client"; "use client";
import { signout } from "@/app/lib/actions/auth"; import { signout } from "@/lib/actions/auth";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
export default function SignoutButton({ export default function SignoutButton({