[APP-511] metrics overhaul: frontend work (#506)
* WIP * fix types and update imports * wip * tagged events that should be server side * remove server-side analytics * remove useless import * add additional profile header events * remove useless import * track follow/unfollow clicks * add missing typeszio/stable
parent
1695ae34db
commit
17e7590bcd
|
@ -13,7 +13,7 @@ import * as view from './view/index'
|
||||||
import {RootStoreModel, setupState, RootStoreProvider} from './state'
|
import {RootStoreModel, setupState, RootStoreProvider} from './state'
|
||||||
import {Shell} from './view/shell'
|
import {Shell} from './view/shell'
|
||||||
import * as notifee from 'lib/notifee'
|
import * as notifee from 'lib/notifee'
|
||||||
import * as analytics from 'lib/analytics'
|
import * as analytics from 'lib/analytics/analytics'
|
||||||
import * as Toast from './view/com/util/Toast'
|
import * as Toast from './view/com/util/Toast'
|
||||||
import {handleLink} from './Navigation'
|
import {handleLink} from './Navigation'
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'lib/sentry' // must be relatively on top
|
||||||
import {SafeAreaProvider} from 'react-native-safe-area-context'
|
import {SafeAreaProvider} from 'react-native-safe-area-context'
|
||||||
import {RootSiblingParent} from 'react-native-root-siblings'
|
import {RootSiblingParent} from 'react-native-root-siblings'
|
||||||
import * as view from './view/index'
|
import * as view from './view/index'
|
||||||
import * as analytics from 'lib/analytics'
|
import * as analytics from 'lib/analytics/analytics'
|
||||||
import {RootStoreModel, setupState, RootStoreProvider} from './state'
|
import {RootStoreModel, setupState, RootStoreProvider} from './state'
|
||||||
import {Shell} from './view/shell/index'
|
import {Shell} from './view/shell/index'
|
||||||
import {ToastContainer} from './view/com/util/Toast.web'
|
import {ToastContainer} from './view/com/util/Toast.web'
|
||||||
|
|
|
@ -4,10 +4,12 @@ import {
|
||||||
createClient,
|
createClient,
|
||||||
AnalyticsProvider,
|
AnalyticsProvider,
|
||||||
useAnalytics as useAnalyticsOrig,
|
useAnalytics as useAnalyticsOrig,
|
||||||
|
ClientMethods,
|
||||||
} from '@segment/analytics-react-native'
|
} from '@segment/analytics-react-native'
|
||||||
import {RootStoreModel, AppInfo} from 'state/models/root-store'
|
import {RootStoreModel, AppInfo} from 'state/models/root-store'
|
||||||
import {useStores} from 'state/models/root-store'
|
import {useStores} from 'state/models/root-store'
|
||||||
import {sha256} from 'js-sha256'
|
import {sha256} from 'js-sha256'
|
||||||
|
import {ScreenEvent, TrackEvent} from './types'
|
||||||
|
|
||||||
const segmentClient = createClient({
|
const segmentClient = createClient({
|
||||||
writeKey: '8I6DsgfiSLuoONyaunGoiQM7A6y2ybdI',
|
writeKey: '8I6DsgfiSLuoONyaunGoiQM7A6y2ybdI',
|
||||||
|
@ -16,20 +18,28 @@ const segmentClient = createClient({
|
||||||
|
|
||||||
export function useAnalytics() {
|
export function useAnalytics() {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const methods = useAnalyticsOrig()
|
const methods: ClientMethods = useAnalyticsOrig()
|
||||||
return React.useMemo(() => {
|
return React.useMemo(() => {
|
||||||
if (store.session.hasSession) {
|
if (store.session.hasSession) {
|
||||||
return methods
|
return {
|
||||||
|
screen: methods.screen as ScreenEvent, // ScreenEvents defines all the possible screen names
|
||||||
|
track: methods.track as TrackEvent, // TrackEvents defines all the possible track events and their properties
|
||||||
|
identify: methods.identify,
|
||||||
|
flush: methods.flush,
|
||||||
|
group: methods.group,
|
||||||
|
alias: methods.alias,
|
||||||
|
reset: methods.reset,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// dont send analytics pings for anonymous users
|
// dont send analytics pings for anonymous users
|
||||||
return {
|
return {
|
||||||
screen: () => {},
|
screen: () => Promise<void>,
|
||||||
track: () => {},
|
track: () => Promise<void>,
|
||||||
identify: () => {},
|
identify: () => Promise<void>,
|
||||||
flush: () => {},
|
flush: () => Promise<void>,
|
||||||
group: () => {},
|
group: () => Promise<void>,
|
||||||
alias: () => {},
|
alias: () => Promise<void>,
|
||||||
reset: () => {},
|
reset: () => Promise<void>,
|
||||||
}
|
}
|
||||||
}, [store, methods])
|
}, [store, methods])
|
||||||
}
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
export type TrackEvent = (
|
||||||
|
event: keyof TrackPropertiesMap,
|
||||||
|
properties?: TrackPropertiesMap[keyof TrackPropertiesMap],
|
||||||
|
) => Promise<void>
|
||||||
|
|
||||||
|
export type ScreenEvent = (
|
||||||
|
name: keyof ScreenPropertiesMap,
|
||||||
|
properties?: ScreenPropertiesMap[keyof ScreenPropertiesMap],
|
||||||
|
) => Promise<void>
|
||||||
|
interface TrackPropertiesMap {
|
||||||
|
// LOGIN / SIGN UP events
|
||||||
|
'Sign In': {resumedSession: boolean} // CAN BE SERVER
|
||||||
|
'Create Account': {} // CAN BE SERVER
|
||||||
|
'Signin:PressedForgotPassword': {}
|
||||||
|
'Signin:PressedSelectService': {}
|
||||||
|
// COMPOSER / CREATE POST events
|
||||||
|
'Create Post': {imageCount: string} // CAN BE SERVER
|
||||||
|
'Composer:PastedPhotos': {}
|
||||||
|
'Composer:CameraOpened': {}
|
||||||
|
'Composer:GalleryOpened': {}
|
||||||
|
'HomeScreen:PressCompose': {}
|
||||||
|
'ProfileScreen:PressCompose': {}
|
||||||
|
// EDIT PROFILE events
|
||||||
|
'EditHandle:ViewCustomForm': {}
|
||||||
|
'EditHandle:ViewProvidedForm': {}
|
||||||
|
'EditHandle:SetNewHandle': {}
|
||||||
|
'EditProfile:AvatarSelected': {}
|
||||||
|
'EditProfile:BannerSelected': {}
|
||||||
|
'EditProfile:Save': {} // CAN BE SERVER
|
||||||
|
// FEED events
|
||||||
|
'Feed:onRefresh': {}
|
||||||
|
'Feed:onEndReached': {}
|
||||||
|
// FEED ITEM events
|
||||||
|
'FeedItem:PostReply': {} // CAN BE SERVER
|
||||||
|
'FeedItem:PostRepost': {} // CAN BE SERVER
|
||||||
|
'FeedItem:PostLike': {} // CAN BE SERVER
|
||||||
|
'FeedItem:PostDelete': {} // CAN BE SERVER
|
||||||
|
'FeedItem:ThreadMute': {} // CAN BE SERVER
|
||||||
|
// PROFILE HEADER events
|
||||||
|
'ProfileHeader:EditProfileButtonClicked': {}
|
||||||
|
'ProfileHeader:FollowersButtonClicked': {}
|
||||||
|
'ProfileHeader:FollowsButtonClicked': {}
|
||||||
|
'ProfileHeader:ShareButtonClicked': {}
|
||||||
|
'ProfileHeader:MuteAccountButtonClicked': {}
|
||||||
|
'ProfileHeader:UnmuteAccountButtonClicked': {}
|
||||||
|
'ProfileHeader:ReportAccountButtonClicked': {}
|
||||||
|
'ProfileHeader:AddToListsButtonClicked': {}
|
||||||
|
'ProfileHeader:BlockAccountButtonClicked': {}
|
||||||
|
'ProfileHeader:UnblockAccountButtonClicked': {}
|
||||||
|
'ProfileHeader:FollowButtonClicked': {}
|
||||||
|
'ProfileHeader:UnfollowButtonClicked': {}
|
||||||
|
'ViewHeader:MenuButtonClicked': {}
|
||||||
|
// SETTINGS events
|
||||||
|
'Settings:SwitchAccountButtonClicked': {}
|
||||||
|
'Settings:AddAccountButtonClicked': {}
|
||||||
|
'Settings:ChangeHandleButtonClicked': {}
|
||||||
|
'Settings:InvitecodesButtonClicked': {}
|
||||||
|
'Settings:ContentfilteringButtonClicked': {}
|
||||||
|
'Settings:SignOutButtonClicked': {}
|
||||||
|
'Settings:ContentlanguagesButtonClicked': {}
|
||||||
|
// MENU events
|
||||||
|
'Menu:ItemClicked': {url: string}
|
||||||
|
'Menu:FeedbackClicked': {}
|
||||||
|
// MOBILE SHELL events
|
||||||
|
'MobileShell:MyProfileButtonPressed': {}
|
||||||
|
'MobileShell:HomeButtonPressed': {}
|
||||||
|
'MobileShell:SearchButtonPressed': {}
|
||||||
|
'MobileShell:NotificationsButtonPressed': {}
|
||||||
|
'MobileShell:FeedsButtonPressed': {}
|
||||||
|
// LISTS events
|
||||||
|
'Lists:onRefresh': {}
|
||||||
|
'Lists:onEndReached': {}
|
||||||
|
'CreateMuteList:AvatarSelected': {}
|
||||||
|
'CreateMuteList:Save': {} // CAN BE SERVER
|
||||||
|
// CUSTOM FEED events
|
||||||
|
'MultiFeed:onEndReached': {}
|
||||||
|
'MultiFeed:onRefresh': {}
|
||||||
|
// MODERATION events
|
||||||
|
'Moderation:ContentfilteringButtonClicked': {}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ScreenPropertiesMap {
|
||||||
|
Login: {}
|
||||||
|
CreateAccount: {}
|
||||||
|
'Choose Account': {}
|
||||||
|
'Signin:ForgotPassword': {}
|
||||||
|
'Signin:SetNewPasswordForm': {}
|
||||||
|
'Signin:PasswordUpdatedForm': {}
|
||||||
|
Feed: {}
|
||||||
|
Notifications: {}
|
||||||
|
Profile: {}
|
||||||
|
Settings: {}
|
||||||
|
AppPasswords: {}
|
||||||
|
Moderation: {}
|
||||||
|
BlockedAccounts: {}
|
||||||
|
MutedAccounts: {}
|
||||||
|
SavedFeeds: {}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import {ErrorBoundary} from 'view/com/util/ErrorBoundary'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {SplashScreen} from './SplashScreen'
|
import {SplashScreen} from './SplashScreen'
|
||||||
import {CenteredView} from '../util/Views'
|
import {CenteredView} from '../util/Views'
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
View,
|
View,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {Text} from '../../util/text/Text'
|
import {Text} from '../../util/text/Text'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
} from '@fortawesome/react-native-fontawesome'
|
} from '@fortawesome/react-native-fontawesome'
|
||||||
import * as EmailValidator from 'email-validator'
|
import * as EmailValidator from 'email-validator'
|
||||||
import {BskyAgent} from '@atproto/api'
|
import {BskyAgent} from '@atproto/api'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {Text} from '../../util/text/Text'
|
import {Text} from '../../util/text/Text'
|
||||||
import {UserAvatar} from '../../util/UserAvatar'
|
import {UserAvatar} from '../../util/UserAvatar'
|
||||||
import {s, colors} from 'lib/styles'
|
import {s, colors} from 'lib/styles'
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import LinearGradient from 'react-native-linear-gradient'
|
import LinearGradient from 'react-native-linear-gradient'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
import {RichText} from '@atproto/api'
|
import {RichText} from '@atproto/api'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete'
|
import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete'
|
||||||
import {ExternalEmbed} from './ExternalEmbed'
|
import {ExternalEmbed} from './ExternalEmbed'
|
||||||
import {Text} from '../util/text/Text'
|
import {Text} from '../util/text/Text'
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
FontAwesomeIconStyle,
|
FontAwesomeIconStyle,
|
||||||
} from '@fortawesome/react-native-fontawesome'
|
} from '@fortawesome/react-native-fontawesome'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {isDesktopWeb} from 'platform/detection'
|
||||||
import {openCamera} from 'lib/media/picker'
|
import {openCamera} from 'lib/media/picker'
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
FontAwesomeIconStyle,
|
FontAwesomeIconStyle,
|
||||||
} from '@fortawesome/react-native-fontawesome'
|
} from '@fortawesome/react-native-fontawesome'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {isDesktopWeb} from 'platform/detection'
|
||||||
import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions'
|
import {usePhotoLibraryPermission} from 'lib/hooks/usePermissions'
|
||||||
import {GalleryModel} from 'state/models/media/gallery'
|
import {GalleryModel} from 'state/models/media/gallery'
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {RichText as RichTextCom} from '../util/text/RichText'
|
||||||
import {UserAvatar} from '../util/UserAvatar'
|
import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {TextLink} from '../util/Link'
|
import {TextLink} from '../util/Link'
|
||||||
import {ListModel} from 'state/models/content/list'
|
import {ListModel} from 'state/models/content/list'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
||||||
import {Button} from '../util/forms/Button'
|
import {Button} from '../util/forms/Button'
|
||||||
import {Text} from '../util/text/Text'
|
import {Text} from '../util/text/Text'
|
||||||
import {ListsListModel} from 'state/models/lists/lists-list'
|
import {ListsListModel} from 'state/models/lists/lists-list'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ import {s} from 'lib/styles'
|
||||||
import {makeValidHandle, createFullHandle} from 'lib/strings/handles'
|
import {makeValidHandle, createFullHandle} from 'lib/strings/handles'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {cleanError} from 'lib/strings/errors'
|
import {cleanError} from 'lib/strings/errors'
|
||||||
|
|
||||||
export const snapPoints = ['100%']
|
export const snapPoints = ['100%']
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {compressIfNeeded} from 'lib/media/manip'
|
||||||
import {UserAvatar} from '../util/UserAvatar'
|
import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {cleanError, isNetworkError} from 'lib/strings/errors'
|
import {cleanError, isNetworkError} from 'lib/strings/errors'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {isDesktopWeb} from 'platform/detection'
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import {UserBanner} from '../util/UserBanner'
|
||||||
import {UserAvatar} from '../util/UserAvatar'
|
import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {cleanError, isNetworkError} from 'lib/strings/errors'
|
import {cleanError, isNetworkError} from 'lib/strings/errors'
|
||||||
|
|
||||||
export const snapPoints = ['fullscreen']
|
export const snapPoints = ['fullscreen']
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {FeedSlice} from './FeedSlice'
|
||||||
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
||||||
import {OnScrollCb} from 'lib/hooks/useOnMainScroll'
|
import {OnScrollCb} from 'lib/hooks/useOnMainScroll'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
||||||
|
|
||||||
export const FeedItem = observer(function ({
|
export const FeedItem = observer(function ({
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {Link} from '../util/Link'
|
||||||
import {UserAvatar} from '../util/UserAvatar'
|
import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {OnScrollCb} from 'lib/hooks/useOnMainScroll'
|
import {OnScrollCb} from 'lib/hooks/useOnMainScroll'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {isDesktopWeb} from 'platform/detection'
|
||||||
|
|
|
@ -29,7 +29,7 @@ import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {UserBanner} from '../util/UserBanner'
|
import {UserBanner} from '../util/UserBanner'
|
||||||
import {ProfileHeaderWarnings} from '../util/moderation/ProfileHeaderWarnings'
|
import {ProfileHeaderWarnings} from '../util/moderation/ProfileHeaderWarnings'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
import {listUriToHref} from 'lib/strings/url-helpers'
|
import {listUriToHref} from 'lib/strings/url-helpers'
|
||||||
import {isDesktopWeb, isNative} from 'platform/detection'
|
import {isDesktopWeb, isNative} from 'platform/detection'
|
||||||
|
@ -117,6 +117,11 @@ const ProfileHeaderLoaded = observer(
|
||||||
}, [store, view])
|
}, [store, view])
|
||||||
|
|
||||||
const onPressToggleFollow = React.useCallback(() => {
|
const onPressToggleFollow = React.useCallback(() => {
|
||||||
|
track(
|
||||||
|
view.viewer.following
|
||||||
|
? 'ProfileHeader:FollowButtonClicked'
|
||||||
|
: 'ProfileHeader:UnfollowButtonClicked',
|
||||||
|
)
|
||||||
view?.toggleFollowing().then(
|
view?.toggleFollowing().then(
|
||||||
() => {
|
() => {
|
||||||
Toast.show(
|
Toast.show(
|
||||||
|
@ -127,7 +132,7 @@ const ProfileHeaderLoaded = observer(
|
||||||
},
|
},
|
||||||
err => store.log.error('Failed to toggle follow', err),
|
err => store.log.error('Failed to toggle follow', err),
|
||||||
)
|
)
|
||||||
}, [view, store])
|
}, [track, view, store.log])
|
||||||
|
|
||||||
const onPressEditProfile = React.useCallback(() => {
|
const onPressEditProfile = React.useCallback(() => {
|
||||||
track('ProfileHeader:EditProfileButtonClicked')
|
track('ProfileHeader:EditProfileButtonClicked')
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {MagnifyingGlassIcon} from 'lib/icons'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
|
|
||||||
const MENU_HITSLOP = {left: 10, top: 10, right: 30, bottom: 10}
|
const MENU_HITSLOP = {left: 10, top: 10, right: 30, bottom: 10}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {Text} from './text/Text'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
|
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {isDesktopWeb} from 'platform/detection'
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
import {CommonNavigatorParams} from 'lib/routes/types'
|
import {CommonNavigatorParams} from 'lib/routes/types'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {useFocusEffect} from '@react-navigation/native'
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
import {ViewHeader} from '../com/util/ViewHeader'
|
import {ViewHeader} from '../com/util/ViewHeader'
|
||||||
import {CenteredView} from 'view/com/util/Views'
|
import {CenteredView} from 'view/com/util/Views'
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {FAB} from '../com/util/fab/FAB'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {ComposeIcon2} from 'lib/icons'
|
import {ComposeIcon2} from 'lib/icons'
|
||||||
import {isDesktopWeb, isMobileWebMediaQuery, isWeb} from 'platform/detection'
|
import {isDesktopWeb, isMobileWebMediaQuery, isWeb} from 'platform/detection'
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {ViewHeader} from '../com/util/ViewHeader'
|
||||||
import {Link} from '../com/util/Link'
|
import {Link} from '../com/util/Link'
|
||||||
import {Text} from '../com/util/text/Text'
|
import {Text} from '../com/util/text/Text'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {isDesktopWeb} from 'platform/detection'
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Moderation'>
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Moderation'>
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {observer} from 'mobx-react-lite'
|
||||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
import {CommonNavigatorParams} from 'lib/routes/types'
|
import {CommonNavigatorParams} from 'lib/routes/types'
|
||||||
import {BlockedAccountsModel} from 'state/models/lists/blocked-accounts'
|
import {BlockedAccountsModel} from 'state/models/lists/blocked-accounts'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {useFocusEffect} from '@react-navigation/native'
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
import {ViewHeader} from '../com/util/ViewHeader'
|
import {ViewHeader} from '../com/util/ViewHeader'
|
||||||
import {CenteredView} from 'view/com/util/Views'
|
import {CenteredView} from 'view/com/util/Views'
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {observer} from 'mobx-react-lite'
|
||||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
import {CommonNavigatorParams} from 'lib/routes/types'
|
import {CommonNavigatorParams} from 'lib/routes/types'
|
||||||
import {MutedAccountsModel} from 'state/models/lists/muted-accounts'
|
import {MutedAccountsModel} from 'state/models/lists/muted-accounts'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {useFocusEffect} from '@react-navigation/native'
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
import {ViewHeader} from '../com/util/ViewHeader'
|
import {ViewHeader} from '../com/util/ViewHeader'
|
||||||
import {CenteredView} from 'view/com/util/Views'
|
import {CenteredView} from 'view/com/util/Views'
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {useStores} from 'state/index'
|
||||||
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
||||||
import {useTabFocusEffect} from 'lib/hooks/useTabFocusEffect'
|
import {useTabFocusEffect} from 'lib/hooks/useTabFocusEffect'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {isWeb} from 'platform/detection'
|
import {isWeb} from 'platform/detection'
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<
|
type Props = NativeStackScreenProps<
|
||||||
|
|
|
@ -23,7 +23,7 @@ import {EmptyState} from '../com/util/EmptyState'
|
||||||
import {Text} from '../com/util/text/Text'
|
import {Text} from '../com/util/text/Text'
|
||||||
import {FAB} from '../com/util/fab/FAB'
|
import {FAB} from '../com/util/fab/FAB'
|
||||||
import {s, colors} from 'lib/styles'
|
import {s, colors} from 'lib/styles'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {ComposeIcon2} from 'lib/icons'
|
import {ComposeIcon2} from 'lib/icons'
|
||||||
import {CustomFeed} from 'view/com/feeds/CustomFeed'
|
import {CustomFeed} from 'view/com/feeds/CustomFeed'
|
||||||
import {CustomFeedModel} from 'state/models/feeds/custom-feed'
|
import {CustomFeedModel} from 'state/models/feeds/custom-feed'
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {useFocusEffect} from '@react-navigation/native'
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {CommonNavigatorParams} from 'lib/routes/types'
|
import {CommonNavigatorParams} from 'lib/routes/types'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
|
|
|
@ -35,7 +35,7 @@ import {ToggleButton} from 'view/com/util/forms/ToggleButton'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useCustomPalette} from 'lib/hooks/useCustomPalette'
|
import {useCustomPalette} from 'lib/hooks/useCustomPalette'
|
||||||
import {AccountData} from 'state/models/session'
|
import {AccountData} from 'state/models/session'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
import {isDesktopWeb} from 'platform/detection'
|
import {isDesktopWeb} from 'platform/detection'
|
||||||
import {pluralize} from 'lib/strings/helpers'
|
import {pluralize} from 'lib/strings/helpers'
|
||||||
|
|
|
@ -36,7 +36,7 @@ import {UserAvatar} from 'view/com/util/UserAvatar'
|
||||||
import {Text} from 'view/com/util/text/Text'
|
import {Text} from 'view/com/util/text/Text'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {pluralize} from 'lib/strings/helpers'
|
import {pluralize} from 'lib/strings/helpers'
|
||||||
import {getTabState, TabState} from 'lib/routes/helpers'
|
import {getTabState, TabState} from 'lib/routes/helpers'
|
||||||
import {NavigationProp} from 'lib/routes/types'
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {Text} from 'view/com/util/text/Text'
|
import {Text} from 'view/com/util/text/Text'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {clamp} from 'lib/numbers'
|
import {clamp} from 'lib/numbers'
|
||||||
import {
|
import {
|
||||||
HomeIcon,
|
HomeIcon,
|
||||||
|
@ -30,6 +30,8 @@ import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
|
||||||
import {useNavigationTabState} from 'lib/hooks/useNavigationTabState'
|
import {useNavigationTabState} from 'lib/hooks/useNavigationTabState'
|
||||||
import {UserAvatar} from 'view/com/util/UserAvatar'
|
import {UserAvatar} from 'view/com/util/UserAvatar'
|
||||||
|
|
||||||
|
type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds'
|
||||||
|
|
||||||
export const BottomBar = observer(({navigation}: BottomTabBarProps) => {
|
export const BottomBar = observer(({navigation}: BottomTabBarProps) => {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
@ -42,7 +44,7 @@ export const BottomBar = observer(({navigation}: BottomTabBarProps) => {
|
||||||
const {notifications} = store.me
|
const {notifications} = store.me
|
||||||
|
|
||||||
const onPressTab = React.useCallback(
|
const onPressTab = React.useCallback(
|
||||||
(tab: string) => {
|
(tab: TabOptions) => {
|
||||||
track(`MobileShell:${tab}ButtonPressed`)
|
track(`MobileShell:${tab}ButtonPressed`)
|
||||||
const state = navigation.getState()
|
const state = navigation.getState()
|
||||||
const tabState = getTabState(state, tab)
|
const tabState = getTabState(state, tab)
|
||||||
|
|
Loading…
Reference in New Issue