More prefs cleanup (#1882)

* Update useHomeTabs

* Use queryClient to fetch

* Replace useHomeTabs and useDesktopRightNavItems

* Fix type error

* Some cleanup
zio/stable
Eric Bailey 2023-11-13 12:21:53 -06:00 committed by GitHub
parent 37a2204483
commit c3edde8ac6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 177 additions and 176 deletions

View File

@ -1,51 +0,0 @@
import {useEffect, useState} from 'react'
import {useStores} from 'state/index'
import isEqual from 'lodash.isequal'
import {AtUri} from '@atproto/api'
import {FeedSourceModel} from 'state/models/content/feed-source'
interface RightNavItem {
uri: string
href: string
hostname: string
collection: string
rkey: string
displayName: string
}
export function useDesktopRightNavItems(uris: string[]): RightNavItem[] {
const store = useStores()
const [items, setItems] = useState<RightNavItem[]>([])
const [lastUris, setLastUris] = useState<string[]>([])
useEffect(() => {
if (isEqual(uris, lastUris)) {
// no changes
return
}
async function fetchFeedInfo() {
const models = uris
.slice(0, 25)
.map(uri => new FeedSourceModel(store, uri))
await Promise.all(models.map(m => m.setup()))
setItems(
models.map(model => {
const {hostname, collection, rkey} = new AtUri(model.uri)
return {
uri: model.uri,
href: model.href,
hostname,
collection,
rkey,
displayName: model.displayName,
}
}),
)
setLastUris(uris)
}
fetchFeedInfo()
}, [store, uris, lastUris, setLastUris, setItems])
return items
}

View File

@ -1,29 +0,0 @@
import {useEffect, useState} from 'react'
import {useStores} from 'state/index'
import isEqual from 'lodash.isequal'
import {FeedSourceModel} from 'state/models/content/feed-source'
export function useHomeTabs(uris: string[]): string[] {
const store = useStores()
const [tabs, setTabs] = useState<string[]>(['Following'])
const [lastUris, setLastUris] = useState<string[]>([])
useEffect(() => {
if (isEqual(uris, lastUris)) {
// no changes
return
}
async function fetchFeedInfo() {
const models = uris
.slice(0, 25)
.map(uri => new FeedSourceModel(store, uri))
await Promise.all(models.map(m => m.setup()))
setTabs(['Following'].concat(models.map(f => f.displayName)))
setLastUris(uris)
}
fetchFeedInfo()
}, [store, uris, lastUris, setLastUris, setTabs])
return tabs
}

View File

@ -61,7 +61,7 @@ export class FeedSourceModel {
} }
get isPinned() { get isPinned() {
return this.rootStore.preferences.isPinnedFeed(this.uri) return false
} }
get isLiked() { get isLiked() {

View File

@ -4,7 +4,6 @@ import {
BskyFeedViewPreference, BskyFeedViewPreference,
BskyThreadViewPreference, BskyThreadViewPreference,
} from '@atproto/api' } from '@atproto/api'
import AwaitLock from 'await-lock'
import {isObj, hasProp} from 'lib/type-guards' import {isObj, hasProp} from 'lib/type-guards'
import {RootStoreModel} from '../root-store' import {RootStoreModel} from '../root-store'
import {ModerationOpts} from '@atproto/api' import {ModerationOpts} from '@atproto/api'
@ -33,30 +32,17 @@ export class LabelPreferencesModel {
} }
export class PreferencesModel { export class PreferencesModel {
adultContentEnabled = false
contentLabels = new LabelPreferencesModel() contentLabels = new LabelPreferencesModel()
savedFeeds: string[] = [] savedFeeds: string[] = []
pinnedFeeds: string[] = [] pinnedFeeds: string[] = []
birthDate: Date | undefined = undefined
homeFeed: FeedViewPreference = {
hideReplies: false,
hideRepliesByUnfollowed: false,
hideRepliesByLikeCount: 0,
hideReposts: false,
hideQuotePosts: false,
lab_mergeFeedEnabled: false, // experimental
}
thread: ThreadViewPreference = { thread: ThreadViewPreference = {
sort: 'oldest', sort: 'oldest',
prioritizeFollowedUsers: true, prioritizeFollowedUsers: true,
lab_treeViewEnabled: false, // experimental lab_treeViewEnabled: false, // experimental
} }
// used to linearize async modifications to state
lock = new AwaitLock()
constructor(public rootStore: RootStoreModel) { constructor(public rootStore: RootStoreModel) {
makeAutoObservable(this, {lock: false}, {autoBind: true}) makeAutoObservable(this, {}, {autoBind: true})
} }
serialize() { serialize() {
@ -106,7 +92,7 @@ export class PreferencesModel {
get moderationOpts(): ModerationOpts { get moderationOpts(): ModerationOpts {
return { return {
userDid: this.rootStore.session.currentSession?.did || '', userDid: this.rootStore.session.currentSession?.did || '',
adultContentEnabled: this.adultContentEnabled, adultContentEnabled: false,
labels: { labels: {
// TEMP translate old settings until this UI can be migrated -prf // TEMP translate old settings until this UI can be migrated -prf
porn: tempfixLabelPref(this.contentLabels.nsfw), porn: tempfixLabelPref(this.contentLabels.nsfw),

View File

@ -1,9 +1,11 @@
import React from 'react'
import { import {
useQuery, useQuery,
useInfiniteQuery, useInfiniteQuery,
InfiniteData, InfiniteData,
QueryKey, QueryKey,
useMutation, useMutation,
useQueryClient,
} from '@tanstack/react-query' } from '@tanstack/react-query'
import { import {
AtUri, AtUri,
@ -13,16 +15,22 @@ import {
AppBskyUnspeccedGetPopularFeedGenerators, AppBskyUnspeccedGetPopularFeedGenerators,
} from '@atproto/api' } from '@atproto/api'
import {router} from '#/routes'
import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {sanitizeHandle} from '#/lib/strings/handles' import {sanitizeHandle} from '#/lib/strings/handles'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {usePreferencesQuery} from '#/state/queries/preferences'
type FeedSourceInfo = export type FeedSourceInfo =
| { | {
type: 'feed' type: 'feed'
uri: string uri: string
cid: string route: {
href: string href: string
name: string
params: Record<string, string>
}
cid: string
avatar: string | undefined avatar: string | undefined
displayName: string displayName: string
description: RichText description: RichText
@ -34,8 +42,12 @@ type FeedSourceInfo =
| { | {
type: 'list' type: 'list'
uri: string uri: string
cid: string route: {
href: string href: string
name: string
params: Record<string, string>
}
cid: string
avatar: string | undefined avatar: string | undefined
displayName: string displayName: string
description: RichText description: RichText
@ -43,7 +55,7 @@ type FeedSourceInfo =
creatorHandle: string creatorHandle: string
} }
export const useFeedSourceInfoQueryKey = ({uri}: {uri: string}) => [ export const feedSourceInfoQueryKey = ({uri}: {uri: string}) => [
'getFeedSourceInfo', 'getFeedSourceInfo',
uri, uri,
] ]
@ -53,19 +65,24 @@ const feedSourceNSIDs = {
list: 'app.bsky.graph.list', list: 'app.bsky.graph.list',
} }
function hydrateFeedGenerator( export function hydrateFeedGenerator(
view: AppBskyFeedDefs.GeneratorView, view: AppBskyFeedDefs.GeneratorView,
): FeedSourceInfo { ): FeedSourceInfo {
const urip = new AtUri(view.uri) const urip = new AtUri(view.uri)
const collection = const collection =
urip.collection === 'app.bsky.feed.generator' ? 'feed' : 'lists' urip.collection === 'app.bsky.feed.generator' ? 'feed' : 'lists'
const href = `/profile/${urip.hostname}/${collection}/${urip.rkey}` const href = `/profile/${urip.hostname}/${collection}/${urip.rkey}`
const route = router.matchPath(href)
return { return {
type: 'feed', type: 'feed',
uri: view.uri, uri: view.uri,
cid: view.cid, cid: view.cid,
route: {
href, href,
name: route[0],
params: route[1],
},
avatar: view.avatar, avatar: view.avatar,
displayName: view.displayName displayName: view.displayName
? sanitizeDisplayName(view.displayName) ? sanitizeDisplayName(view.displayName)
@ -81,17 +98,22 @@ function hydrateFeedGenerator(
} }
} }
function hydrateList(view: AppBskyGraphDefs.ListView): FeedSourceInfo { export function hydrateList(view: AppBskyGraphDefs.ListView): FeedSourceInfo {
const urip = new AtUri(view.uri) const urip = new AtUri(view.uri)
const collection = const collection =
urip.collection === 'app.bsky.feed.generator' ? 'feed' : 'lists' urip.collection === 'app.bsky.feed.generator' ? 'feed' : 'lists'
const href = `/profile/${urip.hostname}/${collection}/${urip.rkey}` const href = `/profile/${urip.hostname}/${collection}/${urip.rkey}`
const route = router.matchPath(href)
return { return {
type: 'list', type: 'list',
uri: view.uri, uri: view.uri,
cid: view.cid, route: {
href, href,
name: route[0],
params: route[1],
},
cid: view.cid,
avatar: view.avatar, avatar: view.avatar,
description: new RichText({ description: new RichText({
text: view.description || '', text: view.description || '',
@ -105,13 +127,17 @@ function hydrateList(view: AppBskyGraphDefs.ListView): FeedSourceInfo {
} }
} }
export function getFeedTypeFromUri(uri: string) {
const {pathname} = new AtUri(uri)
return pathname.includes(feedSourceNSIDs.feed) ? 'feed' : 'list'
}
export function useFeedSourceInfoQuery({uri}: {uri: string}) { export function useFeedSourceInfoQuery({uri}: {uri: string}) {
const {agent} = useSession() const {agent} = useSession()
const {pathname} = new AtUri(uri) const type = getFeedTypeFromUri(uri)
const type = pathname.includes(feedSourceNSIDs.feed) ? 'feed' : 'list'
return useQuery({ return useQuery({
queryKey: useFeedSourceInfoQueryKey({uri}), queryKey: feedSourceInfoQueryKey({uri}),
queryFn: async () => { queryFn: async () => {
let view: FeedSourceInfo let view: FeedSourceInfo
@ -170,3 +196,87 @@ export function useSearchPopularFeedsMutation() {
}, },
}) })
} }
const FOLLOWING_FEED_STUB: FeedSourceInfo = {
type: 'feed',
displayName: 'Following',
uri: '',
route: {
href: '/',
name: 'Home',
params: {},
},
cid: '',
avatar: '',
description: new RichText({text: ''}),
creatorDid: '',
creatorHandle: '',
likeCount: 0,
likeUri: '',
}
export function usePinnedFeedsInfos(): FeedSourceInfo[] {
const {agent} = useSession()
const queryClient = useQueryClient()
const [tabs, setTabs] = React.useState<FeedSourceInfo[]>([
FOLLOWING_FEED_STUB,
])
const {data: preferences} = usePreferencesQuery()
const pinnedFeedsKey = JSON.stringify(preferences?.feeds?.pinned)
React.useEffect(() => {
if (!preferences?.feeds?.pinned) return
const uris = preferences.feeds.pinned
async function fetchFeedInfo() {
const reqs = []
for (const uri of uris) {
const cached = queryClient.getQueryData<FeedSourceInfo>(
feedSourceInfoQueryKey({uri}),
)
if (cached) {
reqs.push(cached)
} else {
reqs.push(
queryClient.fetchQuery({
queryKey: feedSourceInfoQueryKey({uri}),
queryFn: async () => {
const type = getFeedTypeFromUri(uri)
if (type === 'feed') {
const res = await agent.app.bsky.feed.getFeedGenerator({
feed: uri,
})
return hydrateFeedGenerator(res.data.view)
} else {
const res = await agent.app.bsky.graph.getList({
list: uri,
limit: 1,
})
return hydrateList(res.data.list)
}
},
}),
)
}
}
const views = await Promise.all(reqs)
setTabs([FOLLOWING_FEED_STUB].concat(views))
}
fetchFeedInfo()
}, [
agent,
queryClient,
setTabs,
preferences?.feeds?.pinned,
// ensure we react to re-ordering
pinnedFeedsKey,
])
return tabs
}

View File

@ -2,6 +2,7 @@ import {
BskyPreferences, BskyPreferences,
LabelPreference, LabelPreference,
BskyThreadViewPreference, BskyThreadViewPreference,
BskyFeedViewPreference,
} from '@atproto/api' } from '@atproto/api'
export type ConfigurableLabelGroup = export type ConfigurableLabelGroup =
@ -29,7 +30,9 @@ export type UsePreferencesQueryResponse = Omit<
* we clean up the data in `usePreferencesQuery`. * we clean up the data in `usePreferencesQuery`.
*/ */
contentLabels: Record<ConfigurableLabelGroup, LabelPreference> contentLabels: Record<ConfigurableLabelGroup, LabelPreference>
feedViewPrefs: BskyPreferences['feedViewPrefs']['home'] feedViewPrefs: BskyFeedViewPreference & {
lab_mergeFeedEnabled: boolean
}
/** /**
* User thread-view prefs, including newer fields that may not be typed yet. * User thread-view prefs, including newer fields that may not be typed yet.
*/ */

View File

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import {BskyPreferences, LabelPreference} from '@atproto/api' import {LabelPreference} from '@atproto/api'
import {StyleSheet, Pressable, View} from 'react-native' import {StyleSheet, Pressable, View} from 'react-native'
import LinearGradient from 'react-native-linear-gradient' import LinearGradient from 'react-native-linear-gradient'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
@ -23,6 +23,7 @@ import {
usePreferencesSetAdultContentMutation, usePreferencesSetAdultContentMutation,
ConfigurableLabelGroup, ConfigurableLabelGroup,
CONFIGURABLE_LABEL_GROUPS, CONFIGURABLE_LABEL_GROUPS,
UsePreferencesQueryResponse,
} from '#/state/queries/preferences' } from '#/state/queries/preferences'
export const snapPoints = ['90%'] export const snapPoints = ['90%']
@ -175,7 +176,7 @@ const ContentLabelPref = observer(function ContentLabelPrefImpl({
labelGroup, labelGroup,
disabled, disabled,
}: { }: {
preferences?: BskyPreferences preferences?: UsePreferencesQueryResponse
labelGroup: ConfigurableLabelGroup labelGroup: ConfigurableLabelGroup
disabled?: boolean disabled?: boolean
}) { }) {

View File

@ -4,13 +4,12 @@ import Animated from 'react-native-reanimated'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import {TabBar} from 'view/com/pager/TabBar' import {TabBar} from 'view/com/pager/TabBar'
import {RenderTabBarFnProps} from 'view/com/pager/Pager' import {RenderTabBarFnProps} from 'view/com/pager/Pager'
import {useStores} from 'state/index'
import {useHomeTabs} from 'lib/hooks/useHomeTabs'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {FeedsTabBar as FeedsTabBarMobile} from './FeedsTabBarMobile' import {FeedsTabBar as FeedsTabBarMobile} from './FeedsTabBarMobile'
import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode' import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
import {useShellLayout} from '#/state/shell/shell-layout' import {useShellLayout} from '#/state/shell/shell-layout'
import {usePinnedFeedsInfos} from '#/state/queries/feed'
export const FeedsTabBar = observer(function FeedsTabBarImpl( export const FeedsTabBar = observer(function FeedsTabBarImpl(
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void}, props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
@ -28,11 +27,11 @@ export const FeedsTabBar = observer(function FeedsTabBarImpl(
const FeedsTabBarTablet = observer(function FeedsTabBarTabletImpl( const FeedsTabBarTablet = observer(function FeedsTabBarTabletImpl(
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void}, props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
) { ) {
const store = useStores() const feeds = usePinnedFeedsInfos()
const items = useHomeTabs(store.preferences.pinnedFeeds)
const pal = usePalette('default') const pal = usePalette('default')
const {headerMinimalShellTransform} = useMinimalShellMode() const {headerMinimalShellTransform} = useMinimalShellMode()
const {headerHeight} = useShellLayout() const {headerHeight} = useShellLayout()
const items = feeds.map(f => f.displayName)
return ( return (
// @ts-ignore the type signature for transform wrong here, translateX and translateY need to be in separate objects -prf // @ts-ignore the type signature for transform wrong here, translateX and translateY need to be in separate objects -prf

View File

@ -3,8 +3,6 @@ import {StyleSheet, TouchableOpacity, View} from 'react-native'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import {TabBar} from 'view/com/pager/TabBar' import {TabBar} from 'view/com/pager/TabBar'
import {RenderTabBarFnProps} from 'view/com/pager/Pager' import {RenderTabBarFnProps} from 'view/com/pager/Pager'
import {useStores} from 'state/index'
import {useHomeTabs} from 'lib/hooks/useHomeTabs'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle' import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
import {Link} from '../util/Link' import {Link} from '../util/Link'
@ -20,19 +18,20 @@ import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
import {useSetDrawerOpen} from '#/state/shell/drawer-open' import {useSetDrawerOpen} from '#/state/shell/drawer-open'
import {useShellLayout} from '#/state/shell/shell-layout' import {useShellLayout} from '#/state/shell/shell-layout'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {usePinnedFeedsInfos} from '#/state/queries/feed'
export const FeedsTabBar = observer(function FeedsTabBarImpl( export const FeedsTabBar = observer(function FeedsTabBarImpl(
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void}, props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
) { ) {
const pal = usePalette('default') const pal = usePalette('default')
const store = useStores()
const {isSandbox} = useSession() const {isSandbox} = useSession()
const {_} = useLingui() const {_} = useLingui()
const setDrawerOpen = useSetDrawerOpen() const setDrawerOpen = useSetDrawerOpen()
const items = useHomeTabs(store.preferences.pinnedFeeds) const feeds = usePinnedFeedsInfos()
const brandBlue = useColorSchemeStyle(s.brandBlue, s.blue3) const brandBlue = useColorSchemeStyle(s.brandBlue, s.blue3)
const {headerHeight} = useShellLayout() const {headerHeight} = useShellLayout()
const {headerMinimalShellTransform} = useMinimalShellMode() const {headerMinimalShellTransform} = useMinimalShellMode()
const items = feeds.map(f => f.displayName)
const onPressAvi = React.useCallback(() => { const onPressAvi = React.useCallback(() => {
setDrawerOpen(true) setDrawerOpen(true)

View File

@ -508,7 +508,7 @@ function SavedFeed({feedUri}: {feedUri: string}) {
return ( return (
<Link <Link
testID={`saved-feed-${info.displayName}`} testID={`saved-feed-${info.displayName}`}
href={info.href} href={info.route.href}
style={[pal.border, styles.savedFeed, isMobile && styles.savedFeedMobile]} style={[pal.border, styles.savedFeed, isMobile && styles.savedFeedMobile]}
hoverStyle={pal.viewLight} hoverStyle={pal.viewLight}
accessibilityLabel={info.displayName} accessibilityLabel={info.displayName}

View File

@ -1,7 +1,6 @@
import React from 'react' import React from 'react'
import {useFocusEffect} from '@react-navigation/native' import {useFocusEffect} from '@react-navigation/native'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import isEqual from 'lodash.isequal'
import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types' import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types'
import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed' import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
import {withAuthRequired} from 'view/com/auth/withAuthRequired' import {withAuthRequired} from 'view/com/auth/withAuthRequired'
@ -13,6 +12,7 @@ import {Pager, PagerRef, RenderTabBarFnProps} from 'view/com/pager/Pager'
import {useStores} from 'state/index' import {useStores} from 'state/index'
import {FeedPage} from 'view/com/feeds/FeedPage' import {FeedPage} from 'view/com/feeds/FeedPage'
import {useSetMinimalShellMode, useSetDrawerSwipeDisabled} from '#/state/shell' import {useSetMinimalShellMode, useSetDrawerSwipeDisabled} from '#/state/shell'
import {usePreferencesQuery} from '#/state/queries/preferences'
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'> type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
export const HomeScreen = withAuthRequired( export const HomeScreen = withAuthRequired(
@ -23,19 +23,15 @@ export const HomeScreen = withAuthRequired(
const pagerRef = React.useRef<PagerRef>(null) const pagerRef = React.useRef<PagerRef>(null)
const [selectedPage, setSelectedPage] = React.useState(0) const [selectedPage, setSelectedPage] = React.useState(0)
const [customFeeds, setCustomFeeds] = React.useState<FeedDescriptor[]>([]) const [customFeeds, setCustomFeeds] = React.useState<FeedDescriptor[]>([])
const [requestedCustomFeeds, setRequestedCustomFeeds] = React.useState< const {data: preferences} = usePreferencesQuery()
string[]
>([])
React.useEffect(() => { React.useEffect(() => {
const pinned = store.preferences.pinnedFeeds if (!preferences?.feeds?.pinned) return
if (isEqual(pinned, requestedCustomFeeds)) { const pinned = preferences.feeds.pinned
// no changes
return
}
const feeds: FeedDescriptor[] = [] const feeds: FeedDescriptor[] = []
for (const uri of pinned) { for (const uri of pinned) {
if (uri.includes('app.bsky.feed.generator')) { if (uri.includes('app.bsky.feed.generator')) {
feeds.push(`feedgen|${uri}`) feeds.push(`feedgen|${uri}`)
@ -43,31 +39,20 @@ export const HomeScreen = withAuthRequired(
feeds.push(`list|${uri}`) feeds.push(`list|${uri}`)
} }
} }
pagerRef.current?.setPage(0)
setCustomFeeds(feeds) setCustomFeeds(feeds)
setRequestedCustomFeeds(pinned)
}, [ pagerRef.current?.setPage(0)
store, }, [preferences?.feeds?.pinned, setCustomFeeds, pagerRef])
store.preferences.pinnedFeeds,
customFeeds,
setCustomFeeds,
pagerRef,
requestedCustomFeeds,
setRequestedCustomFeeds,
])
const homeFeedParams = React.useMemo<FeedParams>(() => { const homeFeedParams = React.useMemo<FeedParams>(() => {
if (!store.preferences.homeFeed.lab_mergeFeedEnabled) { if (!preferences) return {}
return {}
}
return { return {
mergeFeedEnabled: true, mergeFeedEnabled: preferences.feedViewPrefs.lab_mergeFeedEnabled,
mergeFeedSources: store.preferences.savedFeeds, mergeFeedSources: preferences.feeds.saved,
} }
}, [ }, [preferences])
store.preferences.homeFeed.lab_mergeFeedEnabled,
store.preferences.savedFeeds,
])
useFocusEffect( useFocusEffect(
React.useCallback(() => { React.useCallback(() => {

View File

@ -2,16 +2,14 @@ import React from 'react'
import {View, StyleSheet} from 'react-native' import {View, StyleSheet} from 'react-native'
import {useNavigationState} from '@react-navigation/native' import {useNavigationState} from '@react-navigation/native'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import {useStores} from 'state/index'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {useDesktopRightNavItems} from 'lib/hooks/useDesktopRightNavItems'
import {TextLink} from 'view/com/util/Link' import {TextLink} from 'view/com/util/Link'
import {getCurrentRoute} from 'lib/routes/helpers' import {getCurrentRoute} from 'lib/routes/helpers'
import {usePinnedFeedsInfos} from '#/state/queries/feed'
export const DesktopFeeds = observer(function DesktopFeeds() { export const DesktopFeeds = observer(function DesktopFeeds() {
const store = useStores()
const pal = usePalette('default') const pal = usePalette('default')
const items = useDesktopRightNavItems(store.preferences.pinnedFeeds) const feeds = usePinnedFeedsInfos()
const route = useNavigationState(state => { const route = useNavigationState(state => {
if (!state) { if (!state) {
@ -23,22 +21,22 @@ export const DesktopFeeds = observer(function DesktopFeeds() {
return ( return (
<View style={[styles.container, pal.view, pal.border]}> <View style={[styles.container, pal.view, pal.border]}>
<FeedItem href="/" title="Following" current={route.name === 'Home'} /> <FeedItem href="/" title="Following" current={route.name === 'Home'} />
{items.map(item => { {feeds
.filter(f => f.displayName !== 'Following')
.map(feed => {
try { try {
const params = route.params as Record<string, string> const params = route.params as Record<string, string>
const routeName = const routeName =
item.collection === 'app.bsky.feed.generator' feed.type === 'feed' ? 'ProfileFeed' : 'ProfileList'
? 'ProfileFeed'
: 'ProfileList'
return ( return (
<FeedItem <FeedItem
key={item.uri} key={feed.uri}
href={item.href} href={feed.route.href}
title={item.displayName} title={feed.displayName}
current={ current={
route.name === routeName && route.name === routeName &&
params.name === item.hostname && params.name === feed.route.params.name &&
params.rkey === item.rkey params.rkey === feed.route.params.rkey
} }
/> />
) )