Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

Feeds tab fixes (#1486)

* Bold the saved feeds on mobile

* Improve the saved feeds loading state

* Add soft reset handler to feeds page

* Show feed descriptions in profile listing

* Add an 'about this feed' modal

* Fix type assertion

authored by

Paul Frazee and committed by
GitHub
971c8025 753fb8bf

+74 -12
+7 -1
src/state/models/ui/my-feeds.ts
··· 10 10 } 11 11 | { 12 12 _reactKey: string 13 + type: 'saved-feeds-loading' 14 + numItems: number 15 + } 16 + | { 17 + _reactKey: string 13 18 type: 'discover-feeds-loading' 14 19 } 15 20 | { ··· 91 96 if (this.saved.isLoading) { 92 97 items.push({ 93 98 _reactKey: '__saved_feeds_loading__', 94 - type: 'spinner', 99 + type: 'saved-feeds-loading', 100 + numItems: this.rootStore.preferences.savedFeeds.length || 3, 95 101 }) 96 102 } else if (this.saved.hasError) { 97 103 items.push({
+29 -4
src/view/screens/CustomFeed.tsx
··· 185 185 }) 186 186 }, [store, currentFeed]) 187 187 188 + const onPressAbout = React.useCallback(() => { 189 + store.shell.openModal({ 190 + name: 'confirm', 191 + title: currentFeed?.displayName || '', 192 + message: 193 + currentFeed?.data.description || 'This feed has no description.', 194 + confirmBtnText: 'Close', 195 + onPressConfirm() {}, 196 + }) 197 + }, [store, currentFeed]) 198 + 188 199 const onPressViewAuthor = React.useCallback(() => { 189 200 navigation.navigate('Profile', {name: handleOrDid}) 190 201 }, [handleOrDid, navigation]) ··· 233 244 }, [store, onSoftReset, isScreenFocused]) 234 245 235 246 const dropdownItems: DropdownItem[] = React.useMemo(() => { 236 - let items: DropdownItem[] = [ 247 + return [ 248 + currentFeed 249 + ? { 250 + testID: 'feedHeaderDropdownAboutBtn', 251 + label: 'About this feed', 252 + onPress: onPressAbout, 253 + icon: { 254 + ios: { 255 + name: 'info.circle', 256 + }, 257 + android: '', 258 + web: 'info', 259 + }, 260 + } 261 + : undefined, 237 262 { 238 263 testID: 'feedHeaderDropdownViewAuthorBtn', 239 264 label: 'View author', ··· 292 317 web: 'share', 293 318 }, 294 319 }, 295 - ] 296 - return items 320 + ].filter(Boolean) as DropdownItem[] 297 321 }, [ 298 - currentFeed?.isSaved, 322 + currentFeed, 323 + onPressAbout, 299 324 onToggleSaved, 300 325 onPressReport, 301 326 onPressShare,
+35 -6
src/view/screens/Feeds.tsx
··· 16 16 import {s} from 'lib/styles' 17 17 import {SearchInput} from 'view/com/util/forms/SearchInput' 18 18 import {UserAvatar} from 'view/com/util/UserAvatar' 19 - import {FeedFeedLoadingPlaceholder} from 'view/com/util/LoadingPlaceholder' 19 + import { 20 + LoadingPlaceholder, 21 + FeedFeedLoadingPlaceholder, 22 + } from 'view/com/util/LoadingPlaceholder' 20 23 import {ErrorMessage} from 'view/com/util/error/ErrorMessage' 21 24 import debounce from 'lodash.debounce' 22 25 import {Text} from 'view/com/util/text/Text' ··· 42 45 React.useCallback(() => { 43 46 store.shell.setMinimalShellMode(false) 44 47 myFeeds.setup() 45 - }, [store.shell, myFeeds]), 48 + 49 + const softResetSub = store.onScreenSoftReset(() => myFeeds.refresh()) 50 + return () => { 51 + softResetSub.remove() 52 + } 53 + }, [store, myFeeds]), 46 54 ) 47 55 48 56 const onPressCompose = React.useCallback(() => { ··· 119 127 ) 120 128 } 121 129 return <View /> 130 + } else if (item.type === 'saved-feeds-loading') { 131 + return ( 132 + <> 133 + {Array.from(Array(item.numItems)).map((_, i) => ( 134 + <SavedFeedLoadingPlaceholder key={`placeholder-${i}`} /> 135 + ))} 136 + </> 137 + ) 122 138 } else if (item.type === 'saved-feed') { 123 139 return ( 124 140 <SavedFeed ··· 262 278 asAnchor 263 279 anchorNoUnderline> 264 280 <UserAvatar type="algo" size={28} avatar={avatar} /> 265 - <Text 266 - type={isMobile ? 'lg' : 'lg-medium'} 267 - style={[pal.text, s.flex1]} 268 - numberOfLines={1}> 281 + <Text type="lg-medium" style={[pal.text, s.flex1]} numberOfLines={1}> 269 282 {displayName} 270 283 </Text> 271 284 {isMobile && ( ··· 276 289 /> 277 290 )} 278 291 </Link> 292 + ) 293 + } 294 + 295 + function SavedFeedLoadingPlaceholder() { 296 + const pal = usePalette('default') 297 + const {isMobile} = useWebMediaQueries() 298 + return ( 299 + <View 300 + style={[ 301 + pal.border, 302 + styles.savedFeed, 303 + isMobile && styles.savedFeedMobile, 304 + ]}> 305 + <LoadingPlaceholder width={28} height={28} style={{borderRadius: 4}} /> 306 + <LoadingPlaceholder width={140} height={12} /> 307 + </View> 279 308 ) 280 309 } 281 310
+3 -1
src/view/screens/Profile.tsx
··· 187 187 /> 188 188 ) 189 189 } else if (item instanceof CustomFeedModel) { 190 - return <CustomFeed item={item} showSaveBtn showLikes /> 190 + return ( 191 + <CustomFeed item={item} showSaveBtn showLikes showDescription /> 192 + ) 191 193 } 192 194 // if section is posts or posts & replies 193 195 } else {