diff --git a/app/globals.css b/app/globals.css index cad0201..bd6213e 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,33 +1,3 @@ @tailwind base; @tailwind components; -@tailwind utilities; - -/* :root { - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; -} - -@media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; - } -} - -body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); -} - -@layer utilities { - .text-balance { - text-wrap: balance; - } -} */ \ No newline at end of file +@tailwind utilities; \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index 3314e47..0bcecca 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -15,7 +15,7 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - + {children} ); diff --git a/app/music/danmu.tsx b/app/music/danmu.tsx new file mode 100644 index 0000000..860e2f2 --- /dev/null +++ b/app/music/danmu.tsx @@ -0,0 +1,96 @@ +'use client'; +import { useState, useEffect, useCallback } from "react"; +import useWebSocket, { ReadyState } from 'react-use-websocket'; + +const MOMO_IM_URL = 'wss://live-ws.immomo.com/ws/im' + +export const Danmu: React.FC = () => { + //Public API that will echo messages sent to it back to the client + const [socketUrl, setSocketUrl] = useState(MOMO_IM_URL); + const [messageHistory, setMessageHistory] = useState[]>([]); + + // { "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, { + heartbeat: + { + message: () => { + const pingMessage = { "msg_id": 2, "client_time": Date.now(), "type": "Ping", "data": {} } + return JSON.stringify(pingMessage); + }, + interval: 5000, + } + }); + + const momoId = "404821828" + const roomId = "14515460054" + const momoToken = "97e721d0bd3bf2e63a9797f9daf50919" + + const clientTime = Date.now() + const data = { + "msg_id": 1, + "client_time": clientTime, + "type": "Sauth", + "data": { + "momoid": momoId, "roomid": roomId, + "role": 6, "isVisitor": false, + "token": momoToken + }, + } + + useEffect(() => { + if (ReadyState.OPEN === readyState) { + sendMessage(JSON.stringify(data)); + } + }, [readyState]) + + + + useEffect(() => { + if (lastMessage !== null) { + if (lastMessage.data) { + const message = JSON.parse(lastMessage.data); + if (message.type === 'pong') { + return; + } + 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 ( +
+ {messageHistory.map((message, idx) => ( + + ))} +
+
You underestimate my power!
+
+
+ ); +}; + +// TODO +const MessageDispatcher: React.FC = ({ message }) => { + + const messageType = message?.groups?.[0]?.units?.[0]?.type + 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 (
+
{nick}: {content}
+
) + +}; \ No newline at end of file diff --git a/app/music/page.tsx b/app/music/page.tsx index 57e519a..e5eafd3 100644 --- a/app/music/page.tsx +++ b/app/music/page.tsx @@ -1,3 +1,7 @@ +import { Danmu } from "./danmu"; + export default function Page() { - return
hello world
+ return
hello world + +
} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index dcc2b40..2c359a2 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -3,115 +3,122 @@ import SignoutButton from "@/app/components/signout-button"; import Link from "next/link"; export default function Home() { - return ( -
- - 弹幕测试 -
-

- Get started by editing  - app/page.tsx -

-
- - By{" "} - Vercel Logo - -
-
- -
- Next.js Logo -
- -
- -

- Docs{" "} - - -> - -

-

- Find in-depth information about Next.js features and API. -

-
- - -

- Learn{" "} - - -> - -

-

- Learn about Next.js in an interactive course with quizzes! -

-
- - -

- Templates{" "} - - -> - -

-

- Explore starter templates for Next.js. -

-
- - -

- Deploy{" "} - - -> - -

-

- Instantly deploy your Next.js site to a shareable URL with Vercel. -

-
-
-
- ); + return
+ + 弹幕测试 +
} + +// export default function Home() { +// return ( +//
+// +// 弹幕测试 +//
+//

+// Get started by editing  +// app/page.tsx +//

+//
+// +// By{" "} +// Vercel Logo +// +//
+//
+ +//
+// Next.js Logo +//
+ +//
+// +//

+// Docs{" "} +// +// -> +// +//

+//

+// Find in-depth information about Next.js features and API. +//

+//
+ +// +//

+// Learn{" "} +// +// -> +// +//

+//

+// Learn about Next.js in an interactive course with quizzes! +//

+//
+ +// +//

+// Templates{" "} +// +// -> +// +//

+//

+// Explore starter templates for Next.js. +//

+//
+ +// +//

+// Deploy{" "} +// +// -> +// +//

+//

+// Instantly deploy your Next.js site to a shareable URL with Vercel. +//

+//
+//
+//
+// ); +// } diff --git a/package.json b/package.json index f7aca14..244b6a5 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "axios": "^1.6.8", "next": "14.1.4", "react": "^18", - "react-dom": "^18" + "react-dom": "^18", + "react-use-websocket": "^4.8.1" }, "devDependencies": { "@types/node": "^20", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a62d75d..1e9fbd3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ dependencies: react-dom: specifier: ^18 version: 18.2.0(react@18.2.0) + react-use-websocket: + specifier: ^4.8.1 + version: 4.8.1(react-dom@18.2.0)(react@18.2.0) devDependencies: '@types/node': @@ -2393,6 +2396,16 @@ packages: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} dev: true + /react-use-websocket@4.8.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-FTXuG5O+LFozmu1BRfrzl7UIQngECvGJmL7BHsK4TYXuVt+mCizVA8lT0hGSIF0Z0TedF7bOo1nRzOUdginhDw==} + peerDependencies: + react: '>= 18.0.0' + react-dom: '>= 18.0.0' + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} diff --git a/tailwind.config.ts b/tailwind.config.ts index 8d0d047..2d8e539 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -17,5 +17,15 @@ const config: Config = { }, }, plugins: [daisyui], + daisyui: { + themes: false, // false: only light + dark | true: all themes | array: specific themes like this ["light", "dark", "cupcake"] + darkTheme: "dark", // name of one of the included themes for dark mode + base: true, // applies background color and foreground color for root element by default + styled: true, // include daisyUI colors and design decisions for all components + utils: true, // adds responsive and modifier utility classes + prefix: "", // prefix for daisyUI classnames (components, modifiers and responsive class names. Not colors) + logs: true, // Shows info about daisyUI version and used config in the console when building your CSS + themeRoot: ":root", // The element that receives theme color CSS variables + }, }; export default config;