117 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			117 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { useRouter } from 'next/router'
 | 
						|
import { Select } from './form'
 | 
						|
import { EXTRA_LONG_POLL_INTERVAL, SSR } from '@/lib/constants'
 | 
						|
import { SUBS } from '@/fragments/subs'
 | 
						|
import { useQuery } from '@apollo/client'
 | 
						|
import { useEffect, useState } from 'react'
 | 
						|
import styles from './sub-select.module.css'
 | 
						|
 | 
						|
export function SubSelectInitial ({ sub }) {
 | 
						|
  const router = useRouter()
 | 
						|
  sub = sub || router.query.sub || 'pick territory'
 | 
						|
 | 
						|
  return {
 | 
						|
    sub
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
const DEFAULT_PREPEND_SUBS = []
 | 
						|
const DEFAULT_APPEND_SUBS = []
 | 
						|
const DEFAULT_FILTER_SUBS = () => true
 | 
						|
 | 
						|
export function useSubs ({ prependSubs = DEFAULT_PREPEND_SUBS, sub, filterSubs = DEFAULT_FILTER_SUBS, appendSubs = DEFAULT_APPEND_SUBS }) {
 | 
						|
  const { data } = useQuery(SUBS, SSR
 | 
						|
    ? {}
 | 
						|
    : {
 | 
						|
        pollInterval: EXTRA_LONG_POLL_INTERVAL,
 | 
						|
        nextFetchPolicy: 'cache-and-network'
 | 
						|
      })
 | 
						|
 | 
						|
  const [subs, setSubs] = useState([
 | 
						|
    ...prependSubs.filter(s => s !== sub),
 | 
						|
    ...(sub ? [sub] : []),
 | 
						|
    ...appendSubs.filter(s => s !== sub)])
 | 
						|
  useEffect(() => {
 | 
						|
    if (!data) return
 | 
						|
    const joined = data.subs.filter(filterSubs).filter(s => !s.meMuteSub).map(s => s.name)
 | 
						|
    const muted = data.subs.filter(filterSubs).filter(s => s.meMuteSub).map(s => s.name)
 | 
						|
    const mutedSection = muted.length ? [{ label: 'muted', items: muted }] : []
 | 
						|
    setSubs([
 | 
						|
      ...prependSubs,
 | 
						|
      ...joined,
 | 
						|
      ...mutedSection,
 | 
						|
      ...appendSubs])
 | 
						|
  }, [data])
 | 
						|
 | 
						|
  return subs
 | 
						|
}
 | 
						|
 | 
						|
export default function SubSelect ({ prependSubs, sub, onChange, size, appendSubs, filterSubs, className, ...props }) {
 | 
						|
  const router = useRouter()
 | 
						|
  const subs = useSubs({ prependSubs, sub, filterSubs, appendSubs })
 | 
						|
  const valueProps = props.noForm
 | 
						|
    ? {
 | 
						|
        value: sub
 | 
						|
      }
 | 
						|
    : {
 | 
						|
        overrideValue: sub
 | 
						|
      }
 | 
						|
 | 
						|
  // If logged out user directly visits a nsfw sub, subs will not contain `sub`, so manually add it
 | 
						|
  // to display the correct sub name in the sub selector
 | 
						|
  const subItems = !sub || subs.find((s) => s === sub) ? subs : [sub].concat(subs)
 | 
						|
 | 
						|
  return (
 | 
						|
    <Select
 | 
						|
      onChange={onChange || ((_, e) => {
 | 
						|
        const sub = ['home', 'pick territory'].includes(e.target.value) ? undefined : e.target.value
 | 
						|
        if (sub === 'create') {
 | 
						|
          router.push('/territory')
 | 
						|
          return
 | 
						|
        }
 | 
						|
 | 
						|
        let asPath
 | 
						|
        // are we currently in a sub (ie not home)
 | 
						|
        if (router.query.sub) {
 | 
						|
          // are we going to a sub or home?
 | 
						|
          const subReplace = sub ? `/~${sub}` : ''
 | 
						|
 | 
						|
          // if we are going to a sub, replace the current sub with the new one
 | 
						|
          asPath = router.asPath.replace(`/~${router.query.sub}`, subReplace)
 | 
						|
          // if we're going to home, just go there directly
 | 
						|
          if (asPath === '') {
 | 
						|
            router.push('/')
 | 
						|
            return
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          // we're currently on the home sub
 | 
						|
          // are we in a sub aware route?
 | 
						|
          if (router.pathname.startsWith('/~')) {
 | 
						|
            // if we are, go to the same path but in the sub
 | 
						|
            asPath = `/~${sub}` + router.asPath
 | 
						|
          } else {
 | 
						|
            // otherwise, just go to the sub
 | 
						|
            router.push(sub ? `/~${sub}` : '/')
 | 
						|
            return
 | 
						|
          }
 | 
						|
        }
 | 
						|
        const query = {
 | 
						|
          ...router.query,
 | 
						|
          sub
 | 
						|
        }
 | 
						|
        delete query.nodata
 | 
						|
        router.push({
 | 
						|
          pathname: router.pathname,
 | 
						|
          query
 | 
						|
        }, asPath)
 | 
						|
      })}
 | 
						|
      name='sub'
 | 
						|
      size='sm'
 | 
						|
      {...valueProps}
 | 
						|
      {...props}
 | 
						|
      className={`${className} ${styles.subSelect} ${size === 'large' ? styles.subSelectLarge : size === 'medium' ? styles.subSelectMedium : ''}`}
 | 
						|
      items={subItems}
 | 
						|
    />
 | 
						|
  )
 | 
						|
}
 |