diff --git a/todoblue/src/app/board/[board]/BoardBody.tsx b/todoblue/src/app/board/[board]/BoardBody.tsx new file mode 100644 index 0000000..0e634c9 --- /dev/null +++ b/todoblue/src/app/board/[board]/BoardBody.tsx @@ -0,0 +1,20 @@ +import {BoardError} from "@/app/board/[board]/BoardError" +import {BoardLoading} from "@/app/board/[board]/BoardLoading" +import {useBoardContext} from "@/app/board/[board]/useBoardContext" + + +export function BoardBody() { + const {websocketState} = useBoardContext() + + switch(websocketState) { + case undefined: + return + case WebSocket.CONNECTING: + return + case WebSocket.OPEN: + return <>nothing here + case WebSocket.CLOSING: + case WebSocket.CLOSED: + return + } +} diff --git a/todoblue/src/app/board/[board]/BoardContext.tsx b/todoblue/src/app/board/[board]/BoardContext.tsx new file mode 100644 index 0000000..fc3ba0c --- /dev/null +++ b/todoblue/src/app/board/[board]/BoardContext.tsx @@ -0,0 +1,4 @@ +import {UseBoardReturns} from "@/app/board/[board]/useBoard" +import {createContext, useContext} from "react" + +export const BoardContext = createContext(null); diff --git a/todoblue/src/app/board/[board]/BoardError.module.css b/todoblue/src/app/board/[board]/BoardError.module.css new file mode 100644 index 0000000..f3dbcfa --- /dev/null +++ b/todoblue/src/app/board/[board]/BoardError.module.css @@ -0,0 +1,7 @@ +.boardError { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 8px; +} diff --git a/todoblue/src/app/board/[board]/BoardError.tsx b/todoblue/src/app/board/[board]/BoardError.tsx new file mode 100644 index 0000000..4fee653 --- /dev/null +++ b/todoblue/src/app/board/[board]/BoardError.tsx @@ -0,0 +1,18 @@ +import style from "./BoardError.module.css" +import {faExclamationCircle} from "@fortawesome/free-solid-svg-icons" +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome" +import classNames from "classnames" + + +export function BoardError({text}: {text: string}) { + return ( +
+
+ +
+
+ {text} +
+
+ ) +} diff --git a/todoblue/src/app/board/[board]/page.module.css b/todoblue/src/app/board/[board]/BoardHeader.module.css similarity index 78% rename from todoblue/src/app/board/[board]/page.module.css rename to todoblue/src/app/board/[board]/BoardHeader.module.css index 475ce0e..ae48cc2 100644 --- a/todoblue/src/app/board/[board]/page.module.css +++ b/todoblue/src/app/board/[board]/BoardHeader.module.css @@ -2,6 +2,8 @@ display: grid; align-items: center; padding-top: 4px; + grid-row-gap: 4px; + grid-column-gap: 10px; } @media screen and (max-width: 450px) { @@ -9,10 +11,9 @@ grid-template-areas: "left right" "title title" - ; + ; grid-template-columns: auto auto; grid-template-rows: auto auto; - } } @@ -20,7 +21,7 @@ .boardHeader { grid-template-areas: "left title right" - ; + ; grid-template-columns: auto 1fr auto; grid-template-rows: auto; } @@ -46,6 +47,19 @@ .boardTitle { grid-area: title; + height: 80px; +} + +.boardTitle div { + padding-top: 0.125em; + padding-right: 0.75ex; + padding-left: 0.75ex; + padding-bottom: calc(0.125em + 2px); +} + +.boardTitle input { + text-align: center; + width: 100%; } .boardButtons button { diff --git a/todoblue/src/app/board/[board]/BoardHeader.tsx b/todoblue/src/app/board/[board]/BoardHeader.tsx new file mode 100644 index 0000000..bcc1fbe --- /dev/null +++ b/todoblue/src/app/board/[board]/BoardHeader.tsx @@ -0,0 +1,40 @@ +import style from "./BoardHeader.module.css" +import {useBoardContext} from "@/app/board/[board]/useBoardContext" +import {faArrowDownWideShort, faHouse, faPencil, faTableColumns} from "@fortawesome/free-solid-svg-icons" +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome" +import cn from "classnames" + + +export function BoardHeader() { + const {title, isEditingTitle, editTitle, setEditTitle, toggleEditingTitle, nextGrouper, nextSorter, websocketState} = useBoardContext(); + + const isReady = websocketState === WebSocket.OPEN + + return ( +
+
+ + +
+

+ {isEditingTitle ? + setEditTitle(e.target.value)} value={editTitle}/> + : +
{title}
+ } +

