Bluesky app fork with some witchin' additions 💫 witchsky.app
bluesky fork client

1.115.0 fast follows (#9743)

* Fix caching, fix attributes setting

* Use useCallOnce hook

* Update dismissal handling

* Update copy

authored by

Eric Bailey and committed by
GitHub
3523e7ce 967b3b49

+57 -38
+1 -1
src/analytics/features/index.ts
··· 16 return value != null ? JSON.parse(value) : null 17 }, 18 setItem: async (key, value) => { 19 - CACHE.set(key, JSON.stringify(value)) 20 }, 21 }, 22 })
··· 16 return value != null ? JSON.parse(value) : null 17 }, 18 setItem: async (key, value) => { 19 + CACHE.set(key, value) 20 }, 21 }, 22 })
+7 -4
src/analytics/index.tsx
··· 180 }) { 181 const parentContext = useContext(Context) 182 183 useEffect(() => { 184 feats.setTrackingCallback((experiment, result) => { 185 parentContext.metric('experiment:viewed', { ··· 188 }) 189 }) 190 }, [parentContext.metric]) 191 - 192 - useEffect(() => { 193 - setAttributes(parentContext.metadata) 194 - }, [parentContext.metadata]) 195 196 const childContext = useMemo<AnalyticsContextType>(() => { 197 return {
··· 180 }) { 181 const parentContext = useContext(Context) 182 183 + /** 184 + * Side-effect: we need to synchronously set this during the 185 + * same render cycle. It does not trigger a re-render, it just 186 + * sets properties on the singleton GrowthBook instance. 187 + */ 188 + setAttributes(parentContext.metadata) 189 + 190 useEffect(() => { 191 feats.setTrackingCallback((experiment, result) => { 192 parentContext.metric('experiment:viewed', { ··· 195 }) 196 }) 197 }, [parentContext.metric]) 198 199 const childContext = useMemo<AnalyticsContextType>(() => { 200 return {
+40 -20
src/features/liveEvents/components/DiscoverFeedLiveEventFeedsAndTrendingBanner.tsx
··· 1 import {View} from 'react-native' 2 - import {msg} from '@lingui/macro' 3 import {useLingui} from '@lingui/react' 4 5 import {useTrendingSettings} from '#/state/preferences/trending' 6 import {atoms as a, useLayoutBreakpoints} from '#/alf' 7 import {Button} from '#/components/Button' 8 - import {DotGrid_Stroke2_Corner0_Rounded as EllipsisIcon} from '#/components/icons/DotGrid' 9 import {TrendingInterstitial} from '#/components/interstitials/Trending' 10 import {LiveEventFeedCardWide} from '#/features/liveEvents/components/LiveEventFeedCardWide' 11 - import { 12 - LiveEventFeedOptionsMenu, 13 - useDialogControl, 14 - } from '#/features/liveEvents/components/LiveEventFeedOptionsMenu' 15 import {useUserPreferencedLiveEvents} from '#/features/liveEvents/context' 16 import {type LiveEventFeed} from '#/features/liveEvents/types' 17 18 export function DiscoverFeedLiveEventFeedsAndTrendingBanner() { ··· 38 39 function Inner({feed}: {feed: LiveEventFeed}) { 40 const {_} = useLingui() 41 - const optionsMenuControl = useDialogControl() 42 const layout = feed.layouts.wide 43 44 return ( 45 <> 46 <View style={[a.px_lg, a.pt_md, a.pb_xs]}> ··· 48 <LiveEventFeedCardWide feed={feed} metricContext="discover" /> 49 50 <Button 51 - label={_(msg`Configure live event banner`)} 52 size="tiny" 53 shape="round" 54 style={[a.absolute, a.z_10, {top: 6, right: 6}]} 55 onPress={() => { 56 - optionsMenuControl.open() 57 }}> 58 {({hovered, pressed}) => ( 59 <> ··· 68 }, 69 ]} 70 /> 71 - <EllipsisIcon 72 - size="sm" 73 - fill={layout.textColor} 74 - style={[a.z_20]} 75 - /> 76 </> 77 )} 78 </Button> 79 </View> 80 </View> 81 - 82 - <LiveEventFeedOptionsMenu 83 - feed={feed} 84 - control={optionsMenuControl} 85 - metricContext="discover" 86 - /> 87 </> 88 ) 89 }
··· 1 import {View} from 'react-native' 2 + import {msg, Trans} from '@lingui/macro' 3 import {useLingui} from '@lingui/react' 4 5 import {useTrendingSettings} from '#/state/preferences/trending' 6 import {atoms as a, useLayoutBreakpoints} from '#/alf' 7 import {Button} from '#/components/Button' 8 + import {TimesLarge_Stroke2_Corner0_Rounded as CloseIcon} from '#/components/icons/Times' 9 import {TrendingInterstitial} from '#/components/interstitials/Trending' 10 + import * as Toast from '#/components/Toast' 11 import {LiveEventFeedCardWide} from '#/features/liveEvents/components/LiveEventFeedCardWide' 12 import {useUserPreferencedLiveEvents} from '#/features/liveEvents/context' 13 + import {useUpdateLiveEventPreferences} from '#/features/liveEvents/preferences' 14 import {type LiveEventFeed} from '#/features/liveEvents/types' 15 16 export function DiscoverFeedLiveEventFeedsAndTrendingBanner() { ··· 36 37 function Inner({feed}: {feed: LiveEventFeed}) { 38 const {_} = useLingui() 39 const layout = feed.layouts.wide 40 41 + const {mutate: update, variables} = useUpdateLiveEventPreferences({ 42 + feed, 43 + metricContext: 'discover', 44 + onUpdateSuccess({undoAction}) { 45 + Toast.show( 46 + <Toast.Outer> 47 + <Toast.Icon /> 48 + <Toast.Text> 49 + {undoAction ? ( 50 + <Trans>Live event hidden</Trans> 51 + ) : ( 52 + <Trans>Live event unhidden</Trans> 53 + )} 54 + </Toast.Text> 55 + {undoAction && ( 56 + <Toast.Action 57 + label={_(msg`Undo`)} 58 + onPress={() => { 59 + if (undoAction) { 60 + update(undoAction) 61 + } 62 + }}> 63 + <Trans>Undo</Trans> 64 + </Toast.Action> 65 + )} 66 + </Toast.Outer>, 67 + {type: 'success'}, 68 + ) 69 + }, 70 + }) 71 + 72 + if (variables) return null 73 + 74 return ( 75 <> 76 <View style={[a.px_lg, a.pt_md, a.pb_xs]}> ··· 78 <LiveEventFeedCardWide feed={feed} metricContext="discover" /> 79 80 <Button 81 + label={_(msg`Dismiss live event banner`)} 82 size="tiny" 83 shape="round" 84 style={[a.absolute, a.z_10, {top: 6, right: 6}]} 85 onPress={() => { 86 + update({type: 'hideFeed', id: feed.id}) 87 }}> 88 {({hovered, pressed}) => ( 89 <> ··· 98 }, 99 ]} 100 /> 101 + <CloseIcon size="xs" fill={layout.textColor} style={[a.z_20]} /> 102 </> 103 )} 104 </Button> 105 </View> 106 </View> 107 </> 108 ) 109 }
+4 -4
src/features/liveEvents/components/LiveEventFeedCardCompact.tsx
··· 1 - import {useEffect, useMemo} from 'react' 2 import {View} from 'react-native' 3 import {Image} from 'expo-image' 4 import {LinearGradient} from 'expo-linear-gradient' 5 import {msg} from '@lingui/macro' 6 import {useLingui} from '@lingui/react' 7 8 import {isBskyCustomFeedUrl} from '#/lib/strings/url-helpers' 9 import {atoms as a, utils} from '#/alf' 10 import {Live_Stroke2_Corner0_Rounded as LiveIcon} from '#/components/icons/Live' ··· 39 return '/' 40 }, [feed.url]) 41 42 - useEffect(() => { 43 ax.metric('liveEvents:feedBanner:seen', { 44 feed: feed.url, 45 context: metricContext, 46 }) 47 - // eslint-disable-next-line react-hooks/exhaustive-deps 48 - }, []) 49 50 return ( 51 <Link
··· 1 + import {useMemo} from 'react' 2 import {View} from 'react-native' 3 import {Image} from 'expo-image' 4 import {LinearGradient} from 'expo-linear-gradient' 5 import {msg} from '@lingui/macro' 6 import {useLingui} from '@lingui/react' 7 8 + import {useCallOnce} from '#/lib/once' 9 import {isBskyCustomFeedUrl} from '#/lib/strings/url-helpers' 10 import {atoms as a, utils} from '#/alf' 11 import {Live_Stroke2_Corner0_Rounded as LiveIcon} from '#/components/icons/Live' ··· 40 return '/' 41 }, [feed.url]) 42 43 + useCallOnce(() => { 44 ax.metric('liveEvents:feedBanner:seen', { 45 feed: feed.url, 46 context: metricContext, 47 }) 48 + })() 49 50 return ( 51 <Link
+4 -1
src/lib/hooks/useIsBskyTeam.ts
··· 4 5 export function useIsBskyTeam() { 6 const ax = useAnalytics() 7 - return useMemo(() => ax.features.enabled(ax.features.IsBskyTeam), [ax]) 8 }
··· 4 5 export function useIsBskyTeam() { 6 const ax = useAnalytics() 7 + return useMemo( 8 + () => ax.features.enabled(ax.features.IsBskyTeam), 9 + [ax.features], 10 + ) 11 }
+1 -8
src/screens/Settings/ContentAndMediaSettings.tsx
··· 26 import * as Layout from '#/components/Layout' 27 import {useAnalytics} from '#/analytics' 28 import {IS_NATIVE} from '#/env' 29 - import {LiveEventFeedsSettingsToggle} from '#/features/liveEvents/components/LiveEventFeedsSettingsToggle' 30 31 type Props = NativeStackScreenProps< 32 CommonNavigatorParams, ··· 150 <Toggle.Platform /> 151 </SettingsList.Item> 152 </Toggle.Item> 153 - <LiveEventFeedsSettingsToggle /> 154 <Toggle.Item 155 name="show_trending_videos" 156 label={_(msg`Enable trending videos in your Discover feed`)} ··· 173 </SettingsList.Item> 174 </Toggle.Item> 175 </> 176 - ) : ( 177 - <> 178 - <SettingsList.Divider /> 179 - <LiveEventFeedsSettingsToggle /> 180 - </> 181 - )} 182 </SettingsList.Container> 183 </Layout.Content> 184 </Layout.Screen>
··· 26 import * as Layout from '#/components/Layout' 27 import {useAnalytics} from '#/analytics' 28 import {IS_NATIVE} from '#/env' 29 30 type Props = NativeStackScreenProps< 31 CommonNavigatorParams, ··· 149 <Toggle.Platform /> 150 </SettingsList.Item> 151 </Toggle.Item> 152 <Toggle.Item 153 name="show_trending_videos" 154 label={_(msg`Enable trending videos in your Discover feed`)} ··· 171 </SettingsList.Item> 172 </Toggle.Item> 173 </> 174 + ) : null} 175 </SettingsList.Container> 176 </Layout.Content> 177 </Layout.Screen>