diff --git a/src/components/features/charactersAndCampaigns/GameLog/GameLogEntry.tsx b/src/components/features/charactersAndCampaigns/GameLog/GameLogEntry.tsx index e31bf592..350f332d 100644 --- a/src/components/features/charactersAndCampaigns/GameLog/GameLogEntry.tsx +++ b/src/components/features/charactersAndCampaigns/GameLog/GameLogEntry.tsx @@ -26,7 +26,7 @@ export function GameLogEntry(props: GameLogEntryProps) { ); const logCreatorName = useStore( - (store) => store.users.userMap[log.uid].doc?.displayName + (store) => store.users.userMap[log.uid]?.doc?.displayName ); const isYourEntry = log.characterId diff --git a/src/components/shared/Layout/nav/CustomTokenDialog/CustomTokenDialog.tsx b/src/components/shared/Layout/nav/CustomTokenDialog/CustomTokenDialog.tsx new file mode 100644 index 00000000..e12cecbb --- /dev/null +++ b/src/components/shared/Layout/nav/CustomTokenDialog/CustomTokenDialog.tsx @@ -0,0 +1,54 @@ +import { + Button, + Dialog, + DialogActions, + DialogContent, + TextField, +} from "@mui/material"; +import { DialogTitleWithCloseButton } from "components/shared/DialogTitleWithCloseButton"; +import { loginWithToken } from "lib/auth.lib"; +import { useState } from "react"; + +export interface CustomTokenDialogProps { + open: boolean; + onClose: () => void; +} + +export function CustomTokenDialog(props: CustomTokenDialogProps) { + const { open, onClose } = props; + + const [token, setToken] = useState(""); + const handleLogin = () => { + loginWithToken(token) + .then(() => { + location.reload(); + }) + .catch((error) => { + console.error(error); + }); + }; + + return ( + + + Login with Custom Token + + + setToken(evt.target.value)} + /> + + + + + + + ); +} diff --git a/src/components/shared/Layout/nav/SettingsMenu.tsx b/src/components/shared/Layout/nav/SettingsMenu.tsx index 6c5b8a01..bdcf3012 100644 --- a/src/components/shared/Layout/nav/SettingsMenu.tsx +++ b/src/components/shared/Layout/nav/SettingsMenu.tsx @@ -31,6 +31,8 @@ import { useStore } from "stores/store"; import { AUTH_STATE } from "stores/auth/auth.slice.type"; import { UserNameDialog } from "components/shared/UserNameDialog"; import UsernameIcon from "@mui/icons-material/AccountCircle"; +import TokenIcon from "@mui/icons-material/Contacts"; +import { CustomTokenDialog } from "./CustomTokenDialog/CustomTokenDialog"; export function SettingsMenu() { const [menuOpen, setMenuOpen] = useState(false); @@ -46,6 +48,7 @@ export function SettingsMenu() { const [betaTestsOpen, setBetaTestsOpen] = useState(false); const [usernameDialogOpen, setUsernameDialogOpen] = useState(false); + const [customTokenDialogOpen, setCustomTokenDialogOpen] = useState(false); const isMobile = useIsMobile(); @@ -178,6 +181,14 @@ export function SettingsMenu() { Switch System )} + {isLocal && ( + setCustomTokenDialogOpen(true)}> + + + + Login with Custom Token + + )} setUsernameDialogOpen(false)} updating /> + {isLocal && ( + setCustomTokenDialogOpen(false)} + /> + )} ); } diff --git a/src/lib/auth.lib.ts b/src/lib/auth.lib.ts index 2b8cb4a6..ba4bdd21 100644 --- a/src/lib/auth.lib.ts +++ b/src/lib/auth.lib.ts @@ -3,6 +3,7 @@ import { isSignInWithEmailLink, onAuthStateChanged, sendSignInLinkToEmail, + signInWithCustomToken, signInWithEmailLink, signInWithPopup, signOut, @@ -30,6 +31,19 @@ export function loginWithGoogle() { }); } +export function loginWithToken(token: string) { + return new Promise((resolve, reject) => { + signInWithCustomToken(firebaseAuth, token) + .then(() => { + resolve(true); + }) + .catch((e) => { + console.error(e); + reject(e); + }); + }); +} + export function sendMagicEmailLink( email: string, name?: string