diff --git a/components/header.js b/components/header.js deleted file mode 100644 index 59c4518a..00000000 --- a/components/header.js +++ /dev/null @@ -1,356 +0,0 @@ -import Dropdown from 'react-bootstrap/Dropdown' -import Navbar from 'react-bootstrap/Navbar' -import Nav from 'react-bootstrap/Nav' -import Link from 'next/link' -import styles from './header.module.css' -import { useRouter } from 'next/router' -import Button from 'react-bootstrap/Button' -import Container from 'react-bootstrap/Container' -import Price from './price' -import { useMe } from './me' -import Head from 'next/head' -import { signOut } from 'next-auth/react' -import { useCallback, useEffect } from 'react' -import { randInRange } from '@/lib/rand' -import { abbrNum, msatsToSats } from '@/lib/format' -import NoteIcon from '@/svgs/notification-4-fill.svg' -import { useQuery } from '@apollo/client' -import LightningIcon from '@/svgs/bolt.svg' -import SearchIcon from '@/svgs/search-line.svg' -import BackArrow from '@/svgs/arrow-left-line.svg' -import { BALANCE_LIMIT_MSATS, SSR } from '@/lib/constants' -import { useLightning } from './lightning' -import { HAS_NOTIFICATIONS } from '@/fragments/notifications' -import AnonIcon from '@/svgs/spy-fill.svg' -import Hat from './hat' -import HiddenWalletSummary from './hidden-wallet-summary' -import { clearNotifications } from '@/lib/badge' -import { useServiceWorker } from './serviceworker' -import SubSelect from './sub-select' - -function WalletSummary ({ me }) { - if (!me) return null - if (me.privates?.hideWalletBalance) { - return - } - return `${abbrNum(me.privates?.sats)}` -} - -function Back () { - const router = useRouter() - - return router.asPath !== '/' && - { - if (typeof window.navigation === 'undefined' || window.navigation.canGoBack === undefined || window?.navigation.canGoBack) { - router.back() - } else { - router.push('/') - } - }} - > - - -} - -function NotificationBell () { - const { data } = useQuery(HAS_NOTIFICATIONS, SSR - ? {} - : { - pollInterval: 30000, - nextFetchPolicy: 'cache-and-network', - onCompleted: ({ hasNewNotes }) => { - if (!hasNewNotes) { - clearNotifications() - } - } - }) - - return ( - <> - - - - - - - {data?.hasNewNotes && - - {' '} - } - - - - ) -} - -function NavProfileMenu ({ me, dropNavKey }) { - const { registration: swRegistration, togglePushSubscription } = useServiceWorker() - return ( -
- - - - {`@${me.name}`} - - - - - - profile - {me && !me.bioId && -
- {' '} -
} -
- - - bookmarks - - - wallet - - - satistics - - - - referrals - - -
- - settings - -
- - { - try { - // order is important because we need to be logged in to delete push subscription on server - const pushSubscription = await swRegistration?.pushManager.getSubscription() - if (pushSubscription) { - await togglePushSubscription() - } - } catch (err) { - // don't prevent signout because of an unsubscription error - console.error(err) - } - await signOut({ callbackUrl: '/' }) - }} - >logout - -
-
- {!me.bioId && - - {' '} - } -
- ) -} - -function StackerCorner ({ dropNavKey }) { - const me = useMe() - - const walletLimitReached = me.privates?.sats >= msatsToSats(BALANCE_LIMIT_MSATS) - - return ( -
- - - - - - - - - -
- ) -} - -function LurkerCorner ({ path }) { - const router = useRouter() - const strike = useLightning() - - useEffect(() => { - if (!window.localStorage.getItem('striked')) { - const to = setTimeout(() => { - strike() - window.localStorage.setItem('striked', 'yep') - }, randInRange(3000, 10000)) - return () => clearTimeout(to) - } - }, []) - - const handleLogin = useCallback(async pathname => await router.push({ - pathname, - query: { callbackUrl: window.location.origin + router.asPath } - }), [router]) - - return path !== '/login' && path !== '/signup' && !path.startsWith('/invites') && -
- - -
-} - -const PREPEND_SUBS = ['home'] -const APPEND_SUBS = [{ label: '--------', items: ['create'] }] -function NavItems ({ className, sub: subName, prefix }) { - const sub = subName || 'home' - - return ( - <> - - - - - - hot - - - - - recent - - - {sub !== 'jobs' && - - - top - - } - - ) -} - -function PostItem ({ className, prefix }) { - const me = useMe() - - if (me) { - return ( - - post - - ) - } - - return ( - - post - - ) -} - -export default function Header ({ sub }) { - const router = useRouter() - const path = router.asPath.split('?')[0] - const prefix = sub ? `/~${sub}` : '' - const topNavKey = path.split('/')[sub ? 2 : 1] ?? '' - const dropNavKey = path.split('/').slice(sub ? 2 : 1).join('/') - const me = useMe() - - return ( - - - - - - - - - ) -} - -export function HeaderStatic () { - return ( - - - - - - ) -} diff --git a/components/navigation/common.js b/components/navigation/common.js index 31bc4256..51f57013 100644 --- a/components/navigation/common.js +++ b/components/navigation/common.js @@ -6,10 +6,7 @@ import BackArrow from '../../svgs/arrow-left-line.svg' import { useCallback, useEffect, useState } from 'react' import Price from '../price' import SubSelect from '../sub-select' -import { useQuery } from '@apollo/client' -import { HAS_NOTIFICATIONS } from '../../fragments/notifications' -import { ANON_USER_ID, BALANCE_LIMIT_MSATS, SSR } from '../../lib/constants' -import { clearNotifications } from '../../lib/badge' +import { ANON_USER_ID, BALANCE_LIMIT_MSATS } from '../../lib/constants' import Head from 'next/head' import NoteIcon from '../../svgs/notification-4-fill.svg' import { useMe } from '../me' @@ -24,6 +21,7 @@ import LightningIcon from '../../svgs/bolt.svg' import SearchIcon from '../../svgs/search-line.svg' import classNames from 'classnames' import SnIcon from '@/svgs/sn.svg' +import { useHasNewNotes } from '../use-has-new-notes' export function Brand ({ className }) { return ( @@ -100,7 +98,7 @@ export function BackOrBrand ({ className }) { export function SearchItem ({ prefix, className }) { return ( - + @@ -132,27 +130,17 @@ export function NavSelect ({ sub: subName, className, size }) { } export function NavNotifications ({ className }) { - const { data } = useQuery(HAS_NOTIFICATIONS, SSR - ? {} - : { - pollInterval: 30000, - nextFetchPolicy: 'cache-and-network', - onCompleted: ({ hasNewNotes }) => { - if (!hasNewNotes) { - clearNotifications() - } - } - }) + const hasNewNotes = useHasNewNotes() return ( <> - + - {data?.hasNewNotes && + {hasNewNotes && {' '} } diff --git a/components/use-has-new-notes.js b/components/use-has-new-notes.js new file mode 100644 index 00000000..7ed393f2 --- /dev/null +++ b/components/use-has-new-notes.js @@ -0,0 +1,32 @@ +import { HAS_NOTIFICATIONS } from '@/fragments/notifications' +import { clearNotifications } from '@/lib/badge' +import { SSR } from '@/lib/constants' +import { useQuery } from '@apollo/client' +import React, { useContext } from 'react' + +export const HasNewNotesContext = React.createContext(false) + +export function HasNewNotesProvider ({ me, children }) { + const { data } = useQuery(HAS_NOTIFICATIONS, + SSR + ? {} + : { + pollInterval: 30000, + nextFetchPolicy: 'cache-and-network', + onCompleted: ({ hasNewNotes }) => { + if (!hasNewNotes) { + clearNotifications() + } + } + }) + + return ( + + {children} + + ) +} + +export function useHasNewNotes () { + return useContext(HasNewNotesContext) +} diff --git a/pages/_app.js b/pages/_app.js index 9e1e5d28..2b200f63 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -20,6 +20,7 @@ import { LoggerProvider } from '@/components/logger' import { ChainFeeProvider } from '@/components/chain-fee.js' import { WebLNProvider } from '@/components/webln' import dynamic from 'next/dynamic' +import { HasNewNotesProvider } from '@/components/use-has-new-notes' const PWAPrompt = dynamic(() => import('react-ios-pwa-prompt'), { ssr: false }) @@ -102,28 +103,30 @@ export default function MyApp ({ Component, pageProps: { ...props } }) { - - - - - - - - - - - - {!router?.query?.disablePrompt && } - - - - - - - - - - + + + + + + + + + + + + + {!router?.query?.disablePrompt && } + + + + + + + + + + +