diff --git a/package.json b/package.json index cdb123f..9520656 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,5 @@ "sass": "^1.72.0", "typescript": "^5.4.2" }, - "resolutions": { - "formidable": "^3.2.5" - }, "packageManager": "pnpm@8.15.4" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e5d5e73..858aea6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,9 +4,6 @@ autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - formidable: ^3.2.5 - importers: .: @@ -180,6 +177,9 @@ reactstrap: specifier: ^9.2.2 version: 9.2.2(react-dom@18.2.0)(react@18.2.0) + redis: + specifier: ^4.6.13 + version: 4.6.13 sweetalert2: specifier: ^11.10.6 version: 11.10.6 @@ -778,6 +778,55 @@ resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} dev: false + /@redis/bloom@1.2.0(@redis/client@1.5.14): + resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.5.14 + dev: false + + /@redis/client@1.5.14: + resolution: {integrity: sha512-YGn0GqsRBFUQxklhY7v562VMOP0DcmlrHHs3IV1mFE3cbxe31IITUkqhBcIhVSI/2JqtWAJXg5mjV4aU+zD0HA==} + engines: {node: '>=14'} + dependencies: + cluster-key-slot: 1.1.2 + generic-pool: 3.9.0 + yallist: 4.0.0 + dev: false + + /@redis/graph@1.1.1(@redis/client@1.5.14): + resolution: {integrity: sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.5.14 + dev: false + + /@redis/json@1.0.6(@redis/client@1.5.14): + resolution: {integrity: sha512-rcZO3bfQbm2zPRpqo82XbW8zg4G/w4W3tI7X8Mqleq9goQjAGLL7q/1n1ZX4dXEAmORVZ4s1+uKLaUOg7LrUhw==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.5.14 + dev: false + + /@redis/search@1.1.6(@redis/client@1.5.14): + resolution: {integrity: sha512-mZXCxbTYKBQ3M2lZnEddwEAks0Kc7nauire8q20oA0oA/LoA+E/b5Y5KZn232ztPb1FkIGqo12vh3Lf+Vw5iTw==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.5.14 + dev: false + + /@redis/time-series@1.0.5(@redis/client@1.5.14): + resolution: {integrity: sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.5.14 + dev: false + /@rollup/plugin-typescript@11.1.6(rollup@4.13.0)(tslib@2.6.2)(typescript@5.4.2): resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} engines: {node: '>=14.0.0'} @@ -1417,8 +1466,8 @@ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + /binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} /bootstrap@5.3.3(@popperjs/core@2.11.8): @@ -1504,8 +1553,8 @@ '@kurkle/color': 0.3.2 dev: false - /chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + /chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} dependencies: anymatch: 3.1.3 @@ -1540,6 +1589,11 @@ engines: {node: '>=6'} dev: false + /cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + dev: false + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -2443,6 +2497,11 @@ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} dev: true + /generic-pool@3.9.0: + resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} + engines: {node: '>= 4'} + dev: false + /get-intrinsic@1.2.1: resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} dependencies: @@ -2682,8 +2741,8 @@ engines: {node: '>= 4'} dev: true - /immutable@4.3.1: - resolution: {integrity: sha512-lj9cnmB/kVS0QHsJnYKD1uo3o39nrbKxszjnqS9Fr6NB7bZzW45U6WSGBPKXDL/CvDKqDNPA4r3DoDQ8GTxo2A==} + /immutable@4.3.5: + resolution: {integrity: sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==} /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} @@ -2771,7 +2830,7 @@ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} dependencies: - binary-extensions: 2.2.0 + binary-extensions: 2.3.0 /is-boolean-object@1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} @@ -3761,6 +3820,17 @@ dependencies: picomatch: 2.3.1 + /redis@4.6.13: + resolution: {integrity: sha512-MHgkS4B+sPjCXpf+HfdetBwbRz6vCtsceTmw1pHNYJAsYxrfpOP6dz+piJWGos8wqG7qb3vj/Rrc5qOlmInUuA==} + dependencies: + '@redis/bloom': 1.2.0(@redis/client@1.5.14) + '@redis/client': 1.5.14 + '@redis/graph': 1.1.1(@redis/client@1.5.14) + '@redis/json': 1.0.6(@redis/client@1.5.14) + '@redis/search': 1.1.6(@redis/client@1.5.14) + '@redis/time-series': 1.0.5(@redis/client@1.5.14) + dev: false + /reflect.getprototypeof@1.0.5: resolution: {integrity: sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==} engines: {node: '>= 0.4'} @@ -3936,8 +4006,8 @@ engines: {node: '>=14.0.0'} hasBin: true dependencies: - chokidar: 3.5.3 - immutable: 4.3.1 + chokidar: 3.6.0 + immutable: 4.3.5 source-map-js: 1.0.2 /saxes@6.0.0: diff --git "a/qwilight-fe/src/app/\133language\135/etc/query/useGetEtc.ts" "b/qwilight-fe/src/app/\133language\135/etc/query/useGetEtc.ts" index c3ad143..fbb2ce2 100644 --- "a/qwilight-fe/src/app/\133language\135/etc/query/useGetEtc.ts" +++ "b/qwilight-fe/src/app/\133language\135/etc/query/useGetEtc.ts" @@ -2,15 +2,15 @@ import { wwwAPI } from "@/utilities/wwwAPI"; import { useQuery } from "@tanstack/react-query"; import { useIsPath } from "taehui-ts/fe-utilities"; -import { getLanguage } from "taehui-ts/language"; +import { useLanguage } from "taehui-ts/language"; export default function useGetEtc() { const isPath = useIsPath(); + const language = useLanguage(); - const language = getLanguage(); return useQuery({ enabled: isPath("/etc"), - queryKey: ["etc"], + queryKey: ["etc", language], queryFn: async () => { const { data } = await wwwAPI.get("/etc", { params: { language }, diff --git "a/qwilight-fe/src/app/\133language\135/note/query/useGetComment.ts" "b/qwilight-fe/src/app/\133language\135/note/query/useGetComment.ts" index 8cba68d..f7a86b2 100644 --- "a/qwilight-fe/src/app/\133language\135/note/query/useGetComment.ts" +++ "b/qwilight-fe/src/app/\133language\135/note/query/useGetComment.ts" @@ -2,15 +2,15 @@ import { GetCommentAPI } from "@/type/wwwAPI"; import { wwwAPI } from "@/utilities/wwwAPI"; import { useQuery } from "@tanstack/react-query"; -import { getLanguage } from "taehui-ts/language"; +import { useLanguage } from "taehui-ts/language"; export default function useGetComment( noteID: string, isCommentOpened: boolean, ) { const { siteAvatarID } = useSiteStore(); + const language = useLanguage(); - const language = getLanguage(); return useQuery({ enabled: isCommentOpened, queryKey: ["comment", noteID, siteAvatarID, language], diff --git "a/qwilight-fe/src/app/\133language\135/site/components/LogInWindow.tsx" "b/qwilight-fe/src/app/\133language\135/site/components/LogInWindow.tsx" index 1873944..68d9df6 100644 --- "a/qwilight-fe/src/app/\133language\135/site/components/LogInWindow.tsx" +++ "b/qwilight-fe/src/app/\133language\135/site/components/LogInWindow.tsx" @@ -1,4 +1,4 @@ -import SiteComponent from "@/app/[language]/site/components/SiteComponent"; +import wsAPI from "@/app/[language]/site/lib/wsAPI"; import { useSiteStore } from "@/state/Stores"; import CryptoJS from "crypto-js"; import { observer } from "mobx-react-lite"; @@ -28,7 +28,7 @@ ); } window.localStorage.setItem("autoLogIn", autoLogIn.toString()); - SiteComponent.send({ + wsAPI.send({ eventID: EventPB.Event.EventID.LOG_IN, text: JSON.stringify({ avatarID, avatarCipher }), }); diff --git "a/qwilight-fe/src/app/\133language\135/site/components/NewSiteWindow.tsx" "b/qwilight-fe/src/app/\133language\135/site/components/NewSiteWindow.tsx" index 44d04ff..a23a31d 100644 --- "a/qwilight-fe/src/app/\133language\135/site/components/NewSiteWindow.tsx" +++ "b/qwilight-fe/src/app/\133language\135/site/components/NewSiteWindow.tsx" @@ -1,4 +1,4 @@ -import SiteComponent from "@/app/[language]/site/components/SiteComponent"; +import wsAPI from "@/app/[language]/site/lib/wsAPI"; import { useSiteStore } from "@/state/Stores"; import { observer } from "mobx-react-lite"; @@ -16,7 +16,7 @@ const t = useTranslations(); const onNewSite = () => { - SiteComponent.send({ + wsAPI.send({ eventID: EventPB.Event.EventID.NEW_SITE, text: JSON.stringify({ siteName: siteName, diff --git "a/qwilight-fe/src/app/\133language\135/site/components/SiteCipherWindow.tsx" "b/qwilight-fe/src/app/\133language\135/site/components/SiteCipherWindow.tsx" index 594a521..2ada79d 100644 --- "a/qwilight-fe/src/app/\133language\135/site/components/SiteCipherWindow.tsx" +++ "b/qwilight-fe/src/app/\133language\135/site/components/SiteCipherWindow.tsx" @@ -1,4 +1,4 @@ -import SiteComponent from "@/app/[language]/site/components/SiteComponent"; +import wsAPI from "@/app/[language]/site/lib/wsAPI"; import { useSiteStore } from "@/state/Stores"; import { observer } from "mobx-react-lite"; @@ -19,7 +19,7 @@ const t = useTranslations(); const onEnterSite = () => { - SiteComponent.send({ + wsAPI.send({ eventID: EventPB.Event.EventID.ENTER_SITE, text: JSON.stringify({ siteID, siteCipher }), }); diff --git "a/qwilight-fe/src/app/\133language\135/site/components/SiteComponent.ts" "b/qwilight-fe/src/app/\133language\135/site/components/SiteComponent.ts" deleted file mode 100644 index 70875d4..0000000 --- "a/qwilight-fe/src/app/\133language\135/site/components/SiteComponent.ts" +++ /dev/null @@ -1,97 +0,0 @@ -import { - CloseEventHandler, - Event, - EventHandler, -} from "@/app/[language]/site/type"; -import { getMillis } from "taehui-ts/date"; -import { getLanguage } from "taehui-ts/language"; - -const EventPB = require("@/Event_pb"); - -const siteComponent = new (class { - ws?: WebSocket; - avatarID: string; - eventDefaultHandler: EventHandler; - eventCloseHandler: CloseEventHandler; - onLoaded: () => void; - onData: ({ data }: { data: MessageEvent }) => void; - onClosed: () => void; - - constructor() { - this.ws = undefined; - this.avatarID = ""; - this.eventDefaultHandler = () => {}; - this.eventCloseHandler = () => {}; - - this.onLoaded = () => { - this.send({ - eventID: EventPB.Event.EventID.ESTABLISH, - text: JSON.stringify({ - language: getLanguage(), - }), - }); - }; - - this.onData = ({ data }) => { - try { - const { array } = EventPB.Event.deserializeBinary(data); - this.eventDefaultHandler({ - eventID: array[2], - text: array[3], - data: array[4], - }); - } catch (e) {} - }; - - this.onClosed = () => { - this.eventCloseHandler(); - this.connect(); - }; - } - - connect() { - this.ws = new WebSocket( - `${process.env.NEXT_PUBLIC_WS_API ?? "wss://taehui.ddns.net"}/qwilight/ws`, - ); - this.ws.binaryType = "arraybuffer"; - this.ws.addEventListener("open", this.onLoaded); - this.ws.addEventListener("message", this.onData); - this.ws.addEventListener("close", this.onClosed); - } - - disconnect() { - this.eventCloseHandler(); - this.ws?.removeEventListener("open", this.onLoaded); - this.ws?.removeEventListener("message", this.onData); - this.ws?.removeEventListener("close", this.onClosed); - this.ws?.close(); - } - - send({ eventID, text, data }: Event) { - try { - const event = new EventPB.Event(); - event.setMillis(getMillis()); - event.setAvatarid(this.avatarID); - event.setEventid(eventID); - event.setText(text); - data?.forEach((dataItem) => { - event.addData(dataItem); - }); - this.ws?.send(event.serializeBinary()); - } catch (e) {} - } - - setEventDefaultHandler(eventDefaultHandler: EventHandler) { - this.eventDefaultHandler = eventDefaultHandler; - } - - setEventCloseHandler(eventCloseHandler: CloseEventHandler) { - this.eventCloseHandler = eventCloseHandler; - } - - setAvatarID(avatarID: string) { - this.avatarID = avatarID; - } -})(); - -export default siteComponent; diff --git "a/qwilight-fe/src/app/\133language\135/site/components/SiteInput.tsx" "b/qwilight-fe/src/app/\133language\135/site/components/SiteInput.tsx" index f80bbd7..3e5da5f 100644 --- "a/qwilight-fe/src/app/\133language\135/site/components/SiteInput.tsx" +++ "b/qwilight-fe/src/app/\133language\135/site/components/SiteInput.tsx" @@ -1,4 +1,4 @@ -import SiteComponent from "@/app/[language]/site/components/SiteComponent"; +import wsAPI from "@/app/[language]/site/lib/wsAPI"; import { useSiteStore } from "@/state/Stores"; import { observer } from "mobx-react-lite"; @@ -25,7 +25,7 @@ fr.readAsArrayBuffer(file); fr.addEventListener("loadend", () => { const { result } = fr; - SiteComponent.send({ + wsAPI.send({ eventID: EventPB.Event.EventID.POST_FILE, text: file.name, data: [new Uint8Array(result as ArrayBufferLike)], @@ -63,7 +63,7 @@ onKeyDown={({ key }) => { if (key === "Enter") { if (input.length > 0) { - SiteComponent.send({ + wsAPI.send({ eventID: EventPB.Event.EventID.SITE_YELL, text: JSON.stringify({ siteID: targetSiteID, @@ -92,7 +92,7 @@ onClick={() => { window.localStorage.removeItem("avatarCipher"); window.localStorage.removeItem("autoLogIn"); - SiteComponent.send({ + wsAPI.send({ eventID: EventPB.Event.EventID.NOT_LOG_IN, }); }} diff --git "a/qwilight-fe/src/app/\133language\135/site/components/SiteWindow.tsx" "b/qwilight-fe/src/app/\133language\135/site/components/SiteWindow.tsx" index 97c9f08..a496361 100644 --- "a/qwilight-fe/src/app/\133language\135/site/components/SiteWindow.tsx" +++ "b/qwilight-fe/src/app/\133language\135/site/components/SiteWindow.tsx" @@ -1,6 +1,6 @@ import NewSiteWindow from "@/app/[language]/site/components/NewSiteWindow"; import SiteCipherWindow from "@/app/[language]/site/components/SiteCipherWindow"; -import SiteComponent from "@/app/[language]/site/components/SiteComponent"; +import wsAPI from "@/app/[language]/site/lib/wsAPI"; import useGetSites from "@/app/[language]/site/query/useGetSites"; import sc from "@/assets/sc.png"; @@ -61,7 +61,7 @@ setSiteName(siteName); setSiteCipherWindowOpened(true); } else { - SiteComponent.send({ + wsAPI.send({ eventID: EventPB.Event.EventID.ENTER_SITE, text: JSON.stringify({ siteID, siteCipher: "" }), }); diff --git "a/qwilight-fe/src/app/\133language\135/site/components/SiteYellItem.tsx" "b/qwilight-fe/src/app/\133language\135/site/components/SiteYellItem.tsx" index 85622a7..40890d3 100644 --- "a/qwilight-fe/src/app/\133language\135/site/components/SiteYellItem.tsx" +++ "b/qwilight-fe/src/app/\133language\135/site/components/SiteYellItem.tsx" @@ -1,5 +1,5 @@ -import SiteComponent from "@/app/[language]/site/components/SiteComponent"; import scss from "@/app/[language]/site/components/SiteYellItem.module.scss"; +import wsAPI from "@/app/[language]/site/lib/wsAPI"; import { AbilitySiteYell, CommentSiteYell, @@ -216,7 +216,7 @@ { - SiteComponent.send({ + wsAPI.send({ eventID: EventPB.Event.EventID.ENTER_SITE, text: JSON.stringify({ siteID, diff --git "a/qwilight-fe/src/app/\133language\135/site/lib/useWSAPI.tsx" "b/qwilight-fe/src/app/\133language\135/site/lib/useWSAPI.tsx" new file mode 100644 index 0000000..d0381b0 --- /dev/null +++ "b/qwilight-fe/src/app/\133language\135/site/lib/useWSAPI.tsx" @@ -0,0 +1,50 @@ +import wsAPI from "@/app/[language]/site/lib/wsAPI"; +import { useSiteStore } from "@/state/Stores"; +import { useTranslations } from "next-intl"; +import { useEffect } from "react"; +import { useLanguage } from "taehui-ts/language"; + +export default function useWSAPI() { + const { + targetSiteID, + getSiteView, + setVisible, + setEventHandler, + setEventCloseHandler, + } = useSiteStore(); + const t = useTranslations(); + + useEffect(() => { + const onVisibilityModified = () => { + if (setVisible()) { + const siteView = getSiteView(targetSiteID); + if (siteView) { + siteView.wasNotify = false; + } + } + }; + + document.addEventListener("visibilitychange", onVisibilityModified); + + return () => { + document.removeEventListener("visibilitychange", onVisibilityModified); + }; + }, [getSiteView, setVisible, targetSiteID]); + + useEffect(() => { + setVisible(); + setEventHandler(t); + setEventCloseHandler(); + }, [setEventCloseHandler, setEventHandler, setVisible, t]); + + const language = useLanguage(); + + useEffect(() => { + wsAPI.setLanguage(language); + wsAPI.connect(); + + return () => { + wsAPI.disconnect(); + }; + }, [language]); +} diff --git "a/qwilight-fe/src/app/\133language\135/site/lib/wsAPI.ts" "b/qwilight-fe/src/app/\133language\135/site/lib/wsAPI.ts" new file mode 100644 index 0000000..ea41a25 --- /dev/null +++ "b/qwilight-fe/src/app/\133language\135/site/lib/wsAPI.ts" @@ -0,0 +1,102 @@ +import { + CloseEventHandler, + Event, + EventHandler, +} from "@/app/[language]/site/type"; +import { getMillis } from "taehui-ts/date"; +import { useLanguage } from "taehui-ts/language"; + +const EventPB = require("@/Event_pb"); + +const wsAPI = new (class { + ws?: WebSocket; + avatarID: string; + eventDefaultHandler: EventHandler; + eventCloseHandler: CloseEventHandler; + onLoaded: () => void; + onData: ({ data }: { data: MessageEvent }) => void; + onClosed: () => void; + language?: ReturnType; + + constructor() { + this.ws = undefined; + this.avatarID = ""; + this.eventDefaultHandler = () => {}; + this.eventCloseHandler = () => {}; + + this.onLoaded = () => { + this.send({ + eventID: EventPB.Event.EventID.ESTABLISH, + text: JSON.stringify({ + language: this.language, + }), + }); + }; + + this.onData = ({ data }) => { + try { + const { array } = EventPB.Event.deserializeBinary(data); + this.eventDefaultHandler({ + eventID: array[2], + text: array[3], + data: array[4], + }); + } catch (e) {} + }; + + this.onClosed = () => { + this.eventCloseHandler(); + this.connect(); + }; + } + + setLanguage(language: ReturnType) { + this.language = language; + } + + connect() { + this.ws = new WebSocket( + `${process.env.NEXT_PUBLIC_WS_API ?? "wss://taehui.ddns.net"}/qwilight/ws`, + ); + this.ws.binaryType = "arraybuffer"; + this.ws.addEventListener("open", this.onLoaded); + this.ws.addEventListener("message", this.onData); + this.ws.addEventListener("close", this.onClosed); + } + + disconnect() { + this.eventCloseHandler(); + this.ws?.removeEventListener("open", this.onLoaded); + this.ws?.removeEventListener("message", this.onData); + this.ws?.removeEventListener("close", this.onClosed); + this.ws?.close(); + } + + send({ eventID, text, data }: Event) { + try { + const event = new EventPB.Event(); + event.setMillis(getMillis()); + event.setAvatarid(this.avatarID); + event.setEventid(eventID); + event.setText(text); + data?.forEach((dataItem) => { + event.addData(dataItem); + }); + this.ws?.send(event.serializeBinary()); + } catch (e) {} + } + + setEventDefaultHandler(eventDefaultHandler: EventHandler) { + this.eventDefaultHandler = eventDefaultHandler; + } + + setEventCloseHandler(eventCloseHandler: CloseEventHandler) { + this.eventCloseHandler = eventCloseHandler; + } + + setAvatarID(avatarID: string) { + this.avatarID = avatarID; + } +})(); + +export default wsAPI; diff --git "a/qwilight-fe/src/app/\133language\135/site/page.tsx" "b/qwilight-fe/src/app/\133language\135/site/page.tsx" index 6b92aef..6a6f3e6 100644 --- "a/qwilight-fe/src/app/\133language\135/site/page.tsx" +++ "b/qwilight-fe/src/app/\133language\135/site/page.tsx" @@ -2,11 +2,11 @@ import AvatarItems from "@/app/[language]/site/components/AvatarItems"; import ConfigureWindow from "@/app/[language]/site/components/ConfigureWindow"; -import SiteComponent from "@/app/[language]/site/components/SiteComponent"; import SiteInput from "@/app/[language]/site/components/SiteInput"; import SiteWindow from "@/app/[language]/site/components/SiteWindow"; import SiteYellItem from "@/app/[language]/site/components/SiteYellItem"; import SiteYellItems from "@/app/[language]/site/components/SiteYellItems"; +import wsAPI from "@/app/[language]/site/lib/wsAPI"; import scss from "@/app/[language]/site/page.module.scss"; import { OnSiteYellInput } from "@/app/[language]/site/type"; @@ -125,7 +125,7 @@ if (current) { const siteYellID = siteYells[0]?.siteYellID; if (siteYellID && siteYellID > 0 && !current.scrollTop) { - SiteComponent.send({ + wsAPI.send({ eventID: EventPB.Event.EventID.GET_SITE_YELLS, text: JSON.stringify({ siteID: targetSiteID, @@ -218,7 +218,7 @@