+
+ + +
+
+ ) +} diff --git a/todoblue/src/app/board/[board]/BoardLoading.module.css b/todoblue/src/app/board/[board]/BoardLoading.module.css new file mode 100644 index 0000000..06a7dfb --- /dev/null +++ b/todoblue/src/app/board/[board]/BoardLoading.module.css @@ -0,0 +1,7 @@ +.boardLoading { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 8px; +} diff --git a/todoblue/src/app/board/[board]/BoardLoading.tsx b/todoblue/src/app/board/[board]/BoardLoading.tsx new file mode 100644 index 0000000..5541614 --- /dev/null +++ b/todoblue/src/app/board/[board]/BoardLoading.tsx @@ -0,0 +1,17 @@ +import style from "./BoardLoading.module.css" +import {faSpinner} from "@fortawesome/free-solid-svg-icons" +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome" + + +export function BoardLoading({text}: {text: string}) { + return ( +
+
+ +
+
+ {text} +
+
+ ) +} diff --git a/todoblue/src/app/board/[board]/BoardManager.tsx b/todoblue/src/app/board/[board]/BoardManager.tsx new file mode 100644 index 0000000..ef0e0a0 --- /dev/null +++ b/todoblue/src/app/board/[board]/BoardManager.tsx @@ -0,0 +1,14 @@ +import {BoardContext} from "@/app/board/[board]/BoardContext" +import {useBoard} from "@/app/board/[board]/useBoard" +import {ReactNode} from "react" + + +export function BoardManager({name, children}: {name: string, children: ReactNode}) { + const context = useBoard(name); + + return ( + + {children} + + ) +} diff --git a/todoblue/src/app/board/[board]/groupAndSortTasks.ts b/todoblue/src/app/board/[board]/groupAndSortTasks.ts deleted file mode 100644 index e3d56ef..0000000 --- a/todoblue/src/app/board/[board]/groupAndSortTasks.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {Task} from "@/app/board/[board]/types" - - -export function groupAndSortTasks(tasks: Task[], grouping: (a: Task) => string, sorting: (a: Task, b: Task) => number) { - const groups: {[group: string]: Task[]} = {} - - for(const task of tasks) { - const group = grouping(task); - if(!groups[group]) { - groups[group] = []; - } - groups[group].push(task); - } - - for(const group of Object.keys(groups)) { - groups[group].sort(sorting); - } - - return groups; -} diff --git a/todoblue/src/app/board/[board]/page.tsx b/todoblue/src/app/board/[board]/page.tsx index 9a61f02..1ae2ddb 100644 --- a/todoblue/src/app/board/[board]/page.tsx +++ b/todoblue/src/app/board/[board]/page.tsx @@ -1,73 +1,15 @@ "use client"; -import {FontAwesomeIcon} from "@fortawesome/react-fontawesome" -import {useEffect} from "react" -import {useBoardWebSocket} from "@/app/board/[board]/useBoardWebSocket" -import style from "./page.module.css"; -import classNames from "classnames" -import {faHouse, faPencil, faTableColumns, faArrowDownWideShort} from "@fortawesome/free-solid-svg-icons" +import {BoardBody} from "@/app/board/[board]/BoardBody" +import {BoardManager} from "@/app/board/[board]/BoardManager" +import {BoardHeader} from "@/app/board/[board]/BoardHeader" export default function Page({params: {board}}: {params: {board: string}}) { - const {tasks, title, pushEvent, readyState} = useBoardWebSocket(board); - - useEffect(() => { - console.debug("[Page] Current events: ", tasks) - }, [tasks]) - - return <> -
-
- - -
-

- {title} -

-
- - -
-
-
-
-
-

- Gruppo A -

-
-
-

- Gruppo B -

-
-
-

- Gruppo C -

-
-
-

- Gruppo D -

-
-
-

- Gruppo E -

-
-
-
-
- sos -
- + return ( + + + + + ) } diff --git a/todoblue/src/app/board/[board]/types.ts b/todoblue/src/app/board/[board]/types.ts index c857b99..b271c0c 100644 --- a/todoblue/src/app/board/[board]/types.ts +++ b/todoblue/src/app/board/[board]/types.ts @@ -1,44 +1,44 @@ export type TaskIcon = - "User" & - "Image" & - "Envelope" & - "Star" & - "Heart" & - "Comment" & - "FaceSmile" & - "File" & - "Bell" & - "Bookmark" & - "Eye" & - "Hand" & - "PaperPlane" & - "Handshake" & - "Sun" & - "Clock" & - "Circle" & - "Square" & - "Building" & - "Flag" & + "User" | + "Image" | + "Envelope" | + "Star" | + "Heart" | + "Comment" | + "FaceSmile" | + "File" | + "Bell" | + "Bookmark" | + "Eye" | + "Hand" | + "PaperPlane" | + "Handshake" | + "Sun" | + "Clock" | + "Circle" | + "Square" | + "Building" | + "Flag" | "Moon"; export type TaskImportance = - "Highest" & - "High" & - "Normal" & - "Low" & + "Highest" | + "High" | + "Normal" | + "Low" | "Lowest"; export type TaskPriority = - "Highest" & - "High" & - "Normal" & - "Low" & + "Highest" | + "High" | + "Normal" | + "Low" | "Lowest"; export type TaskStatus = - "Unfinished" & - "InProgress" & - "Complete" + "Unfinished" | + "InProgress" | + "Complete"; export type Task = { text: string, @@ -48,6 +48,10 @@ export type Task = { status: TaskStatus, } +export type TaskWithId = Task & { + id: string, +} + export type TitleBoardAction = { "Title": string, } @@ -59,4 +63,6 @@ export type TaskBoardAction = { ] } -export type BoardAction = TitleBoardAction & TaskBoardAction; +export type BoardAction = + TitleBoardAction | + TaskBoardAction; diff --git a/todoblue/src/app/board/[board]/useBoard.ts b/todoblue/src/app/board/[board]/useBoard.ts new file mode 100644 index 0000000..cef9159 --- /dev/null +++ b/todoblue/src/app/board/[board]/useBoard.ts @@ -0,0 +1,67 @@ +"use client"; + +import {TaskWithId} from "@/app/board/[board]/types" +import {useBoardWebSocket} from "@/app/board/[board]/useBoardWebSocket" +import {GroupSortingFunction, TaskGroup, TaskGroupingFunction, TaskSortingFunction, useBoardTaskArranger} from "@/app/board/[board]/useBoardTaskArranger" +import {useBoardTitleEditor} from "@/app/board/[board]/useBoardTitleEditor" +import {useCycleState} from "@/app/useCycleState" +import {Dispatch, SetStateAction} from "react" + +function groupTasksByIcon(a: TaskWithId) {return a.icon} +function sortGroupsByKey(a: TaskGroup, b: TaskGroup) {return a.key.localeCompare(b.key)} + +const TASK_GROUPERS: [TaskGroupingFunction, GroupSortingFunction][] = [ + [groupTasksByIcon, sortGroupsByKey], +] + +function sortTasksByText(a: TaskWithId, b: TaskWithId) {return a.text.localeCompare(b.text)} + +const TASK_SORTERS: TaskSortingFunction[] = [ + sortTasksByText, +]; + +export interface UseBoardReturns { + title: string, + taskGroups: TaskGroup[], + websocketState: number, + isEditingTitle: boolean, + stopEditingTitle: () => void, + startEditingTitle: () => void, + toggleEditingTitle: () => void, + moveGrouper: (n: number) => void, + nextGrouper: () => void, + previousGrouper: () => void, + moveSorter: (n: number) => void, + nextSorter: () => void, + previousSorter: () => void, + editTitle: string, + setEditTitle: Dispatch>, +} + +export function useBoard(name: string): UseBoardReturns { + const {state: {title, tasksById}, send, websocketState} = useBoardWebSocket(name); + + const {value: [taskGrouper, groupSorter], move: moveGrouper, next: nextGrouper, previous: previousGrouper} = useCycleState(TASK_GROUPERS); + const {value: taskSorter, move: moveSorter, next: nextSorter, previous: previousSorter} = useCycleState(TASK_SORTERS); + + const {taskGroups} = useBoardTaskArranger(tasksById, taskGrouper, groupSorter, taskSorter); + const {isEditingTitle, stopEditingTitle, startEditingTitle, toggleEditingTitle, editTitle, setEditTitle} = useBoardTitleEditor(title, send); + + return { + title, + taskGroups, + websocketState, + isEditingTitle, + stopEditingTitle, + startEditingTitle, + toggleEditingTitle, + moveGrouper, + nextGrouper, + previousGrouper, + moveSorter, + nextSorter, + previousSorter, + editTitle, + setEditTitle, + } +} diff --git a/todoblue/src/app/board/[board]/useBoardContext.ts b/todoblue/src/app/board/[board]/useBoardContext.ts new file mode 100644 index 0000000..e547b75 --- /dev/null +++ b/todoblue/src/app/board/[board]/useBoardContext.ts @@ -0,0 +1,14 @@ +import {BoardContext} from "@/app/board/[board]/BoardContext" +import {UseBoardReturns} from "@/app/board/[board]/useBoard" +import {useContext} from "react" + + +export function useBoardContext(): UseBoardReturns { + const context = useContext(BoardContext); + + if(context === null) { + throw Error() + } + + return context +} diff --git a/todoblue/src/app/board/[board]/useBoardState.ts b/todoblue/src/app/board/[board]/useBoardState.ts new file mode 100644 index 0000000..1bcac35 --- /dev/null +++ b/todoblue/src/app/board/[board]/useBoardState.ts @@ -0,0 +1,48 @@ +"use client"; + +import {BoardAction, Task, TaskBoardAction, TitleBoardAction} from "@/app/board/[board]/types" +import {Reducer, useReducer} from "react" + + +type BoardState = { + title: string, + tasksById: {[key: string]: Task}, +} + +function boardReducer(state: BoardState, action: BoardAction | null) { + if(action === null) { + console.debug("[boardReducer] Initializing state..."); + return {title: "", tasksById: {}} + } + else if(Object.hasOwn(action, "Title")) { + const titleAction = action as TitleBoardAction; + const title = titleAction["Title"] + console.debug("[boardReducer] Setting board title to:", title) + return {...state, title} + } + else if(Object.hasOwn(action, "Task")) { + const taskAction = action as TaskBoardAction; + const id = taskAction["Task"][0] + const task = taskAction["Task"][1] + const tasksById = {...state.tasksById} + if(task === null) { + console.debug("[boardReducer] Deleting task:", id) + delete tasksById[id] + } + else { + console.debug("[boardReducer] Putting task:", id) + tasksById[id] = task + } + return {...state, tasksById} + } + else { + console.warn("[boardReducer] Received unknown action, ignoring:", action) + return state + } +} + +export function useBoardState() { + const [state, act] = useReducer>(boardReducer, {title: "", tasksById: {}}) + + return {state, act} +} diff --git a/todoblue/src/app/board/[board]/useBoardTaskArranger.ts b/todoblue/src/app/board/[board]/useBoardTaskArranger.ts new file mode 100644 index 0000000..8e9c8c4 --- /dev/null +++ b/todoblue/src/app/board/[board]/useBoardTaskArranger.ts @@ -0,0 +1,47 @@ +"use client"; + +import {Task, TaskWithId} from "@/app/board/[board]/types" +import {useMemo} from "react" + +export type TaskGroup = { + key: string, + tasks: TaskWithId[], +} + +export type TaskGroupingFunction = (a: TaskWithId) => string +export type TaskSortingFunction = (a: TaskWithId, b: TaskWithId) => number; +export type GroupSortingFunction = (a: TaskGroup, b: TaskGroup) => number; + +export function arrangeBoardTasks(tasksById: { [p: string]: Task }, taskGrouper: TaskGroupingFunction, groupSorter: GroupSortingFunction, taskSorter: TaskSortingFunction): TaskGroup[] { + const groupsByKey: {[group: string]: TaskWithId[]} = {} + + for(const [id, task] of Object.entries(tasksById)) { + const taskWithId = {...task, id}; + const group = taskGrouper(taskWithId); + if(!groupsByKey[group]) { + groupsByKey[group] = []; + } + groupsByKey[group].push(taskWithId); + } + + for(const group of Object.keys(groupsByKey)) { + groupsByKey[group].sort(taskSorter); + } + + const groups: TaskGroup[] = [] + + for(const [key, tasks] of Object.entries(groupsByKey)) { + groups.push({key, tasks}) + } + + groups.sort(groupSorter) + + return groups; +} + + +export function useBoardTaskArranger(tasksById: { [p: string]: Task }, taskGrouper: TaskGroupingFunction, groupSorter: GroupSortingFunction, taskSorter: TaskSortingFunction) { + const taskGroups = useMemo(() => arrangeBoardTasks(tasksById, taskGrouper, groupSorter, taskSorter), [tasksById, taskGrouper, taskSorter, groupSorter]) + + return {taskGroups}; +} diff --git a/todoblue/src/app/board/[board]/useBoardTitleEditor.ts b/todoblue/src/app/board/[board]/useBoardTitleEditor.ts new file mode 100644 index 0000000..38124c6 --- /dev/null +++ b/todoblue/src/app/board/[board]/useBoardTitleEditor.ts @@ -0,0 +1,31 @@ +"use client"; + +import {BoardAction} from "@/app/board/[board]/types" +import {useCallback, useState} from "react" + + +export function useBoardTitleEditor(title: string, send: (action: BoardAction) => void) { + const [isEditingTitle, setEditingTitle] = useState(false) + const [editTitle, setEditTitle] = useState(title) + + const startEditingTitle = useCallback(() => { + console.debug("[useEditableTitle] Starting title edit..."); + setEditingTitle(true); + setEditTitle(title); + }, [title]) + + const stopEditingTitle = useCallback(() => { + console.debug("[useEditableTitle] Ending title edit..."); + setEditingTitle(false); + if(editTitle) { + console.debug("[useEditableTitle] Sending title change event..."); + send({"Title": editTitle}) + } + }, [send, editTitle]) + + const toggleEditingTitle = useCallback(() => { + return isEditingTitle ? stopEditingTitle() : startEditingTitle() + }, [isEditingTitle, stopEditingTitle, startEditingTitle]) + + return {isEditingTitle, startEditingTitle, stopEditingTitle, toggleEditingTitle, editTitle, setEditTitle} +} diff --git a/todoblue/src/app/board/[board]/useBoardWebSocket.ts b/todoblue/src/app/board/[board]/useBoardWebSocket.ts index 767a978..1bdcfcf 100644 --- a/todoblue/src/app/board/[board]/useBoardWebSocket.ts +++ b/todoblue/src/app/board/[board]/useBoardWebSocket.ts @@ -1,57 +1,36 @@ 'use client'; -import {BoardAction, Task} from "@/app/board/[board]/types" -import {useMemo, useCallback, useState} from "react" -import {useWebSocket} from "@/app/board/[board]/useWebSocket" +import {BoardAction} from "@/app/board/[board]/types" +import {useBoardState} from "@/app/board/[board]/useBoardState" +import {useBoardWebSocketURL} from "@/app/board/[board]/useBoardWebSocketURL" +import {useCallback} from "react" +import {useWebSocket} from "@/app/useWebSocket" -export function useBoardWebSocket(board: string) { - const url = useMemo(() => `ws://127.0.0.1:8080/board/${board}/ws`, [board]); - const [title, setTitle] = useState("Nuovo tabellone"); - const [tasks, setTasks] = useState<{[key: string]: Task}>(() => ({})); +export function useBoardWebSocket(name: string) { + const {webSocketURL} = useBoardWebSocketURL(name) + const {state, act} = useBoardState(); - const onopen = useCallback((sock: WebSocket, event: Event) => { - setTasks(() => ({})) - console.debug("[useBoardWebSocket] Connected to the websocket of board:", board); - }, []) + const {websocket, websocketState} = useWebSocket(webSocketURL, { + onopen: useCallback((_sock: WebSocket, _event: Event) => { + console.debug("[useBoard] Connected to board:", name); + act(null); + }, []), + onmessage: useCallback((_sock: WebSocket, event: MessageEvent) => { + const action: BoardAction = JSON.parse(event.data); + console.debug("[useBoard] Received:", action); + act(action) + }, []), + }); - const onmessage = useCallback((sock: WebSocket, event: MessageEvent) => { - const data: BoardAction = JSON.parse(event.data); - console.debug("[useBoardWebSocket] Received:", data); - if(data["Title"] !== undefined) { - setTitle(data["Title"]); - } - else if(data["Task"] !== undefined) { - const id = data["Task"][0] - const task = data["Task"][1] - setTasks((prevTasks) => { - const tasks = {...prevTasks} - if(task === null) { - delete tasks[id] - } - else { - tasks[id] = task - } - return tasks - }) - } - }, []) - - const {websocket} = useWebSocket(url, {onopen, onmessage}); - const readyState = websocket?.readyState; - - const pushEvent = useCallback((data: any) => { - if(!websocket) { - console.warn("[useBoardWebSocket] Socket does not exist yet, cannot send:", data) - return; - } - if(readyState != 1) { - console.warn("[useBoardWebSocket] Socket isn't ready yet, cannot send:", data); + const send = useCallback((data: BoardAction) => { + if(!websocket || websocketState !== WebSocket.OPEN) { + console.warn("[useBoardWebSocket] Webbsocket is not yet ready, cannot send:", data); return; } console.debug("[useBoardWebSocket] Sending:", data); websocket.send(JSON.stringify(data)); - }, [websocket, readyState]) + }, [websocket, websocketState]) - return {title, tasks, pushEvent, readyState} + return {state, send, websocketState} } diff --git a/todoblue/src/app/board/[board]/useBoardWebSocketURL.ts b/todoblue/src/app/board/[board]/useBoardWebSocketURL.ts new file mode 100644 index 0000000..1d77a88 --- /dev/null +++ b/todoblue/src/app/board/[board]/useBoardWebSocketURL.ts @@ -0,0 +1,7 @@ +import {useMemo} from "react" + + +export function useBoardWebSocketURL(name: string) { + const webSocketURL = useMemo(() => `ws://127.0.0.1:8080/board/${name}/ws`, [name]); + return {webSocketURL} +} diff --git a/todoblue/src/app/useCycleState.ts b/todoblue/src/app/useCycleState.ts new file mode 100644 index 0000000..bbb6eae --- /dev/null +++ b/todoblue/src/app/useCycleState.ts @@ -0,0 +1,17 @@ +import {useCallback, useMemo, useState} from "react" + + +export function useCycleState(items: any[]) { + const [index, setIndex] = useState(0); + + const value = useMemo(() => items[index], [index]) + + const move = useCallback((num: number) => { + setIndex((prevIndex) => (prevIndex + num) % items.length); + }, [items]) + + const next = useCallback(() => move(1), [move]); + const previous = useCallback(() => move(-1), [move]); + + return {index, value, move, next, previous} +} diff --git a/todoblue/src/app/board/[board]/useWebSocket.ts b/todoblue/src/app/useWebSocket.ts similarity index 82% rename from todoblue/src/app/board/[board]/useWebSocket.ts rename to todoblue/src/app/useWebSocket.ts index 24e1402..c08800f 100644 --- a/todoblue/src/app/board/[board]/useWebSocket.ts +++ b/todoblue/src/app/useWebSocket.ts @@ -11,22 +11,22 @@ export interface WebSocketHandlers { export function useWebSocket(url: string, {onclose, onerror, onmessage, onopen}: WebSocketHandlers) { const [websocket, setWebsocket] = useState(null) - const [readyState, setReadyState] = useState(0); + const [websocketState, setWebsocketState] = useState(0); useEffect(() => { console.debug("[useWebSocket] Creating websocket..."); const sock = new WebSocket(url); setWebsocket(sock); sock.onopen = (ev) => { - setReadyState(sock.readyState); + setWebsocketState(sock.readyState); onopen?.(sock, ev); } sock.onclose = (ev) => { - setReadyState(sock.readyState); + setWebsocketState(sock.readyState); onclose?.(sock, ev); } sock.onerror = (ev) => { - setReadyState(sock.readyState); + setWebsocketState(sock.readyState); onerror?.(sock, ev); } sock.onmessage = (ev) => { @@ -39,5 +39,5 @@ export function useWebSocket(url: string, {onclose, onerror, onmessage, onopen}: } }, [url, onclose, onerror, onmessage, onopen]) - return {websocket, readyState} + return {websocket, websocketState} } diff --git a/todoblue/yarn.lock b/todoblue/yarn.lock index cb75545..8ac7a59 100644 --- a/todoblue/yarn.lock +++ b/todoblue/yarn.lock @@ -114,7 +114,16 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@18.2.17": +"@types/react@*": + version "18.2.18" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.18.tgz#c8b233919eef1bdc294f6f34b37f9727ad677516" + integrity sha512-da4NTSeBv/P34xoZPhtcLkmZuJ+oYaCxHmyHzwaDQo9RQPBeXV+06gEk2FpqEcsX9XrnNLvRpVh6bdavDSjtiQ== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/react@18.2.17": version "18.2.17" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.17.tgz#baa565b17ddb649c2dac85b5eaf9e9a1fe0f3b4e" integrity sha512-u+e7OlgPPh+aryjOm5UJMX32OvB2E3QASOAqVMY6Ahs90djagxwv2ya0IctglNbNTexC12qCSMZG47KPfy1hAA== @@ -136,9 +145,9 @@ busboy@1.6.0: streamsearch "^1.1.0" caniuse-lite@^1.0.30001406: - version "1.0.30001517" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz#90fabae294215c3495807eb24fc809e11dc2f0a8" - integrity sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA== + version "1.0.30001518" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001518.tgz#b3ca93904cb4699c01218246c4d77a71dbe97150" + integrity sha512-rup09/e3I0BKjncL+FesTayKtPrdwKhUufQFd3riFw1hHg8JmIFoInYfB102cFcY/pPgGmdyl/iy+jgiDi2vdA== classnames@^2.3.2: version "2.3.2"