Skip to content

Commit

Permalink
Rename jadi hardware websocket dan mengubah useEffect menjadi subscri…
Browse files Browse the repository at this point in the history
…be method (#67)

* feat: mengubah nama jadi hardware websocket dan implement subscribe method

* fix: ketinggalan

* fix: memperbaiki eslint
  • Loading branch information
reacto11mecha authored Nov 12, 2024
1 parent 1d74ca0 commit 0a1c16a
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 81 deletions.
6 changes: 3 additions & 3 deletions apps/clients/chooser/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import superjson from "superjson";

import { ClientNotFound } from "@sora-vp/ui/client-not-found";

import { KeyboardWebsocketProvider } from "./context/keyboard-websocket";
import { HardwareWebsocketProvider } from "./context/hardware-websocket";
import { env } from "./env";

const router = createBrowserRouter([
Expand Down Expand Up @@ -78,13 +78,13 @@ export default function App() {
return (
<api.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
<KeyboardWebsocketProvider>
<HardwareWebsocketProvider>
<ParticipantProvider>
<ServerSettingProvider>
<RouterProvider router={router} />
</ServerSettingProvider>
</ParticipantProvider>
</KeyboardWebsocketProvider>
</HardwareWebsocketProvider>
</QueryClientProvider>
</api.Provider>
);
Expand Down
21 changes: 11 additions & 10 deletions apps/clients/chooser/src/components/scanner/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useState } from "react";
import { useKeyboardWebsocket } from "@/context/keyboard-websocket";
import { useHardwareWebsocket } from "@/context/hardware-websocket";
import { useParticipant } from "@/context/participant-context";
import { api } from "@/utils/api";
import { Navigate } from "react-router-dom";
Expand All @@ -10,24 +10,21 @@ import { MainScanner } from "./main-scanner";

export function ScannerComponent() {
const { qrId, setQRCode } = useParticipant();
const { wsEnabled, lastMessage, setLastMessage } = useKeyboardWebsocket();
const { subscribe } = useHardwareWebsocket();

const [isQrInvalid, setInvalidQr] = useState(false);

const participantAttended =
api.clientConsumer.checkParticipantAttended.useMutation({
onSuccess() {
setLastMessage(null);

setQRCode(participantAttended.variables!);
},
});

useEffect(() => {
if (wsEnabled && lastMessage) {
// Precheck before consuming command
if (lastMessage.startsWith("SORA-KEYBIND-")) {
const actualCommand = lastMessage.replace("SORA-KEYBIND-", "");
const unsubHardware = subscribe((message) => {
if (message.startsWith("SORA-KEYBIND-")) {
const actualCommand = message.replace("SORA-KEYBIND-", "");

switch (actualCommand) {
case "RELOAD": {
Expand All @@ -37,8 +34,12 @@ export function ScannerComponent() {
}
}
}
}
}, [isQrInvalid, participantAttended.isError, wsEnabled, lastMessage]);
});

return () => {
unsubHardware();
};
}, [isQrInvalid, participantAttended.isError]);

const setIsQrValid = useCallback(
(invalid: boolean) => setInvalidQr(invalid),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,39 @@ import {
useCallback,
useContext,
useEffect,
useMemo,
useState,
useRef,
} from "react";
import { defaultWSPortAtom, enableWSConnectionAtom } from "@/utils/atom";
import { useAtomValue } from "jotai";
import useWebSocket, { ReadyState } from "react-use-websocket";

import { toast } from "@sora-vp/ui/toast";

export interface IKeyboardWebsocket {
export type THardwareWebsocketCallback = (message: string) => void;

export interface IHardwareWebsocket {
wsEnabled: boolean;
lastMessage: string | null;
setLastMessage: (msg: string | null) => void;
subscribe(callbacK: THardwareWebsocketCallback): () => void;
}

export const KeyboardWebsocketContext = createContext<IKeyboardWebsocket>(
{} as IKeyboardWebsocket,
export const HardwareWebsocketContext = createContext<IHardwareWebsocket>(
{} as IHardwareWebsocket,
);

export const KeyboardWebsocketProvider = ({
export const HardwareWebsocketProvider = ({
children,
}: {
children: React.ReactNode;
}) => {
const [lastMessage, setLastMessageState] =
useState<IKeyboardWebsocket["lastMessage"]>(null);
const currentSubscriberIdRef = useRef<number>(0);
const subscribersRef = useRef<Map<number, THardwareWebsocketCallback>>(
new Map(),
);

const wsPortNumber = useAtomValue(defaultWSPortAtom);
const wsEnabled = useAtomValue(enableWSConnectionAtom);

const { lastMessage: libLastMessage, readyState } = useWebSocket<string>(
const { lastMessage, readyState } = useWebSocket<string>(
wsEnabled ? `ws://127.0.0.1:${wsPortNumber}/ws` : null,
{
share: true,
Expand All @@ -47,23 +49,23 @@ export const KeyboardWebsocketProvider = ({
},
);

const setLastMessage = useCallback(
(msg: IKeyboardWebsocket["lastMessage"]) => setLastMessageState(msg),
[],
);
const subscribe = useCallback((callback: THardwareWebsocketCallback) => {
const id = currentSubscriberIdRef.current;
subscribersRef.current.set(id, callback);
currentSubscriberIdRef.current++;

const contextValue = useMemo(
() => ({
wsEnabled,
lastMessage,
setLastMessage,
}),
[wsEnabled, lastMessage],
);
return () => {
subscribersRef.current.delete(id);
};
}, []);

useEffect(() => {
if (libLastMessage) setLastMessageState(libLastMessage.data);
}, [libLastMessage]);
if (lastMessage) {
Array.from(subscribersRef.current).forEach(([, callback]) => {
callback(lastMessage.data);
});
}
}, [lastMessage]);

useEffect(() => {
if (wsEnabled) {
Expand Down Expand Up @@ -96,11 +98,16 @@ export const KeyboardWebsocketProvider = ({
}, [readyState, wsEnabled]);

return (
<KeyboardWebsocketContext.Provider value={contextValue}>
<HardwareWebsocketContext.Provider
value={{
wsEnabled,
subscribe,
}}
>
{children}
</KeyboardWebsocketContext.Provider>
</HardwareWebsocketContext.Provider>
);
};

export const useKeyboardWebsocket = () =>
useContext(KeyboardWebsocketContext) as IKeyboardWebsocket;
export const useHardwareWebsocket = () =>
useContext(HardwareWebsocketContext) as IHardwareWebsocket;
25 changes: 11 additions & 14 deletions apps/clients/chooser/src/context/participant-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { api } from "@/utils/api";
import { motion } from "framer-motion";
import { Navigate } from "react-router-dom";

import { useKeyboardWebsocket } from "./keyboard-websocket";
import { useHardwareWebsocket } from "./hardware-websocket";

export interface IParticipantContext {
name: string | null;
Expand All @@ -30,7 +30,7 @@ export const ParticipantProvider = ({
}: {
children: React.ReactNode;
}) => {
const { wsEnabled, lastMessage } = useKeyboardWebsocket();
const { subscribe } = useHardwareWebsocket();

const [qrId, setQrId] = useState<string | null>(null);
const [votedSuccessfully, setVoted] = useState(false);
Expand All @@ -50,10 +50,9 @@ export const ParticipantProvider = ({
);

useEffect(() => {
if (wsEnabled && lastMessage) {
// Precheck before consuming command
if (lastMessage.startsWith("SORA-KEYBIND-")) {
const actualCommand = lastMessage.replace("SORA-KEYBIND-", "");
const unsubHardware = subscribe((message) => {
if (message.startsWith("SORA-KEYBIND-")) {
const actualCommand = message.replace("SORA-KEYBIND-", "");

switch (actualCommand) {
case "RELOAD": {
Expand All @@ -69,14 +68,12 @@ export const ParticipantProvider = ({
}
}
}
}
}, [
qrId,
participantQuery.isFetched,
participantQuery.data,
wsEnabled,
lastMessage,
]);

return () => {
unsubHardware();
};
});
}, [qrId, participantQuery.isFetched, participantQuery.data]);

const propsValue = useMemo(() => {
if (!qrId)
Expand Down
19 changes: 11 additions & 8 deletions apps/clients/chooser/src/context/server-setting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { api } from "@/utils/api";
import { motion } from "framer-motion";
import { Loader } from "lucide-react";

import { useKeyboardWebsocket } from "./keyboard-websocket";
import { useHardwareWebsocket } from "./hardware-websocket";
import { useParticipant } from "./participant-context";

interface ISettingContext {
Expand All @@ -20,7 +20,7 @@ export const ServerSettingProvider = ({
}: {
children: React.ReactNode;
}) => {
const { wsEnabled, lastMessage } = useKeyboardWebsocket();
const { subscribe } = useHardwareWebsocket();
const { qrId, setQRCode } = useParticipant();

const [errorMessage, setErrorMessage] = useState("");
Expand All @@ -31,10 +31,9 @@ export const ServerSettingProvider = ({
});

useEffect(() => {
if (wsEnabled && lastMessage) {
// Precheck before consuming command
if (lastMessage.startsWith("SORA-KEYBIND-")) {
const actualCommand = lastMessage.replace("SORA-KEYBIND-", "");
const unsubHardware = subscribe((message) => {
if (message.startsWith("SORA-KEYBIND-")) {
const actualCommand = message.replace("SORA-KEYBIND-", "");

switch (actualCommand) {
case "RELOAD": {
Expand All @@ -44,8 +43,12 @@ export const ServerSettingProvider = ({
}
}
}
}
}, [settingsQuery.errorUpdateCount, wsEnabled, lastMessage]);
});

return () => {
unsubHardware();
};
}, [settingsQuery.errorUpdateCount]);

useEffect(() => {
if (settingsQuery.error) setErrorMessage(settingsQuery.error.message);
Expand Down
27 changes: 10 additions & 17 deletions apps/clients/chooser/src/routes/vote-page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { UniversalError } from "@/components/universal-error";
import { useKeyboardWebsocket } from "@/context/keyboard-websocket";
import { useHardwareWebsocket } from "@/context/hardware-websocket";
import { ensureQRIDExist, useParticipant } from "@/context/participant-context";
import { env } from "@/env";
import { api } from "@/utils/api";
Expand Down Expand Up @@ -91,7 +91,7 @@ const CurrentParticipantInfo = (props: { isSuccess?: boolean }) => {

function VotePage() {
const { qrId, setQRCode, setVotedSuccessfully } = useParticipant();
const { wsEnabled, lastMessage, setLastMessage } = useKeyboardWebsocket();
const { subscribe } = useHardwareWebsocket();

const successTimeout = useAtomValue(successTimeoutAtom);

Expand All @@ -116,9 +116,6 @@ function VotePage() {
setAlertOpen(false);
setID(null);
},
onSettled() {
setLastMessage(null);
},
});

const candidateName = useMemo(
Expand All @@ -141,8 +138,6 @@ function VotePage() {
const chooseCandidate = useCallback(() => {
if (!cannotPushKey) {
if (qrId && currentID && alertOpen) {
setLastMessage(null);

upvoteCandidate.mutate({
id: currentID,
qrId,
Expand Down Expand Up @@ -176,7 +171,6 @@ function VotePage() {
if (!upvoteCandidate.isPending) {
setID(null);
setAlertOpen(false);
setLastMessage(null);
}

break;
Expand Down Expand Up @@ -228,17 +222,15 @@ function VotePage() {
}, [upvoteCandidate.isPending, alertOpen, triggerOpen, chooseCandidate]);

useEffect(() => {
if (wsEnabled && lastMessage) {
// Precheck before consuming command
if (lastMessage.startsWith("SORA-KEYBIND-")) {
const actualCommand = lastMessage.replace("SORA-KEYBIND-", "");
const unsubHardware = subscribe((message) => {
if (message.startsWith("SORA-KEYBIND-")) {
const actualCommand = message.replace("SORA-KEYBIND-", "");

switch (actualCommand) {
case "ESC": {
if (!upvoteCandidate.isPending) {
setID(null);
setAlertOpen(false);
setLastMessage(null);
}

break;
Expand Down Expand Up @@ -288,15 +280,17 @@ function VotePage() {
}
}
}
}
});

return () => {
unsubHardware();
};
}, [
upvoteCandidate.isPending,
candidateList.errorUpdateCount,
alertOpen,
triggerOpen,
chooseCandidate,
wsEnabled,
lastMessage,
]);

useEffect(() => {
Expand Down Expand Up @@ -443,7 +437,6 @@ function VotePage() {
open={alertOpen || (upvoteCandidate.isPending && !!qrId)}
onOpenChange={() => {
setAlertOpen((prev) => !prev);
setLastMessage(null);
}}
>
<AlertDialogContent
Expand Down

0 comments on commit 0a1c16a

Please sign in to comment.