Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

Add likes tab (#1227)

* add likes tab

(cherry picked from commit 6c5ffd964ca0b185ddfc37088d82712a006a1163)

* only show Likes tab to authenticated user

(cherry picked from commit ecc1254411d760158b6d7a4c5f05d940db872dfc)

* Bump @atproto/api@0.6.5

* fix types

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>

authored by

Eric Bailey
Paul Frazee
and committed by
GitHub
2b13dc0f 548ec6c8

+62 -30
+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.6.3", 27 + "@atproto/api": "^0.6.5", 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",
+7 -2
src/state/models/feeds/posts.ts
··· 3 3 AppBskyFeedGetTimeline as GetTimeline, 4 4 AppBskyFeedGetAuthorFeed as GetAuthorFeed, 5 5 AppBskyFeedGetFeed as GetCustomFeed, 6 + AppBskyFeedGetActorLikes as GetActorLikes, 6 7 } from '@atproto/api' 7 8 import AwaitLock from 'await-lock' 8 9 import {bundleAsync} from 'lib/async/bundle' ··· 57 58 58 59 constructor( 59 60 public rootStore: RootStoreModel, 60 - public feedType: 'home' | 'author' | 'custom', 61 + public feedType: 'home' | 'author' | 'custom' | 'likes', 61 62 params: QueryParams, 62 63 options?: Options, 63 64 ) { ··· 429 430 res.data.feed = res.data.feed.slice(0, params.limit) 430 431 } 431 432 return res 432 - } else { 433 + } else if (this.feedType === 'author') { 433 434 return this.rootStore.agent.getAuthorFeed( 434 435 params as GetAuthorFeed.QueryParams, 436 + ) 437 + } else { 438 + return this.rootStore.agent.getActorLikes( 439 + params as GetActorLikes.QueryParams, 435 440 ) 436 441 } 437 442 }
+50 -23
src/state/models/ui/profile.ts
··· 9 9 PostsNoReplies = 'Posts', 10 10 PostsWithReplies = 'Posts & replies', 11 11 PostsWithMedia = 'Media', 12 + Likes = 'Likes', 12 13 CustomAlgorithms = 'Feeds', 13 14 Lists = 'Lists', 14 15 } ··· 21 22 static LOADING_ITEM = {_reactKey: '__loading__'} 22 23 static END_ITEM = {_reactKey: '__end__'} 23 24 static EMPTY_ITEM = {_reactKey: '__empty__'} 25 + 26 + isAuthenticatedUser = false 24 27 25 28 // data 26 29 profile: ProfileModel ··· 57 60 if ( 58 61 this.selectedView === Sections.PostsNoReplies || 59 62 this.selectedView === Sections.PostsWithReplies || 60 - this.selectedView === Sections.PostsWithMedia 63 + this.selectedView === Sections.PostsWithMedia || 64 + this.selectedView === Sections.Likes 61 65 ) { 62 66 return this.feed 63 67 } else if (this.selectedView === Sections.Lists) { ··· 83 87 Sections.PostsNoReplies, 84 88 Sections.PostsWithReplies, 85 89 Sections.PostsWithMedia, 86 - ] 90 + this.isAuthenticatedUser && Sections.Likes, 91 + ].filter(Boolean) as string[] 87 92 if (this.algos.hasLoaded && !this.algos.isEmpty) { 88 93 items.push(Sections.CustomAlgorithms) 89 94 } ··· 117 122 if ( 118 123 this.selectedView === Sections.PostsNoReplies || 119 124 this.selectedView === Sections.PostsWithReplies || 120 - this.selectedView === Sections.PostsWithMedia 125 + this.selectedView === Sections.PostsWithMedia || 126 + this.selectedView === Sections.Likes 121 127 ) { 122 128 if (this.feed.hasContent) { 123 129 arr = this.feed.slices.slice() ··· 151 157 if ( 152 158 this.selectedView === Sections.PostsNoReplies || 153 159 this.selectedView === Sections.PostsWithReplies || 154 - this.selectedView === Sections.PostsWithMedia 160 + this.selectedView === Sections.PostsWithMedia || 161 + this.selectedView === Sections.Likes 155 162 ) { 156 163 return this.feed.hasContent && this.feed.hasMore && this.feed.isLoading 157 164 } else if (this.selectedView === Sections.Lists) { ··· 169 176 170 177 this.selectedViewIndex = index 171 178 172 - let filter = 'posts_no_replies' 173 - if (this.selectedView === Sections.PostsWithReplies) { 174 - filter = 'posts_with_replies' 175 - } else if (this.selectedView === Sections.PostsWithMedia) { 176 - filter = 'posts_with_media' 177 - } 179 + if ( 180 + this.selectedView === Sections.PostsNoReplies || 181 + this.selectedView === Sections.PostsWithReplies || 182 + this.selectedView === Sections.PostsWithMedia 183 + ) { 184 + let filter = 'posts_no_replies' 185 + if (this.selectedView === Sections.PostsWithReplies) { 186 + filter = 'posts_with_replies' 187 + } else if (this.selectedView === Sections.PostsWithMedia) { 188 + filter = 'posts_with_media' 189 + } 190 + 191 + this.feed = new PostsFeedModel( 192 + this.rootStore, 193 + 'author', 194 + { 195 + actor: this.params.user, 196 + limit: 10, 197 + filter, 198 + }, 199 + { 200 + isSimpleFeed: ['posts_with_media'].includes(filter), 201 + }, 202 + ) 178 203 179 - this.feed = new PostsFeedModel( 180 - this.rootStore, 181 - 'author', 182 - { 183 - actor: this.params.user, 184 - limit: 10, 185 - filter, 186 - }, 187 - { 188 - isSimpleFeed: ['posts_with_media'].includes(filter), 189 - }, 190 - ) 204 + this.feed.setup() 205 + } else if (this.selectedView === Sections.Likes) { 206 + this.feed = new PostsFeedModel( 207 + this.rootStore, 208 + 'likes', 209 + { 210 + actor: this.params.user, 211 + limit: 10, 212 + }, 213 + { 214 + isSimpleFeed: true, 215 + }, 216 + ) 191 217 192 - if (this.currentView instanceof PostsFeedModel) { 193 218 this.feed.setup() 194 219 } 195 220 } ··· 203 228 .setup() 204 229 .catch(err => this.rootStore.log.error('Failed to fetch feed', err)), 205 230 ]) 231 + this.isAuthenticatedUser = 232 + this.profile.did === this.rootStore.session.currentSession?.did 206 233 this.algos.refresh() 207 234 // HACK: need to use the DID as a param, not the username -prf 208 235 this.lists.source = this.profile.did
+4 -4
yarn.lock
··· 40 40 tlds "^1.234.0" 41 41 typed-emitter "^2.1.0" 42 42 43 - "@atproto/api@^0.6.3": 44 - version "0.6.3" 45 - resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.6.3.tgz#2d604897df9098d84f3dfb3bffe1d4859513b1ba" 46 - integrity sha512-vgwJn6M4wEyMm/oQKSATO3C0iRUZ/u5LTTl3E/MqV1mrWzvWLVhOqlATw7CDhEdzwJciO83ei72re6skhSp+Zg== 43 + "@atproto/api@^0.6.5": 44 + version "0.6.5" 45 + resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.6.5.tgz#496a011b7e8fbf2af32a30cec07a021aa6ef3f4b" 46 + integrity sha512-u6NVkYpdUU5jKGxio2FIRmok0LL+eqqMzihm9LDfydZ4Pi4NqfrOrWw0H1WA7zO3vH9AaxnLSMTwSEAkRRb2FA== 47 47 dependencies: 48 48 "@atproto/common-web" "*" 49 49 "@atproto/uri" "*"