Fix header carousel desync (#1696)
This commit is contained in:
parent
d05a27a6c3
commit
61fb1c445f
|
@ -0,0 +1,46 @@
|
||||||
|
import { createContext, useCallback, useContext, useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'asSats'
|
||||||
|
const DEFAULT_SELECTION = 'fiat'
|
||||||
|
|
||||||
|
const carousel = [
|
||||||
|
'fiat',
|
||||||
|
'yep',
|
||||||
|
'1btc',
|
||||||
|
'blockHeight',
|
||||||
|
'chainFee',
|
||||||
|
'halving'
|
||||||
|
]
|
||||||
|
|
||||||
|
export const CarouselContext = createContext({
|
||||||
|
selection: undefined,
|
||||||
|
handleClick: () => {}
|
||||||
|
})
|
||||||
|
|
||||||
|
export function CarouselProvider ({ children }) {
|
||||||
|
const [selection, setSelection] = useState(undefined)
|
||||||
|
const [pos, setPos] = useState(0)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const selection = window.localStorage.getItem(STORAGE_KEY) ?? DEFAULT_SELECTION
|
||||||
|
setSelection(selection)
|
||||||
|
setPos(carousel.findIndex((item) => item === selection))
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleClick = useCallback(() => {
|
||||||
|
const nextPos = (pos + 1) % carousel.length
|
||||||
|
window.localStorage.setItem(STORAGE_KEY, carousel[nextPos])
|
||||||
|
setSelection(carousel[nextPos])
|
||||||
|
setPos(nextPos)
|
||||||
|
}, [pos])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CarouselContext.Provider value={[selection, handleClick]}>
|
||||||
|
{children}
|
||||||
|
</CarouselContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useCarousel () {
|
||||||
|
return useContext(CarouselContext)
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import { useRouter } from 'next/router'
|
||||||
import DesktopHeader from './desktop/header'
|
import DesktopHeader from './desktop/header'
|
||||||
import MobileHeader from './mobile/header'
|
import MobileHeader from './mobile/header'
|
||||||
import StickyBar from './sticky-bar'
|
import StickyBar from './sticky-bar'
|
||||||
|
import { CarouselProvider } from './carousel'
|
||||||
|
|
||||||
export default function Navigation ({ sub }) {
|
export default function Navigation ({ sub }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
@ -16,10 +17,10 @@ export default function Navigation ({ sub }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<CarouselProvider>
|
||||||
<DesktopHeader {...props} />
|
<DesktopHeader {...props} />
|
||||||
<MobileHeader {...props} />
|
<MobileHeader {...props} />
|
||||||
<StickyBar {...props} />
|
<StickyBar {...props} />
|
||||||
</>
|
</CarouselProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useContext, useEffect, useMemo, useState } from 'react'
|
import React, { useContext, useMemo } from 'react'
|
||||||
import { useQuery } from '@apollo/client'
|
import { useQuery } from '@apollo/client'
|
||||||
import { fixedDecimal } from '@/lib/format'
|
import { fixedDecimal } from '@/lib/format'
|
||||||
import { useMe } from './me'
|
import { useMe } from './me'
|
||||||
|
@ -8,6 +8,7 @@ import { NORMAL_POLL_INTERVAL, SSR } from '@/lib/constants'
|
||||||
import { useBlockHeight } from './block-height'
|
import { useBlockHeight } from './block-height'
|
||||||
import { useChainFee } from './chain-fee'
|
import { useChainFee } from './chain-fee'
|
||||||
import { CompactLongCountdown } from './countdown'
|
import { CompactLongCountdown } from './countdown'
|
||||||
|
import { useCarousel } from './nav/carousel'
|
||||||
|
|
||||||
export const PriceContext = React.createContext({
|
export const PriceContext = React.createContext({
|
||||||
price: null,
|
price: null,
|
||||||
|
@ -43,43 +44,16 @@ export function PriceProvider ({ price, children }) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const STORAGE_KEY = 'asSats'
|
|
||||||
const DEFAULT_SELECTION = 'fiat'
|
|
||||||
|
|
||||||
const carousel = [
|
|
||||||
'fiat',
|
|
||||||
'yep',
|
|
||||||
'1btc',
|
|
||||||
'blockHeight',
|
|
||||||
'chainFee',
|
|
||||||
'halving'
|
|
||||||
]
|
|
||||||
|
|
||||||
export default function Price ({ className }) {
|
export default function Price ({ className }) {
|
||||||
const [asSats, setAsSats] = useState(undefined)
|
const [selection, handleClick] = useCarousel()
|
||||||
const [pos, setPos] = useState(0)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const selection = window.localStorage.getItem(STORAGE_KEY) ?? DEFAULT_SELECTION
|
|
||||||
setAsSats(selection)
|
|
||||||
setPos(carousel.findIndex((item) => item === selection))
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const { price, fiatSymbol } = usePrice()
|
const { price, fiatSymbol } = usePrice()
|
||||||
const { height: blockHeight, halving } = useBlockHeight()
|
const { height: blockHeight, halving } = useBlockHeight()
|
||||||
const { fee: chainFee } = useChainFee()
|
const { fee: chainFee } = useChainFee()
|
||||||
|
|
||||||
const handleClick = () => {
|
|
||||||
const nextPos = (pos + 1) % carousel.length
|
|
||||||
|
|
||||||
window.localStorage.setItem(STORAGE_KEY, carousel[nextPos])
|
|
||||||
setAsSats(carousel[nextPos])
|
|
||||||
setPos(nextPos)
|
|
||||||
}
|
|
||||||
|
|
||||||
const compClassName = (className || '') + ' text-reset pointer'
|
const compClassName = (className || '') + ' text-reset pointer'
|
||||||
|
|
||||||
if (asSats === 'yep') {
|
if (selection === 'yep') {
|
||||||
if (!price || price < 0) return null
|
if (!price || price < 0) return null
|
||||||
return (
|
return (
|
||||||
<div className={compClassName} onClick={handleClick} variant='link'>
|
<div className={compClassName} onClick={handleClick} variant='link'>
|
||||||
|
@ -88,7 +62,7 @@ export default function Price ({ className }) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asSats === '1btc') {
|
if (selection === '1btc') {
|
||||||
return (
|
return (
|
||||||
<div className={compClassName} onClick={handleClick} variant='link'>
|
<div className={compClassName} onClick={handleClick} variant='link'>
|
||||||
1sat=1sat
|
1sat=1sat
|
||||||
|
@ -96,7 +70,7 @@ export default function Price ({ className }) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asSats === 'blockHeight') {
|
if (selection === 'blockHeight') {
|
||||||
if (blockHeight <= 0) return null
|
if (blockHeight <= 0) return null
|
||||||
return (
|
return (
|
||||||
<div className={compClassName} onClick={handleClick} variant='link'>
|
<div className={compClassName} onClick={handleClick} variant='link'>
|
||||||
|
@ -105,7 +79,7 @@ export default function Price ({ className }) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asSats === 'halving') {
|
if (selection === 'halving') {
|
||||||
if (!halving) return null
|
if (!halving) return null
|
||||||
return (
|
return (
|
||||||
<div className={compClassName} onClick={handleClick} variant='link'>
|
<div className={compClassName} onClick={handleClick} variant='link'>
|
||||||
|
@ -114,7 +88,7 @@ export default function Price ({ className }) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asSats === 'chainFee') {
|
if (selection === 'chainFee') {
|
||||||
if (chainFee <= 0) return null
|
if (chainFee <= 0) return null
|
||||||
return (
|
return (
|
||||||
<div className={compClassName} onClick={handleClick} variant='link'>
|
<div className={compClassName} onClick={handleClick} variant='link'>
|
||||||
|
@ -123,7 +97,7 @@ export default function Price ({ className }) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asSats === 'fiat') {
|
if (selection === 'fiat') {
|
||||||
if (!price || price < 0) return null
|
if (!price || price < 0) return null
|
||||||
return (
|
return (
|
||||||
<div className={compClassName} onClick={handleClick} variant='link'>
|
<div className={compClassName} onClick={handleClick} variant='link'>
|
||||||
|
|
Loading…
Reference in New Issue