index.tsx raw

   1  import NoteList, { TNoteListRef } from '@/components/NoteList'
   2  import PostEditor from '@/components/PostEditor'
   3  import Tabs from '@/components/Tabs'
   4  import { isTouchDevice } from '@/lib/utils'
   5  import { useCompose } from '@/providers/ComposeProvider'
   6  import { useKindFilter } from '@/providers/KindFilterProvider'
   7  import { useUserTrust } from '@/providers/UserTrustProvider'
   8  import storage, { dispatchSettingsChanged } from '@/services/local-storage.service'
   9  import { TFeedSubRequest, TNoteListMode } from '@/types'
  10  import { useMemo, useRef, useState } from 'react'
  11  import KindFilter from '../KindFilter'
  12  import { RefreshButton } from '../RefreshButton'
  13  
  14  export default function NormalFeed({
  15    subRequests,
  16    areAlgoRelays = false,
  17    isMainFeed = false,
  18    showRelayCloseReason = false,
  19    enableSocialGraphFilter = false,
  20    onRefresh,
  21    onInitialLoad
  22  }: {
  23    subRequests: TFeedSubRequest[]
  24    areAlgoRelays?: boolean
  25    isMainFeed?: boolean
  26    showRelayCloseReason?: boolean
  27    enableSocialGraphFilter?: boolean
  28    onRefresh?: () => void
  29    onInitialLoad?: () => void
  30  }) {
  31    const { hideUntrustedNotes } = useUserTrust()
  32    const { showKinds } = useKindFilter()
  33    const { composeOpen, closeCompose } = useCompose()
  34    const [temporaryShowKinds, setTemporaryShowKinds] = useState(showKinds)
  35    const [listMode, setListMode] = useState<TNoteListMode>(() => {
  36      const stored = storage.getNoteListMode() as string
  37      // If stored mode was 'posts' or '24h' (legacy), use 'postsAndReplies' instead
  38      return stored === 'posts' || stored === '24h' ? 'postsAndReplies' : stored as TNoteListMode
  39    })
  40    const supportTouch = useMemo(() => isTouchDevice(), [])
  41    const noteListRef = useRef<TNoteListRef>(null)
  42    const topRef = useRef<HTMLDivElement>(null)
  43    const showKindsFilter = useMemo(() => {
  44      return subRequests.every((req) => !req.filter.kinds?.length)
  45    }, [subRequests])
  46  
  47    const handleListModeChange = (mode: TNoteListMode) => {
  48      setListMode(mode)
  49      if (isMainFeed) {
  50        storage.setNoteListMode(mode)
  51        dispatchSettingsChanged()
  52      }
  53      topRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' })
  54    }
  55  
  56    const handleShowKindsChange = (newShowKinds: number[]) => {
  57      setTemporaryShowKinds(newShowKinds)
  58      noteListRef.current?.scrollToTop()
  59    }
  60  
  61    return (
  62      <>
  63        <Tabs
  64          value={listMode}
  65          tabs={[
  66            { value: 'postsAndReplies', label: 'Feed' }
  67          ]}
  68          onTabChange={(listMode) => {
  69            handleListModeChange(listMode as TNoteListMode)
  70          }}
  71          options={
  72            <>
  73              {!supportTouch && (
  74                <RefreshButton
  75                  onClick={() => {
  76                    if (onRefresh) {
  77                      onRefresh()
  78                      return
  79                    }
  80                    noteListRef.current?.refresh()
  81                  }}
  82                />
  83              )}
  84              {showKindsFilter && (
  85                <KindFilter
  86                  showKinds={temporaryShowKinds}
  87                  onShowKindsChange={handleShowKindsChange}
  88                  showSocialGraphFilter={enableSocialGraphFilter}
  89                />
  90              )}
  91            </>
  92          }
  93        />
  94        {composeOpen && (
  95          <PostEditor
  96            inline
  97            open={composeOpen}
  98            setOpen={(v) => { if (!v) closeCompose() }}
  99          />
 100        )}
 101        <div ref={topRef} className="scroll-mt-[calc(6rem+1px)]" />
 102        <NoteList
 103          ref={noteListRef}
 104          showKinds={temporaryShowKinds}
 105          subRequests={subRequests}
 106          hideReplies={listMode === 'posts'}
 107          hideUntrustedNotes={hideUntrustedNotes}
 108          areAlgoRelays={areAlgoRelays}
 109          showRelayCloseReason={showRelayCloseReason}
 110          applySocialGraphFilter={enableSocialGraphFilter}
 111          onInitialLoad={onInitialLoad}
 112        />
 113      </>
 114    )
 115  }
 116