diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go
index 07df8514..462740f5 100644
--- a/bskyweb/cmd/bskyweb/server.go
+++ b/bskyweb/cmd/bskyweb/server.go
@@ -105,6 +105,7 @@ func serve(cctx *cli.Context) error {
// generic routes
e.GET("/search", server.WebGeneric)
+ e.GET("/search/feeds", server.WebGeneric)
e.GET("/notifications", server.WebGeneric)
e.GET("/moderation", server.WebGeneric)
e.GET("/moderation/mute-lists", server.WebGeneric)
diff --git a/package.json b/package.json
index 5c30a0ca..253c3b78 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
"e2e:run": "detox test --configuration ios.sim.debug --take-screenshots all"
},
"dependencies": {
- "@atproto/api": "0.3.7",
+ "@atproto/api": "0.3.8",
"@bam.tech/react-native-image-resizer": "^3.0.4",
"@braintree/sanitize-url": "^6.0.2",
"@expo/webpack-config": "^18.0.1",
diff --git a/src/Navigation.tsx b/src/Navigation.tsx
index ff7a5f5c..0664ac52 100644
--- a/src/Navigation.tsx
+++ b/src/Navigation.tsx
@@ -35,6 +35,7 @@ import {SearchScreen} from './view/screens/Search'
import {NotificationsScreen} from './view/screens/Notifications'
import {ModerationScreen} from './view/screens/Moderation'
import {ModerationMuteListsScreen} from './view/screens/ModerationMuteLists'
+import {DiscoverFeedsScreen} from 'view/screens/DiscoverFeeds'
import {NotFoundScreen} from './view/screens/NotFound'
import {SettingsScreen} from './view/screens/Settings'
import {ProfileScreen} from './view/screens/Profile'
@@ -103,6 +104,11 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
component={ModerationBlockedAccounts}
options={{title: title('Blocked Accounts')}}
/>
+
0
+ }
+
+ get hasError() {
+ return this.error !== ''
+ }
+
+ get isEmpty() {
+ return this.hasLoaded && !this.hasContent
+ }
+
+ // public api
+ // =
+
+ refresh = bundleAsync(async () => {
+ this._xLoading()
+ try {
+ const res =
+ await this.rootStore.agent.app.bsky.unspecced.getPopularFeedGenerators(
+ {},
+ )
+ this._replaceAll(res)
+ this._xIdle()
+ } catch (e: any) {
+ this._xIdle(e)
+ }
+ })
+
+ clear() {
+ this.isLoading = false
+ this.isRefreshing = false
+ this.hasLoaded = false
+ this.error = ''
+ this.feeds = []
+ }
+
+ // state transitions
+ // =
+
+ _xLoading() {
+ this.isLoading = true
+ this.isRefreshing = true
+ this.error = ''
+ }
+
+ _xIdle(err?: any) {
+ this.isLoading = false
+ this.isRefreshing = false
+ this.hasLoaded = true
+ this.error = cleanError(err)
+ if (err) {
+ this.rootStore.log.error('Failed to fetch popular feeds', err)
+ }
+ }
+
+ // helper functions
+ // =
+
+ _replaceAll(res: AppBskyUnspeccedGetPopularFeedGenerators.Response) {
+ this.feeds = []
+ for (const f of res.data.feeds) {
+ this.feeds.push(new CustomFeedModel(this.rootStore, f))
+ }
+ }
+}
diff --git a/src/view/com/feeds/SavedFeeds.tsx b/src/view/com/feeds/SavedFeeds.tsx
index e92e741d..610562c9 100644
--- a/src/view/com/feeds/SavedFeeds.tsx
+++ b/src/view/com/feeds/SavedFeeds.tsx
@@ -53,14 +53,28 @@ export const SavedFeeds = observer(
const renderListFooterComponent = useCallback(() => {
return (
<>
-
-
-
- Change Order
-
-
+
+
+
+
+ Discover new feeds
+
+
+ {!store.me.savedFeeds.isEmpty && (
+
+
+
+ Change Order
+
+
+ )}
+
>
)
- }, [pal])
+ }, [pal, store.me.savedFeeds.isEmpty])
const renderItem = useCallback(
({item}) => ,
@@ -118,14 +132,16 @@ export const SavedFeeds = observer(
)
const styles = StyleSheet.create({
+ footerLinks: {
+ marginTop: 8,
+ borderBottomWidth: 1,
+ },
footerLink: {
flexDirection: 'row',
borderTopWidth: 1,
- borderBottomWidth: 1,
paddingHorizontal: 26,
paddingVertical: 18,
gap: 18,
- marginTop: 8,
},
empty: {
paddingHorizontal: 18,
@@ -134,7 +150,4 @@ const styles = StyleSheet.create({
marginHorizontal: 18,
marginTop: 10,
},
- feedItem: {
- borderTopWidth: 1,
- },
})
diff --git a/src/view/screens/CustomFeed.tsx b/src/view/screens/CustomFeed.tsx
index 0690a17d..49798d75 100644
--- a/src/view/screens/CustomFeed.tsx
+++ b/src/view/screens/CustomFeed.tsx
@@ -220,7 +220,7 @@ export const CustomFeedScreen = withAuthRequired(
)}
{isDesktopWeb && (
-
+