diff --git a/components/me.js b/components/me.js index d79063bb..99cc6a48 100644 --- a/components/me.js +++ b/components/me.js @@ -9,9 +9,13 @@ export const MeContext = React.createContext({ export function MeProvider ({ me, children }) { const { data, refetch } = useQuery(ME, SSR ? {} : { pollInterval: 1000, nextFetchPolicy: 'cache-and-network' }) + // this makes sure that we always use the fetched data if it's null. + // without this, we would always fallback to the `me` object + // which was passed during page load which (visually) breaks switching to anon + const futureMe = data?.me ?? (data?.me === null ? null : me) return ( - + {children} ) diff --git a/components/switch-account.js b/components/switch-account.js index 17050e73..87a1af21 100644 --- a/components/switch-account.js +++ b/components/switch-account.js @@ -1,4 +1,4 @@ -import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react' +import { createContext, useCallback, useContext, useEffect, useState } from 'react' import AnonIcon from '../svgs/spy-fill.svg' import { useRouter } from 'next/router' import cookie from 'cookie' @@ -14,6 +14,7 @@ const b64Decode = str => Buffer.from(str, 'base64').toString('utf-8') export const AccountProvider = ({ children }) => { const me = useMe() const [accounts, setAccounts] = useState([]) + const [isAnon, setIsAnon] = useState(true) useEffect(() => { try { @@ -35,21 +36,21 @@ export const AccountProvider = ({ children }) => { setAccounts(accounts => accounts.filter(({ id }) => id !== userId)) }, [setAccounts]) - const isAnon = useMemo(() => { + useEffect(() => { // document not defined on server - if (SSR) return false + if (SSR) return const { 'multi_auth.user-id': multiAuthUserIdCookie } = cookie.parse(document.cookie) if (!multiAuthUserIdCookie) return false - return multiAuthUserIdCookie === 'anonymous' - }, [accounts]) + setIsAnon(multiAuthUserIdCookie === 'anonymous') + }, []) - return {children} + return {children} } export const useAccounts = () => useContext(AccountContext) -const AnonAccount = () => { - const me = useMe() +const AnonAccount = ({ selected, onClick }) => { + const { isAnon, setIsAnon } = useAccounts() const refreshMe = useMeRefresh() return (
{ > { + width='135' height='135' style={{ cursor: 'pointer' }} onClick={async () => { document.cookie = 'multi_auth.user-id=anonymous' - refreshMe() + // order is important to prevent flashes of no session + setIsAnon(true) + await refreshMe() }} />
anonymous
- {!me &&
selected
} + {isAnon &&
selected
}
) } @@ -71,15 +74,18 @@ const AnonAccount = () => { const Account = ({ account, className }) => { const me = useMe() const refreshMe = useMeRefresh() + const { setIsAnon } = useAccounts() const src = account.photoId ? `https://${process.env.NEXT_PUBLIC_MEDIA_DOMAIN}/${account.photoId}` : '/dorian400.jpg' return (
{ + width='135' height='135' src={src} style={{ cursor: 'pointer' }} onClick={async () => { document.cookie = `multi_auth.user-id=${account.id}` - refreshMe() + await refreshMe() + // order is important to prevent flashes of inconsistent data in switch account dialog + setIsAnon(false) }} /> @{account.name}