diff --git a/src/lib/analytics/analytics.tsx b/src/lib/analytics/analytics.tsx
index d1eb50f8a9..b3db9149c9 100644
--- a/src/lib/analytics/analytics.tsx
+++ b/src/lib/analytics/analytics.tsx
@@ -51,10 +51,10 @@ export function init(store: RootStoreModel) {
store.onSessionLoaded(() => {
const sess = store.session.currentSession
if (sess) {
- if (sess.email) {
+ if (sess.did) {
+ const did_hashed = sha256(sess.did)
+ segmentClient.identify(did_hashed, {did_hashed})
store.log.debug('Ping w/hash')
- const email_hashed = sha256(sess.email)
- segmentClient.identify(email_hashed, {email_hashed})
} else {
store.log.debug('Ping w/o hash')
segmentClient.identify()
diff --git a/src/lib/analytics/analytics.web.tsx b/src/lib/analytics/analytics.web.tsx
index db9d86e3cc..78bd9b42bb 100644
--- a/src/lib/analytics/analytics.web.tsx
+++ b/src/lib/analytics/analytics.web.tsx
@@ -46,10 +46,10 @@ export function init(store: RootStoreModel) {
store.onSessionLoaded(() => {
const sess = store.session.currentSession
if (sess) {
- if (sess.email) {
+ if (sess.did) {
+ const did_hashed = sha256(sess.did)
+ segmentClient.identify(did_hashed, {did_hashed})
store.log.debug('Ping w/hash')
- const email_hashed = sha256(sess.email)
- segmentClient.identify(email_hashed, {email_hashed})
} else {
store.log.debug('Ping w/o hash')
segmentClient.identify()
diff --git a/src/state/models/feeds/post.ts b/src/state/models/feeds/post.ts
index ae4f291054..d46cced756 100644
--- a/src/state/models/feeds/post.ts
+++ b/src/state/models/feeds/post.ts
@@ -116,6 +116,7 @@ export class PostsFeedItemModel {
},
() => this.rootStore.agent.deleteLike(url),
)
+ track('Post:Unlike')
} else {
// like
await updateDataOptimistically(
@@ -129,11 +130,10 @@ export class PostsFeedItemModel {
this.post.viewer!.like = res.uri
},
)
+ track('Post:Like')
}
} catch (error) {
this.rootStore.log.error('Failed to toggle like', error)
- } finally {
- track(this.post.viewer.like ? 'Post:Unlike' : 'Post:Like')
}
}
@@ -141,6 +141,7 @@ export class PostsFeedItemModel {
this.post.viewer = this.post.viewer || {}
try {
if (this.post.viewer?.repost) {
+ // unrepost
const url = this.post.viewer.repost
await updateDataOptimistically(
this.post,
@@ -150,7 +151,9 @@ export class PostsFeedItemModel {
},
() => this.rootStore.agent.deleteRepost(url),
)
+ track('Post:Unrepost')
} else {
+ // repost
await updateDataOptimistically(
this.post,
() => {
@@ -162,11 +165,10 @@ export class PostsFeedItemModel {
this.post.viewer!.repost = res.uri
},
)
+ track('Post:Repost')
}
} catch (error) {
this.rootStore.log.error('Failed to toggle repost', error)
- } finally {
- track(this.post.viewer.repost ? 'Post:Unrepost' : 'Post:Repost')
}
}
@@ -174,13 +176,13 @@ export class PostsFeedItemModel {
try {
if (this.isThreadMuted) {
this.rootStore.mutedThreads.uris.delete(this.rootUri)
+ track('Post:ThreadUnmute')
} else {
this.rootStore.mutedThreads.uris.add(this.rootUri)
+ track('Post:ThreadMute')
}
} catch (error) {
this.rootStore.log.error('Failed to toggle thread mute', error)
- } finally {
- track(this.isThreadMuted ? 'Post:ThreadUnmute' : 'Post:ThreadMute')
}
}
diff --git a/src/view/com/modals/CreateOrEditMuteList.tsx b/src/view/com/modals/CreateOrEditMuteList.tsx
index 3f3cfc5f01..4a440afebe 100644
--- a/src/view/com/modals/CreateOrEditMuteList.tsx
+++ b/src/view/com/modals/CreateOrEditMuteList.tsx
@@ -18,7 +18,7 @@ import {ListModel} from 'state/models/content/list'
import {s, colors, gradients} from 'lib/styles'
import {enforceLen} from 'lib/strings/helpers'
import {compressIfNeeded} from 'lib/media/manip'
-import {UserAvatar} from '../util/UserAvatar'
+import {EditableUserAvatar} from '../util/UserAvatar'
import {usePalette} from 'lib/hooks/usePalette'
import {useTheme} from 'lib/ThemeContext'
import {useAnalytics} from 'lib/analytics/analytics'
@@ -148,7 +148,7 @@ export function Component({
)}
List Avatar
-
-
diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx
index df19ecad57..5514bf98e9 100644
--- a/src/view/com/profile/ProfileHeader.tsx
+++ b/src/view/com/profile/ProfileHeader.tsx
@@ -132,20 +132,19 @@ const ProfileHeaderLoaded = observer(function ProfileHeaderLoadedImpl({
}, [store, view])
const onPressToggleFollow = React.useCallback(() => {
- track(
- view.viewer.following
- ? 'ProfileHeader:FollowButtonClicked'
- : 'ProfileHeader:UnfollowButtonClicked',
- )
view?.toggleFollowing().then(
() => {
setShowSuggestedFollows(Boolean(view.viewer.following))
-
Toast.show(
`${
view.viewer.following ? 'Following' : 'No longer following'
} ${sanitizeDisplayName(view.displayName || view.handle)}`,
)
+ track(
+ view.viewer.following
+ ? 'ProfileHeader:FollowButtonClicked'
+ : 'ProfileHeader:UnfollowButtonClicked',
+ )
},
err => store.log.error('Failed to toggle follow', err),
)
diff --git a/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx b/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx
index c5b187fb3d..cf759ddd17 100644
--- a/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx
+++ b/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import {View, StyleSheet, ScrollView, Pressable} from 'react-native'
+import {View, StyleSheet, Pressable, ScrollView} from 'react-native'
import Animated, {
useSharedValue,
withTiming,
@@ -26,6 +26,7 @@ import {sanitizeHandle} from 'lib/strings/handles'
import {makeProfileLink} from 'lib/routes/links'
import {Link} from 'view/com/util/Link'
import {useAnalytics} from 'lib/analytics/analytics'
+import {isWeb} from 'platform/detection'
const OUTER_PADDING = 10
const INNER_PADDING = 14
@@ -100,7 +101,6 @@ export function ProfileHeaderSuggestedFollows({
backgroundColor: pal.viewLight.backgroundColor,
height: '100%',
paddingTop: INNER_PADDING / 2,
- paddingBottom: INNER_PADDING,
}}>
{isLoading ? (
<>
diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx
index 6915d3e083..35524bcc65 100644
--- a/src/view/com/util/Link.tsx
+++ b/src/view/com/util/Link.tsx
@@ -1,5 +1,4 @@
-import React, {ComponentProps, useMemo} from 'react'
-import {observer} from 'mobx-react-lite'
+import React, {ComponentProps, memo, useMemo} from 'react'
import {
Linking,
GestureResponderEvent,
@@ -50,7 +49,7 @@ interface Props extends ComponentProps {
anchorNoUnderline?: boolean
}
-export const Link = observer(function Link({
+export const Link = memo(function Link({
testID,
style,
href,
@@ -136,7 +135,7 @@ export const Link = observer(function Link({
)
})
-export const TextLink = observer(function TextLink({
+export const TextLink = memo(function TextLink({
testID,
type = 'md',
style,
@@ -236,7 +235,7 @@ interface DesktopWebTextLinkProps extends TextProps {
accessibilityHint?: string
title?: string
}
-export const DesktopWebTextLink = observer(function DesktopWebTextLink({
+export const DesktopWebTextLink = memo(function DesktopWebTextLink({
testID,
type = 'md',
style,
diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx
index d24e474997..fbc0b5e113 100644
--- a/src/view/com/util/UserAvatar.tsx
+++ b/src/view/com/util/UserAvatar.tsx
@@ -23,14 +23,18 @@ interface BaseUserAvatarProps {
type?: Type
size: number
avatar?: string | null
- moderation?: ModerationUI
}
interface UserAvatarProps extends BaseUserAvatarProps {
- onSelectNewAvatar?: (img: RNImage | null) => void
+ moderation?: ModerationUI
+}
+
+interface EditableUserAvatarProps extends BaseUserAvatarProps {
+ onSelectNewAvatar: (img: RNImage | null) => void
}
interface PreviewableUserAvatarProps extends BaseUserAvatarProps {
+ moderation?: ModerationUI
did: string
handle: string
}
@@ -106,8 +110,65 @@ export function UserAvatar({
size,
avatar,
moderation,
- onSelectNewAvatar,
}: UserAvatarProps) {
+ const pal = usePalette('default')
+
+ const aviStyle = useMemo(() => {
+ if (type === 'algo' || type === 'list') {
+ return {
+ width: size,
+ height: size,
+ borderRadius: size > 32 ? 8 : 3,
+ }
+ }
+ return {
+ width: size,
+ height: size,
+ borderRadius: Math.floor(size / 2),
+ }
+ }, [type, size])
+
+ const alert = useMemo(() => {
+ if (!moderation?.alert) {
+ return null
+ }
+ return (
+
+
+
+ )
+ }, [moderation?.alert, size, pal])
+
+ return avatar &&
+ !((moderation?.blur && isAndroid) /* android crashes with blur */) ? (
+
+
+ {alert}
+
+ ) : (
+
+
+ {alert}
+
+ )
+}
+
+export function EditableUserAvatar({
+ type = 'user',
+ size,
+ avatar,
+ onSelectNewAvatar,
+}: EditableUserAvatarProps) {
const store = useStores()
const pal = usePalette('default')
const {requestCameraAccessIfNeeded} = useCameraPermission()
@@ -146,7 +207,7 @@ export function UserAvatar({
return
}
- onSelectNewAvatar?.(
+ onSelectNewAvatar(
await openCamera(store, {
width: 1000,
height: 1000,
@@ -186,7 +247,7 @@ export function UserAvatar({
path: item.path,
})
- onSelectNewAvatar?.(croppedImage)
+ onSelectNewAvatar(croppedImage)
},
},
!!avatar && {
@@ -203,7 +264,7 @@ export function UserAvatar({
web: 'trash',
},
onPress: async () => {
- onSelectNewAvatar?.(null)
+ onSelectNewAvatar(null)
},
},
].filter(Boolean) as DropdownItem[],
@@ -216,23 +277,7 @@ export function UserAvatar({
],
)
- const alert = useMemo(() => {
- if (!moderation?.alert) {
- return null
- }
- return (
-
-
-
- )
- }, [moderation?.alert, size, pal])
-
- // onSelectNewAvatar is only passed as prop on the EditProfile component
- return onSelectNewAvatar ? (
+ return (
- ) : avatar &&
- !((moderation?.blur && isAndroid) /* android crashes with blur */) ? (
-
-
- {alert}
-
- ) : (
-
-
- {alert}
-
)
}
diff --git a/src/view/com/util/images/ImageLayoutGrid.tsx b/src/view/com/util/images/ImageLayoutGrid.tsx
index 2e352d0864..4aa6f28de5 100644
--- a/src/view/com/util/images/ImageLayoutGrid.tsx
+++ b/src/view/com/util/images/ImageLayoutGrid.tsx
@@ -63,8 +63,8 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) {
case 4:
return (
-
-
+ <>
+
@@ -72,7 +72,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) {
-
+
@@ -80,7 +80,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) {
-
+ >
)
default:
diff --git a/src/view/screens/Support.tsx b/src/view/screens/Support.tsx
index de1b38b848..dc00d473d5 100644
--- a/src/view/screens/Support.tsx
+++ b/src/view/screens/Support.tsx
@@ -9,6 +9,7 @@ import {TextLink} from 'view/com/util/Link'
import {CenteredView} from 'view/com/util/Views'
import {usePalette} from 'lib/hooks/usePalette'
import {s} from 'lib/styles'
+import {HELP_DESK_URL} from 'lib/constants'
type Props = NativeStackScreenProps
export const SupportScreen = (_props: Props) => {
@@ -29,14 +30,13 @@ export const SupportScreen = (_props: Props) => {
Support
- If you need help, email us at{' '}
+ The support form has been moved. If you need help, please
{' '}
- with a description of your issue and information about how we can help
- you.
+ or visit {HELP_DESK_URL} to get in touch with us.