Fix stale me used on switch to anon
This commit is contained in:
parent
d0a47fd304
commit
c610f20773
|
@ -9,9 +9,13 @@ export const MeContext = React.createContext({
|
||||||
|
|
||||||
export function MeProvider ({ me, children }) {
|
export function MeProvider ({ me, children }) {
|
||||||
const { data, refetch } = useQuery(ME, SSR ? {} : { pollInterval: 1000, nextFetchPolicy: 'cache-and-network' })
|
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 (
|
return (
|
||||||
<MeContext.Provider value={{ me: data?.me || me, refetch }}>
|
<MeContext.Provider value={{ me: futureMe, refetch }}>
|
||||||
{children}
|
{children}
|
||||||
</MeContext.Provider>
|
</MeContext.Provider>
|
||||||
)
|
)
|
||||||
|
|
|
@ -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 AnonIcon from '../svgs/spy-fill.svg'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import cookie from 'cookie'
|
import cookie from 'cookie'
|
||||||
|
@ -14,6 +14,7 @@ const b64Decode = str => Buffer.from(str, 'base64').toString('utf-8')
|
||||||
export const AccountProvider = ({ children }) => {
|
export const AccountProvider = ({ children }) => {
|
||||||
const me = useMe()
|
const me = useMe()
|
||||||
const [accounts, setAccounts] = useState([])
|
const [accounts, setAccounts] = useState([])
|
||||||
|
const [isAnon, setIsAnon] = useState(true)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
try {
|
try {
|
||||||
|
@ -35,21 +36,21 @@ export const AccountProvider = ({ children }) => {
|
||||||
setAccounts(accounts => accounts.filter(({ id }) => id !== userId))
|
setAccounts(accounts => accounts.filter(({ id }) => id !== userId))
|
||||||
}, [setAccounts])
|
}, [setAccounts])
|
||||||
|
|
||||||
const isAnon = useMemo(() => {
|
useEffect(() => {
|
||||||
// document not defined on server
|
// document not defined on server
|
||||||
if (SSR) return false
|
if (SSR) return
|
||||||
const { 'multi_auth.user-id': multiAuthUserIdCookie } = cookie.parse(document.cookie)
|
const { 'multi_auth.user-id': multiAuthUserIdCookie } = cookie.parse(document.cookie)
|
||||||
if (!multiAuthUserIdCookie) return false
|
if (!multiAuthUserIdCookie) return false
|
||||||
return multiAuthUserIdCookie === 'anonymous'
|
setIsAnon(multiAuthUserIdCookie === 'anonymous')
|
||||||
}, [accounts])
|
}, [])
|
||||||
|
|
||||||
return <AccountContext.Provider value={{ accounts, addAccount, removeAccount, isAnon }}>{children}</AccountContext.Provider>
|
return <AccountContext.Provider value={{ accounts, addAccount, removeAccount, isAnon, setIsAnon }}>{children}</AccountContext.Provider>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useAccounts = () => useContext(AccountContext)
|
export const useAccounts = () => useContext(AccountContext)
|
||||||
|
|
||||||
const AnonAccount = () => {
|
const AnonAccount = ({ selected, onClick }) => {
|
||||||
const me = useMe()
|
const { isAnon, setIsAnon } = useAccounts()
|
||||||
const refreshMe = useMeRefresh()
|
const refreshMe = useMeRefresh()
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -57,13 +58,15 @@ const AnonAccount = () => {
|
||||||
>
|
>
|
||||||
<AnonIcon
|
<AnonIcon
|
||||||
className='fill-muted'
|
className='fill-muted'
|
||||||
width='135' height='135' style={{ cursor: 'pointer' }} onClick={() => {
|
width='135' height='135' style={{ cursor: 'pointer' }} onClick={async () => {
|
||||||
document.cookie = 'multi_auth.user-id=anonymous'
|
document.cookie = 'multi_auth.user-id=anonymous'
|
||||||
refreshMe()
|
// order is important to prevent flashes of no session
|
||||||
|
setIsAnon(true)
|
||||||
|
await refreshMe()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className='fst-italic'>anonymous</div>
|
<div className='fst-italic'>anonymous</div>
|
||||||
{!me && <div className='text-muted fst-italic'>selected</div>}
|
{isAnon && <div className='text-muted fst-italic'>selected</div>}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -71,15 +74,18 @@ const AnonAccount = () => {
|
||||||
const Account = ({ account, className }) => {
|
const Account = ({ account, className }) => {
|
||||||
const me = useMe()
|
const me = useMe()
|
||||||
const refreshMe = useMeRefresh()
|
const refreshMe = useMeRefresh()
|
||||||
|
const { setIsAnon } = useAccounts()
|
||||||
const src = account.photoId ? `https://${process.env.NEXT_PUBLIC_MEDIA_DOMAIN}/${account.photoId}` : '/dorian400.jpg'
|
const src = account.photoId ? `https://${process.env.NEXT_PUBLIC_MEDIA_DOMAIN}/${account.photoId}` : '/dorian400.jpg'
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className='d-flex flex-column me-2 my-1 text-center'
|
className='d-flex flex-column me-2 my-1 text-center'
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
width='135' height='135' src={src} style={{ cursor: 'pointer' }} onClick={() => {
|
width='135' height='135' src={src} style={{ cursor: 'pointer' }} onClick={async () => {
|
||||||
document.cookie = `multi_auth.user-id=${account.id}`
|
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)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Link href={`/${account.name}`}>@{account.name}</Link>
|
<Link href={`/${account.name}`}>@{account.name}</Link>
|
||||||
|
|
Loading…
Reference in New Issue