diff --git a/src/view/screens/Storybook/Toasts.tsx b/src/view/screens/Storybook/Toasts.tsx
new file mode 100644
index 000000000..714afdfbd
--- /dev/null
+++ b/src/view/screens/Storybook/Toasts.tsx
@@ -0,0 +1,69 @@
+import {View} from 'react-native'
+
+import {atoms as a} from '#/alf'
+import {Button, ButtonText} from '#/components/Button'
+import {H1} from '#/components/Typography'
+import * as Toast from '#/view/com/util/Toast'
+import * as ToastHelpers from '#/view/com/util/ToastHelpers'
+
+export function Toasts() {
+ return (
+
+ Toasts
+
+
+
+ Toast.show('Operation completed successfully!', 'success')
+ }>
+ Success!
+
+
+ Toast.show('Something went wrong!', 'error')}>
+ Error
+
+
+ Toast.show('Please check your input', 'warning')}>
+ Warning
+
+
+ Toast.show("Here's some helpful information", 'info')}>
+ Info
+
+
+
+ Toast.show(
+ 'This is a longer message to test how the toast handles multiple lines of text content.',
+ 'info',
+ )
+ }>
+ Long Message
+
+
+
+ )
+}
diff --git a/src/view/screens/Storybook/index.tsx b/src/view/screens/Storybook/index.tsx
index a6c2ecdde..afcc1c4e7 100644
--- a/src/view/screens/Storybook/index.tsx
+++ b/src/view/screens/Storybook/index.tsx
@@ -20,6 +20,7 @@ import {Settings} from './Settings'
import {Shadows} from './Shadows'
import {Spacing} from './Spacing'
import {Theming} from './Theming'
+import {Toasts} from './Toasts'
import {Typography} from './Typography'
export function Storybook() {
@@ -122,6 +123,7 @@ function StorybookInner() {
+
Date: Mon, 28 Jul 2025 20:53:03 -0700
Subject: [PATCH 02/45] update: web toast
---
src/view/com/util/Toast.tsx | 78 +++++++++++++++++++++----
src/view/com/util/Toast.web.tsx | 100 ++++++++++++++++++++++++++++----
2 files changed, 158 insertions(+), 20 deletions(-)
diff --git a/src/view/com/util/Toast.tsx b/src/view/com/util/Toast.tsx
index 56c6780ad..fc9bdf672 100644
--- a/src/view/com/util/Toast.tsx
+++ b/src/view/com/util/Toast.tsx
@@ -21,20 +21,36 @@ import {
FontAwesomeIcon,
type Props as FontAwesomeProps,
} from '@fortawesome/react-native-fontawesome'
-
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
+import {isWeb} from '#/platform/detection'
import {atoms as a, useTheme} from '#/alf'
import {Text} from '#/components/Typography'
const TIMEOUT = 2e3
+export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info'
+
+const TOAST_TYPE_TO_ICON: Record = {
+ default: 'check',
+ success: 'check',
+ error: 'exclamation',
+ warning: 'circle-exclamation',
+ info: 'info',
+}
+
export function show(
message: string,
- icon: FontAwesomeProps['icon'] = 'check',
+ type: ToastType | FontAwesomeProps['icon'] = 'default',
) {
if (process.env.NODE_ENV === 'test') {
return
}
+
+ const icon =
+ typeof type === 'string' && type in TOAST_TYPE_TO_ICON
+ ? TOAST_TYPE_TO_ICON[type as ToastType]
+ : (type as FontAwesomeProps['icon'])
+
AccessibilityInfo.announceForAccessibility(message)
const item = new RootSiblings(
item.destroy()} />,
@@ -153,9 +169,41 @@ function Toast({
}
})
+ // Web-specific styles for better compatibility
+ const webContainerStyle = isWeb
+ ? {
+ position: 'absolute' as const,
+ top: topOffset,
+ left: 16,
+ right: 16,
+ zIndex: 9999,
+ pointerEvents: 'auto' as const,
+ }
+ : {}
+
+ const webToastStyle = isWeb
+ ? {
+ backgroundColor:
+ t.name === 'dark' ? t.palette.contrast_25 : t.palette.white,
+ shadowColor: '#000',
+ shadowOffset: {width: 0, height: 10},
+ shadowOpacity: 0.1,
+ shadowRadius: 15,
+ elevation: 10,
+ borderColor: t.palette.contrast_300,
+ borderWidth: 1,
+ borderRadius: 8,
+ minHeight: 60,
+ }
+ : {}
+
return (
{alive && (
@@ -200,7 +252,13 @@ function Toast({
style={t.atoms.text_contrast_medium}
/>
-
+
{message}
diff --git a/src/view/com/util/Toast.web.tsx b/src/view/com/util/Toast.web.tsx
index d3b7bda33..949dce7ef 100644
--- a/src/view/com/util/Toast.web.tsx
+++ b/src/view/com/util/Toast.web.tsx
@@ -9,12 +9,24 @@ import {
type FontAwesomeIconStyle,
type Props as FontAwesomeProps,
} from '@fortawesome/react-native-fontawesome'
+import {atoms as a, useBreakpoints, useTheme} from '#/alf'
-const DURATION = 3500
+const DURATION = 60000
+
+export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info'
+
+const TOAST_TYPE_TO_ICON: Record = {
+ default: 'check',
+ success: 'check',
+ error: 'exclamation',
+ warning: 'circle-exclamation',
+ info: 'info',
+}
interface ActiveToast {
text: string
icon: FontAwesomeProps['icon']
+ type: ToastType
}
type GlobalSetActiveToast = (_activeToast: ActiveToast | undefined) => void
@@ -33,16 +45,76 @@ export const ToastContainer: React.FC = ({}) => {
setActiveToast(t)
}
})
+
+ const t = useTheme()
+
+ const TOAST_TYPE_TO_STYLES = {
+ default: {
+ backgroundColor: t.atoms.text_contrast_low.color,
+ borderColor: t.atoms.border_contrast_medium.borderColor,
+ iconColor: '#fff',
+ textColor: '#fff',
+ },
+ success: {
+ backgroundColor: '#059669',
+ borderColor: '#047857',
+ iconColor: '#fff',
+ textColor: '#fff',
+ },
+ error: {
+ backgroundColor: t.palette.negative_100,
+ borderColor: t.palette.negative_400,
+ iconColor: t.palette.negative_600,
+ textColor: t.palette.negative_600,
+ },
+ warning: {
+ backgroundColor: t.palette.negative_500,
+ borderColor: t.palette.negative_600,
+ iconColor: '#fff',
+ textColor: '#fff',
+ },
+ info: {
+ backgroundColor: t.atoms.text_contrast_low.color,
+ borderColor: t.atoms.border_contrast_medium.borderColor,
+ iconColor: '#fff',
+ textColor: '#fff',
+ },
+ }
+
+ const toastStyles = activeToast
+ ? TOAST_TYPE_TO_STYLES[activeToast.type]
+ : TOAST_TYPE_TO_STYLES.default
+
return (
<>
{activeToast && (
-
+
- {activeToast.text}
+
+ {activeToast.text}
+
= ({}) => {
// methods
// =
-export function show(text: string, icon: FontAwesomeProps['icon'] = 'check') {
+export function show(
+ text: string,
+ type: ToastType | FontAwesomeProps['icon'] = 'default',
+) {
if (toastTimeout) {
clearTimeout(toastTimeout)
}
- globalSetActiveToast?.({text, icon})
+
+ // Determine if type is a semantic type or direct icon
+ const isSemanticType = typeof type === 'string' && type in TOAST_TYPE_TO_ICON
+ const icon = isSemanticType
+ ? TOAST_TYPE_TO_ICON[type as ToastType]
+ : (type as FontAwesomeProps['icon'])
+ const toastType = isSemanticType ? (type as ToastType) : 'default'
+
+ globalSetActiveToast?.({text, icon, type: toastType})
toastTimeout = setTimeout(() => {
globalSetActiveToast?.(undefined)
}, DURATION)
@@ -82,8 +165,8 @@ const styles = StyleSheet.create({
padding: 20,
flexDirection: 'row',
alignItems: 'center',
- backgroundColor: '#000c',
borderRadius: 10,
+ borderWidth: 1,
},
dismissBackdrop: {
position: 'absolute',
@@ -93,12 +176,9 @@ const styles = StyleSheet.create({
right: 0,
},
icon: {
- color: '#fff',
flexShrink: 0,
},
text: {
- color: '#fff',
- fontSize: 18,
marginLeft: 10,
},
})
--
2.51.2
From 287f5c0d42cddd112b65a56ccf60dde90205b06c Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Thu, 24 Jul 2025 16:30:34 -0700
Subject: [PATCH 03/45] feat(ui): update suggested profiles interstitial top
padding 16 -> 12
---
src/components/FeedInterstitials.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index a92e7be7f..aaaa17d3c 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -333,7 +333,7 @@ export function ProfileGrid({
{gtMobile ? (
-
+
{content}
@@ -372,7 +372,7 @@ export function ProfileGrid({
showsHorizontalScrollIndicator={false}
snapToInterval={MOBILE_CARD_WIDTH + a.gap_md.gap}
decelerationRate="fast">
-
+
{content}
Date: Thu, 24 Jul 2025 16:32:18 -0700
Subject: [PATCH 04/45] feat(ui): updated suggested profiles interstitial
"Suggested for you" text color
---
src/components/FeedInterstitials.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index aaaa17d3c..cf0f0cc21 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -338,7 +338,7 @@ export function ProfileGrid({
a.align_center,
a.justify_between,
]}>
-
+
{viewContext === 'profile' ? (
Similar accounts
) : (
--
2.51.2
From b8a257a1c782126e525efadc5a602817cc4c2619 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Thu, 24 Jul 2025 17:33:26 -0700
Subject: [PATCH 05/45] feat(ui): replace suggested profiles interstital icon
with link "See all"
---
src/components/FeedInterstitials.tsx | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index cf0f0cc21..dec2dac1b 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -29,7 +29,6 @@ import {Button} from '#/components/Button'
import * as FeedCard from '#/components/FeedCard'
import {ArrowRight_Stroke2_Corner0_Rounded as Arrow} from '#/components/icons/Arrow'
import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag'
-import {PersonPlus_Stroke2_Corner0_Rounded as Person} from '#/components/icons/Person'
import {InlineLinkText} from '#/components/Link'
import * as ProfileCard from '#/components/ProfileCard'
import {Text} from '#/components/Typography'
@@ -345,7 +344,9 @@ export function ProfileGrid({
Suggested for you
)}
-
+
+ See all
+
{gtMobile ? (
--
2.51.2
From e465c9e4612c41bfffce90f734b8f01d93eda95d Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Thu, 24 Jul 2025 18:37:03 -0700
Subject: [PATCH 06/45] feat(ui): add dropshadow to suggested profile card
---
src/components/FeedInterstitials.tsx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index dec2dac1b..7af2384b0 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -282,6 +282,7 @@ export function ProfileGrid({
style={[
a.flex_1,
(hovered || pressed) && t.atoms.border_contrast_high,
+ t.atoms.shadow_sm,
]}>
@@ -372,7 +373,8 @@ export function ProfileGrid({
horizontal
showsHorizontalScrollIndicator={false}
snapToInterval={MOBILE_CARD_WIDTH + a.gap_md.gap}
- decelerationRate="fast">
+ decelerationRate="fast"
+ style={[a.overflow_visible]}>
{content}
--
2.51.2
From 2a6d04e6e203430fad61ed87cbbfa8e6836e70a5 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Thu, 24 Jul 2025 18:37:41 -0700
Subject: [PATCH 07/45] feat: update ProfileCard.Avatar to take size prop
---
src/components/ProfileCard.tsx | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/components/ProfileCard.tsx b/src/components/ProfileCard.tsx
index e01c27655..b2d4d16fb 100644
--- a/src/components/ProfileCard.tsx
+++ b/src/components/ProfileCard.tsx
@@ -20,7 +20,13 @@ import {useProfileFollowMutationQueue} from '#/state/queries/profile'
import {useSession} from '#/state/session'
import * as Toast from '#/view/com/util/Toast'
import {PreviewableUserAvatar, UserAvatar} from '#/view/com/util/UserAvatar'
-import {atoms as a, platform, useTheme} from '#/alf'
+import {
+ atoms as a,
+ platform,
+ TextStyleProp,
+ useTheme,
+ ViewStyleProp,
+} from '#/alf'
import {
Button,
ButtonIcon,
@@ -136,12 +142,14 @@ export function Avatar({
onPress,
disabledPreview,
liveOverride,
+ size = 40,
}: {
profile: bsky.profile.AnyProfileView
moderationOpts: ModerationOpts
onPress?: () => void
disabledPreview?: boolean
liveOverride?: boolean
+ size?: number
}) {
const moderation = moderateProfile(profile, moderationOpts)
@@ -149,7 +157,7 @@ export function Avatar({
return disabledPreview ? (
) : (
Date: Thu, 24 Jul 2025 18:38:10 -0700
Subject: [PATCH 08/45] feat: update ProfileCard.Description to take style prop
---
src/components/ProfileCard.tsx | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/components/ProfileCard.tsx b/src/components/ProfileCard.tsx
index b2d4d16fb..4e135c8a2 100644
--- a/src/components/ProfileCard.tsx
+++ b/src/components/ProfileCard.tsx
@@ -354,10 +354,11 @@ export function NameAndHandlePlaceholder() {
export function Description({
profile: profileUnshadowed,
numberOfLines = 3,
+ style,
}: {
profile: bsky.profile.AnyProfileView
numberOfLines?: number
-}) {
+} & TextStyleProp) {
const profile = useProfileShadow(profileUnshadowed)
const rt = useMemo(() => {
if (!('description' in profile)) return
@@ -377,7 +378,7 @@ export function Description({
--
2.51.2
From c6e7816fa73d57468bad5cd0dc4c2ed63fc972e5 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Thu, 24 Jul 2025 18:39:02 -0700
Subject: [PATCH 09/45] feat(ui): update padding, border radius, and border on
suggested profile card
---
src/components/FeedInterstitials.tsx | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 7af2384b0..44f390da5 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -47,8 +47,8 @@ function CardOuter({
--
2.51.2
From c93c36f6e51edb150cb7d27025a9c70c38d120b0 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Thu, 24 Jul 2025 18:39:37 -0700
Subject: [PATCH 10/45] feat(ui): force width on suggested profile card
---
src/components/FeedInterstitials.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 44f390da5..47bf228db 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -285,6 +285,7 @@ export function ProfileGrid({
t.atoms.border_contrast_low,
(hovered || pressed) && t.atoms.border_contrast_high,
t.atoms.shadow_sm,
+ {width: 165},
]}>
--
2.51.2
From 3c89552e924fa5380ecbe0fcdce96c2282feb875 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Thu, 24 Jul 2025 18:40:54 -0700
Subject: [PATCH 11/45] refactor(ui): replace ProfileCard.Header with custom
View
---
src/components/FeedInterstitials.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 47bf228db..7318c5c5d 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -288,7 +288,7 @@ export function ProfileGrid({
{width: 165},
]}>
-
+
-
+
)}
--
2.51.2
From 205e7f01909c36047a5194ac9ac2d135bd095956 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Thu, 24 Jul 2025 18:41:30 -0700
Subject: [PATCH 12/45] feat(ui): update ProfileCard.Avatar size 40 -> 88
---
src/components/FeedInterstitials.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 7318c5c5d..16167d83f 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -292,6 +292,7 @@ export function ProfileGrid({
Date: Thu, 24 Jul 2025 18:41:55 -0700
Subject: [PATCH 13/45] refactor(ui): swap ProfileCard.NameAndHandle for
ProfileCard.Name
---
src/components/FeedInterstitials.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 16167d83f..fe41d322a 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -294,7 +294,7 @@ export function ProfileGrid({
moderationOpts={moderationOpts}
size={88}
/>
-
--
2.51.2
From 0598d73617eda3da7946573850813593a6fc9bba Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Thu, 24 Jul 2025 18:53:41 -0700
Subject: [PATCH 14/45] refactor(ui): follow button and description to match
design
---
src/components/FeedInterstitials.tsx | 57 +++++++++++++++++-----------
1 file changed, 34 insertions(+), 23 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index fe41d322a..28c4cbba6 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -294,30 +294,41 @@ export function ProfileGrid({
moderationOpts={moderationOpts}
size={88}
/>
-
- {
- logEvent('suggestedUser:follow', {
- logContext:
- viewContext === 'feed'
- ? 'InterstitialDiscover'
- : 'InterstitialProfile',
- location: 'Card',
- recId,
- position: index,
- })
- }}
- />
-
+
+
+
+
+
+ {
+ logEvent('suggestedUser:follow', {
+ logContext:
+ viewContext === 'feed'
+ ? 'InterstitialDiscover'
+ : 'InterstitialProfile',
+ location: 'Card',
+ recId,
+ position: index,
+ })
+ }}
+ />
)}
--
2.51.2
From 955a864245b5da81b02363d6a2d69ffa1e6f27a3 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Fri, 25 Jul 2025 16:13:04 -0700
Subject: [PATCH 15/45] refactor: update MOBILE_CARD_WIDTH instead of using
inline width
---
src/components/FeedInterstitials.tsx | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 28c4cbba6..b54c6622c 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -35,7 +35,7 @@ import {Text} from '#/components/Typography'
import type * as bsky from '#/types/bsky'
import {ProgressGuideList} from './ProgressGuide/List'
-const MOBILE_CARD_WIDTH = 300
+const MOBILE_CARD_WIDTH = 165
function CardOuter({
children,
@@ -285,7 +285,6 @@ export function ProfileGrid({
t.atoms.border_contrast_low,
(hovered || pressed) && t.atoms.border_contrast_high,
t.atoms.shadow_sm,
- {width: 165},
]}>
--
2.51.2
From 48f670f26ab9d2578958ba4d9805b3e52212edbb Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Fri, 25 Jul 2025 16:26:25 -0700
Subject: [PATCH 16/45] fix(ui): follow button should always be pushed to the
bottom on the profile card
---
src/components/FeedInterstitials.tsx | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index b54c6622c..7cc3a92d9 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -287,7 +287,14 @@ export function ProfileGrid({
t.atoms.shadow_sm,
]}>
-
+
Date: Fri, 25 Jul 2025 16:29:18 -0700
Subject: [PATCH 17/45] fix(ui): suggested profile card grid on web sm -> md
---
src/components/FeedInterstitials.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 7cc3a92d9..123733923 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -373,7 +373,7 @@ export function ProfileGrid({
{gtMobile ? (
-
+
{content}
--
2.51.2
From f58ad8e4199eacf922dfe0bc3d41fd948677b6bd Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Fri, 25 Jul 2025 16:38:25 -0700
Subject: [PATCH 18/45] refactor: replace magic 6px with dynamic a.gap_md/2
---
src/components/FeedInterstitials.tsx | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 123733923..70e025a94 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -253,7 +253,10 @@ export function ProfileGrid({
.map((_, i) => (
+ style={[
+ gtMobile &&
+ web([a.flex_0, {width: `calc(50% - ${a.gap_md.gap / 2}px)`}]),
+ ]}>
))
@@ -275,7 +278,8 @@ export function ProfileGrid({
}}
style={[
a.flex_1,
- gtMobile && web([a.flex_0, {width: 'calc(50% - 6px)'}]),
+ gtMobile &&
+ web([a.flex_0, {width: `calc(50% - ${a.gap_md.gap / 2}px)`}]),
]}>
{({hovered, pressed}) => (
Date: Fri, 25 Jul 2025 17:18:59 -0700
Subject: [PATCH 19/45] feat: create NamePlaceholder component
---
src/components/ProfileCard.tsx | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/src/components/ProfileCard.tsx b/src/components/ProfileCard.tsx
index 4e135c8a2..99a68083a 100644
--- a/src/components/ProfileCard.tsx
+++ b/src/components/ProfileCard.tsx
@@ -23,9 +23,9 @@ import {PreviewableUserAvatar, UserAvatar} from '#/view/com/util/UserAvatar'
import {
atoms as a,
platform,
- TextStyleProp,
+ type TextStyleProp,
useTheme,
- ViewStyleProp,
+ type ViewStyleProp,
} from '#/alf'
import {
Button,
@@ -351,6 +351,24 @@ export function NameAndHandlePlaceholder() {
)
}
+export function NamePlaceholder({style}: ViewStyleProp) {
+ const t = useTheme()
+
+ return (
+
+ )
+}
+
export function Description({
profile: profileUnshadowed,
numberOfLines = 3,
--
2.51.2
From 4e507caa7c5c11c41d44364270180fb4186235d1 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Fri, 25 Jul 2025 17:19:13 -0700
Subject: [PATCH 20/45] feat: update AvatarPlaceholder to take size prop
---
src/components/ProfileCard.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/components/ProfileCard.tsx b/src/components/ProfileCard.tsx
index 99a68083a..65e20ba9a 100644
--- a/src/components/ProfileCard.tsx
+++ b/src/components/ProfileCard.tsx
@@ -174,7 +174,7 @@ export function Avatar({
)
}
-export function AvatarPlaceholder() {
+export function AvatarPlaceholder({size = 40}: {size?: number}) {
const t = useTheme()
return (
--
2.51.2
From f35dc19a48966cb57c9d80b84267ec98b7d5c11b Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Fri, 25 Jul 2025 17:19:41 -0700
Subject: [PATCH 21/45] feat(ui): update SuggestedFollowPlaceholder to match
new design
---
src/components/FeedInterstitials.tsx | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 70e025a94..f2caddd74 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -66,12 +66,14 @@ export function SuggestedFollowPlaceholder() {
const t = useTheme()
return (
-
-
-
-
-
-
+
+
+
+
+
)
}
--
2.51.2
From b2fe27afe72bee4fbebf3bf57418a900fb62ef45 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Fri, 25 Jul 2025 17:26:06 -0700
Subject: [PATCH 22/45] refactor(ui): remove "Browse more suggestions" on web
in favor of "See all"
---
src/components/FeedInterstitials.tsx | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index f2caddd74..f16b33786 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -378,20 +378,10 @@ export function ProfileGrid({
{gtMobile ? (
-
+
{content}
-
-
-
- Browse more suggestions
-
-
-
) : (
--
2.51.2
From 4c8d5db6a65852da244a5adc2d8e833f19be306f Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Fri, 25 Jul 2025 18:36:26 -0700
Subject: [PATCH 23/45] refactor(ui): web profile cards maxLength 4 -> 3 with
flex grow
---
src/components/FeedInterstitials.tsx | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index f16b33786..e9e2ee2a2 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -247,7 +247,7 @@ export function ProfileGrid({
const navigation = useNavigation()
const {gtMobile} = useBreakpoints()
const isLoading = isSuggestionsLoading || !moderationOpts
- const maxLength = gtMobile ? 4 : 6
+ const maxLength = gtMobile ? 3 : 6
const content = isLoading ? (
Array(maxLength)
@@ -281,7 +281,11 @@ export function ProfileGrid({
style={[
a.flex_1,
gtMobile &&
- web([a.flex_0, {width: `calc(50% - ${a.gap_md.gap / 2}px)`}]),
+ web([
+ a.flex_0,
+ a.flex_grow,
+ {width: `calc(30% - ${a.gap_md.gap / 2}px)`},
+ ]),
]}>
{({hovered, pressed}) => (
Date: Mon, 28 Jul 2025 16:55:27 -0700
Subject: [PATCH 24/45] feat(feed): update suggested profiles link text
---
src/components/FeedInterstitials.tsx | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index e9e2ee2a2..d2d65eddc 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -376,8 +376,10 @@ export function ProfileGrid({
Suggested for you
)}
-
- See all
+
+ See more
--
2.51.2
From ab5be5cb3fe92ca2fb0b5013fbe72136054ddb91 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Mon, 28 Jul 2025 16:56:00 -0700
Subject: [PATCH 25/45] refactor(feed): wrap placeholder description
placeholder in full-width view
---
src/components/FeedInterstitials.tsx | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index d2d65eddc..48965ffb7 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -69,10 +69,9 @@ export function SuggestedFollowPlaceholder() {
-
+
+
+
)
--
2.51.2
From da47cd0d1b8aac5a19c753a08fdcdf2006cd7eec Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Mon, 28 Jul 2025 16:58:03 -0700
Subject: [PATCH 26/45] fix(ui): placeholder web size and flex grow
---
src/components/FeedInterstitials.tsx | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 48965ffb7..6cb10a523 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -256,7 +256,11 @@ export function ProfileGrid({
key={i}
style={[
gtMobile &&
- web([a.flex_0, {width: `calc(50% - ${a.gap_md.gap / 2}px)`}]),
+ web([
+ a.flex_0,
+ a.flex_grow,
+ {width: `calc(30% - ${a.gap_md.gap / 2}px)`},
+ ]),
]}>
--
2.51.2
From 8dc074c47798f69d886ed6eec7b8cb01171aced8 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Mon, 28 Jul 2025 17:38:58 -0700
Subject: [PATCH 27/45] fix(ui): profile name and description overflowing on
web
---
src/components/FeedInterstitials.tsx | 2 +-
src/components/ProfileCard.tsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 6cb10a523..1566db1bf 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -313,7 +313,7 @@ export function ProfileGrid({
moderationOpts={moderationOpts}
size={88}
/>
-
+
+
Date: Mon, 28 Jul 2025 18:48:40 -0700
Subject: [PATCH 28/45] refactor(ui): remove "Browse more accounts" card on
mobile view
---
src/components/FeedInterstitials.tsx | 21 ---------------------
1 file changed, 21 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 1566db1bf..aab54b7df 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -243,7 +243,6 @@ export function ProfileGrid({
const t = useTheme()
const {_} = useLingui()
const moderationOpts = useModerationOpts()
- const navigation = useNavigation()
const {gtMobile} = useBreakpoints()
const isLoading = isSuggestionsLoading || !moderationOpts
const maxLength = gtMobile ? 3 : 6
@@ -403,26 +402,6 @@ export function ProfileGrid({
style={[a.overflow_visible]}>
{content}
-
- {
- navigation.navigate('SearchTab')
- }}>
-
-
-
-
-
- Browse more suggestions on the Explore page
-
-
-
-
-
-
-
-
--
2.51.2
From e5457c946a5bf56fafde790ced9014e1cb73cd34 Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Tue, 29 Jul 2025 17:04:47 -0700
Subject: [PATCH 29/45] feat(ui): improve suggested follow placeholder card
Now matches the same size and shape as the rendered card, which prevents
content layout shift.
---
src/components/FeedInterstitials.tsx | 31 +++++++++++++++++++++-------
1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index aab54b7df..e4419838d 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -25,7 +25,7 @@ import {
type ViewStyleProp,
web,
} from '#/alf'
-import {Button} from '#/components/Button'
+import {Button, ButtonText} from '#/components/Button'
import * as FeedCard from '#/components/FeedCard'
import {ArrowRight_Stroke2_Corner0_Rounded as Arrow} from '#/components/icons/Arrow'
import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag'
@@ -64,15 +64,30 @@ function CardOuter({
export function SuggestedFollowPlaceholder() {
const t = useTheme()
+
return (
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+ Follow
+
+
)
}
--
2.51.2
From 7b4ec21e3e60cb25197fb277f3ba54fa627e4e1e Mon Sep 17 00:00:00 2001
From: Caidan Williams
Date: Tue, 29 Jul 2025 17:05:13 -0700
Subject: [PATCH 30/45] refactor(ui): adjust border styles in ProfileGrid card
---
src/components/FeedInterstitials.tsx | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index e4419838d..9bdfcbc5e 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -308,10 +308,8 @@ export function ProfileGrid({
Date: Tue, 29 Jul 2025 17:29:22 -0700
Subject: [PATCH 31/45] feat(ui): add "See More Suggested Profiles" card
---
src/components/FeedInterstitials.tsx | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx
index 9bdfcbc5e..2a3a00ba7 100644
--- a/src/components/FeedInterstitials.tsx
+++ b/src/components/FeedInterstitials.tsx
@@ -415,6 +415,8 @@ export function ProfileGrid({
style={[a.overflow_visible]}>
{content}
+
+
@@ -424,6 +426,32 @@ export function ProfileGrid({
)
}
+function SeeMoreSuggestedProfilesCard() {
+ const navigation = useNavigation()
+ const t = useTheme()
+ const {_} = useLingui()
+
+ return (
+ {
+ navigation.navigate('SearchTab')
+ }}>
+
+
+
+
+ See more accounts you might like
+
+
+
+
+
+
+
+ )
+}
+
export function SuggestedFeeds() {
const numFeedsToDisplay = 3
const t = useTheme()
--
2.51.2
From 2b92697e3ec67c058119e88c4779e04a3cb952ce Mon Sep 17 00:00:00 2001
From: Austin McKinley
Date: Tue, 29 Jul 2025 17:51:55 -0700
Subject: [PATCH 32/45] switch to using DefaultServeMux, include go.mod and
go.sum changes
---
bskyweb/cmd/embedr/server.go | 4 +++-
bskyweb/go.mod | 41 +++++++++++++++++++-----------------
bskyweb/go.sum | 38 +++++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 20 deletions(-)
diff --git a/bskyweb/cmd/embedr/server.go b/bskyweb/cmd/embedr/server.go
index 07c25afad..d8df4276f 100644
--- a/bskyweb/cmd/embedr/server.go
+++ b/bskyweb/cmd/embedr/server.go
@@ -13,6 +13,8 @@ import (
"syscall"
"time"
+ _ "net/http/pprof"
+
"github.com/bluesky-social/indigo/atproto/identity"
"github.com/bluesky-social/indigo/util/cliutil"
"github.com/bluesky-social/indigo/xrpc"
@@ -70,7 +72,7 @@ func serve(cctx *cli.Context) error {
return err
}
- metricsMux := http.NewServeMux()
+ metricsMux := http.DefaultServeMux
metricsMux.Handle("/metrics", promhttp.Handler())
metricsHttpd := &http.Server{
diff --git a/bskyweb/go.mod b/bskyweb/go.mod
index 630d5d256..af0c5c6fc 100644
--- a/bskyweb/go.mod
+++ b/bskyweb/go.mod
@@ -1,24 +1,26 @@
module github.com/bluesky-social/social-app/bskyweb
-go 1.23
+go 1.24
-toolchain go1.23.4
+toolchain go1.24.5
require (
- github.com/bluesky-social/indigo v0.0.0-20250605010711-db9bb60025dc
+ github.com/bluesky-social/indigo v0.0.0-20250729223159-573ae927246a
github.com/flosch/pongo2/v6 v6.0.0
github.com/ipfs/go-log v1.0.5
github.com/joho/godotenv v1.5.1
- github.com/klauspost/compress v1.17.3
- github.com/labstack/echo/v4 v4.11.3
+ github.com/klauspost/compress v1.18.0
+ github.com/labstack/echo/v4 v4.13.3
github.com/urfave/cli/v2 v2.25.7
)
+require github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
github.com/carlmjohnson/versioninfo v0.22.5 // indirect
- github.com/cespare/xxhash/v2 v2.2.0 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
@@ -52,14 +54,15 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
- github.com/labstack/gommon v0.4.1 // indirect
+ github.com/labstack/echo-contrib v0.17.4
+ github.com/labstack/gommon v0.4.2 // indirect
github.com/lestrrat-go/blackmagic v1.0.1 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc v1.0.4 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/jwx/v2 v2.0.12 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
- github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
@@ -73,10 +76,10 @@ require (
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/orandin/slog-gorm v1.3.2 // indirect
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect
- github.com/prometheus/client_golang v1.17.0 // indirect
- github.com/prometheus/client_model v0.5.0 // indirect
- github.com/prometheus/common v0.45.0 // indirect
- github.com/prometheus/procfs v0.12.0 // indirect
+ github.com/prometheus/client_golang v1.22.0 // indirect
+ github.com/prometheus/client_model v0.6.2 // indirect
+ github.com/prometheus/common v0.63.0 // indirect
+ github.com/prometheus/procfs v0.16.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
@@ -94,14 +97,14 @@ require (
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect
- golang.org/x/crypto v0.21.0 // indirect
- golang.org/x/net v0.23.0 // indirect
- golang.org/x/sync v0.7.0 // indirect
- golang.org/x/sys v0.22.0 // indirect
- golang.org/x/text v0.14.0 // indirect
- golang.org/x/time v0.3.0 // indirect
+ golang.org/x/crypto v0.38.0 // indirect
+ golang.org/x/net v0.40.0 // indirect
+ golang.org/x/sync v0.14.0 // indirect
+ golang.org/x/sys v0.33.0 // indirect
+ golang.org/x/text v0.25.0 // indirect
+ golang.org/x/time v0.11.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
- google.golang.org/protobuf v1.33.0 // indirect
+ google.golang.org/protobuf v1.36.6 // indirect
gorm.io/driver/postgres v1.5.7 // indirect
gorm.io/driver/sqlite v1.5.5 // indirect
gorm.io/gorm v1.25.9 // indirect
diff --git a/bskyweb/go.sum b/bskyweb/go.sum
index c0ba4f6cc..cbd815ebe 100644
--- a/bskyweb/go.sum
+++ b/bskyweb/go.sum
@@ -4,12 +4,16 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bluesky-social/indigo v0.0.0-20250605010711-db9bb60025dc h1:chbGD59Cn1mw07kbq9Uvb8WUFIr1dcoL5TOhT+I9bV4=
github.com/bluesky-social/indigo v0.0.0-20250605010711-db9bb60025dc/go.mod h1:ovyxp8AMO1Hoe838vMJUbqHTZaAR8ABM3g3TXu+A5Ng=
+github.com/bluesky-social/indigo v0.0.0-20250729223159-573ae927246a h1:S12KN45uIkRglMHC8PqD/Vsz0+u3KbIaBF/6rit8/Pg=
+github.com/bluesky-social/indigo v0.0.0-20250729223159-573ae927246a/go.mod h1:0XUyOCRtL4/OiyeqMTmr6RlVHQMDgw3LS7CfibuZR5Q=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
github.com/carlmjohnson/versioninfo v0.22.5 h1:O00sjOLUAFxYQjlN/bzYTuZiS0y6fWDQjMRvwtKgwwc=
github.com/carlmjohnson/versioninfo v0.22.5/go.mod h1:QT9mph3wcVfISUKd0i9sZfVrPviHuSF+cUtLjm2WSf8=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
@@ -104,6 +108,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA=
github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
+github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
+github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -113,10 +119,16 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/labstack/echo-contrib v0.17.4 h1:g5mfsrJfJTKv+F5uNKCyrjLK7js+ZW6HTjg4FnDxxgk=
+github.com/labstack/echo-contrib v0.17.4/go.mod h1:9O7ZPAHUeMGTOAfg80YqQduHzt0CzLak36PZRldYrZ0=
github.com/labstack/echo/v4 v4.11.3 h1:Upyu3olaqSHkCjs1EJJwQ3WId8b8b1hxbogyommKktM=
github.com/labstack/echo/v4 v4.11.3/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws=
+github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
+github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
github.com/labstack/gommon v0.4.1 h1:gqEff0p/hTENGMABzezPoPSRtIh1Cvw0ueMOe0/dfOk=
github.com/labstack/gommon v0.4.1/go.mod h1:TyTrpPqxR5KMk8LKVtLmfMjeQ5FEkBYdxLYPw/WfrOM=
+github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
+github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
@@ -132,6 +144,8 @@ github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNB
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
+github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@@ -154,6 +168,8 @@ github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7B
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/orandin/slog-gorm v1.3.2 h1:C0lKDQPAx/pF+8K2HL7bdShPwOEJpPM0Bn80zTzxU1g=
@@ -165,12 +181,20 @@ github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
+github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
+github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
+github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
+github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
+github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
+github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
+github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
+github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
@@ -254,6 +278,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
+golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
+golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -273,6 +299,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
+golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
+golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -281,6 +309,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
+golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -299,6 +329,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
+golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -312,8 +344,12 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
+golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
+golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@@ -334,6 +370,8 @@ golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSm
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
--
2.51.2
From 27c51401d2d828db5a52c99dd9b73a700ba65368 Mon Sep 17 00:00:00 2001
From: Austin McKinley
Date: Tue, 29 Jul 2025 17:54:11 -0700
Subject: [PATCH 33/45] git tidy
---
bskyweb/go.mod | 4 +---
bskyweb/go.sum | 50 ++++++--------------------------------------------
2 files changed, 7 insertions(+), 47 deletions(-)
diff --git a/bskyweb/go.mod b/bskyweb/go.mod
index af0c5c6fc..f4689af5a 100644
--- a/bskyweb/go.mod
+++ b/bskyweb/go.mod
@@ -28,7 +28,6 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
@@ -65,7 +64,6 @@ require (
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
- github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
@@ -76,7 +74,7 @@ require (
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/orandin/slog-gorm v1.3.2 // indirect
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect
- github.com/prometheus/client_golang v1.22.0 // indirect
+ github.com/prometheus/client_golang v1.22.0
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.63.0 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
diff --git a/bskyweb/go.sum b/bskyweb/go.sum
index cbd815ebe..144ad7cfa 100644
--- a/bskyweb/go.sum
+++ b/bskyweb/go.sum
@@ -2,16 +2,12 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
-github.com/bluesky-social/indigo v0.0.0-20250605010711-db9bb60025dc h1:chbGD59Cn1mw07kbq9Uvb8WUFIr1dcoL5TOhT+I9bV4=
-github.com/bluesky-social/indigo v0.0.0-20250605010711-db9bb60025dc/go.mod h1:ovyxp8AMO1Hoe838vMJUbqHTZaAR8ABM3g3TXu+A5Ng=
github.com/bluesky-social/indigo v0.0.0-20250729223159-573ae927246a h1:S12KN45uIkRglMHC8PqD/Vsz0+u3KbIaBF/6rit8/Pg=
github.com/bluesky-social/indigo v0.0.0-20250729223159-573ae927246a/go.mod h1:0XUyOCRtL4/OiyeqMTmr6RlVHQMDgw3LS7CfibuZR5Q=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
github.com/carlmjohnson/versioninfo v0.22.5 h1:O00sjOLUAFxYQjlN/bzYTuZiS0y6fWDQjMRvwtKgwwc=
github.com/carlmjohnson/versioninfo v0.22.5/go.mod h1:QT9mph3wcVfISUKd0i9sZfVrPviHuSF+cUtLjm2WSf8=
-github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
-github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@@ -37,10 +33,8 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
-github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
-github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -106,8 +100,6 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA=
-github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
@@ -119,14 +111,12 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labstack/echo-contrib v0.17.4 h1:g5mfsrJfJTKv+F5uNKCyrjLK7js+ZW6HTjg4FnDxxgk=
github.com/labstack/echo-contrib v0.17.4/go.mod h1:9O7ZPAHUeMGTOAfg80YqQduHzt0CzLak36PZRldYrZ0=
-github.com/labstack/echo/v4 v4.11.3 h1:Upyu3olaqSHkCjs1EJJwQ3WId8b8b1hxbogyommKktM=
-github.com/labstack/echo/v4 v4.11.3/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws=
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
-github.com/labstack/gommon v0.4.1 h1:gqEff0p/hTENGMABzezPoPSRtIh1Cvw0ueMOe0/dfOk=
-github.com/labstack/gommon v0.4.1/go.mod h1:TyTrpPqxR5KMk8LKVtLmfMjeQ5FEkBYdxLYPw/WfrOM=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
@@ -142,18 +132,13 @@ github.com/lestrrat-go/jwx/v2 v2.0.12/go.mod h1:Mq4KN1mM7bp+5z/W5HS8aCNs5RKZ911G
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
-github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
-github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
-github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
-github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
@@ -179,20 +164,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0=
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
-github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
-github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
-github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
-github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
-github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
-github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
-github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
-github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -221,8 +198,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
-github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
@@ -276,8 +253,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
-golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
-golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@@ -297,8 +272,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
-golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -307,8 +280,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
-golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -322,13 +293,10 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
-golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -342,12 +310,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
-golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
-golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -368,8 +332,6 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
-google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
-google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
--
2.51.2
From 0a00e02c701aee2151b8f708e9b53af81a41d44e Mon Sep 17 00:00:00 2001
From: pfrazee <1270099+pfrazee@users.noreply.github.com>
Date: Wed, 30 Jul 2025 02:51:39 +0000
Subject: [PATCH 34/45] Nightly source-language update
---
src/locale/locales/en/messages.po | 53 ++++++++++++++++++-------------
1 file changed, 31 insertions(+), 22 deletions(-)
diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po
index 69532591c..3a5480a5c 100644
--- a/src/locale/locales/en/messages.po
+++ b/src/locale/locales/en/messages.po
@@ -966,8 +966,8 @@ msgstr ""
#: src/components/hooks/useFollowMethods.ts:35
#: src/components/hooks/useFollowMethods.ts:50
-#: src/components/ProfileCard.tsx:457
-#: src/components/ProfileCard.tsx:478
+#: src/components/ProfileCard.tsx:484
+#: src/components/ProfileCard.tsx:505
#: src/view/com/profile/FollowButton.tsx:38
#: src/view/com/profile/FollowButton.tsx:48
msgid "An issue occurred, please try again."
@@ -1262,7 +1262,7 @@ msgid "Birthday"
msgstr ""
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:757
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:319
+#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:320
#: src/view/com/profile/ProfileMenu.tsx:473
msgid "Block"
msgstr ""
@@ -1423,23 +1423,20 @@ msgstr ""
msgid "Books"
msgstr ""
-#: src/components/FeedInterstitials.tsx:379
+#: src/components/FeedInterstitials.tsx:436
msgid "Browse more accounts on the Explore page"
msgstr ""
-#: src/components/FeedInterstitials.tsx:517
+#: src/components/FeedInterstitials.tsx:566
msgid "Browse more feeds on the Explore page"
msgstr ""
-#: src/components/FeedInterstitials.tsx:359
-#: src/components/FeedInterstitials.tsx:362
-#: src/components/FeedInterstitials.tsx:498
-#: src/components/FeedInterstitials.tsx:501
+#: src/components/FeedInterstitials.tsx:547
+#: src/components/FeedInterstitials.tsx:550
msgid "Browse more suggestions"
msgstr ""
-#: src/components/FeedInterstitials.tsx:387
-#: src/components/FeedInterstitials.tsx:526
+#: src/components/FeedInterstitials.tsx:575
msgid "Browse more suggestions on the Explore page"
msgstr ""
@@ -3618,7 +3615,7 @@ msgid "Flexible"
msgstr ""
#. User is not following this account, click to follow
-#: src/components/ProfileCard.tsx:490
+#: src/components/ProfileCard.tsx:517
#: src/components/ProfileHoverCard/index.web.tsx:494
#: src/components/ProfileHoverCard/index.web.tsx:505
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:245
@@ -3696,7 +3693,7 @@ msgid "Followers you know"
msgstr ""
#. User is following this account, click to unfollow
-#: src/components/ProfileCard.tsx:484
+#: src/components/ProfileCard.tsx:511
#: src/components/ProfileHoverCard/index.web.tsx:493
#: src/components/ProfileHoverCard/index.web.tsx:504
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:241
@@ -3711,7 +3708,7 @@ msgctxt "feed-name"
msgid "Following"
msgstr ""
-#: src/components/ProfileCard.tsx:447
+#: src/components/ProfileCard.tsx:474
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:89
msgid "Following {0}"
msgstr ""
@@ -5459,7 +5456,7 @@ msgstr ""
msgid "No likes yet"
msgstr ""
-#: src/components/ProfileCard.tsx:469
+#: src/components/ProfileCard.tsx:496
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:110
msgid "No longer following {0}"
msgstr ""
@@ -7398,6 +7395,18 @@ msgstr ""
msgid "See jobs at Bluesky"
msgstr ""
+#: src/components/FeedInterstitials.tsx:397
+msgid "See more"
+msgstr ""
+
+#: src/components/FeedInterstitials.tsx:444
+msgid "See more accounts you might like"
+msgstr ""
+
+#: src/components/FeedInterstitials.tsx:395
+msgid "See more suggested profiles on the Explore page"
+msgstr ""
+
#: src/view/screens/SavedFeeds.tsx:213
msgid "See this guide"
msgstr ""
@@ -7975,7 +7984,7 @@ msgstr ""
msgid "Signed in as @{0}"
msgstr ""
-#: src/components/FeedInterstitials.tsx:343
+#: src/components/FeedInterstitials.tsx:389
msgid "Similar accounts"
msgstr ""
@@ -8005,7 +8014,7 @@ msgstr ""
msgid "Some of your verifications are invalid."
msgstr ""
-#: src/components/FeedInterstitials.tsx:480
+#: src/components/FeedInterstitials.tsx:529
msgid "Some other feeds you might like"
msgstr ""
@@ -8237,7 +8246,7 @@ msgstr ""
msgid "Suggested Accounts"
msgstr ""
-#: src/components/FeedInterstitials.tsx:345
+#: src/components/FeedInterstitials.tsx:391
msgid "Suggested for you"
msgstr ""
@@ -8421,7 +8430,7 @@ msgstr ""
msgid "That's everything!"
msgstr ""
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:315
+#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:316
#: src/view/com/profile/ProfileMenu.tsx:461
msgid "The account will be able to interact with you after unblocking."
msgstr ""
@@ -9046,7 +9055,7 @@ msgstr ""
#: src/components/dms/MessagesListBlockedFooter.tsx:112
#: src/components/dms/MessagesListBlockedFooter.tsx:119
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:203
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:319
+#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:320
#: src/view/com/profile/ProfileMenu.tsx:473
#: src/view/screens/ProfileList.tsx:723
msgid "Unblock"
@@ -9064,7 +9073,7 @@ msgstr ""
msgid "Unblock account"
msgstr ""
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:313
+#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:314
#: src/view/com/profile/ProfileMenu.tsx:455
msgid "Unblock Account?"
msgstr ""
@@ -9571,7 +9580,7 @@ msgstr ""
msgid "View {0}'s avatar"
msgstr ""
-#: src/components/ProfileCard.tsx:118
+#: src/components/ProfileCard.tsx:124
#: src/screens/Profile/components/ProfileFeedHeader.tsx:454
#: src/screens/Search/components/SearchProfileCard.tsx:36
#: src/screens/VideoFeed/index.tsx:790
--
2.51.2
From 34ea6e8f3499eeeb1013dfbf7c4dcd3bdcf149a3 Mon Sep 17 00:00:00 2001
From: Ana
Date: Tue, 29 Jul 2025 18:15:32 -0700
Subject: [PATCH 35/45] update: toast styles that reuse consistent style
---
src/view/com/util/Toast.tsx | 182 +++++++++-----------------
src/view/com/util/Toast.web.tsx | 148 ++++++++++-----------
src/view/screens/Storybook/Toasts.tsx | 139 ++++++++++++--------
3 files changed, 216 insertions(+), 253 deletions(-)
diff --git a/src/view/com/util/Toast.tsx b/src/view/com/util/Toast.tsx
index fc9bdf672..2f8888bef 100644
--- a/src/view/com/util/Toast.tsx
+++ b/src/view/com/util/Toast.tsx
@@ -6,8 +6,8 @@ import {
GestureHandlerRootView,
} from 'react-native-gesture-handler'
import Animated, {
- FadeInUp,
- FadeOutUp,
+ FadeIn,
+ FadeOut,
runOnJS,
useAnimatedReaction,
useAnimatedStyle,
@@ -17,53 +17,36 @@ import Animated, {
} from 'react-native-reanimated'
import RootSiblings from 'react-native-root-siblings'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
-import {
- FontAwesomeIcon,
- type Props as FontAwesomeProps,
-} from '@fortawesome/react-native-fontawesome'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
-import {isWeb} from '#/platform/detection'
import {atoms as a, useTheme} from '#/alf'
import {Text} from '#/components/Typography'
+import {
+ type ToastType,
+ TOAST_TYPE_TO_ICON,
+ getToastTypeStyles,
+ TOAST_ANIMATION_CONFIG,
+} from './Toast.style'
const TIMEOUT = 2e3
-export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info'
-
-const TOAST_TYPE_TO_ICON: Record = {
- default: 'check',
- success: 'check',
- error: 'exclamation',
- warning: 'circle-exclamation',
- info: 'info',
-}
-
-export function show(
- message: string,
- type: ToastType | FontAwesomeProps['icon'] = 'default',
-) {
+export function show(message: string, type: ToastType = 'default') {
if (process.env.NODE_ENV === 'test') {
return
}
- const icon =
- typeof type === 'string' && type in TOAST_TYPE_TO_ICON
- ? TOAST_TYPE_TO_ICON[type as ToastType]
- : (type as FontAwesomeProps['icon'])
-
AccessibilityInfo.announceForAccessibility(message)
const item = new RootSiblings(
- item.destroy()} />,
+ item.destroy()} />,
)
}
function Toast({
message,
- icon,
+ type,
destroy,
}: {
message: string
- icon: FontAwesomeProps['icon']
+ type: ToastType
destroy: () => void
}) {
const t = useTheme()
@@ -72,6 +55,10 @@ function Toast({
const dismissSwipeTranslateY = useSharedValue(0)
const [cardHeight, setCardHeight] = useState(0)
+ const toastStyles = getToastTypeStyles(t)
+ const colors = toastStyles[type]
+ const IconComponent = TOAST_TYPE_TO_ICON[type]
+
// for the exit animation to work on iOS the animated component
// must not be the root component
// so we need to wrap it in a view and unmount the toast ahead of time
@@ -169,103 +156,58 @@ function Toast({
}
})
- // Web-specific styles for better compatibility
- const webContainerStyle = isWeb
- ? {
- position: 'absolute' as const,
- top: topOffset,
- left: 16,
- right: 16,
- zIndex: 9999,
- pointerEvents: 'auto' as const,
- }
- : {}
-
- const webToastStyle = isWeb
- ? {
- backgroundColor:
- t.name === 'dark' ? t.palette.contrast_25 : t.palette.white,
- shadowColor: '#000',
- shadowOffset: {width: 0, height: 10},
- shadowOpacity: 0.1,
- shadowRadius: 15,
- elevation: 10,
- borderColor: t.palette.contrast_300,
- borderWidth: 1,
- borderRadius: 8,
- minHeight: 60,
- }
- : {}
-
return (
{alive && (
- setCardHeight(evt.nativeEvent.layout.height)}
- accessibilityRole="alert"
- accessible={true}
- accessibilityLabel={message}
- accessibilityHint=""
- onAccessibilityEscape={hideAndDestroyImmediately}
- style={[
- a.flex_1,
- isWeb
- ? webToastStyle
- : [
- t.name === 'dark' ? t.atoms.bg_contrast_25 : t.atoms.bg,
- a.shadow_lg,
- t.atoms.border_contrast_medium,
- a.rounded_sm,
- a.border,
- ],
- !isWeb && animatedStyle,
- ]}>
-
-
-
-
-
-
-
- {message}
-
-
+ entering={FadeIn.duration(TOAST_ANIMATION_CONFIG.duration)}
+ exiting={FadeOut.duration(TOAST_ANIMATION_CONFIG.duration * 0.7)}
+ onLayout={evt => setCardHeight(evt.nativeEvent.layout.height)}
+ accessibilityRole="alert"
+ accessible={true}
+ accessibilityLabel={message}
+ accessibilityHint=""
+ onAccessibilityEscape={hideAndDestroyImmediately}
+ style={[
+ a.flex_1,
+ {backgroundColor: colors.backgroundColor},
+ a.shadow_sm,
+ {borderColor: colors.borderColor, borderWidth: 1},
+ a.rounded_sm,
+ animatedStyle,
+ ]}>
+
+
+
+
+
+
+
+ {message}
+
-
-
+
+
)}
diff --git a/src/view/com/util/Toast.web.tsx b/src/view/com/util/Toast.web.tsx
index 949dce7ef..331a8b539 100644
--- a/src/view/com/util/Toast.web.tsx
+++ b/src/view/com/util/Toast.web.tsx
@@ -4,28 +4,19 @@
import {useEffect, useState} from 'react'
import {Pressable, StyleSheet, Text, View} from 'react-native'
+import {atoms as a, useTheme} from '#/alf'
import {
- FontAwesomeIcon,
- type FontAwesomeIconStyle,
- type Props as FontAwesomeProps,
-} from '@fortawesome/react-native-fontawesome'
-import {atoms as a, useBreakpoints, useTheme} from '#/alf'
-
-const DURATION = 60000
-
-export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info'
-
-const TOAST_TYPE_TO_ICON: Record = {
- default: 'check',
- success: 'check',
- error: 'exclamation',
- warning: 'circle-exclamation',
- info: 'info',
-}
+ type ToastType,
+ TOAST_TYPE_TO_ICON,
+ getToastTypeStyles,
+ getToastWebAnimationStyles,
+ TOAST_WEB_KEYFRAMES,
+} from './Toast.style'
+
+const DURATION = 3500
interface ActiveToast {
text: string
- icon: FontAwesomeProps['icon']
type: ToastType
}
type GlobalSetActiveToast = (_activeToast: ActiveToast | undefined) => void
@@ -40,50 +31,45 @@ let toastTimeout: NodeJS.Timeout | undefined
type ToastContainerProps = {}
export const ToastContainer: React.FC = ({}) => {
const [activeToast, setActiveToast] = useState()
+ const [isExiting, setIsExiting] = useState(false)
+
useEffect(() => {
globalSetActiveToast = (t: ActiveToast | undefined) => {
- setActiveToast(t)
+ if (!t && activeToast) {
+ setIsExiting(true)
+ setTimeout(() => {
+ setActiveToast(t)
+ setIsExiting(false)
+ }, 200)
+ } else {
+ setActiveToast(t)
+ setIsExiting(false)
+ }
}
- })
+ }, [activeToast])
- const t = useTheme()
+ useEffect(() => {
+ const styleId = 'toast-animations'
+ if (!document.getElementById(styleId)) {
+ const style = document.createElement('style')
+ style.id = styleId
+ style.textContent = TOAST_WEB_KEYFRAMES
+ document.head.appendChild(style)
+ }
+ }, [])
- const TOAST_TYPE_TO_STYLES = {
- default: {
- backgroundColor: t.atoms.text_contrast_low.color,
- borderColor: t.atoms.border_contrast_medium.borderColor,
- iconColor: '#fff',
- textColor: '#fff',
- },
- success: {
- backgroundColor: '#059669',
- borderColor: '#047857',
- iconColor: '#fff',
- textColor: '#fff',
- },
- error: {
- backgroundColor: t.palette.negative_100,
- borderColor: t.palette.negative_400,
- iconColor: t.palette.negative_600,
- textColor: t.palette.negative_600,
- },
- warning: {
- backgroundColor: t.palette.negative_500,
- borderColor: t.palette.negative_600,
- iconColor: '#fff',
- textColor: '#fff',
- },
- info: {
- backgroundColor: t.atoms.text_contrast_low.color,
- borderColor: t.atoms.border_contrast_medium.borderColor,
- iconColor: '#fff',
- textColor: '#fff',
- },
- }
+ const t = useTheme()
+ const toastTypeStyles = getToastTypeStyles(t)
const toastStyles = activeToast
- ? TOAST_TYPE_TO_STYLES[activeToast.type]
- : TOAST_TYPE_TO_STYLES.default
+ ? toastTypeStyles[activeToast.type]
+ : toastTypeStyles.default
+
+ const IconComponent = activeToast
+ ? TOAST_TYPE_TO_ICON[activeToast.type]
+ : TOAST_TYPE_TO_ICON.default
+
+ const animationStyles = getToastWebAnimationStyles()
return (
<>
@@ -94,18 +80,24 @@ export const ToastContainer: React.FC = ({}) => {
{
backgroundColor: toastStyles.backgroundColor,
borderColor: toastStyles.borderColor,
+ ...(isExiting
+ ? animationStyles.exiting
+ : animationStyles.entering),
},
]}>
-
+
+
+
= ({}) => {
// methods
// =
-export function show(
- text: string,
- type: ToastType | FontAwesomeProps['icon'] = 'default',
-) {
+export function show(text: string, type: ToastType = 'default') {
if (toastTimeout) {
clearTimeout(toastTimeout)
}
- // Determine if type is a semantic type or direct icon
- const isSemanticType = typeof type === 'string' && type in TOAST_TYPE_TO_ICON
- const icon = isSemanticType
- ? TOAST_TYPE_TO_ICON[type as ToastType]
- : (type as FontAwesomeProps['icon'])
- const toastType = isSemanticType ? (type as ToastType) : 'default'
-
- globalSetActiveToast?.({text, icon, type: toastType})
+ globalSetActiveToast?.({text, type})
toastTimeout = setTimeout(() => {
globalSetActiveToast?.(undefined)
}, DURATION)
@@ -161,10 +143,10 @@ const styles = StyleSheet.create({
bottom: 20,
// @ts-ignore web only
width: 'calc(100% - 40px)',
- maxWidth: 350,
+ maxWidth: 380,
padding: 20,
flexDirection: 'row',
- alignItems: 'center',
+ alignItems: 'flex-start',
borderRadius: 10,
borderWidth: 1,
},
@@ -175,6 +157,14 @@ const styles = StyleSheet.create({
bottom: 0,
right: 0,
},
+ iconContainer: {
+ width: 32,
+ height: 32,
+ borderRadius: 16,
+ alignItems: 'center',
+ justifyContent: 'center',
+ flexShrink: 0,
+ },
icon: {
flexShrink: 0,
},
diff --git a/src/view/screens/Storybook/Toasts.tsx b/src/view/screens/Storybook/Toasts.tsx
index 714afdfbd..5197ec2f4 100644
--- a/src/view/screens/Storybook/Toasts.tsx
+++ b/src/view/screens/Storybook/Toasts.tsx
@@ -1,68 +1,99 @@
-import {View} from 'react-native'
+import {View, Pressable} from 'react-native'
-import {atoms as a} from '#/alf'
-import {Button, ButtonText} from '#/components/Button'
-import {H1} from '#/components/Typography'
+import {atoms as a, useTheme} from '#/alf'
+import {Text, H1} from '#/components/Typography'
+import {
+ type ToastType,
+ TOAST_TYPE_TO_ICON,
+ getToastTypeStyles,
+} from '#/view/com/util/Toast.style'
import * as Toast from '#/view/com/util/Toast'
-import * as ToastHelpers from '#/view/com/util/ToastHelpers'
+
+function ToastPreview({message, type}: {message: string; type: ToastType}) {
+ const t = useTheme()
+ const toastStyles = getToastTypeStyles(t)
+ const colors = toastStyles[type]
+ const IconComponent = TOAST_TYPE_TO_ICON[type]
+
+ return (
+ Toast.show(message, type)}
+ style={[
+ {backgroundColor: colors.backgroundColor},
+ a.shadow_sm,
+ {borderColor: colors.borderColor},
+ a.rounded_sm,
+ a.border,
+ a.px_sm,
+ a.py_sm,
+ a.flex_row,
+ a.gap_sm,
+ a.align_center,
+ ]}>
+
+
+
+
+
+ {message}
+
+
+
+ )
+}
export function Toasts() {
return (
- Toasts
+ Toast Examples
+
+
+
+
+
-
-
- Toast.show('Operation completed successfully!', 'success')
- }>
- Success!
-
+
+
+
- Toast.show('Something went wrong!', 'error')}>
- Error
-
+
+
+
- Toast.show('Please check your input', 'warning')}>
- Warning
-
+
+
+
- Toast.show("Here's some helpful information", 'info')}>
- Info
-
+
+
+
-
- Toast.show(
- 'This is a longer message to test how the toast handles multiple lines of text content.',
- 'info',
- )
- }>
- Long Message
-
+
+
+
)
--
2.51.2
From 61969e8dfa92fb200b83f13f691093ccaab2a031 Mon Sep 17 00:00:00 2001
From: Ana
Date: Tue, 29 Jul 2025 23:28:10 -0700
Subject: [PATCH 36/45] add: Toast.style
---
src/view/com/util/Toast.style.tsx | 167 ++++++++++++++++++++++++++++++
1 file changed, 167 insertions(+)
create mode 100644 src/view/com/util/Toast.style.tsx
diff --git a/src/view/com/util/Toast.style.tsx b/src/view/com/util/Toast.style.tsx
new file mode 100644
index 000000000..9a7e6b82d
--- /dev/null
+++ b/src/view/com/util/Toast.style.tsx
@@ -0,0 +1,167 @@
+import {type Theme, select} from '#/alf'
+import {CircleInfo_Stroke2_Corner0_Rounded as ErrorIcon} from '#/components/icons/CircleInfo'
+import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
+import {Check_Stroke2_Corner0_Rounded as SuccessIcon} from '#/components/icons/Check'
+import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
+
+export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info'
+
+export const TOAST_ANIMATION_CONFIG = {
+ duration: 300,
+ damping: 15,
+ stiffness: 150,
+ mass: 0.8,
+ overshootClamping: false,
+ restSpeedThreshold: 0.01,
+ restDisplacementThreshold: 0.01,
+}
+
+export const TOAST_TYPE_TO_ICON = {
+ default: SuccessIcon,
+ success: SuccessIcon,
+ error: ErrorIcon,
+ warning: WarningIcon,
+ info: CircleInfo,
+}
+
+export const getToastTypeStyles = (t: Theme) => ({
+ default: {
+ backgroundColor: select(t.name, {
+ light: t.atoms.bg_contrast_25.backgroundColor,
+ dim: t.atoms.bg_contrast_100.backgroundColor,
+ dark: t.atoms.bg_contrast_100.backgroundColor,
+ }),
+ borderColor: select(t.name, {
+ light: t.atoms.border_contrast_low.borderColor,
+ dim: t.atoms.border_contrast_high.borderColor,
+ dark: t.atoms.border_contrast_high.borderColor,
+ }),
+ iconColor: select(t.name, {
+ light: t.atoms.text_contrast_medium.color,
+ dim: t.atoms.text_contrast_medium.color,
+ dark: t.atoms.text_contrast_medium.color,
+ }),
+ textColor: select(t.name, {
+ light: t.atoms.text_contrast_medium.color,
+ dim: t.atoms.text_contrast_medium.color,
+ dark: t.atoms.text_contrast_medium.color,
+ }),
+ },
+ success: {
+ backgroundColor: select(t.name, {
+ light: t.palette.primary_100,
+ dim: t.palette.primary_100,
+ dark: t.palette.primary_50,
+ }),
+ borderColor: select(t.name, {
+ light: t.palette.primary_500,
+ dim: t.palette.primary_500,
+ dark: t.palette.primary_500,
+ }),
+ iconColor: select(t.name, {
+ light: t.palette.primary_500,
+ dim: t.palette.primary_600,
+ dark: t.palette.primary_600,
+ }),
+ textColor: select(t.name, {
+ light: t.palette.primary_500,
+ dim: t.palette.primary_600,
+ dark: t.palette.primary_600,
+ }),
+ },
+ error: {
+ backgroundColor: select(t.name, {
+ light: t.palette.negative_200,
+ dim: t.palette.negative_25,
+ dark: t.palette.negative_25,
+ }),
+ borderColor: select(t.name, {
+ light: t.palette.negative_300,
+ dim: t.palette.negative_300,
+ dark: t.palette.negative_300,
+ }),
+ iconColor: select(t.name, {
+ light: t.palette.negative_600,
+ dim: t.palette.negative_600,
+ dark: t.palette.negative_600,
+ }),
+ textColor: select(t.name, {
+ light: t.palette.negative_600,
+ dim: t.palette.negative_600,
+ dark: t.palette.negative_600,
+ }),
+ },
+ warning: {
+ backgroundColor: select(t.name, {
+ light: t.atoms.bg_contrast_25.backgroundColor,
+ dim: t.atoms.bg_contrast_100.backgroundColor,
+ dark: t.atoms.bg_contrast_100.backgroundColor,
+ }),
+ borderColor: select(t.name, {
+ light: t.atoms.border_contrast_low.borderColor,
+ dim: t.atoms.border_contrast_high.borderColor,
+ dark: t.atoms.border_contrast_high.borderColor,
+ }),
+ iconColor: select(t.name, {
+ light: t.atoms.text_contrast_medium.color,
+ dim: t.atoms.text_contrast_medium.color,
+ dark: t.atoms.text_contrast_medium.color,
+ }),
+ textColor: select(t.name, {
+ light: t.atoms.text_contrast_medium.color,
+ dim: t.atoms.text_contrast_medium.color,
+ dark: t.atoms.text_contrast_medium.color,
+ }),
+ },
+ info: {
+ backgroundColor: select(t.name, {
+ light: t.atoms.bg_contrast_25.backgroundColor,
+ dim: t.atoms.bg_contrast_100.backgroundColor,
+ dark: t.atoms.bg_contrast_100.backgroundColor,
+ }),
+ borderColor: select(t.name, {
+ light: t.atoms.border_contrast_low.borderColor,
+ dim: t.atoms.border_contrast_high.borderColor,
+ dark: t.atoms.border_contrast_high.borderColor,
+ }),
+ iconColor: select(t.name, {
+ light: t.atoms.text_contrast_medium.color,
+ dim: t.atoms.text_contrast_medium.color,
+ dark: t.atoms.text_contrast_medium.color,
+ }),
+ textColor: select(t.name, {
+ light: t.atoms.text_contrast_medium.color,
+ dim: t.atoms.text_contrast_medium.color,
+ dark: t.atoms.text_contrast_medium.color,
+ }),
+ },
+})
+
+export const getToastWebAnimationStyles = () => ({
+ entering: {
+ animation: 'toastFadeIn 0.3s ease-out forwards',
+ },
+ exiting: {
+ animation: 'toastFadeOut 0.2s ease-in forwards',
+ },
+})
+
+export const TOAST_WEB_KEYFRAMES = `
+ @keyframes toastFadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+ }
+
+ @keyframes toastFadeOut {
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
+ }
+`
--
2.51.2
From 67ba92fa624f8edb2878fe65ac19439dff042c29 Mon Sep 17 00:00:00 2001
From: Ana
Date: Wed, 30 Jul 2025 00:02:03 -0700
Subject: [PATCH 37/45] update: imports for toast
---
src/view/com/util/Toast.tsx | 2 +-
src/view/com/util/Toast.web.tsx | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/view/com/util/Toast.tsx b/src/view/com/util/Toast.tsx
index 2f8888bef..9c20e56be 100644
--- a/src/view/com/util/Toast.tsx
+++ b/src/view/com/util/Toast.tsx
@@ -25,7 +25,7 @@ import {
TOAST_TYPE_TO_ICON,
getToastTypeStyles,
TOAST_ANIMATION_CONFIG,
-} from './Toast.style'
+} from '#/view/com/util/Toast.style'
const TIMEOUT = 2e3
diff --git a/src/view/com/util/Toast.web.tsx b/src/view/com/util/Toast.web.tsx
index 331a8b539..fbe31528e 100644
--- a/src/view/com/util/Toast.web.tsx
+++ b/src/view/com/util/Toast.web.tsx
@@ -11,7 +11,7 @@ import {
getToastTypeStyles,
getToastWebAnimationStyles,
TOAST_WEB_KEYFRAMES,
-} from './Toast.style'
+} from '#/view/com/util/Toast.style'
const DURATION = 3500
@@ -146,7 +146,7 @@ const styles = StyleSheet.create({
maxWidth: 380,
padding: 20,
flexDirection: 'row',
- alignItems: 'flex-start',
+ alignItems: 'center',
borderRadius: 10,
borderWidth: 1,
},
--
2.51.2
From f472c7f540840df7d98af22719742944e70ccfa2 Mon Sep 17 00:00:00 2001
From: Ana
Date: Wed, 30 Jul 2025 00:14:28 -0700
Subject: [PATCH 38/45] update sorting
---
src/view/com/util/Toast.style.tsx | 6 +++---
src/view/com/util/Toast.tsx | 18 +++++++++---------
src/view/com/util/Toast.web.tsx | 7 ++++---
src/view/screens/Storybook/Toasts.tsx | 14 +++++++-------
4 files changed, 23 insertions(+), 22 deletions(-)
diff --git a/src/view/com/util/Toast.style.tsx b/src/view/com/util/Toast.style.tsx
index 9a7e6b82d..6bfb12bc1 100644
--- a/src/view/com/util/Toast.style.tsx
+++ b/src/view/com/util/Toast.style.tsx
@@ -1,8 +1,8 @@
-import {type Theme, select} from '#/alf'
-import {CircleInfo_Stroke2_Corner0_Rounded as ErrorIcon} from '#/components/icons/CircleInfo'
-import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
import {Check_Stroke2_Corner0_Rounded as SuccessIcon} from '#/components/icons/Check'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
+import {CircleInfo_Stroke2_Corner0_Rounded as ErrorIcon} from '#/components/icons/CircleInfo'
+import {type Theme, select} from '#/alf'
+import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info'
diff --git a/src/view/com/util/Toast.tsx b/src/view/com/util/Toast.tsx
index 9c20e56be..6fe04f793 100644
--- a/src/view/com/util/Toast.tsx
+++ b/src/view/com/util/Toast.tsx
@@ -1,3 +1,12 @@
+import {atoms as a, useTheme} from '#/alf'
+import {Text} from '#/components/Typography'
+import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
+import {
+ type ToastType,
+ getToastTypeStyles,
+ TOAST_ANIMATION_CONFIG,
+ TOAST_TYPE_TO_ICON,
+} from '#/view/com/util/Toast.style'
import {useEffect, useMemo, useRef, useState} from 'react'
import {AccessibilityInfo, View} from 'react-native'
import {
@@ -17,15 +26,6 @@ import Animated, {
} from 'react-native-reanimated'
import RootSiblings from 'react-native-root-siblings'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
-import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
-import {atoms as a, useTheme} from '#/alf'
-import {Text} from '#/components/Typography'
-import {
- type ToastType,
- TOAST_TYPE_TO_ICON,
- getToastTypeStyles,
- TOAST_ANIMATION_CONFIG,
-} from '#/view/com/util/Toast.style'
const TIMEOUT = 2e3
diff --git a/src/view/com/util/Toast.web.tsx b/src/view/com/util/Toast.web.tsx
index fbe31528e..9ed1f0397 100644
--- a/src/view/com/util/Toast.web.tsx
+++ b/src/view/com/util/Toast.web.tsx
@@ -4,14 +4,15 @@
import {useEffect, useState} from 'react'
import {Pressable, StyleSheet, Text, View} from 'react-native'
-import {atoms as a, useTheme} from '#/alf'
+
import {
- type ToastType,
- TOAST_TYPE_TO_ICON,
getToastTypeStyles,
getToastWebAnimationStyles,
+ TOAST_TYPE_TO_ICON,
TOAST_WEB_KEYFRAMES,
+ type ToastType,
} from '#/view/com/util/Toast.style'
+import {atoms as a, useTheme} from '#/alf'
const DURATION = 3500
diff --git a/src/view/screens/Storybook/Toasts.tsx b/src/view/screens/Storybook/Toasts.tsx
index 5197ec2f4..da0f1c416 100644
--- a/src/view/screens/Storybook/Toasts.tsx
+++ b/src/view/screens/Storybook/Toasts.tsx
@@ -1,13 +1,13 @@
-import {View, Pressable} from 'react-native'
+import {Pressable,View} from 'react-native'
-import {atoms as a, useTheme} from '#/alf'
-import {Text, H1} from '#/components/Typography'
+import * as Toast from '#/view/com/util/Toast'
import {
- type ToastType,
- TOAST_TYPE_TO_ICON,
getToastTypeStyles,
+ TOAST_TYPE_TO_ICON,
+ type ToastType,
} from '#/view/com/util/Toast.style'
-import * as Toast from '#/view/com/util/Toast'
+import {atoms as a, useTheme} from '#/alf'
+import {H1,Text} from '#/components/Typography'
function ToastPreview({message, type}: {message: string; type: ToastType}) {
const t = useTheme()
@@ -16,7 +16,7 @@ function ToastPreview({message, type}: {message: string; type: ToastType}) {
const IconComponent = TOAST_TYPE_TO_ICON[type]
return (
- Toast.show(message, type)}
style={[
{backgroundColor: colors.backgroundColor},
--
2.51.2
From f8781270e5df1d3730192ac463331845af028b4b Mon Sep 17 00:00:00 2001
From: Ana
Date: Wed, 30 Jul 2025 00:36:14 -0700
Subject: [PATCH 39/45] update: toast style after lint
---
src/view/com/util/Toast.style.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/view/com/util/Toast.style.tsx b/src/view/com/util/Toast.style.tsx
index 6bfb12bc1..dfa4f4fd6 100644
--- a/src/view/com/util/Toast.style.tsx
+++ b/src/view/com/util/Toast.style.tsx
@@ -1,7 +1,7 @@
+import {select, type Theme} from '#/alf'
import {Check_Stroke2_Corner0_Rounded as SuccessIcon} from '#/components/icons/Check'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
import {CircleInfo_Stroke2_Corner0_Rounded as ErrorIcon} from '#/components/icons/CircleInfo'
-import {type Theme, select} from '#/alf'
import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info'
--
2.51.2
From 315e7341bf99243bb0249567f62ca20d147e7b53 Mon Sep 17 00:00:00 2001
From: Ana
Date: Wed, 30 Jul 2025 00:40:34 -0700
Subject: [PATCH 40/45] update: lint fixes for toast.tsx
---
src/view/com/util/Toast.tsx | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/view/com/util/Toast.tsx b/src/view/com/util/Toast.tsx
index 6fe04f793..7258eac9d 100644
--- a/src/view/com/util/Toast.tsx
+++ b/src/view/com/util/Toast.tsx
@@ -1,12 +1,3 @@
-import {atoms as a, useTheme} from '#/alf'
-import {Text} from '#/components/Typography'
-import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
-import {
- type ToastType,
- getToastTypeStyles,
- TOAST_ANIMATION_CONFIG,
- TOAST_TYPE_TO_ICON,
-} from '#/view/com/util/Toast.style'
import {useEffect, useMemo, useRef, useState} from 'react'
import {AccessibilityInfo, View} from 'react-native'
import {
@@ -27,6 +18,16 @@ import Animated, {
import RootSiblings from 'react-native-root-siblings'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
+import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
+import {
+ getToastTypeStyles,
+ TOAST_ANIMATION_CONFIG,
+ TOAST_TYPE_TO_ICON,
+ type ToastType,
+} from '#/view/com/util/Toast.style'
+import {atoms as a, useTheme} from '#/alf'
+import {Text} from '#/components/Typography'
+
const TIMEOUT = 2e3
export function show(message: string, type: ToastType = 'default') {
--
2.51.2
From d141921abf23d0694ce399615e70011492434e69 Mon Sep 17 00:00:00 2001
From: Ana
Date: Wed, 30 Jul 2025 00:48:56 -0700
Subject: [PATCH 41/45] add: prettier formating
---
src/view/screens/Storybook/Toasts.tsx | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/view/screens/Storybook/Toasts.tsx b/src/view/screens/Storybook/Toasts.tsx
index da0f1c416..54735f7bb 100644
--- a/src/view/screens/Storybook/Toasts.tsx
+++ b/src/view/screens/Storybook/Toasts.tsx
@@ -1,4 +1,4 @@
-import {Pressable,View} from 'react-native'
+import {Pressable, View} from 'react-native'
import * as Toast from '#/view/com/util/Toast'
import {
@@ -7,7 +7,7 @@ import {
type ToastType,
} from '#/view/com/util/Toast.style'
import {atoms as a, useTheme} from '#/alf'
-import {H1,Text} from '#/components/Typography'
+import {H1, Text} from '#/components/Typography'
function ToastPreview({message, type}: {message: string; type: ToastType}) {
const t = useTheme()
@@ -16,7 +16,8 @@ function ToastPreview({message, type}: {message: string; type: ToastType}) {
const IconComponent = TOAST_TYPE_TO_ICON[type]
return (
- Toast.show(message, type)}
style={[
{backgroundColor: colors.backgroundColor},
--
2.51.2
From 18add1cff9eb36568439d8ea80180c36c1a30260 Mon Sep 17 00:00:00 2001
From: Ana
Date: Wed, 30 Jul 2025 01:08:14 -0700
Subject: [PATCH 42/45] update type errors
---
src/view/com/util/Toast.style.tsx | 12 +++++++++++-
src/view/com/util/Toast.tsx | 5 +++--
src/view/com/util/Toast.web.tsx | 4 ++--
src/view/screens/Storybook/Toasts.tsx | 5 +++--
4 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/src/view/com/util/Toast.style.tsx b/src/view/com/util/Toast.style.tsx
index dfa4f4fd6..8b952fd00 100644
--- a/src/view/com/util/Toast.style.tsx
+++ b/src/view/com/util/Toast.style.tsx
@@ -4,7 +4,17 @@ import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/ico
import {CircleInfo_Stroke2_Corner0_Rounded as ErrorIcon} from '#/components/icons/CircleInfo'
import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
-export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info'
+export type ToastType =
+ | 'default'
+ | 'success'
+ | 'error'
+ | 'warning'
+ | 'info'
+ | 'xmark'
+ | 'exclamation-circle'
+ | 'check'
+ | 'clipboard-check'
+ | 'circle-exclamation'
export const TOAST_ANIMATION_CONFIG = {
duration: 300,
diff --git a/src/view/com/util/Toast.tsx b/src/view/com/util/Toast.tsx
index 7258eac9d..4c999ca2a 100644
--- a/src/view/com/util/Toast.tsx
+++ b/src/view/com/util/Toast.tsx
@@ -57,8 +57,9 @@ function Toast({
const [cardHeight, setCardHeight] = useState(0)
const toastStyles = getToastTypeStyles(t)
- const colors = toastStyles[type]
- const IconComponent = TOAST_TYPE_TO_ICON[type]
+ const colors = toastStyles[type as keyof typeof toastStyles]
+ const IconComponent =
+ TOAST_TYPE_TO_ICON[type as keyof typeof TOAST_TYPE_TO_ICON]
// for the exit animation to work on iOS the animated component
// must not be the root component
diff --git a/src/view/com/util/Toast.web.tsx b/src/view/com/util/Toast.web.tsx
index 9ed1f0397..1abbaa003 100644
--- a/src/view/com/util/Toast.web.tsx
+++ b/src/view/com/util/Toast.web.tsx
@@ -63,11 +63,11 @@ export const ToastContainer: React.FC = ({}) => {
const toastTypeStyles = getToastTypeStyles(t)
const toastStyles = activeToast
- ? toastTypeStyles[activeToast.type]
+ ? toastTypeStyles[activeToast.type as keyof typeof toastTypeStyles]
: toastTypeStyles.default
const IconComponent = activeToast
- ? TOAST_TYPE_TO_ICON[activeToast.type]
+ ? TOAST_TYPE_TO_ICON[activeToast.type as keyof typeof TOAST_TYPE_TO_ICON]
: TOAST_TYPE_TO_ICON.default
const animationStyles = getToastWebAnimationStyles()
diff --git a/src/view/screens/Storybook/Toasts.tsx b/src/view/screens/Storybook/Toasts.tsx
index 54735f7bb..4c17f1c33 100644
--- a/src/view/screens/Storybook/Toasts.tsx
+++ b/src/view/screens/Storybook/Toasts.tsx
@@ -12,8 +12,9 @@ import {H1, Text} from '#/components/Typography'
function ToastPreview({message, type}: {message: string; type: ToastType}) {
const t = useTheme()
const toastStyles = getToastTypeStyles(t)
- const colors = toastStyles[type]
- const IconComponent = TOAST_TYPE_TO_ICON[type]
+ const colors = toastStyles[type as keyof typeof toastStyles]
+ const IconComponent =
+ TOAST_TYPE_TO_ICON[type as keyof typeof TOAST_TYPE_TO_ICON]
return (
Date: Wed, 30 Jul 2025 18:17:57 +0300
Subject: [PATCH 43/45] Fix dataSet for noFeedback links (#8745)
* fix dataSet for noFeedback links
* rm memo
* rm useless spread
---
src/view/com/util/Link.tsx | 22 ++++++++--------------
1 file changed, 8 insertions(+), 14 deletions(-)
diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx
index 6a931d9a4..496b77182 100644
--- a/src/view/com/util/Link.tsx
+++ b/src/view/com/util/Link.tsx
@@ -101,13 +101,9 @@ export const Link = memo(function Link({
{name: 'activate', label: title},
]
- const dataSet = useMemo(() => {
- const ds = {...dataSetProp}
- if (anchorNoUnderline) {
- ds.noUnderline = 1
- }
- return ds
- }, [dataSetProp, anchorNoUnderline])
+ const dataSet = anchorNoUnderline
+ ? {...dataSetProp, noUnderline: 1}
+ : dataSetProp
if (noFeedback) {
return (
@@ -125,6 +121,8 @@ export const Link = memo(function Link({
onAccessibilityAction?.(e)
}
}}
+ // @ts-ignore web only -sfn
+ dataSet={dataSet}
{...props}
android_ripple={{
color: t.atoms.bg_contrast_25.backgroundColor,
@@ -198,13 +196,9 @@ export const TextLink = memo(function TextLink({
console.error('Unable to detect mismatching label')
}
- const dataSet = useMemo(() => {
- const ds = {...dataSetProp}
- if (anchorNoUnderline) {
- ds.noUnderline = 1
- }
- return ds
- }, [dataSetProp, anchorNoUnderline])
+ const dataSet = anchorNoUnderline
+ ? {...dataSetProp, noUnderline: 1}
+ : dataSetProp
const onPress = useCallback(
(e?: Event) => {
--
2.51.2
From db7bdae51a1a06e67856b887e4e63a183fa5f479 Mon Sep 17 00:00:00 2001
From: Samuel Newman
Date: Wed, 30 Jul 2025 18:18:36 +0300
Subject: [PATCH 44/45] Convert old toast types to new ones, mark as deprecated
(#8746)
* convert old types to new types
* add depreciation warning for old warnings
* rm as consts
---
src/view/com/util/Toast.style.tsx | 38 +++++++++++++++++++++++++------
src/view/com/util/Toast.tsx | 27 ++++++++++++++++++----
src/view/com/util/Toast.web.tsx | 13 +++++++----
3 files changed, 62 insertions(+), 16 deletions(-)
diff --git a/src/view/com/util/Toast.style.tsx b/src/view/com/util/Toast.style.tsx
index 8b952fd00..3869e6890 100644
--- a/src/view/com/util/Toast.style.tsx
+++ b/src/view/com/util/Toast.style.tsx
@@ -4,18 +4,42 @@ import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/ico
import {CircleInfo_Stroke2_Corner0_Rounded as ErrorIcon} from '#/components/icons/CircleInfo'
import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
-export type ToastType =
- | 'default'
- | 'success'
- | 'error'
- | 'warning'
- | 'info'
+export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info'
+
+export type LegacyToastType =
| 'xmark'
| 'exclamation-circle'
| 'check'
| 'clipboard-check'
| 'circle-exclamation'
+export const convertLegacyToastType = (
+ type: ToastType | LegacyToastType,
+): ToastType => {
+ switch (type) {
+ // these ones are fine
+ case 'default':
+ case 'success':
+ case 'error':
+ case 'warning':
+ case 'info':
+ return type
+ // legacy ones need conversion
+ case 'xmark':
+ return 'error'
+ case 'exclamation-circle':
+ return 'warning'
+ case 'check':
+ return 'success'
+ case 'clipboard-check':
+ return 'success'
+ case 'circle-exclamation':
+ return 'warning'
+ default:
+ return 'default'
+ }
+}
+
export const TOAST_ANIMATION_CONFIG = {
duration: 300,
damping: 15,
@@ -165,7 +189,7 @@ export const TOAST_WEB_KEYFRAMES = `
opacity: 1;
}
}
-
+
@keyframes toastFadeOut {
from {
opacity: 1;
diff --git a/src/view/com/util/Toast.tsx b/src/view/com/util/Toast.tsx
index 4c999ca2a..54ef7042d 100644
--- a/src/view/com/util/Toast.tsx
+++ b/src/view/com/util/Toast.tsx
@@ -20,7 +20,9 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import {
+ convertLegacyToastType,
getToastTypeStyles,
+ type LegacyToastType,
TOAST_ANIMATION_CONFIG,
TOAST_TYPE_TO_ICON,
type ToastType,
@@ -30,14 +32,30 @@ import {Text} from '#/components/Typography'
const TIMEOUT = 2e3
-export function show(message: string, type: ToastType = 'default') {
+// Use type overloading to mark certain types as deprecated -sfn
+// https://stackoverflow.com/a/78325851/13325987
+export function show(message: string, type?: ToastType): void
+/**
+ * @deprecated type is deprecated - use one of `'default' | 'success' | 'error' | 'warning' | 'info'`
+ */
+export function show(message: string, type?: LegacyToastType): void
+export function show(
+ message: string,
+ type: ToastType | LegacyToastType = 'default',
+): void {
if (process.env.NODE_ENV === 'test') {
return
}
AccessibilityInfo.announceForAccessibility(message)
const item = new RootSiblings(
- item.destroy()} />,
+ (
+ item.destroy()}
+ />
+ ),
)
}
@@ -57,9 +75,8 @@ function Toast({
const [cardHeight, setCardHeight] = useState(0)
const toastStyles = getToastTypeStyles(t)
- const colors = toastStyles[type as keyof typeof toastStyles]
- const IconComponent =
- TOAST_TYPE_TO_ICON[type as keyof typeof TOAST_TYPE_TO_ICON]
+ const colors = toastStyles[type]
+ const IconComponent = TOAST_TYPE_TO_ICON[type]
// for the exit animation to work on iOS the animated component
// must not be the root component
diff --git a/src/view/com/util/Toast.web.tsx b/src/view/com/util/Toast.web.tsx
index 1abbaa003..6b99b30bf 100644
--- a/src/view/com/util/Toast.web.tsx
+++ b/src/view/com/util/Toast.web.tsx
@@ -6,8 +6,10 @@ import {useEffect, useState} from 'react'
import {Pressable, StyleSheet, Text, View} from 'react-native'
import {
+ convertLegacyToastType,
getToastTypeStyles,
getToastWebAnimationStyles,
+ type LegacyToastType,
TOAST_TYPE_TO_ICON,
TOAST_WEB_KEYFRAMES,
type ToastType,
@@ -63,11 +65,11 @@ export const ToastContainer: React.FC = ({}) => {
const toastTypeStyles = getToastTypeStyles(t)
const toastStyles = activeToast
- ? toastTypeStyles[activeToast.type as keyof typeof toastTypeStyles]
+ ? toastTypeStyles[activeToast.type]
: toastTypeStyles.default
const IconComponent = activeToast
- ? TOAST_TYPE_TO_ICON[activeToast.type as keyof typeof TOAST_TYPE_TO_ICON]
+ ? TOAST_TYPE_TO_ICON[activeToast.type]
: TOAST_TYPE_TO_ICON.default
const animationStyles = getToastWebAnimationStyles()
@@ -125,12 +127,15 @@ export const ToastContainer: React.FC = ({}) => {
// methods
// =
-export function show(text: string, type: ToastType = 'default') {
+export function show(
+ text: string,
+ type: ToastType | LegacyToastType = 'default',
+) {
if (toastTimeout) {
clearTimeout(toastTimeout)
}
- globalSetActiveToast?.({text, type})
+ globalSetActiveToast?.({text, type: convertLegacyToastType(type)})
toastTimeout = setTimeout(() => {
globalSetActiveToast?.(undefined)
}, DURATION)
--
2.51.2
From d4b23d3ab4e8448321fecc7bd46b6531ada80348 Mon Sep 17 00:00:00 2001
From: Eric Bailey
Date: Wed, 30 Jul 2025 12:33:40 -0500
Subject: [PATCH 45/45] [APP-1173] Clean up env (#8701)
* Clean up env files
* Use new env in Sentry setup file
* Use new env in Bitdrift setup file
* Use new env in chat proxy header
* Prefix Bitdrift key with EXPO_PUBLIC
* Deprecate SENTRY_RELEASE since we use package.json now
* Use existing EXPO_PUBLIC_BUNDLE_IDENTIFIER short commit has as Sentry dist value
* Fix missing bundle identifier for Render deploys
* Deprecate SENTRY_DIST in favor of EXPO_PUBLIC_BUNDLE_IDENTIFIER
* Prefix SENTRY_DSN with EXPO_PUBLIC to match others
* Remove debugging field
* Replace NODE_ENV in places where its safe
* Self review
* Properly patch Sentry package
* Echo variables to .env in Dockerfile instead of passing to shell script
* Make sure EXPO_PUBLIC_ENV is set for web container builds
* Update IS_TESTFLIGHT to include testflight-android
* Slice bundle hash to match other platforms, needed for render.com deployments
* [APP-1331] Migrate `app-info` to new env (#8703)
* Move env files into directory with platform specific files
* Migrate usages of app-info to new env
* Fix bad import
* Update BUNDLE_DATE format comment
* Trim RENDER_GIT_COMMIT to first 7 to match --short sha
* Clarify build process env vars and ensure they are explicitly passed in
* Revert Sentry patch as a result of prev commit
* Update webpack Sentry dist value based on prev commits
* Add PACKAGE_VERSION and replace in statsig to fix conflict
* Fix render substitution syntax
* Remove invalid syntax
* Remove unnecessary testflight check
* Just use long commit hash
* Slice full hash for display in app
* Fix missing space in ios workflow
* Pass in sentry CLI env vars, align matching values
* Align on RELEASE_VERSION
* Add new env setup to missed OTA spot
* Update webpack to use same SENTRY_RELEASE var
* Just fallback to package version for Render deploys
* Remove TF check for BUNDLE_DATE
* Set EXPO_PUBLIC_ENV for bundle update
* Consistent naming "Env"
* Add comment
* Use RELEASE_VERSION instead of package.json
* Update PR comment CI
---
.env.example | 34 ++++++--
.../workflows/build-and-push-bskyweb-aws.yaml | 17 ++--
.github/workflows/build-submit-android.yml | 36 ++++++---
.github/workflows/build-submit-ios.yml | 25 +++---
.../workflows/bundle-deploy-eas-update.yml | 67 +++++++++++-----
.github/workflows/pull-request-comment.yml | 24 +++---
Dockerfile | 29 ++++---
docs/build.md | 4 +-
src/components/PostControls/DiscoverDebug.tsx | 2 +-
.../PostControls/PostMenu/PostMenuItems.tsx | 2 +-
src/env.ts | 6 --
src/env/common.ts | 79 +++++++++++++++++++
src/env/index.ts | 19 +++++
src/env/index.web.ts | 15 ++++
src/lib/app-info.ts | 18 -----
src/lib/app-info.web.ts | 18 -----
src/lib/hooks/useOTAUpdates.ts | 2 +-
src/lib/statsig/statsig.tsx | 20 +++--
src/logger/bitdrift/setup/index.ts | 3 +-
src/logger/index.ts | 3 +-
src/logger/sentry/setup/index.ts | 29 ++-----
src/screens/Settings/AboutSettings.tsx | 10 +--
.../Settings/AppIconSettings/index.tsx | 8 +-
src/screens/Settings/AppearanceSettings.tsx | 2 +-
src/screens/Settings/Settings.tsx | 2 +-
src/state/queries/messages/const.ts | 4 +-
src/state/session/logging.ts | 10 +--
webpack.config.js | 2 +-
28 files changed, 313 insertions(+), 177 deletions(-)
delete mode 100644 src/env.ts
create mode 100644 src/env/common.ts
create mode 100644 src/env/index.ts
create mode 100644 src/env/index.web.ts
delete mode 100644 src/lib/app-info.ts
delete mode 100644 src/lib/app-info.web.ts
diff --git a/.env.example b/.env.example
index a4d21ac33..e18cda4e5 100644
--- a/.env.example
+++ b/.env.example
@@ -1,8 +1,32 @@
-# Copy this to `.env` and `.env.test` files
+# The env the app is running in e.g. development, testflight, production
+EXPO_PUBLIC_ENV=development
-BITDRIFT_API_KEY=
-SENTRY_AUTH_TOKEN=
-EXPO_PUBLIC_LOG_LEVEL=debug
-EXPO_PUBLIC_LOG_DEBUG=
+# This is the semver release version of the app, pulled from package.json
+EXPO_PUBLIC_RELEASE_VERSION=
+
+# This is the commit hash that the current bundle was made from.
EXPO_PUBLIC_BUNDLE_IDENTIFIER=
+
+# Should be formatted YYMMDDHH so that it increases for each build.
EXPO_PUBLIC_BUNDLE_DATE=0
+
+# The log level for the app's logger transports
+EXPO_PUBLIC_LOG_LEVEL=debug
+
+# Enable debug logs for specific logger instances
+EXPO_PUBLIC_LOG_DEBUG=session
+
+# Chat service DID
+EXPO_PUBLIC_CHAT_PROXY_DID=
+
+#
+#
+# Bluesky specific values
+#
+#
+
+# Sentry DSN for telemetry
+EXPO_PUBLIC_SENTRY_DSN=
+
+# Bitdrift API key. If undefined, Bitdrift will be disabled.
+EXPO_PUBLIC_BITDRIFT_API_KEY=
diff --git a/.github/workflows/build-and-push-bskyweb-aws.yaml b/.github/workflows/build-and-push-bskyweb-aws.yaml
index 399e8669f..6d573b0f7 100644
--- a/.github/workflows/build-and-push-bskyweb-aws.yaml
+++ b/.github/workflows/build-and-push-bskyweb-aws.yaml
@@ -43,12 +43,11 @@ jobs:
tags: |
type=sha,enable=true,priority=100,prefix=,suffix=,format=long
- - name: Set outputs
- id: vars
+ - name: Env
+ id: env
run: |
- echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- echo "SENTRY_DIST=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- echo "SENTRY_RELEASE=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- name: Build and push Docker image
id: build-and-push
@@ -62,8 +61,8 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
- EXPO_PUBLIC_BUNDLE_IDENTIFIER=${{ steps.vars.outputs.sha_short }}
- SENTRY_DIST=${{ steps.vars.outputs.SENTRY_DIST }}
- SENTRY_RELEASE=${{ steps.vars.outputs.SENTRY_RELEASE }}
+ EXPO_PUBLIC_ENV=production
+ EXPO_PUBLIC_RELEASE_VERSION=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
+ EXPO_PUBLIC_BUNDLE_IDENTIFIER=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
+ EXPO_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
- SENTRY_DSN=${{ secrets.SENTRY_DSN }}
diff --git a/.github/workflows/build-submit-android.yml b/.github/workflows/build-submit-android.yml
index e862a701f..f1e75f87e 100644
--- a/.github/workflows/build-submit-android.yml
+++ b/.github/workflows/build-submit-android.yml
@@ -62,23 +62,30 @@ jobs:
- name: Check for i18n compilation errors
run: if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compilation errors!\n\n"; fi
- - name: ✏️ Write environment variables
+ # EXPO_PUBLIC_ENV is handled in eas.json
+ - name: Env
+ id: env
run: |
export json='${{ secrets.GOOGLE_SERVICES_TOKEN }}'
echo "${{ secrets.ENV_TOKEN }}" > .env
- echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse --short HEAD)" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> .env
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
- echo "BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
+ echo "EXPO_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env
+ echo "EXPO_PUBLIC_BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
echo "$json" > google-services.json
- - name: Setup Sentry vars for build-time injection
- id: sentry
- run: |
- echo "SENTRY_DIST=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- echo "SENTRY_RELEASE=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
-
- name: 🏗️ EAS Build
- run: SENTRY_DIST=${{ steps.sentry.outputs.SENTRY_DIST }} SENTRY_RELEASE=${{ steps.sentry.outputs.SENTRY_RELEASE }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN=${{ secrets.SENTRY_DSN }} yarn use-build-number-with-bump eas build -p android --profile ${{ inputs.profile || 'testflight-android' }} --local --output build.aab --non-interactive
+ run: >
+ SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
+ SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
+ SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
+ yarn use-build-number-with-bump
+ eas build -p android
+ --profile ${{ inputs.profile || 'testflight-android' }}
+ --local --output build.aab --non-interactive
- name: ✍️ Rename Testflight bundle
if: ${{ inputs.profile != 'production' }}
@@ -140,7 +147,14 @@ jobs:
- name: 🏗️ Build Production APK
if: ${{ inputs.profile == 'production' }}
- run: SENTRY_DIST=${{ steps.sentry.outputs.SENTRY_DIST }} SENTRY_RELEASE=${{ steps.sentry.outputs.SENTRY_RELEASE }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN=${{ secrets.SENTRY_DSN }} yarn use-build-number-with-bump eas build -p android --profile production-apk --local --output build.apk --non-interactive
+ run: >
+ SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
+ SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
+ SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
+ yarn use-build-number-with-bump
+ eas build -p android
+ --profile production-apk
+ --local --output build.apk --non-interactive
- name: 🚀 Upload Production APK Artifact
id: upload-artifact-production-apk
diff --git a/.github/workflows/build-submit-ios.yml b/.github/workflows/build-submit-ios.yml
index a197695db..f3759d0dd 100644
--- a/.github/workflows/build-submit-ios.yml
+++ b/.github/workflows/build-submit-ios.yml
@@ -75,22 +75,29 @@ jobs:
- name: Check for i18n compilation errors
run: if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compilation errors!\n\n"; fi
+ # EXPO_PUBLIC_ENV is handled in eas.json
- name: ✏️ Write environment variables
+ id: env
run: |
echo "${{ secrets.ENV_TOKEN }}" > .env
- echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse --short HEAD)" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> .env
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
- echo "BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
+ echo "EXPO_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env
+ echo "EXPO_PUBLIC_BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
echo "${{ secrets.GOOGLE_SERVICES_TOKEN }}" > google-services.json
- - name: Setup Sentry vars for build-time injection
- id: sentry
- run: |
- echo "SENTRY_DIST=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- echo "SENTRY_RELEASE=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
-
- name: 🏗️ EAS Build
- run: SENTRY_DIST=${{ steps.sentry.outputs.SENTRY_DIST }} SENTRY_RELEASE=${{ steps.sentry.outputs.SENTRY_RELEASE }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN=${{ secrets.SENTRY_DSN }} yarn use-build-number-with-bump eas build -p ios --profile ${{ inputs.profile || 'testflight' }} --local --output build.ipa --non-interactive
+ run: >
+ SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
+ SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
+ SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
+ yarn use-build-number-with-bump
+ eas build -p ios
+ --profile ${{ inputs.profile || 'testflight' }}
+ --local --output build.ipa --non-interactive
- name: 🚀 Deploy
run: eas submit -p ios --non-interactive --path build.ipa
diff --git a/.github/workflows/bundle-deploy-eas-update.yml b/.github/workflows/bundle-deploy-eas-update.yml
index 475bc087f..1bd0b71c4 100644
--- a/.github/workflows/bundle-deploy-eas-update.yml
+++ b/.github/workflows/bundle-deploy-eas-update.yml
@@ -101,25 +101,30 @@ jobs:
if: ${{ !steps.fingerprint.outputs.includes-changes }}
uses: dcarbone/install-jq-action@v2
- - name: ✏️ Write environment variables
+ # eas.json not used here, set EXPO_PUBLIC_ENV
+ - name: Env
+ id: env
if: ${{ !steps.fingerprint.outputs.includes-changes }}
run: |
export json='${{ secrets.GOOGLE_SERVICES_TOKEN }}'
echo "${{ secrets.ENV_TOKEN }}" > .env
- echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse --short HEAD)" >> .env
+ echo "EXPO_PUBLIC_ENV=${{ inputs.channel || 'testflight' }}" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> .env
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
- echo "BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
+ echo "EXPO_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env
+ echo "EXPO_PUBLIC_BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
echo "$json" > google-services.json
- - name: Setup Sentry vars for build-time injection
- id: sentry
- run: |
- echo "SENTRY_DIST=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- echo "SENTRY_RELEASE=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
-
- name: 🏗️ Create Bundle
if: ${{ !steps.fingerprint.outputs.includes-changes }}
- run: SENTRY_DIST=${{ steps.sentry.outputs.SENTRY_DIST }} SENTRY_RELEASE=${{ steps.sentry.outputs.SENTRY_RELEASE }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN=${{ secrets.SENTRY_DSN }} EXPO_PUBLIC_ENV="${{ inputs.channel || 'testflight' }}" yarn export
+ run: >
+ SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
+ SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
+ SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
+ yarn export
- name: 📦 Package Bundle and 🚀 Deploy
if: ${{ !steps.fingerprint.outputs.includes-changes }}
@@ -205,16 +210,29 @@ jobs:
- name: 🔤 Compile translations
run: yarn intl:build
- - name: ✏️ Write environment variables
+ # EXPO_PUBLIC_ENV is handled in eas.json
+ - name: Env
+ id: env
run: |
echo "${{ secrets.ENV_TOKEN }}" > .env
- echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse --short HEAD)" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> .env
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
- echo "BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
+ echo "EXPO_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env
+ echo "EXPO_PUBLIC_BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
echo "${{ secrets.GOOGLE_SERVICES_TOKEN }}" > google-services.json
- name: 🏗️ EAS Build
- run: yarn use-build-number-with-bump eas build -p ios --profile testflight --local --output build.ipa --non-interactive
+ run: >
+ SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
+ SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
+ SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
+ yarn use-build-number-with-bump
+ eas build -p ios
+ --profile testflight
+ --local --output build.ipa --non-interactive
- name: 🚀 Deploy
run: eas submit -p ios --non-interactive --path build.ipa
@@ -282,17 +300,30 @@ jobs:
- name: 🔤 Compile translations
run: yarn intl:build
- - name: ✏️ Write environment variables
+ # EXPO_PUBLIC_ENV is handled in eas.json
+ - name: Env
+ id: env
run: |
export json='${{ secrets.GOOGLE_SERVICES_TOKEN }}'
echo "${{ secrets.ENV_TOKEN }}" > .env
- echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse --short HEAD)" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> .env
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
- echo "BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
+ echo "EXPO_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env
+ echo "EXPO_PUBLIC_BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
echo "$json" > google-services.json
- name: 🏗️ EAS Build
- run: yarn use-build-number-with-bump eas build -p android --profile testflight-android --local --output build.apk --non-interactive
+ run: >
+ SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
+ SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
+ SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
+ yarn use-build-number-with-bump
+ eas build -p android
+ --profile testflight-android
+ --local --output build.apk --non-interactive
- name: ⏰ Get a timestamp
id: timestamp
diff --git a/.github/workflows/pull-request-comment.yml b/.github/workflows/pull-request-comment.yml
index e40eff6c7..d04301002 100644
--- a/.github/workflows/pull-request-comment.yml
+++ b/.github/workflows/pull-request-comment.yml
@@ -152,23 +152,27 @@ jobs:
- name: 🪛 Setup jq
uses: dcarbone/install-jq-action@v2
- - name: ✏️ Write environment variables
+ - name: Env
+ id: env
run: |
export json='${{ secrets.GOOGLE_SERVICES_TOKEN }}'
echo "${{ secrets.ENV_TOKEN }}" > .env
- echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse --short HEAD)" >> .env
+ echo "EXPO_PUBLIC_ENV=testflight" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> .env
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> .env
+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
- echo "BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
+ echo "EXPO_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env
+ echo "EXPO_PUBLIC_BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
echo "$json" > google-services.json
- - name: Setup Sentry vars for build-time injection
- id: sentry
- run: |
- echo "SENTRY_DIST=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- echo "SENTRY_RELEASE=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
-
- name: 🏗️ Create Bundle
- run: SENTRY_DIST=${{ steps.sentry.outputs.SENTRY_DIST }} SENTRY_RELEASE=${{ steps.sentry.outputs.SENTRY_RELEASE }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN=${{ secrets.SENTRY_DSN }} EXPO_PUBLIC_ENV="testflight" yarn export
+ run: >
+ SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
+ SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
+ SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
+ yarn export
- name: 📦 Package Bundle and 🚀 Deploy
run: yarn use-build-number bash scripts/bundleUpdate.sh
diff --git a/Dockerfile b/Dockerfile
index 50dc28b4b..43d7f4eb4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -19,28 +19,28 @@ ENV GOARCH="amd64"
ENV CGO_ENABLED=1
ENV GOEXPERIMENT="loopvar"
+# The latest git hash of the preview branch on render.com
+# https://render.com/docs/docker-secrets#environment-variables-in-docker-builds
+ARG RENDER_GIT_COMMIT
+
#
# Expo
#
+ARG EXPO_PUBLIC_ENV
+ENV EXPO_PUBLIC_ENV=${EXPO_PUBLIC_ENV:-development}
+ARG EXPO_PUBLIC_RELEASE_VERSION
+ENV EXPO_PUBLIC_RELEASE_VERSION=$EXPO_PUBLIC_RELEASE_VERSION
ARG EXPO_PUBLIC_BUNDLE_IDENTIFIER
-ENV EXPO_PUBLIC_BUNDLE_IDENTIFIER=${EXPO_PUBLIC_BUNDLE_IDENTIFIER:-dev}
-
-# The latest git hash of the preview branch on render.com
-ARG RENDER_GIT_COMMIT
+# If not set by GitHub workflows, we're probably in Render
+ENV EXPO_PUBLIC_BUNDLE_IDENTIFIER=${EXPO_PUBLIC_BUNDLE_IDENTIFIER:-$RENDER_GIT_COMMIT}
#
# Sentry
#
ARG SENTRY_AUTH_TOKEN
ENV SENTRY_AUTH_TOKEN=${SENTRY_AUTH_TOKEN:-unknown}
-# Will fall back to package.json#version, but this is handled elsewhere
-ARG SENTRY_RELEASE
-ENV SENTRY_RELEASE=$SENTRY_RELEASE
-ARG SENTRY_DIST
-# Default to RENDER_GIT_COMMIT if not set by GitHub workflows
-ENV SENTRY_DIST=${SENTRY_DIST:-$RENDER_GIT_COMMIT}
-ARG SENTRY_DSN
-ENV SENTRY_DSN=$SENTRY_DSN
+ARG EXPO_PUBLIC_SENTRY_DSN
+ENV EXPO_PUBLIC_SENTRY_DSN=$EXPO_PUBLIC_SENTRY_DSN
#
# Copy everything into the container
@@ -60,13 +60,16 @@ RUN \. "$NVM_DIR/nvm.sh" && \
nvm install $NODE_VERSION && \
nvm use $NODE_VERSION && \
echo "Using bundle identifier: $EXPO_PUBLIC_BUNDLE_IDENTIFIER" && \
+ echo "EXPO_PUBLIC_ENV=$EXPO_PUBLIC_ENV" >> .env && \
+ echo "EXPO_PUBLIC_RELEASE_VERSION=$EXPO_PUBLIC_RELEASE_VERSION" >> .env && \
echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$EXPO_PUBLIC_BUNDLE_IDENTIFIER" >> .env && \
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env && \
+ echo "EXPO_PUBLIC_SENTRY_DSN=$EXPO_PUBLIC_SENTRY_DSN" >> .env && \
npm install --global yarn && \
yarn && \
yarn intl:build 2>&1 | tee i18n.log && \
if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compile errors!\n\n"; fi && \
- EXPO_PUBLIC_BUNDLE_IDENTIFIER=$EXPO_PUBLIC_BUNDLE_IDENTIFIER EXPO_PUBLIC_BUNDLE_DATE=$() SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN SENTRY_RELEASE=$SENTRY_RELEASE SENTRY_DIST=$SENTRY_DIST SENTRY_DSN=$SENTRY_DSN yarn build-web
+ SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN SENTRY_RELEASE=$EXPO_PUBLIC_RELEASE_VERSION SENTRY_DIST=$EXPO_PUBLIC_BUNDLE_IDENTIFIER yarn build-web
# DEBUG
RUN find ./bskyweb/static && find ./web-build/static
diff --git a/docs/build.md b/docs/build.md
index 7817dd095..87b653bdb 100644
--- a/docs/build.md
+++ b/docs/build.md
@@ -89,9 +89,9 @@ If you change `SENTRY_AUTH_TOKEN`, you need to do `yarn prebuild` before running
### Adding bitdrift
-Adding bitdirft is NOT required. You can keep `BITDRIFT_API_KEY=` in `.env` which will avoid initializing bitdrift during startup.
+Adding bitdrift is NOT required. You can keep `EXPO_PUBLIC_BITDRIFT_API_KEY=` in `.env` which will avoid initializing bitdrift during startup.
-However, if you're a part of the Bluesky team and want to enable bitdrift, fill in `BITDRIFT_API_KEY` in your `.env` to enable bitdrift.
+However, if you're a part of the Bluesky team and want to enable bitdrift, fill in `EXPO_PUBLIC_BITDRIFT_API_KEY` in your `.env` to enable bitdrift.
### Adding and Updating Locales
diff --git a/src/components/PostControls/DiscoverDebug.tsx b/src/components/PostControls/DiscoverDebug.tsx
index 796981f0c..403b50cca 100644
--- a/src/components/PostControls/DiscoverDebug.tsx
+++ b/src/components/PostControls/DiscoverDebug.tsx
@@ -2,13 +2,13 @@ import {Pressable} from 'react-native'
import * as Clipboard from 'expo-clipboard'
import {t} from '@lingui/macro'
-import {IS_INTERNAL} from '#/lib/app-info'
import {DISCOVER_DEBUG_DIDS} from '#/lib/constants'
import {useGate} from '#/lib/statsig/statsig'
import {useSession} from '#/state/session'
import * as Toast from '#/view/com/util/Toast'
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {Text} from '#/components/Typography'
+import {IS_INTERNAL} from '#/env'
export function DiscoverDebug({
feedContext,
diff --git a/src/components/PostControls/PostMenu/PostMenuItems.tsx b/src/components/PostControls/PostMenu/PostMenuItems.tsx
index f0ef9ed05..ecc3d0174 100644
--- a/src/components/PostControls/PostMenu/PostMenuItems.tsx
+++ b/src/components/PostControls/PostMenu/PostMenuItems.tsx
@@ -17,7 +17,6 @@ import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native'
-import {IS_INTERNAL} from '#/lib/app-info'
import {DISCOVER_DEBUG_DIDS} from '#/lib/constants'
import {useOpenLink} from '#/lib/hooks/useOpenLink'
import {getCurrentRoute} from '#/lib/routes/helpers'
@@ -83,6 +82,7 @@ import {
useReportDialogControl,
} from '#/components/moderation/ReportDialog'
import * as Prompt from '#/components/Prompt'
+import {IS_INTERNAL} from '#/env'
import * as bsky from '#/types/bsky'
let PostMenuItems = ({
diff --git a/src/env.ts b/src/env.ts
deleted file mode 100644
index 32ce70670..000000000
--- a/src/env.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export const LOG_DEBUG = process.env.EXPO_PUBLIC_LOG_DEBUG || ''
-export const LOG_LEVEL = (process.env.EXPO_PUBLIC_LOG_LEVEL || 'info') as
- | 'debug'
- | 'info'
- | 'warn'
- | 'error'
diff --git a/src/env/common.ts b/src/env/common.ts
new file mode 100644
index 000000000..e68e9fab8
--- /dev/null
+++ b/src/env/common.ts
@@ -0,0 +1,79 @@
+import {type Did} from '@atproto/api'
+
+import packageJson from '#/../package.json'
+
+/**
+ * The semver version of the app, as defined in `package.json.`
+ *
+ * N.B. The fallback is needed for Render.com deployments
+ */
+export const RELEASE_VERSION: string =
+ process.env.EXPO_PUBLIC_RELEASE_VERSION || packageJson.version
+
+/**
+ * The env the app is running in e.g. development, testflight, production
+ */
+export const ENV: string = process.env.EXPO_PUBLIC_ENV
+
+/**
+ * Indicates whether the app is running in TestFlight
+ */
+export const IS_TESTFLIGHT = ENV === 'testflight'
+
+/**
+ * Indicates whether the app is __DEV__
+ */
+export const IS_DEV = __DEV__
+
+/**
+ * Indicates whether the app is __DEV__ or TestFlight
+ */
+export const IS_INTERNAL = IS_DEV || IS_TESTFLIGHT
+
+/**
+ * The commit hash that the current bundle was made from. The user can
+ * see the commit hash in the app's settings along with the other version info.
+ * Useful for debugging/reporting.
+ */
+export const BUNDLE_IDENTIFIER: string =
+ process.env.EXPO_PUBLIC_BUNDLE_IDENTIFIER || 'dev'
+
+/**
+ * This will always be in the format of YYMMDDHH, so that it always increases
+ * for each build. This should only be used for StatSig reporting and shouldn't
+ * be used to identify a specific bundle.
+ */
+export const BUNDLE_DATE: number = !process.env.EXPO_PUBLIC_BUNDLE_DATE
+ ? 0
+ : Number(process.env.EXPO_PUBLIC_BUNDLE_DATE)
+
+/**
+ * The log level for the app.
+ */
+export const LOG_LEVEL = (process.env.EXPO_PUBLIC_LOG_LEVEL || 'info') as
+ | 'debug'
+ | 'info'
+ | 'warn'
+ | 'error'
+
+/**
+ * Enable debug logs for specific logger instances
+ */
+export const LOG_DEBUG: string = process.env.EXPO_PUBLIC_LOG_DEBUG || ''
+
+/**
+ * The DID of the chat service to proxy to
+ */
+export const CHAT_PROXY_DID: Did =
+ process.env.EXPO_PUBLIC_CHAT_PROXY_DID || 'did:web:api.bsky.chat'
+
+/**
+ * Sentry DSN for telemetry
+ */
+export const SENTRY_DSN: string | undefined = process.env.EXPO_PUBLIC_SENTRY_DSN
+
+/**
+ * Bitdrift API key. If undefined, Bitdrift should be disabled.
+ */
+export const BITDRIFT_API_KEY: string | undefined =
+ process.env.EXPO_PUBLIC_BITDRIFT_API_KEY
diff --git a/src/env/index.ts b/src/env/index.ts
new file mode 100644
index 000000000..8558c55b5
--- /dev/null
+++ b/src/env/index.ts
@@ -0,0 +1,19 @@
+import {nativeBuildVersion} from 'expo-application'
+
+import {BUNDLE_IDENTIFIER, IS_TESTFLIGHT, RELEASE_VERSION} from '#/env/common'
+
+export * from '#/env/common'
+
+/**
+ * The semver version of the app, specified in our `package.json`.file. On
+ * iOs/Android, the native build version is appended to the semver version, so
+ * that it can be used to identify a specific build.
+ */
+export const APP_VERSION = `${RELEASE_VERSION}.${nativeBuildVersion}`
+
+/**
+ * The short commit hash and environment of the current bundle.
+ */
+export const APP_METADATA = `${BUNDLE_IDENTIFIER.slice(0, 7)} (${
+ __DEV__ ? 'dev' : IS_TESTFLIGHT ? 'tf' : 'prod'
+})`
diff --git a/src/env/index.web.ts b/src/env/index.web.ts
new file mode 100644
index 000000000..66087749b
--- /dev/null
+++ b/src/env/index.web.ts
@@ -0,0 +1,15 @@
+import {BUNDLE_IDENTIFIER, RELEASE_VERSION} from '#/env/common'
+
+export * from '#/env/common'
+
+/**
+ * The semver version of the app, specified in our `package.json`.file. On
+ * iOs/Android, the native build version is appended to the semver version, so
+ * that it can be used to identify a specific build.
+ */
+export const APP_VERSION = RELEASE_VERSION
+
+/**
+ * The short commit hash and environment of the current bundle.
+ */
+export const APP_METADATA = `${BUNDLE_IDENTIFIER.slice(0, 7)} (${__DEV__ ? 'dev' : 'prod'})`
diff --git a/src/lib/app-info.ts b/src/lib/app-info.ts
deleted file mode 100644
index 0749087ea..000000000
--- a/src/lib/app-info.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import {nativeApplicationVersion, nativeBuildVersion} from 'expo-application'
-
-export const IS_TESTFLIGHT = process.env.EXPO_PUBLIC_ENV === 'testflight'
-export const IS_INTERNAL = __DEV__ || IS_TESTFLIGHT
-
-// This is the commit hash that the current bundle was made from. The user can see the commit hash in the app's settings
-// along with the other version info. Useful for debugging/reporting.
-export const BUNDLE_IDENTIFIER = process.env.EXPO_PUBLIC_BUNDLE_IDENTIFIER ?? ''
-
-// This will always be in the format of YYMMDD, so that it always increases for each build. This should only be used
-// for Statsig reporting and shouldn't be used to identify a specific bundle.
-export const BUNDLE_DATE =
- IS_TESTFLIGHT || __DEV__ ? 0 : Number(process.env.EXPO_PUBLIC_BUNDLE_DATE)
-
-export const appVersion = `${nativeApplicationVersion}.${nativeBuildVersion}`
-export const bundleInfo = `${BUNDLE_IDENTIFIER} (${
- __DEV__ ? 'dev' : IS_TESTFLIGHT ? 'tf' : 'prod'
-})`
diff --git a/src/lib/app-info.web.ts b/src/lib/app-info.web.ts
deleted file mode 100644
index 1530d9976..000000000
--- a/src/lib/app-info.web.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import packageDotJson from '../../package.json'
-
-export const IS_TESTFLIGHT = false
-export const IS_INTERNAL = __DEV__
-
-// This is the commit hash that the current bundle was made from. The user can see the commit hash in the app's settings
-// along with the other version info. Useful for debugging/reporting.
-export const BUNDLE_IDENTIFIER =
- process.env.EXPO_PUBLIC_BUNDLE_IDENTIFIER ?? 'dev'
-
-// This will always be in the format of YYMMDD, so that it always increases for each build. This should only be used
-// for Statsig reporting and shouldn't be used to identify a specific bundle.
-export const BUNDLE_DATE = __DEV__
- ? 0
- : Number(process.env.EXPO_PUBLIC_BUNDLE_DATE)
-
-export const appVersion = packageDotJson.version
-export const bundleInfo = `${BUNDLE_IDENTIFIER} (${__DEV__ ? 'dev' : 'prod'})`
diff --git a/src/lib/hooks/useOTAUpdates.ts b/src/lib/hooks/useOTAUpdates.ts
index 864d5d697..ba46b6055 100644
--- a/src/lib/hooks/useOTAUpdates.ts
+++ b/src/lib/hooks/useOTAUpdates.ts
@@ -10,9 +10,9 @@ import {
useUpdates,
} from 'expo-updates'
-import {IS_TESTFLIGHT} from '#/lib/app-info'
import {logger} from '#/logger'
import {isIOS} from '#/platform/detection'
+import {IS_TESTFLIGHT} from '#/env'
const MINIMUM_MINIMIZE_TIME = 15 * 60e3
diff --git a/src/lib/statsig/statsig.tsx b/src/lib/statsig/statsig.tsx
index f2d3ffca9..1091c82e0 100644
--- a/src/lib/statsig/statsig.tsx
+++ b/src/lib/statsig/statsig.tsx
@@ -3,12 +3,11 @@ import {Platform} from 'react-native'
import {AppState, type AppStateStatus} from 'react-native'
import {Statsig, StatsigProvider} from 'statsig-react-native-expo'
-import {BUNDLE_DATE, BUNDLE_IDENTIFIER, IS_TESTFLIGHT} from '#/lib/app-info'
import {logger} from '#/logger'
import {type MetricEvents} from '#/logger/metrics'
import {isWeb} from '#/platform/detection'
import * as persisted from '#/state/persisted'
-import packageDotJson from '../../../package.json'
+import * as env from '#/env'
import {useSession} from '../../state/session'
import {timeout} from '../async/timeout'
import {useNonReactiveCallback} from '../hooks/useNonReactiveCallback'
@@ -49,12 +48,11 @@ export type {MetricEvents as LogEvents}
function createStatsigOptions(prefetchUsers: StatsigUser[]) {
return {
environment: {
- tier:
- process.env.NODE_ENV === 'development'
- ? 'development'
- : IS_TESTFLIGHT
- ? 'staging'
- : 'production',
+ tier: env.IS_DEV
+ ? 'development'
+ : env.IS_TESTFLIGHT
+ ? 'staging'
+ : 'production',
},
// Don't block on waiting for network. The fetched config will kick in on next load.
// This ensures the UI is always consistent and doesn't update mid-session.
@@ -212,9 +210,9 @@ function toStatsigUser(did: string | undefined): StatsigUser {
refSrc,
refUrl,
platform: Platform.OS as 'ios' | 'android' | 'web',
- appVersion: packageDotJson.version,
- bundleIdentifier: BUNDLE_IDENTIFIER,
- bundleDate: BUNDLE_DATE,
+ appVersion: env.RELEASE_VERSION,
+ bundleIdentifier: env.BUNDLE_IDENTIFIER,
+ bundleDate: env.BUNDLE_DATE,
appLanguage: languagePrefs.appLanguage,
contentLanguages: languagePrefs.contentLanguages,
},
diff --git a/src/logger/bitdrift/setup/index.ts b/src/logger/bitdrift/setup/index.ts
index d6af3fe24..dd2560acc 100644
--- a/src/logger/bitdrift/setup/index.ts
+++ b/src/logger/bitdrift/setup/index.ts
@@ -2,8 +2,7 @@ import {init, SessionStrategy} from '@bitdrift/react-native'
import {Statsig} from 'statsig-react-native-expo'
import {initPromise} from '#/lib/statsig/statsig'
-
-const BITDRIFT_API_KEY = process.env.BITDRIFT_API_KEY
+import {BITDRIFT_API_KEY} from '#/env'
initPromise.then(() => {
let isEnabled = false
diff --git a/src/logger/index.ts b/src/logger/index.ts
index e7aaf666a..998d02581 100644
--- a/src/logger/index.ts
+++ b/src/logger/index.ts
@@ -14,9 +14,10 @@ import {
} from '#/logger/types'
import {enabledLogLevels} from '#/logger/util'
import {isNative} from '#/platform/detection'
+import {ENV} from '#/env'
const TRANSPORTS: Transport[] = (function configureTransports() {
- switch (process.env.NODE_ENV) {
+ switch (ENV) {
case 'production': {
return [sentryTransport, isNative && bitdriftTransport].filter(
Boolean,
diff --git a/src/logger/sentry/setup/index.ts b/src/logger/sentry/setup/index.ts
index f05a7fc83..d062f05d2 100644
--- a/src/logger/sentry/setup/index.ts
+++ b/src/logger/sentry/setup/index.ts
@@ -1,32 +1,15 @@
-/**
- * Importing these separately from `platform/detection` and `lib/app-info` to
- * avoid future conflicts and/or circular deps
- */
-
import {init} from '@sentry/react-native'
-import pkgJson from '#/../package.json'
-
-/**
- * Examples:
- * - `dev`
- * - `1.99.0`
- */
-const release = process.env.SENTRY_RELEASE || pkgJson.version
-
-/**
- * The latest deployed commit hash
- */
-const dist = process.env.SENTRY_DIST || 'dev'
+import * as env from '#/env'
init({
- enabled: !__DEV__ && !!process.env.SENTRY_DSN,
+ enabled: !env.IS_DEV && !!env.SENTRY_DSN,
autoSessionTracking: false,
- dsn: process.env.SENTRY_DSN,
+ dsn: env.SENTRY_DSN,
debug: false, // If `true`, Sentry will try to print out useful debugging information if something goes wrong with sending the event. Set it to `false` in production
- environment: process.env.NODE_ENV,
- dist,
- release,
+ environment: env.ENV,
+ dist: env.BUNDLE_IDENTIFIER,
+ release: env.RELEASE_VERSION,
ignoreErrors: [
/*
* Unknown internals errors
diff --git a/src/screens/Settings/AboutSettings.tsx b/src/screens/Settings/AboutSettings.tsx
index 0ce127ff3..e48841d9f 100644
--- a/src/screens/Settings/AboutSettings.tsx
+++ b/src/screens/Settings/AboutSettings.tsx
@@ -9,7 +9,6 @@ import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {useMutation} from '@tanstack/react-query'
import {Statsig} from 'statsig-react-native-expo'
-import {appVersion, BUNDLE_DATE, bundleInfo} from '#/lib/app-info'
import {STATUS_PAGE_URL} from '#/lib/constants'
import {type CommonNavigatorParams} from '#/lib/routes/types'
import {isAndroid, isIOS, isNative} from '#/platform/detection'
@@ -23,6 +22,7 @@ import {Newspaper_Stroke2_Corner2_Rounded as NewspaperIcon} from '#/components/i
import {Wrench_Stroke2_Corner2_Rounded as WrenchIcon} from '#/components/icons/Wrench'
import * as Layout from '#/components/Layout'
import {Loader} from '#/components/Loader'
+import * as env from '#/env'
import {useDemoMode} from '#/storage/hooks/demo-mode'
import {useDevMode} from '#/storage/hooks/dev-mode'
import {OTAInfo} from './components/OTAInfo'
@@ -123,7 +123,7 @@ export function AboutSettingsScreen({}: Props) {
)}
{
const newDevModeEnabled = !devModeEnabled
@@ -146,15 +146,15 @@ export function AboutSettingsScreen({}: Props) {
}}
onPress={() => {
setStringAsync(
- `Build version: ${appVersion}; Bundle info: ${bundleInfo}; Bundle date: ${BUNDLE_DATE}; Platform: ${Platform.OS}; Platform version: ${Platform.Version}; Anonymous ID: ${stableID}`,
+ `Build version: ${env.APP_VERSION}; Bundle info: ${env.APP_METADATA}; Bundle date: ${env.BUNDLE_DATE}; Platform: ${Platform.OS}; Platform version: ${Platform.Version}; Anonymous ID: ${stableID}`,
)
Toast.show(_(msg`Copied build version to clipboard`))
}}>
- Version {appVersion}
+ Version {env.APP_VERSION}
- {bundleInfo}
+ {env.APP_METADATA}
{devModeEnabled && (
<>
diff --git a/src/screens/Settings/AppIconSettings/index.tsx b/src/screens/Settings/AppIconSettings/index.tsx
index 954bac68a..799873c2d 100644
--- a/src/screens/Settings/AppIconSettings/index.tsx
+++ b/src/screens/Settings/AppIconSettings/index.tsx
@@ -3,20 +3,20 @@ import {Alert, View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import * as DynamicAppIcon from '@mozzius/expo-dynamic-app-icon'
-import {NativeStackScreenProps} from '@react-navigation/native-stack'
+import {type NativeStackScreenProps} from '@react-navigation/native-stack'
-import {IS_INTERNAL} from '#/lib/app-info'
import {PressableScale} from '#/lib/custom-animations/PressableScale'
-import {CommonNavigatorParams} from '#/lib/routes/types'
+import {type CommonNavigatorParams} from '#/lib/routes/types'
import {useGate} from '#/lib/statsig/statsig'
import {isAndroid} from '#/platform/detection'
import {AppIconImage} from '#/screens/Settings/AppIconSettings/AppIconImage'
-import {AppIconSet} from '#/screens/Settings/AppIconSettings/types'
+import {type AppIconSet} from '#/screens/Settings/AppIconSettings/types'
import {useAppIconSets} from '#/screens/Settings/AppIconSettings/useAppIconSets'
import {atoms as a, useTheme} from '#/alf'
import * as Toggle from '#/components/forms/Toggle'
import * as Layout from '#/components/Layout'
import {Text} from '#/components/Typography'
+import {IS_INTERNAL} from '#/env'
type Props = NativeStackScreenProps
export function AppIconSettingsScreen({}: Props) {
diff --git a/src/screens/Settings/AppearanceSettings.tsx b/src/screens/Settings/AppearanceSettings.tsx
index d0158aaa8..492d6d172 100644
--- a/src/screens/Settings/AppearanceSettings.tsx
+++ b/src/screens/Settings/AppearanceSettings.tsx
@@ -8,7 +8,6 @@ import Animated, {
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
-import {IS_INTERNAL} from '#/lib/app-info'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
@@ -26,6 +25,7 @@ import {TextSize_Stroke2_Corner0_Rounded as TextSize} from '#/components/icons/T
import {TitleCase_Stroke2_Corner0_Rounded as Aa} from '#/components/icons/TitleCase'
import * as Layout from '#/components/Layout'
import {Text} from '#/components/Typography'
+import {IS_INTERNAL} from '#/env'
import * as SettingsList from './components/SettingsList'
type Props = NativeStackScreenProps
diff --git a/src/screens/Settings/Settings.tsx b/src/screens/Settings/Settings.tsx
index b712c054c..719bbf9a2 100644
--- a/src/screens/Settings/Settings.tsx
+++ b/src/screens/Settings/Settings.tsx
@@ -9,7 +9,6 @@ import {useNavigation} from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {useActorStatus} from '#/lib/actor-status'
-import {IS_INTERNAL} from '#/lib/app-info'
import {HELP_DESK_URL} from '#/lib/constants'
import {useAccountSwitcher} from '#/lib/hooks/useAccountSwitcher'
import {useApplyPullRequestOTAUpdate} from '#/lib/hooks/useOTAUpdates'
@@ -66,6 +65,7 @@ import {
shouldShowVerificationCheckButton,
VerificationCheckButton,
} from '#/components/verification/VerificationCheckButton'
+import {IS_INTERNAL} from '#/env'
import {useActivitySubscriptionsNudged} from '#/storage/hooks/activity-subscriptions-nudged'
type Props = NativeStackScreenProps
diff --git a/src/state/queries/messages/const.ts b/src/state/queries/messages/const.ts
index 7642c5d7b..1c5519a63 100644
--- a/src/state/queries/messages/const.ts
+++ b/src/state/queries/messages/const.ts
@@ -1,3 +1,5 @@
+import {CHAT_PROXY_DID} from '#/env'
+
export const DM_SERVICE_HEADERS = {
- 'atproto-proxy': 'did:web:api.bsky.chat#bsky_chat',
+ 'atproto-proxy': `${CHAT_PROXY_DID}#bsky_chat`,
}
diff --git a/src/state/session/logging.ts b/src/state/session/logging.ts
index 98de5a396..bf847f08f 100644
--- a/src/state/session/logging.ts
+++ b/src/state/session/logging.ts
@@ -1,11 +1,11 @@
-import {AtpSessionData, AtpSessionEvent} from '@atproto/api'
+import {type AtpSessionData, type AtpSessionEvent} from '@atproto/api'
import {sha256} from 'js-sha256'
import {Statsig} from 'statsig-react-native-expo'
-import {IS_INTERNAL} from '#/lib/app-info'
-import {Schema} from '../persisted'
-import {Action, State} from './reducer'
-import {SessionAccount} from './types'
+import {IS_INTERNAL} from '#/env'
+import {type Schema} from '../persisted'
+import {type Action, type State} from './reducer'
+import {type SessionAccount} from './types'
type Reducer = (state: State, action: Action) => State
diff --git a/webpack.config.js b/webpack.config.js
index 9a238e549..7f58a7448 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -53,7 +53,7 @@ module.exports = async function (env, argv) {
project: 'app',
authToken: process.env.SENTRY_AUTH_TOKEN,
release: {
- // env is undefined for Render.com builds, fall back
+ // fallback needed for Render.com deployments
name: process.env.SENTRY_RELEASE || version,
dist: process.env.SENTRY_DIST,
},