Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[APP-720] Paginate custom feeds (#1030)

* paginate custom feeds

* Fix loading state bug

* DRY code up

authored by

Ansh and committed by
GitHub
bb99a234 bf00d498

+50 -5
+1 -1
package.json
··· 24 24 "e2e:run": "detox test --configuration ios.sim.debug --take-screenshots all" 25 25 }, 26 26 "dependencies": { 27 - "@atproto/api": "^0.3.13", 27 + "@atproto/api": "^0.4.2", 28 28 "@bam.tech/react-native-image-resizer": "^3.0.4", 29 29 "@braintree/sanitize-url": "^6.0.2", 30 30 "@expo/html-elements": "^0.4.2",
+36 -3
src/state/models/discovery/feeds.ts
··· 5 5 import {cleanError} from 'lib/strings/errors' 6 6 import {CustomFeedModel} from '../feeds/custom-feed' 7 7 8 + const DEFAULT_LIMIT = 50 9 + 8 10 export class FeedsDiscoveryModel { 9 11 // state 10 12 isLoading = false 11 13 isRefreshing = false 12 14 hasLoaded = false 13 15 error = '' 16 + loadMoreCursor: string | undefined = undefined 14 17 15 18 // data 16 19 feeds: CustomFeedModel[] = [] ··· 26 29 } 27 30 28 31 get hasMore() { 32 + if (this.loadMoreCursor) { 33 + return true 34 + } 29 35 return false 30 36 } 31 37 ··· 48 54 this._xLoading() 49 55 try { 50 56 const res = 51 - await this.rootStore.agent.app.bsky.unspecced.getPopularFeedGenerators( 52 - {}, 53 - ) 57 + await this.rootStore.agent.app.bsky.unspecced.getPopularFeedGenerators({ 58 + limit: DEFAULT_LIMIT, 59 + }) 54 60 this._replaceAll(res) 55 61 this._xIdle() 56 62 } catch (e: any) { ··· 58 64 } 59 65 }) 60 66 67 + loadMore = bundleAsync(async () => { 68 + if (!this.hasMore) { 69 + return 70 + } 71 + this._xLoading() 72 + try { 73 + const res = 74 + await this.rootStore.agent.app.bsky.unspecced.getPopularFeedGenerators({ 75 + limit: DEFAULT_LIMIT, 76 + cursor: this.loadMoreCursor, 77 + }) 78 + this._append(res) 79 + } catch (e: any) { 80 + this._xIdle(e) 81 + } 82 + this._xIdle() 83 + }) 84 + 61 85 clear() { 62 86 this.isLoading = false 63 87 this.isRefreshing = false ··· 89 113 // = 90 114 91 115 _replaceAll(res: AppBskyUnspeccedGetPopularFeedGenerators.Response) { 116 + // 1. set feeds data to empty array 92 117 this.feeds = [] 118 + // 2. call this._append() 119 + this._append(res) 120 + } 121 + 122 + _append(res: AppBskyUnspeccedGetPopularFeedGenerators.Response) { 123 + // 1. push data into feeds array 93 124 for (const f of res.data.feeds) { 94 125 this.feeds.push(new CustomFeedModel(this.rootStore, f)) 95 126 } 127 + // 2. set loadMoreCursor 128 + this.loadMoreCursor = res.data.cursor 96 129 } 97 130 }
+1
src/view/screens/DiscoverFeeds.tsx
··· 85 85 renderItem={renderItem} 86 86 initialNumToRender={10} 87 87 ListEmptyComponent={renderListEmptyComponent} 88 + onEndReached={() => feeds.loadMore()} 88 89 extraData={feeds.isLoading} 89 90 /> 90 91 </CenteredView>
+12 -1
yarn.lock
··· 29 29 jsonpointer "^5.0.0" 30 30 leven "^3.1.0" 31 31 32 - "@atproto/api@*", "@atproto/api@^0.3.13": 32 + "@atproto/api@*": 33 33 version "0.3.13" 34 34 resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.3.13.tgz#e5ccaa83bb909e662286cdf74a77a76de6562a47" 35 35 integrity sha512-smDlomgipca16G+jKXAZSMfsAmA5wG8WR3Z1dj29ZShVJlhs6+HHdxX7dWVDYEdSeb2rp/wyHN/tQhxGDAkz/g== 36 + dependencies: 37 + "@atproto/common-web" "*" 38 + "@atproto/uri" "*" 39 + "@atproto/xrpc" "*" 40 + tlds "^1.234.0" 41 + typed-emitter "^2.1.0" 42 + 43 + "@atproto/api@^0.4.2": 44 + version "0.4.2" 45 + resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.4.2.tgz#7790eb049f72437e7454c8ecc29a5ef4201c1ade" 46 + integrity sha512-bwaT+kIJp6wpzlHc1Rus3yi29GKlwvYp4wOWAFmcyYT4qH2ZlE6NfElgi6QwdQD285EhiIKYTv7CAMRp/QO7DQ== 36 47 dependencies: 37 48 "@atproto/common-web" "*" 38 49 "@atproto/uri" "*"