about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/App.native.tsx6
-rw-r--r--src/App.web.tsx6
-rw-r--r--src/components/interstitials/Trending.tsx2
-rw-r--r--src/components/live/GoLiveDialog.tsx21
-rw-r--r--src/components/live/temp.ts41
-rw-r--r--src/lib/actor-status.ts33
-rw-r--r--src/screens/Search/modules/ExploreRecommendations.tsx2
-rw-r--r--src/screens/Search/modules/ExploreTrendingTopics.tsx2
-rw-r--r--src/screens/Settings/ContentAndMediaSettings.tsx2
-rw-r--r--src/state/queries/service-config.ts6
-rw-r--r--src/state/service-config.tsx (renamed from src/state/trending-config.tsx)45
-rw-r--r--src/view/com/posts/PostFeed.tsx12
-rw-r--r--src/view/com/profile/ProfileMenu.tsx5
-rw-r--r--src/view/shell/desktop/SidebarTrendingTopics.tsx2
14 files changed, 111 insertions, 74 deletions
diff --git a/src/App.native.tsx b/src/App.native.tsx
index ea50fdfb9..baab8c838 100644
--- a/src/App.native.tsx
+++ b/src/App.native.tsx
@@ -43,6 +43,7 @@ import {Provider as PrefsStateProvider} from '#/state/preferences'
 import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs'
 import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts'
 import {Provider as UnreadNotifsProvider} from '#/state/queries/notifications/unread'
