From e3eba88eb87a12419801cec697184514b8660d2d Mon Sep 17 00:00:00 2001 From: Pas <74743263+Pasithea0@users.noreply.github.com> Date: Sun, 18 May 2025 09:39:57 -0600 Subject: [PATCH] room code validation --- src/assets/locales/en.json | 2 + .../player/atoms/settings/WatchPartyView.tsx | 57 ++++++++++++++++--- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 96e96530..006364d6 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -958,6 +958,8 @@ "join": "Join", "cancel": "Cancel", "save": "Save", + "emptyRoom": "No one is in this room yet", + "invalidRoom": "Unable to connect to this room", "contentMismatch": "Cannot join watch party: The content does not match the host's content.", "episodeMismatch": "Cannot join watch party: You are watching a different episode than the host.", "validating": "Validating watch party..." diff --git a/src/components/player/atoms/settings/WatchPartyView.tsx b/src/components/player/atoms/settings/WatchPartyView.tsx index 3165ea0d..cb2320ef 100644 --- a/src/components/player/atoms/settings/WatchPartyView.tsx +++ b/src/components/player/atoms/settings/WatchPartyView.tsx @@ -4,6 +4,7 @@ import { Trans, useTranslation } from "react-i18next"; import { useAsync } from "react-use"; import { getBackendMeta } from "@/backend/accounts/meta"; +import { getRoomStatuses } from "@/backend/player/status"; import { Button } from "@/components/buttons/Button"; import { Icon, Icons } from "@/components/Icon"; import { Spinner } from "@/components/layout/Spinner"; @@ -11,6 +12,7 @@ import { Menu } from "@/components/player/internals/ContextMenu"; import { useBackendUrl } from "@/hooks/auth/useBackendUrl"; import { useOverlayRouter } from "@/hooks/useOverlayRouter"; import { useWatchPartySync } from "@/hooks/useWatchPartySync"; +import { useAuthStore } from "@/stores/auth"; import { useWatchPartyStore } from "@/stores/watchParty"; import { useDownloadLink } from "./Downloads"; @@ -26,6 +28,9 @@ export function WatchPartyView({ id }: { id: string }) { const [editingCode, setEditingCode] = useState(false); const [customCode, setCustomCode] = useState(""); const backendUrl = useBackendUrl(); + const [isValidating, setIsValidating] = useState(false); + const [validationError, setValidationError] = useState(null); + const account = useAuthStore((s) => s.account); const backendMeta = useAsync(async () => { if (!backendUrl) return; @@ -118,11 +123,30 @@ export function WatchPartyView({ id }: { id: string }) { setShowJoinInput(false); }; - const handleJoinParty = () => { + const handleJoinParty = async () => { if (joinCode.length > 0) { - setIsJoining(true); - enableAsGuest(joinCode); - setShowJoinInput(false); + setIsValidating(true); + setValidationError(null); + + try { + const response = await getRoomStatuses(backendUrl, account, joinCode); + const hasUsers = Object.keys(response.users).length > 0; + + if (!hasUsers) { + setValidationError(t("watchParty.emptyRoom")); + setIsValidating(false); + return; + } + + setIsJoining(true); + enableAsGuest(joinCode); + setShowJoinInput(false); + } catch (error) { + console.error("Failed to validate room:", error); + setValidationError(t("watchParty.invalidRoom")); + } finally { + setIsValidating(false); + } } }; @@ -341,15 +365,30 @@ export function WatchPartyView({ id }: { id: string }) { className="w-full p-2 text-center text-2xl tracking-widest bg-mediaCard-hoverBackground border border-mediaCard-hoverAccent border-opacity-20 rounded-lg text-type-logo" placeholder="ABCD123456" value={joinCode} - onChange={(e) => - setJoinCode(e.target.value.toUpperCase()) - } + onChange={(e) => { + setJoinCode(e.target.value.toUpperCase()); + setValidationError(null); + }} /> + {validationError && ( +

+ {validationError} +

+ )} + {isValidating && ( +
+ + {t("watchParty.validating")} +
+ )}
@@ -357,7 +396,7 @@ export function WatchPartyView({ id }: { id: string }) { className="w-full" theme="purple" onClick={handleJoinParty} - disabled={joinCode.length === 0} + disabled={joinCode.length === 0 || isValidating} > {t("watchParty.join")}