diff --git a/src/view/com/util/images/ImageLayoutGrid.tsx b/src/view/com/util/images/ImageLayoutGrid.tsx
index 2e352d086..4aa6f28de 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:
--
2.51.2
From 32fbb9dba7a0f27993ac4b3d76975ec577464e2d Mon Sep 17 00:00:00 2001
From: dan
Date: Wed, 25 Oct 2023 04:57:34 +0100
Subject: [PATCH 2/8] Simplify the avatar component (#1744)
* Copypaste UserAvatar to EditableUserAvatar
* Swap usages with onSelectNewAvatar to EditableUserAvatar
* Split prop types into UserAvatarProps and EditableUserAvatarProps
* Remove dead branches from EditableUserAvatar
* Remove dead branches from UserAvatar
---
src/view/com/modals/CreateOrEditMuteList.tsx | 4 +-
src/view/com/modals/EditProfile.tsx | 4 +-
src/view/com/util/UserAvatar.tsx | 108 ++++++++++++-------
3 files changed, 72 insertions(+), 44 deletions(-)
diff --git a/src/view/com/modals/CreateOrEditMuteList.tsx b/src/view/com/modals/CreateOrEditMuteList.tsx
index 3f3cfc5f0..4a440afeb 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
-
- 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}
-
)
}
--
2.51.2
From 4a4be1de1a3475d034fe9a95493c50222ef90e7e Mon Sep 17 00:00:00 2001
From: dan
Date: Wed, 25 Oct 2023 16:47:21 +0100
Subject: [PATCH 3/8] Remove MobX from Link (#1745)
* Remove MobX from Link
* Keep memo() though
We previously had observer() apply it automatically, so re-add it
---
src/view/com/util/Link.tsx | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx
index 6915d3e08..35524bcc6 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,
--
2.51.2
From 3426b24f67c571b697064d79ea83894f9a2f76e1 Mon Sep 17 00:00:00 2001
From: elliot
Date: Wed, 25 Oct 2023 12:41:56 -0400
Subject: [PATCH 4/8] Fixed CropImage modal aspect ratio buttons visibility in
dark mode (#1730)
---
src/view/com/modals/crop-image/CropImage.web.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/view/com/modals/crop-image/CropImage.web.tsx b/src/view/com/modals/crop-image/CropImage.web.tsx
index c5959cf4c..8e35201d1 100644
--- a/src/view/com/modals/crop-image/CropImage.web.tsx
+++ b/src/view/com/modals/crop-image/CropImage.web.tsx
@@ -100,7 +100,7 @@ export function Component({
accessibilityHint="Sets image aspect ratio to wide">
--
2.51.2
From 1781b3aab737a83898dac450daa1d19beb96bb38 Mon Sep 17 00:00:00 2001
From: Ansh
Date: Wed, 25 Oct 2023 09:54:04 -0700
Subject: [PATCH 5/8] allow enter key to trigger waitlist signup (#1723)
---
src/view/com/modals/Waitlist.tsx | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/view/com/modals/Waitlist.tsx b/src/view/com/modals/Waitlist.tsx
index 1104c0a39..0fb371fe4 100644
--- a/src/view/com/modals/Waitlist.tsx
+++ b/src/view/com/modals/Waitlist.tsx
@@ -77,6 +77,8 @@ export function Component({}: {}) {
keyboardAppearance={theme.colorScheme}
value={email}
onChangeText={setEmail}
+ onSubmitEditing={onPressSignup}
+ enterKeyHint="done"
accessible={true}
accessibilityLabel="Email"
accessibilityHint="Input your email to get on the Bluesky waitlist"
--
2.51.2
From ee80cae75f25da33f6527c3df16c90319eeaf0bc Mon Sep 17 00:00:00 2001
From: Ansh
Date: Wed, 25 Oct 2023 09:54:52 -0700
Subject: [PATCH 6/8] add scroll indicator on web to profile suggested follows
card (#1724)
---
.../com/profile/ProfileHeaderSuggestedFollows.tsx | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx b/src/view/com/profile/ProfileHeaderSuggestedFollows.tsx
index c5b187fb3..cf759ddd1 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 ? (
<>
--
2.51.2
From c13b6946bab9600cba670478c2f64771cc75f1af Mon Sep 17 00:00:00 2001
From: Ansh
Date: Wed, 25 Oct 2023 10:00:46 -0700
Subject: [PATCH 7/8] 1721 Update support link (#1722)
* change support page copy
* fix grammar
---
src/view/screens/Support.tsx | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/view/screens/Support.tsx b/src/view/screens/Support.tsx
index de1b38b84..dc00d473d 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.
--
2.51.2
From 927cee18d9c4425398e90811d4ed24098bf67396 Mon Sep 17 00:00:00 2001
From: Ansh
Date: Thu, 26 Oct 2023 08:37:14 -0700
Subject: [PATCH 8/8] Update Analytics (#1743)
---
src/lib/analytics/analytics.tsx | 6 +++---
src/lib/analytics/analytics.web.tsx | 6 +++---
src/state/models/feeds/post.ts | 14 ++++++++------
src/view/com/profile/ProfileHeader.tsx | 11 +++++------
4 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/src/lib/analytics/analytics.tsx b/src/lib/analytics/analytics.tsx
index d1eb50f8a..b3db9149c 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 db9d86e3c..78bd9b42b 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 ae4f29105..d46cced75 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/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx
index df19ecad5..5514bf98e 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),
)