+import {Provider as ServiceAccountManager} from '#/state/service-config'
 import {
   Provider as SessionProvider,
   type SessionAccount,
@@ -57,7 +58,6 @@ import {Provider as ProgressGuideProvider} from '#/state/shell/progress-guide'
 import {Provider as SelectedFeedProvider} from '#/state/shell/selected-feed'
 import {Provider as StarterPackProvider} from '#/state/shell/starter-pack'
 import {Provider as HiddenRepliesProvider} from '#/state/threadgate-hidden-replies'
-import {Provider as TrendingConfigProvider} from '#/state/trending-config'
 import {TestCtrls} from '#/view/com/testing/TestCtrls'
 import {Provider as VideoVolumeProvider} from '#/view/com/util/post-embeds/VideoVolumeContext'
 import * as Toast from '#/view/com/util/Toast'
@@ -149,7 +149,7 @@ function InnerApp() {
                                         <BackgroundNotificationPreferencesProvider>
                                           <MutedThreadsProvider>
                                             <ProgressGuideProvider>
-                                              <TrendingConfigProvider>
+                                              <ServiceAccountManager>
                                                 <GestureHandlerRootView
                                                   style={s.h100pct}>
                                                   <IntentDialogProvider>
@@ -158,7 +158,7 @@ function InnerApp() {
                                                     <NuxDialogs />
                                                   </IntentDialogProvider>
                                                 </GestureHandlerRootView>
-                                              </TrendingConfigProvider>
+                                              </ServiceAccountManager>
                                             </ProgressGuideProvider>
                                           </MutedThreadsProvider>
                                         </BackgroundNotificationPreferencesProvider>
diff --git a/src/App.web.tsx b/src/App.web.tsx
index bbe23e5a5..c5ec0473c 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -33,6 +33,7 @@ import {Provider as PrefsStateProvider} from '#/state/preferences'
 import {Provider as LabelDefsProvider} from '#/state/preferences/label-defs'
 import {Provider as ModerationOptsProvider} from '#/state/preferences/moderation-opts'
 import {Provider as UnreadNotifsProvider} from '#/state/queries/notifications/unread'
+import {Provider as ServiceConfigProvider} from '#/state/service-config'
 import {
   Provider as SessionProvider,
   type SessionAccount,
@@ -47,7 +48,6 @@ import {Provider as ProgressGuideProvider} from '#/state/shell/progress-guide'
 import {Provider as SelectedFeedProvider} from '#/state/shell/selected-feed'
 import {Provider as StarterPackProvider} from '#/state/shell/starter-pack'
 import {Provider as HiddenRepliesProvider} from '#/state/threadgate-hidden-replies'
-import {Provider as TrendingConfigProvider} from '#/state/trending-config'
 import {Provider as ActiveVideoProvider} from '#/view/com/util/post-embeds/ActiveVideoWebContext'
 import {Provider as VideoVolumeProvider} from '#/view/com/util/post-embeds/VideoVolumeContext'
 import * as Toast from '#/view/com/util/Toast'
@@ -130,12 +130,12 @@ function InnerApp() {
                                           <MutedThreadsProvider>
                                             <SafeAreaProvider>
                                               <ProgressGuideProvider>
-                                                <TrendingConfigProvider>
+                                                <ServiceConfigProvider>
                                                   <IntentDialogProvider>
                                                     <Shell />
                                                     <NuxDialogs />
                                                   </IntentDialogProvider>
-                                                </TrendingConfigProvider>
+                                                </ServiceConfigProvider>
                                               </ProgressGuideProvider>
                                             </SafeAreaProvider>
                                           </MutedThreadsProvider>
diff --git a/src/components/interstitials/Trending.tsx b/src/components/interstitials/Trending.tsx
index 56c756c50..5561be18e 100644
--- a/src/components/interstitials/Trending.tsx
+++ b/src/components/interstitials/Trending.tsx
@@ -9,7 +9,7 @@ import {
   useTrendingSettingsApi,
 } from '#/state/preferences/trending'
 import {useTrendingTopics} from '#/state/queries/trending/useTrendingTopics'
-import {useTrendingConfig} from '#/state/trending-config'
+import {useTrendingConfig} from '#/state/service-config'
 import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
 import {BlockDrawerGesture} from '#/view/shell/BlockDrawerGesture'
 import {atoms as a, useGutters, useTheme} from '#/alf'
diff --git a/src/components/live/GoLiveDialog.tsx b/src/components/live/GoLiveDialog.tsx
index 2fad009fd..027447272 100644
--- a/src/components/live/GoLiveDialog.tsx
+++ b/src/components/live/GoLiveDialog.tsx
@@ -10,7 +10,8 @@ import {cleanError} from '#/lib/strings/errors'
 import {toNiceDomain} from '#/lib/strings/url-helpers'
 import {definitelyUrl} from '#/lib/strings/url-helpers'
 import {useModerationOpts} from '#/state/preferences/moderation-opts'
-import {useAgent} from '#/state/session'
+import {useLiveNowConfig} from '#/state/service-config'
+import {useAgent, useSession} from '#/state/session'
 import {useTickEveryMinute} from '#/state/shell'
 import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
 import {atoms as a, ios, native, platform, useTheme, web} from '#/alf'
@@ -58,6 +59,10 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) {
   const [duration, setDuration] = useState(60)
   const moderationOpts = useModerationOpts()
   const tick = useTickEveryMinute()
+  const liveNowConfig = useLiveNowConfig()
+  const {currentAccount} = useSession()
+
+  const config = liveNowConfig.find(cfg => cfg.did === currentAccount?.did)
 
   const time = useCallback(
     (offset: number) => {
@@ -79,7 +84,6 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) {
 
   const liveLinkUrl = definitelyUrl(liveLink)
   const debouncedUrl = useDebouncedValue(liveLinkUrl, 500)
-  const hasLink = !!debouncedUrl
 
   const {
     data: linkMeta,
@@ -91,6 +95,13 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) {
     queryKey: ['link-meta', debouncedUrl],
     queryFn: async () => {
       if (!debouncedUrl) return null
+      if (!config) throw new Error(_(msg`You are not allowed to go live`))
+
+      const urlp = new URL(debouncedUrl)
+      if (!config.domains.includes(urlp.hostname)) {
+        throw new Error(_(msg`${urlp.hostname} is not a valid URL`))
+      }
+
       return getLinkMeta(agent, debouncedUrl)
     },
   })
@@ -101,6 +112,10 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) {
     error: goLiveError,
   } = useUpsertLiveStatusMutation(duration, linkMeta)
 
+  const isSourceInvalid = !!liveLinkError || !!linkMetaError
+
+  const hasLink = !!debouncedUrl && !isSourceInvalid
+
   return (
     <Dialog.ScrollableInner
       label={_(msg`Go Live`)}
@@ -136,7 +151,7 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) {
             <TextField.LabelText>
               <Trans>Live link</Trans>
             </TextField.LabelText>
-            <TextField.Root isInvalid={!!liveLinkError || !!linkMetaError}>
+            <TextField.Root isInvalid={isSourceInvalid}>
               <TextField.Input
                 label={_(msg`Live link`)}
                 placeholder={_(msg`www.mylivestream.tv`)}
diff --git a/src/components/live/temp.ts b/src/components/live/temp.ts
deleted file mode 100644
index fb26b8c06..000000000
--- a/src/components/live/temp.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import {type AppBskyActorDefs, AppBskyEmbedExternal} from '@atproto/api'
-
-import {DISCOVER_DEBUG_DIDS} from '#/lib/constants'
-import type * as bsky from '#/types/bsky'
-
-export const LIVE_DIDS: Record<string, true> = {
-  'did:plc:7sfnardo5xxznxc6esxc5ooe': true, // nba.com
-  'did:plc:gx6fyi3jcfxd7ammq2t7mzp2': true, // rtgame.bsky.social
-}
-
-export const LIVE_SOURCES: Record<string, true> = {
-  'nba.com': true,
-  'twitch.tv': true,
-}
-
-// TEMP: dumb gating
-export function temp__canBeLive(profile: bsky.profile.AnyProfileView) {
-  if (__DEV__)
-    return !!DISCOVER_DEBUG_DIDS[profile.did] || !!LIVE_DIDS[profile.did]
-  return !!LIVE_DIDS[profile.did]
-}
-
-export function temp__canGoLive(profile: bsky.profile.AnyProfileView) {
-  if (__DEV__) return true
-  return !!LIVE_DIDS[profile.did]
-}
-
-// status must have a embed, and the embed must be an approved host for the status to be valid
-export function temp__isStatusValid(status: AppBskyActorDefs.StatusView) {
-  if (status.status !== 'app.bsky.actor.status#live') return false
-  try {
-    if (AppBskyEmbedExternal.isView(status.embed)) {
-      const url = new URL(status.embed.external.uri)
-      return !!LIVE_SOURCES[url.hostname]
-    } else {
-      return false
-    }
-  } catch {
-    return false
-  }
-}
diff --git a/src/lib/actor-status.ts b/src/lib/actor-status.ts
index 30921a88a..7e023be44 100644
--- a/src/lib/actor-status.ts
+++ b/src/lib/actor-status.ts
@@ -2,27 +2,28 @@ import {useMemo} from 'react'
 import {
   type $Typed,
   type AppBskyActorDefs,
-  type AppBskyEmbedExternal,
+  AppBskyEmbedExternal,
 } from '@atproto/api'
 import {isAfter, parseISO} from 'date-fns'
 
 import {useMaybeProfileShadow} from '#/state/cache/profile-shadow'
+import {useLiveNowConfig} from '#/state/service-config'
 import {useTickEveryMinute} from '#/state/shell'
-import {temp__canBeLive, temp__isStatusValid} from '#/components/live/temp'
 import type * as bsky from '#/types/bsky'
 
 export function useActorStatus(actor?: bsky.profile.AnyProfileView) {
   const shadowed = useMaybeProfileShadow(actor)
   const tick = useTickEveryMinute()
+  const config = useLiveNowConfig()
+
   return useMemo(() => {
     tick! // revalidate every minute
 
     if (
       shadowed &&
-      temp__canBeLive(shadowed) &&
       'status' in shadowed &&
       shadowed.status &&
-      temp__isStatusValid(shadowed.status) &&
+      validateStatus(shadowed.did, shadowed.status, config) &&
       isStatusStillActive(shadowed.status.expiresAt)
     ) {
       return {
@@ -39,7 +40,7 @@ export function useActorStatus(actor?: bsky.profile.AnyProfileView) {
         record: {},
       } satisfies AppBskyActorDefs.StatusView
     }
-  }, [shadowed, tick])
+  }, [shadowed, config, tick])
 }
 
 export function isStatusStillActive(timeStr: string | undefined) {
@@ -49,3 +50,25 @@ export function isStatusStillActive(timeStr: string | undefined) {
 
   return isAfter(expiry, now)
 }
+
+export function validateStatus(
+  did: string,
+  status: AppBskyActorDefs.StatusView,
+  config: {did: string; domains: string[]}[],
+) {
+  if (status.status !== 'app.bsky.actor.status#live') return false
+  const sources = config.find(cfg => cfg.did === did)
+  if (!sources) {
+    return false
+  }
+  try {
+    if (AppBskyEmbedExternal.isView(status.embed)) {
+      const url = new URL(status.embed.external.uri)
+      return sources.domains.includes(url.hostname)
+    } else {
+      return false
+    }
+  } catch {
+    return false
+  }
+}
diff --git a/src/screens/Search/modules/ExploreRecommendations.tsx b/src/screens/Search/modules/ExploreRecommendations.tsx
index 4cf84269a..de70240b1 100644
--- a/src/screens/Search/modules/ExploreRecommendations.tsx
+++ b/src/screens/Search/modules/ExploreRecommendations.tsx
@@ -8,7 +8,7 @@ import {
   DEFAULT_LIMIT as RECOMMENDATIONS_COUNT,
   useTrendingTopics,
 } from '#/state/queries/trending/useTrendingTopics'
-import {useTrendingConfig} from '#/state/trending-config'
+import {useTrendingConfig} from '#/state/service-config'
 import {atoms as a, useGutters, useTheme} from '#/alf'
 import {Hashtag_Stroke2_Corner0_Rounded} from '#/components/icons/Hashtag'
 import {
diff --git a/src/screens/Search/modules/ExploreTrendingTopics.tsx b/src/screens/Search/modules/ExploreTrendingTopics.tsx
index 1d3bc2d86..ee541e385 100644
--- a/src/screens/Search/modules/ExploreTrendingTopics.tsx
+++ b/src/screens/Search/modules/ExploreTrendingTopics.tsx
@@ -8,7 +8,7 @@ import {logger} from '#/logger'
 import {useModerationOpts} from '#/state/preferences/moderation-opts'
 import {useTrendingSettings} from '#/state/preferences/trending'
 import {useGetTrendsQuery} from '#/state/queries/trending/useGetTrendsQuery'
-import {useTrendingConfig} from '#/state/trending-config'
+import {useTrendingConfig} from '#/state/service-config'
 import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
 import {formatCount} from '#/view/com/util/numeric/format'
 import {atoms as a, useGutters, useTheme, type ViewStyleProp, web} from '#/alf'
diff --git a/src/screens/Settings/ContentAndMediaSettings.tsx b/src/screens/Settings/ContentAndMediaSettings.tsx
index 6fa90b1e2..10d5b140b 100644
--- a/src/screens/Settings/ContentAndMediaSettings.tsx
+++ b/src/screens/Settings/ContentAndMediaSettings.tsx
@@ -14,7 +14,7 @@ import {
   useTrendingSettings,
   useTrendingSettingsApi,
 } from '#/state/preferences/trending'
-import {useTrendingConfig} from '#/state/trending-config'
+import {useTrendingConfig} from '#/state/service-config'
 import * as SettingsList from '#/screens/Settings/components/SettingsList'
 import * as Toggle from '#/components/forms/Toggle'
 import {Bubbles_Stroke2_Corner2_Rounded as BubblesIcon} from '#/components/icons/Bubble'
diff --git a/src/state/queries/service-config.ts b/src/state/queries/service-config.ts
index 12d2cc6be..890a49a5c 100644
--- a/src/state/queries/service-config.ts
+++ b/src/state/queries/service-config.ts
@@ -6,6 +6,10 @@ import {useAgent} from '#/state/session'
 type ServiceConfig = {
   checkEmailConfirmed: boolean
   topicsEnabled: boolean
+  liveNow: {
+    did: string
+    domains: string[]
+  }[]
 }
 
 export function useServiceConfigQuery() {
@@ -21,11 +25,13 @@ export function useServiceConfigQuery() {
           checkEmailConfirmed: Boolean(data.checkEmailConfirmed),
           // @ts-expect-error not included in types atm
           topicsEnabled: Boolean(data.topicsEnabled),
+          liveNow: data.liveNow ?? [],
         }
       } catch (e) {
         return {
           checkEmailConfirmed: false,
           topicsEnabled: false,
+          liveNow: [],
         }
       }
     },
diff --git a/src/state/trending-config.tsx b/src/state/service-config.tsx
index 1e5db9dc9..37d5685bd 100644
--- a/src/state/trending-config.tsx
+++ b/src/state/service-config.tsx
@@ -1,21 +1,28 @@
-import React from 'react'
+import {createContext, useContext, useMemo} from 'react'
 
 import {useLanguagePrefs} from '#/state/preferences/languages'
 import {useServiceConfigQuery} from '#/state/queries/service-config'
 import {device} from '#/storage'
 
-type Context = {
+type TrendingContext = {
   enabled: boolean
 }
 
-const Context = React.createContext<Context>({
+type LiveNowContext = {
+  did: string
+  domains: string[]
+}[]
+
+const TrendingContext = createContext<TrendingContext>({
   enabled: false,
 })
 
-export function Provider({children}: React.PropsWithChildren<{}>) {
+const LiveNowContext = createContext<LiveNowContext | null>(null)
+
+export function Provider({children}: {children: React.ReactNode}) {
   const langPrefs = useLanguagePrefs()
   const {data: config, isLoading: isInitialLoad} = useServiceConfigQuery()
-  const ctx = React.useMemo<Context>(() => {
+  const trending = useMemo<TrendingContext>(() => {
     if (__DEV__) {
       return {enabled: true}
     }
@@ -49,9 +56,33 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
 
     return {enabled}
   }, [isInitialLoad, config, langPrefs.contentLanguages])
-  return <Context.Provider value={ctx}>{children}</Context.Provider>
+
+  const liveNow = useMemo<LiveNowContext>(() => config?.liveNow ?? [], [config])
+
+  return (
+    <TrendingContext.Provider value={trending}>
+      <LiveNowContext.Provider value={liveNow}>
+        {children}
+      </LiveNowContext.Provider>
+    </TrendingContext.Provider>
+  )
 }
 
 export function useTrendingConfig() {
-  return React.useContext(Context)
+  return useContext(TrendingContext)
+}
+
+export function useLiveNowConfig() {
+  const ctx = useContext(LiveNowContext)
+  if (!ctx) {
+    throw new Error(
+      'useLiveNowConfig must be used within a LiveNowConfigProvider',
+    )
+  }
+  return ctx
+}
+
+export function useCanGoLive(did?: string) {
+  const config = useLiveNowConfig()
+  return !!config.find(cfg => cfg.did === did)
 }
diff --git a/src/view/com/posts/PostFeed.tsx b/src/view/com/posts/PostFeed.tsx
index b4c2b2710..732d0fcab 100644
--- a/src/view/com/posts/PostFeed.tsx
+++ b/src/view/com/posts/PostFeed.tsx
@@ -19,7 +19,7 @@ import {msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {useQueryClient} from '@tanstack/react-query'
 
-import {isStatusStillActive} from '#/lib/actor-status'
+import {isStatusStillActive, validateStatus} from '#/lib/actor-status'
 import {DISCOVER_FEED_URI, KNOWN_SHUTDOWN_FEEDS} from '#/lib/constants'
 import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
 import {logEvent} from '#/lib/statsig/statsig'
@@ -39,6 +39,7 @@ import {
   RQKEY,
   usePostFeedQuery,
 } from '#/state/queries/post-feed'
+import {useLiveNowConfig} from '#/state/service-config'
 import {useSession} from '#/state/session'
 import {useProgressGuide} from '#/state/shell/progress-guide'
 import {List, type ListRef} from '#/view/com/util/List'
@@ -53,7 +54,6 @@ import {
 } from '#/components/feeds/PostFeedVideoGridRow'
 import {TrendingInterstitial} from '#/components/interstitials/Trending'
 import {TrendingVideos as TrendingVideosInterstitial} from '#/components/interstitials/TrendingVideos'
-import {temp__canBeLive, temp__isStatusValid} from '#/components/live/temp'
 import {DiscoverFallbackHeader} from './DiscoverFallbackHeader'
 import {FeedShutdownMsg} from './FeedShutdownMsg'
 import {PostFeedErrorMessage} from './PostFeedErrorMessage'
@@ -777,16 +777,18 @@ let PostFeed = ({
     )
   }, [isFetchingNextPage, shouldRenderEndOfFeed, renderEndOfFeed, headerOffset])
 
+  const liveNowConfig = useLiveNowConfig()
+
   const seenActorWithStatusRef = useRef<Set<string>>(new Set())
   const onItemSeen = useCallback(
     (item: FeedRow) => {
       feedFeedback.onItemSeen(item)
       if (item.type === 'sliceItem') {
         const actor = item.slice.items[item.indexInSlice].post.author
+
         if (
           actor.status &&
-          temp__canBeLive(actor) &&
-          temp__isStatusValid(actor.status) &&
+          validateStatus(actor.did, actor.status, liveNowConfig) &&
           isStatusStillActive(actor.status.expiresAt)
         ) {
           if (!seenActorWithStatusRef.current.has(actor.did)) {
@@ -799,7 +801,7 @@ let PostFeed = ({
         }
       }
     },
-    [feedFeedback, feed],
+    [feedFeedback, feed, liveNowConfig],
   )
 
   return (
diff --git a/src/view/com/profile/ProfileMenu.tsx b/src/view/com/profile/ProfileMenu.tsx
index 1c2a7d62d..f1fd237ec 100644
--- a/src/view/com/profile/ProfileMenu.tsx
+++ b/src/view/com/profile/ProfileMenu.tsx
@@ -20,6 +20,7 @@ import {
   useProfileFollowMutationQueue,
   useProfileMuteMutationQueue,
 } from '#/state/queries/profile'
+import {useCanGoLive} from '#/state/service-config'
 import {useSession} from '#/state/session'
 import {EventStopper} from '#/view/com/util/EventStopper'
 import * as Toast from '#/view/com/util/Toast'
@@ -43,7 +44,6 @@ import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus
 import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as Unmute} from '#/components/icons/Speaker'
 import {EditLiveDialog} from '#/components/live/EditLiveDialog'
 import {GoLiveDialog} from '#/components/live/GoLiveDialog'
-import {temp__canGoLive} from '#/components/live/temp'
 import * as Menu from '#/components/Menu'
 import {
   ReportDialog,
@@ -73,6 +73,7 @@ let ProfileMenu = ({
   const isLabelerAndNotBlocked = !!profile.associated?.labeler && !isBlocked
   const [devModeEnabled] = useDevMode()
   const verification = useFullVerificationState({profile})
+  const canGoLive = useCanGoLive(currentAccount?.did)
 
   const [queueMute, queueUnmute] = useProfileMuteMutationQueue(profile)
   const [queueBlock, queueUnblock] = useProfileBlockMutationQueue(profile)
@@ -299,7 +300,7 @@ let ProfileMenu = ({
                   </Menu.ItemText>
                   <Menu.ItemIcon icon={List} />
                 </Menu.Item>
-                {isSelf && temp__canGoLive(profile) && (
+                {isSelf && canGoLive && (
                   <Menu.Item
                     testID="profileHeaderDropdownListAddRemoveBtn"
                     label={
diff --git a/src/view/shell/desktop/SidebarTrendingTopics.tsx b/src/view/shell/desktop/SidebarTrendingTopics.tsx
index db9492349..6b49f5834 100644
--- a/src/view/shell/desktop/SidebarTrendingTopics.tsx
+++ b/src/view/shell/desktop/SidebarTrendingTopics.tsx
@@ -9,7 +9,7 @@ import {
   useTrendingSettingsApi,
 } from '#/state/preferences/trending'
 import {useTrendingTopics} from '#/state/queries/trending/useTrendingTopics'
-import {useTrendingConfig} from '#/state/trending-config'
+import {useTrendingConfig} from '#/state/service-config'
 import {atoms as a, useTheme} from '#/alf'
 import {Button, ButtonIcon} from '#/components/Button'
 import {Divider} from '#/components/Divider'