From a148b2477b93c60c9b5bd641b2fe1dd3b1e6ba7a Mon Sep 17 00:00:00 2001 From: vineyardbovines Date: Wed, 4 Feb 2026 15:06:42 -0500 Subject: [PATCH 01/59] update design for stacked avatars --- src/components/ProgressGuide/List.tsx | 138 ++++++++++++++------------ src/components/icons/Person.tsx | 5 + 2 files changed, 82 insertions(+), 61 deletions(-) diff --git a/src/components/ProgressGuide/List.tsx b/src/components/ProgressGuide/List.tsx index 81abc586f3..f86059a4c9 100644 --- a/src/components/ProgressGuide/List.tsx +++ b/src/components/ProgressGuide/List.tsx @@ -1,4 +1,10 @@ -import {type StyleProp, View, type ViewStyle} from 'react-native' +import {useState} from 'react' +import { + type LayoutChangeEvent, + type StyleProp, + View, + type ViewStyle, +} from 'react-native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -11,7 +17,7 @@ import { import {UserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, useBreakpoints, useLayoutBreakpoints, useTheme} from '#/alf' import {Button, ButtonIcon} from '#/components/Button' -import {Person_Stroke2_Corner2_Rounded as PersonIcon} from '#/components/icons/Person' +import {Person_Filled as PersonIcon} from '#/components/icons/Person' import {TimesLarge_Stroke2_Corner0_Rounded as Times} from '#/components/icons/Times' import {Text} from '#/components/Typography' import type * as bsky from '#/types/bsky' @@ -51,7 +57,7 @@ export function ProgressGuideList({style}: {style?: StyleProp}) { a.flex_col, a.gap_md, a.rounded_md, - t.atoms.bg_contrast_25, + t.atoms.bg_contrast_50, a.p_lg, style, ]}> @@ -112,70 +118,80 @@ export function ProgressGuideList({style}: {style?: StyleProp}) { function StackedAvatars({follows}: {follows?: bsky.profile.AnyProfileView[]}) { const t = useTheme() - const {centerColumnOffset} = useLayoutBreakpoints() + const [containerWidth, setContainerWidth] = useState(0) - // Smaller avatars for narrower viewport - const avatarSize = centerColumnOffset ? 30 : 37 - const overlap = centerColumnOffset ? 9 : 11 - const iconSize = centerColumnOffset ? 14 : 18 + const onLayout = (e: LayoutChangeEvent) => { + setContainerWidth(e.nativeEvent.layout.width) + } + + // Overlap ratio (22% of avatar size) + const overlapRatio = 0.22 + + // Calculate avatar size to fill container width + // Formula: containerWidth = avatarSize * count - overlap * (count - 1) + // Where overlap = avatarSize * overlapRatio + const visiblePortions = TOTAL_AVATARS - overlapRatio * (TOTAL_AVATARS - 1) + const avatarSize = containerWidth > 0 ? containerWidth / visiblePortions : 0 + const overlap = avatarSize * overlapRatio + const iconSize = avatarSize * 0.45 - // Use actual follows count, not the guide's event counter const followedAvatars = follows?.slice(0, TOTAL_AVATARS) ?? [] const remainingSlots = TOTAL_AVATARS - followedAvatars.length - // Total width calculation: first avatar + (remaining * visible portion) - const totalWidth = avatarSize + (TOTAL_AVATARS - 1) * (avatarSize - overlap) - return ( - - {/* Show followed user avatars */} - {followedAvatars.map((follow, i) => ( - - - - ))} - {/* Show placeholder avatars for remaining slots */} - {Array(remainingSlots) - .fill(0) - .map((_, i) => ( - - - - ))} + + {containerWidth > 0 && ( + <> + {/* Show followed user avatars */} + {followedAvatars.map((follow, i) => ( + + + + ))} + {/* Show placeholder avatars for remaining slots */} + {Array(remainingSlots) + .fill(0) + .map((_, i) => ( + + + + ))} + + )} ) } diff --git a/src/components/icons/Person.tsx b/src/components/icons/Person.tsx index 55324f10d6..74a8ac97dd 100644 --- a/src/components/icons/Person.tsx +++ b/src/components/icons/Person.tsx @@ -36,3 +36,8 @@ export const PersonPlus_Stroke2_Corner2_Rounded = createSinglePathSVG({ export const PersonGroup_Stroke2_Corner2_Rounded = createSinglePathSVG({ path: 'M8 5a2 2 0 1 0 0 4 2 2 0 0 0 0-4ZM4 7a4 4 0 1 1 8 0 4 4 0 0 1-8 0Zm13-1a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Zm-3.5 1.5a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0Zm7.301 9.7c-.836-2.6-2.88-3.503-4.575-3.111a1 1 0 0 1-.451-1.949c2.815-.651 5.81.966 6.93 4.448a2.49 2.49 0 0 1-.506 2.43A2.92 2.92 0 0 1 20 20h-2a1 1 0 1 1 0-2h2a.92.92 0 0 0 .69-.295.49.49 0 0 0 .112-.505ZM8 14c-1.865 0-3.878 1.274-4.681 4.151a.57.57 0 0 0 .132.55c.15.171.4.299.695.299h7.708a.93.93 0 0 0 .695-.299.57.57 0 0 0 .132-.55C11.878 15.274 9.865 14 8 14Zm0-2c2.87 0 5.594 1.98 6.607 5.613.53 1.9-1.09 3.387-2.753 3.387H4.146c-1.663 0-3.283-1.487-2.753-3.387C2.406 13.981 5.129 12 8 12Z', }) + +export const Person_Filled = createSinglePathSVG({ + viewBox: '0 0 14 16', + path: 'M6.5 0C4.567 0 3 1.567 3 3.5C3 5.433 4.567 7 6.5 7C8.43301 7 10 5.433 10 3.5C10 1.567 8.43301 0 6.5 0Z M6.50002 8C3.43062 8 1.08148 9.78593 0.127626 12.2902C-0.145062 13.0062 0.0416292 13.7118 0.475104 14.2134C0.897533 14.7023 1.54964 15 2.25212 15H10.7479C11.4503 15 12.1024 14.7023 12.5249 14.2134C12.9584 13.7118 13.145 13.0062 12.8724 12.2902C11.9185 9.78593 9.56941 8 6.50002 8Z', +}) From a57faedbae1508f89df6c510fcab5d6f35d71c44 Mon Sep 17 00:00:00 2001 From: vineyardbovines Date: Thu, 5 Feb 2026 08:51:53 -0500 Subject: [PATCH 02/59] update icon --- assets/icons/person_filled_corner2_rounded.svg | 1 + src/components/ProgressGuide/List.tsx | 4 ++-- src/components/icons/Person.tsx | 5 ++--- 3 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 assets/icons/person_filled_corner2_rounded.svg diff --git a/assets/icons/person_filled_corner2_rounded.svg b/assets/icons/person_filled_corner2_rounded.svg new file mode 100644 index 0000000000..d22056593d --- /dev/null +++ b/assets/icons/person_filled_corner2_rounded.svg @@ -0,0 +1 @@ + diff --git a/src/components/ProgressGuide/List.tsx b/src/components/ProgressGuide/List.tsx index f86059a4c9..868ee79a3e 100644 --- a/src/components/ProgressGuide/List.tsx +++ b/src/components/ProgressGuide/List.tsx @@ -17,7 +17,7 @@ import { import {UserAvatar} from '#/view/com/util/UserAvatar' import {atoms as a, useBreakpoints, useLayoutBreakpoints, useTheme} from '#/alf' import {Button, ButtonIcon} from '#/components/Button' -import {Person_Filled as PersonIcon} from '#/components/icons/Person' +import {Person_Filled_Corner2_Rounded as PersonIcon} from '#/components/icons/Person' import {TimesLarge_Stroke2_Corner0_Rounded as Times} from '#/components/icons/Times' import {Text} from '#/components/Typography' import type * as bsky from '#/types/bsky' @@ -133,7 +133,7 @@ function StackedAvatars({follows}: {follows?: bsky.profile.AnyProfileView[]}) { const visiblePortions = TOTAL_AVATARS - overlapRatio * (TOTAL_AVATARS - 1) const avatarSize = containerWidth > 0 ? containerWidth / visiblePortions : 0 const overlap = avatarSize * overlapRatio - const iconSize = avatarSize * 0.45 + const iconSize = avatarSize * 0.5 const followedAvatars = follows?.slice(0, TOTAL_AVATARS) ?? [] const remainingSlots = TOTAL_AVATARS - followedAvatars.length diff --git a/src/components/icons/Person.tsx b/src/components/icons/Person.tsx index 74a8ac97dd..83a6db1f28 100644 --- a/src/components/icons/Person.tsx +++ b/src/components/icons/Person.tsx @@ -37,7 +37,6 @@ export const PersonGroup_Stroke2_Corner2_Rounded = createSinglePathSVG({ path: 'M8 5a2 2 0 1 0 0 4 2 2 0 0 0 0-4ZM4 7a4 4 0 1 1 8 0 4 4 0 0 1-8 0Zm13-1a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Zm-3.5 1.5a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0Zm7.301 9.7c-.836-2.6-2.88-3.503-4.575-3.111a1 1 0 0 1-.451-1.949c2.815-.651 5.81.966 6.93 4.448a2.49 2.49 0 0 1-.506 2.43A2.92 2.92 0 0 1 20 20h-2a1 1 0 1 1 0-2h2a.92.92 0 0 0 .69-.295.49.49 0 0 0 .112-.505ZM8 14c-1.865 0-3.878 1.274-4.681 4.151a.57.57 0 0 0 .132.55c.15.171.4.299.695.299h7.708a.93.93 0 0 0 .695-.299.57.57 0 0 0 .132-.55C11.878 15.274 9.865 14 8 14Zm0-2c2.87 0 5.594 1.98 6.607 5.613.53 1.9-1.09 3.387-2.753 3.387H4.146c-1.663 0-3.283-1.487-2.753-3.387C2.406 13.981 5.129 12 8 12Z', }) -export const Person_Filled = createSinglePathSVG({ - viewBox: '0 0 14 16', - path: 'M6.5 0C4.567 0 3 1.567 3 3.5C3 5.433 4.567 7 6.5 7C8.43301 7 10 5.433 10 3.5C10 1.567 8.43301 0 6.5 0Z M6.50002 8C3.43062 8 1.08148 9.78593 0.127626 12.2902C-0.145062 13.0062 0.0416292 13.7118 0.475104 14.2134C0.897533 14.7023 1.54964 15 2.25212 15H10.7479C11.4503 15 12.1024 14.7023 12.5249 14.2134C12.9584 13.7118 13.145 13.0062 12.8724 12.2902C11.9185 9.78593 9.56941 8 6.50002 8Z', +export const Person_Filled_Corner2_Rounded = createSinglePathSVG({ + path: 'M12.233 2a4.433 4.433 0 1 0 0 8.867 4.433 4.433 0 0 0 0-8.867ZM12.233 12.133c-3.888 0-6.863 2.263-8.071 5.435-.346.906-.11 1.8.44 2.436.535.619 1.36.996 2.25.996h10.762c.89 0 1.716-.377 2.25-.996.55-.636.786-1.53.441-2.436-1.208-3.173-4.184-5.435-8.072-5.435Z', }) From 18ab5d6f34f87c2851e02fc4c64afb07f6b6f475 Mon Sep 17 00:00:00 2001 From: Spence Pope Date: Thu, 5 Feb 2026 11:40:25 -0500 Subject: [PATCH 03/59] [APP-1823] Fix 'create account' / 'sign in' buttons stacking (#9830) * ensure enough space for sign in buttons * smallest possible adjustment * smallest possible adjustment --- src/view/shell/NavSignupCard.tsx | 2 +- src/view/shell/desktop/LeftNav.tsx | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/view/shell/NavSignupCard.tsx b/src/view/shell/NavSignupCard.tsx index 062e4f880d..6f3dd749d4 100644 --- a/src/view/shell/NavSignupCard.tsx +++ b/src/view/shell/NavSignupCard.tsx @@ -29,7 +29,7 @@ let NavSignupCard = ({}: {}): React.ReactNode => { }, [requestSwitchToAccount, closeAllActiveElements]) return ( - + diff --git a/src/view/shell/desktop/LeftNav.tsx b/src/view/shell/desktop/LeftNav.tsx index ccbc7aeb22..3e9ccea647 100644 --- a/src/view/shell/desktop/LeftNav.tsx +++ b/src/view/shell/desktop/LeftNav.tsx @@ -628,6 +628,7 @@ export function DesktopLeftNav() { style={[ a.px_xl, styles.leftNav, + !hasSession && !leftNavMinimal && styles.leftNavWide, leftNavMinimal && styles.leftNavMinimal, { transform: [ @@ -821,6 +822,9 @@ const styles = StyleSheet.create({ maxHeight: '100vh', overflowY: 'auto', }, + leftNavWide: { + width: 245, + }, leftNavMinimal: { paddingTop: 0, paddingBottom: 0, From 6bfe758d2a9ea376552fb45e5e589bccd0cf4df5 Mon Sep 17 00:00:00 2001 From: pfrazee <1270099+pfrazee@users.noreply.github.com> Date: Fri, 6 Feb 2026 03:06:58 +0000 Subject: [PATCH 04/59] Nightly source-language update --- src/locale/locales/en/messages.po | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po index 79669e400e..e96d0438e8 100644 --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -3657,7 +3657,7 @@ msgstr "" #: src/Navigation.tsx:789 #: src/screens/Search/Shell.tsx:327 -#: src/view/shell/desktop/LeftNav.tsx:687 +#: src/view/shell/desktop/LeftNav.tsx:688 #: src/view/shell/Drawer.tsx:416 msgid "Explore" msgstr "" @@ -3981,7 +3981,7 @@ msgstr "" #: src/screens/StarterPack/StarterPackScreen.tsx:193 #: src/view/screens/Feeds.tsx:511 #: src/view/screens/Profile.tsx:239 -#: src/view/shell/desktop/LeftNav.tsx:725 +#: src/view/shell/desktop/LeftNav.tsx:726 #: src/view/shell/Drawer.tsx:532 msgid "Feeds" msgstr "" @@ -4794,7 +4794,7 @@ msgstr "" #: src/Navigation.tsx:784 #: src/Navigation.tsx:804 #: src/view/shell/bottom-bar/BottomBar.tsx:176 -#: src/view/shell/desktop/LeftNav.tsx:669 +#: src/view/shell/desktop/LeftNav.tsx:670 #: src/view/shell/Drawer.tsx:442 msgid "Home" msgstr "" @@ -5510,7 +5510,7 @@ msgstr "" #: src/view/screens/Lists.tsx:67 #: src/view/screens/Profile.tsx:233 #: src/view/screens/Profile.tsx:241 -#: src/view/shell/desktop/LeftNav.tsx:743 +#: src/view/shell/desktop/LeftNav.tsx:744 #: src/view/shell/Drawer.tsx:547 msgid "Lists" msgstr "" @@ -6421,7 +6421,7 @@ msgstr "" #: src/screens/Settings/Settings.tsx:203 #: src/view/screens/Notifications.tsx:129 #: src/view/shell/bottom-bar/BottomBar.tsx:250 -#: src/view/shell/desktop/LeftNav.tsx:706 +#: src/view/shell/desktop/LeftNav.tsx:707 #: src/view/shell/Drawer.tsx:495 msgid "Notifications" msgstr "" @@ -7363,7 +7363,7 @@ msgid "profile" msgstr "" #: src/view/shell/bottom-bar/BottomBar.tsx:293 -#: src/view/shell/desktop/LeftNav.tsx:784 +#: src/view/shell/desktop/LeftNav.tsx:785 #: src/view/shell/Drawer.tsx:79 #: src/view/shell/Drawer.tsx:598 msgid "Profile" @@ -8202,7 +8202,7 @@ msgstr "" msgid "Save to my feeds" msgstr "" -#: src/view/shell/desktop/LeftNav.tsx:762 +#: src/view/shell/desktop/LeftNav.tsx:763 #: src/view/shell/Drawer.tsx:573 msgctxt "link to bookmarks screen" msgid "Saved" @@ -8665,7 +8665,7 @@ msgstr "" #: src/Navigation.tsx:216 #: src/screens/Settings/Settings.tsx:103 -#: src/view/shell/desktop/LeftNav.tsx:802 +#: src/view/shell/desktop/LeftNav.tsx:803 #: src/view/shell/Drawer.tsx:611 msgid "Settings" msgstr "" From 917f099e2663e5dc6be9653ea64a58bd87715a61 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Sat, 7 Feb 2026 17:38:48 +0200 Subject: [PATCH 05/59] [Drafts] Some bugs (#9833) * Fix text input not updating * Fix autofocus * make placeholder text fainter * Await invalidation * Image only drafts * tweaks to gif presentation --------- Co-authored-by: Eric Bailey --- .../VideoEmbed/GifPresentationControls.tsx | 24 ++++---- .../Post/Embed/VideoEmbed/index.tsx | 56 +++++++++++-------- src/view/com/composer/Composer.tsx | 4 +- src/view/com/composer/drafts/DraftItem.tsx | 14 +++-- src/view/com/composer/drafts/state/queries.ts | 2 +- .../com/composer/text-input/TextInput.tsx | 4 +- .../com/composer/text-input/TextInput.web.tsx | 13 +---- 7 files changed, 61 insertions(+), 56 deletions(-) diff --git a/src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx b/src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx index 42098a7e9c..f89e5a8ef0 100644 --- a/src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx +++ b/src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx @@ -1,11 +1,16 @@ -import {Pressable, StyleSheet, TouchableOpacity, View} from 'react-native' +import { + ActivityIndicator, + StyleSheet, + TouchableOpacity, + View, +} from 'react-native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {HITSLOP_20} from '#/lib/constants' import {atoms as a, useTheme} from '#/alf' +import {Button} from '#/components/Button' import {Fill} from '#/components/Fill' -import {Loader} from '#/components/Loader' import * as Prompt from '#/components/Prompt' import {Text} from '#/components/Typography' import {PlayButtonIcon} from '#/components/video/PlayButtonIcon' @@ -26,28 +31,27 @@ export function GifPresentationControls({ return ( <> - {isLoading ? ( - + ) : !isPlaying ? ( - ) : undefined} - + ) : ( + <> + )} + {!isPlaying && ( - {showOverlay && ( - - )} + {showOverlay && + (embed.presentation === 'gif' ? ( + { + ref.current?.togglePlayback() + }} + altText={embed.alt} + /> + ) : ( + + ))} ) diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index 1c2f6c209d..425440609b 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -1115,7 +1115,7 @@ export const ComposePost = ({ onLayout={onScrollViewLayout}> {replyTo ? : undefined} {thread.posts.map((post, index) => ( - + - + {!!post.text.trim().length && ( + + )} {!mediaExistsOnOtherDevice && } diff --git a/src/view/com/composer/drafts/state/queries.ts b/src/view/com/composer/drafts/state/queries.ts index 436e16317f..e66c9d023b 100644 --- a/src/view/com/composer/drafts/state/queries.ts +++ b/src/view/com/composer/drafts/state/queries.ts @@ -184,7 +184,7 @@ export function useSaveDraftMutation() { } } - queryClient.invalidateQueries({queryKey: DRAFTS_QUERY_KEY}) + await queryClient.invalidateQueries({queryKey: DRAFTS_QUERY_KEY}) }, onError: error => { // Check for draft limit error diff --git a/src/view/com/composer/text-input/TextInput.tsx b/src/view/com/composer/text-input/TextInput.tsx index f9f50497f8..0ba2e958a6 100644 --- a/src/view/com/composer/text-input/TextInput.tsx +++ b/src/view/com/composer/text-input/TextInput.tsx @@ -224,9 +224,9 @@ export function TextInput({ onPaste={onPaste} onSelectionChange={onSelectionChange} placeholder={placeholder} - placeholderTextColor={t.atoms.text_contrast_medium.color} + placeholderTextColor={t.atoms.text_contrast_low.color} keyboardAppearance={theme.colorScheme} - autoFocus={true} + autoFocus={props.autoFocus !== undefined ? props.autoFocus : true} allowFontScaling multiline scrollEnabled={false} diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx index a087a3d69b..3068c8f9df 100644 --- a/src/view/com/composer/text-input/TextInput.web.tsx +++ b/src/view/com/composer/text-input/TextInput.web.tsx @@ -52,6 +52,7 @@ export function TextInput({ onPressPublish, onNewLink, onFocus, + autoFocus, }: TextInputProps) { const {theme: t, fonts} = useAlf() const autocomplete = useActorAutocompleteFn() @@ -244,20 +245,10 @@ export function TextInput({ content: generateJSON(richTextToHTML(richtext), extensions, { preserveWhitespace: 'full', }), - autofocus: 'end', + autofocus: autoFocus ? 'end' : null, editable: true, injectCSS: true, shouldRerenderOnTransaction: false, - onCreate({editor: editorProp}) { - // HACK - // the 'enter' animation sometimes causes autofocus to fail - // (see Composer.web.tsx in shell) - // so we wait 200ms (the anim is 150ms) and then focus manually - // -prf - setTimeout(() => { - editorProp.chain().focus('end').run() - }, 200) - }, onUpdate({editor: editorProp}) { const json = editorProp.getJSON() const newText = editorJsonToText(json) From 18eea81e76aa67e2ae6fbe0f05ff3f39ea934393 Mon Sep 17 00:00:00 2001 From: pfrazee <1270099+pfrazee@users.noreply.github.com> Date: Sun, 8 Feb 2026 03:12:29 +0000 Subject: [PATCH 06/59] Nightly source-language update --- src/locale/locales/en/messages.po | 46 +++++++++++++++++-------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po index e96d0438e8..e656d26eb8 100644 --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -89,7 +89,7 @@ msgstr "" msgid "{0, plural, one {#mo} other {#mo}}" msgstr "" -#: src/view/com/composer/drafts/DraftItem.tsx:140 +#: src/view/com/composer/drafts/DraftItem.tsx:142 msgid "{0, plural, one {1 more post} other {# more posts}}" msgstr "" @@ -1021,7 +1021,7 @@ msgstr "" msgid "Already signed in as @{0}" msgstr "" -#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:89 +#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:93 #: src/view/com/composer/GifAltText.tsx:100 #: src/view/com/composer/photos/Gallery.tsx:188 msgid "ALT" @@ -1037,7 +1037,7 @@ msgstr "" msgid "Alt text" msgstr "" -#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:95 +#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:99 msgid "Alt Text" msgstr "" @@ -1088,7 +1088,7 @@ msgstr "" msgid "An error occurred while hiding suggestion. {0}" msgstr "" -#: src/components/Post/Embed/VideoEmbed/index.tsx:140 +#: src/components/Post/Embed/VideoEmbed/index.tsx:148 msgid "An error occurred while loading the video. Please try again later." msgstr "" @@ -2114,7 +2114,7 @@ msgstr "" #: src/components/live/EditLiveDialog.tsx:221 #: src/components/NewskieDialog.tsx:167 #: src/components/NewskieDialog.tsx:173 -#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:102 +#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:106 #: src/components/ProgressGuide/FollowDialog.tsx:447 #: src/components/StarterPack/Wizard/WizardEditListDialog.tsx:118 #: src/components/StarterPack/Wizard/WizardEditListDialog.tsx:124 @@ -3006,7 +3006,7 @@ msgstr "" #: src/view/com/composer/Composer.tsx:1149 #: src/view/com/composer/Composer.tsx:1187 #: src/view/com/composer/Composer.tsx:1387 -#: src/view/com/composer/drafts/DraftItem.tsx:239 +#: src/view/com/composer/drafts/DraftItem.tsx:241 #: src/view/com/composer/drafts/DraftsButton.tsx:112 msgid "Discard" msgstr "" @@ -3017,7 +3017,7 @@ msgid "Discard changes?" msgstr "" #: src/view/com/composer/Composer.tsx:1147 -#: src/view/com/composer/drafts/DraftItem.tsx:236 +#: src/view/com/composer/drafts/DraftItem.tsx:238 msgid "Discard draft?" msgstr "" @@ -3187,7 +3187,7 @@ msgstr "" msgid "Drafts" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:375 +#: src/view/com/composer/text-input/TextInput.web.tsx:366 msgid "Drop to add images" msgstr "" @@ -4405,7 +4405,7 @@ msgid "Get started" msgstr "" #: src/components/MediaPreview.tsx:136 -#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:64 +#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:68 msgid "GIF" msgstr "" @@ -5686,11 +5686,11 @@ msgid "Media" msgstr "" #. Example: "Media stored on John's iPhone" -#: src/view/com/composer/drafts/DraftItem.tsx:116 +#: src/view/com/composer/drafts/DraftItem.tsx:118 msgid "Media stored on {0}" msgstr "" -#: src/view/com/composer/drafts/DraftItem.tsx:114 +#: src/view/com/composer/drafts/DraftItem.tsx:116 msgid "Media stored on another device" msgstr "" @@ -5772,7 +5772,7 @@ msgstr "" msgid "Misleading" msgstr "" -#: src/view/com/composer/drafts/DraftItem.tsx:128 +#: src/view/com/composer/drafts/DraftItem.tsx:130 msgid "Missing media" msgstr "" @@ -5848,7 +5848,7 @@ msgid "More languages..." msgstr "" #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:143 -#: src/view/com/composer/drafts/DraftItem.tsx:187 +#: src/view/com/composer/drafts/DraftItem.tsx:189 #: src/view/com/profile/ProfileMenu.tsx:242 #: src/view/com/profile/ProfileMenu.tsx:249 msgid "More options" @@ -6841,12 +6841,15 @@ msgstr "" msgid "Password updated!" msgstr "" -#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:32 #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:151 #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx:385 msgid "Pause" msgstr "" +#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:35 +msgid "Pause GIF" +msgstr "" + #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx:336 msgid "Pause video" msgstr "" @@ -6952,7 +6955,6 @@ msgstr "" msgid "Pinned to your feeds" msgstr "" -#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:32 #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:151 #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx:386 msgid "Play" @@ -6962,7 +6964,11 @@ msgstr "" msgid "Play {0}" msgstr "" -#: src/components/Post/Embed/VideoEmbed/index.tsx:115 +#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:35 +msgid "Play GIF" +msgstr "" + +#: src/components/Post/Embed/VideoEmbed/index.tsx:129 #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx:337 msgid "Play video" msgstr "" @@ -6971,7 +6977,7 @@ msgstr "" msgid "Play Video" msgstr "" -#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:31 +#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:36 msgid "Plays or pauses the GIF" msgstr "" @@ -7442,7 +7448,7 @@ msgstr "" #: src/components/PostControls/RepostButton.tsx:198 #: src/components/PostControls/RepostButton.web.tsx:85 #: src/components/PostControls/RepostButton.web.tsx:92 -#: src/view/com/composer/drafts/DraftItem.tsx:134 +#: src/view/com/composer/drafts/DraftItem.tsx:136 msgid "Quote post" msgstr "" @@ -8818,7 +8824,7 @@ msgstr "" msgid "Show" msgstr "" -#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:81 +#: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:85 msgid "Show alt text" msgstr "" @@ -9815,7 +9821,7 @@ msgstr "" msgid "This conversation is with a deleted or a deactivated account. Press for options" msgstr "" -#: src/view/com/composer/drafts/DraftItem.tsx:237 +#: src/view/com/composer/drafts/DraftItem.tsx:239 msgid "This draft will be permanently deleted." msgstr "" From 3be1f5caa9095bc9348fd770cfe5cacc7c9c696f Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Mon, 9 Feb 2026 18:01:55 +0200 Subject: [PATCH 07/59] Add attribution for starter pack follows (#9834) --- src/screens/Onboarding/StepFinished/index.tsx | 11 +++++++---- .../StepSuggestedStarterpacks/StarterPackCard.tsx | 5 ++++- src/screens/Onboarding/util.ts | 8 +++++++- src/screens/StarterPack/StarterPackScreen.tsx | 5 ++++- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/screens/Onboarding/StepFinished/index.tsx b/src/screens/Onboarding/StepFinished/index.tsx index 5f0d42b3aa..58b84512b4 100644 --- a/src/screens/Onboarding/StepFinished/index.tsx +++ b/src/screens/Onboarding/StepFinished/index.tsx @@ -96,10 +96,13 @@ export function StepFinished() { const {selectedInterests} = interestsStepResults await Promise.all([ - bulkWriteFollows(agent, [ - BSKY_APP_ACCOUNT_DID, - ...(listItems?.map(i => i.subject.did) ?? []), - ]), + bulkWriteFollows( + agent, + [BSKY_APP_ACCOUNT_DID, ...(listItems?.map(i => i.subject.did) ?? [])], + starterPack + ? {uri: starterPack.uri, cid: starterPack.cid} + : undefined, + ), (async () => { // Interests need to get saved first, then we can write the feeds to prefs await agent.setInterestsPref({tags: selectedInterests}) diff --git a/src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx b/src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx index 3ee9cbe52a..f4c3b09e43 100644 --- a/src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx +++ b/src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx @@ -72,7 +72,10 @@ export function StarterPackCard({ let followUris: Map try { - followUris = await bulkWriteFollows(agent, dids) + followUris = await bulkWriteFollows(agent, dids, { + uri: view.uri, + cid: view.cid, + }) } catch (e) { setIsProcessing(false) Toast.show(_(msg`An error occurred while trying to follow all`), { diff --git a/src/screens/Onboarding/util.ts b/src/screens/Onboarding/util.ts index b08f0408eb..acb96ee914 100644 --- a/src/screens/Onboarding/util.ts +++ b/src/screens/Onboarding/util.ts @@ -4,13 +4,18 @@ import { type AppBskyGraphGetFollows, type BskyAgent, type ComAtprotoRepoApplyWrites, + type ComAtprotoRepoStrongRef, } from '@atproto/api' import {TID} from '@atproto/common-web' import chunk from 'lodash.chunk' import {until} from '#/lib/async/until' -export async function bulkWriteFollows(agent: BskyAgent, dids: string[]) { +export async function bulkWriteFollows( + agent: BskyAgent, + dids: string[], + via?: ComAtprotoRepoStrongRef.Main, +) { const session = agent.session if (!session) { @@ -22,6 +27,7 @@ export async function bulkWriteFollows(agent: BskyAgent, dids: string[]) { $type: 'app.bsky.graph.follow', subject: did, createdAt: new Date().toISOString(), + via, } }) diff --git a/src/screens/StarterPack/StarterPackScreen.tsx b/src/screens/StarterPack/StarterPackScreen.tsx index 4dc9cde927..4e4dd1a372 100644 --- a/src/screens/StarterPack/StarterPackScreen.tsx +++ b/src/screens/StarterPack/StarterPackScreen.tsx @@ -372,7 +372,10 @@ function Header({ let followUris: Map try { - followUris = await bulkWriteFollows(agent, dids) + followUris = await bulkWriteFollows(agent, dids, { + uri: starterPack.uri, + cid: starterPack.cid, + }) } catch (e) { setIsProcessing(false) Toast.show(_(msg`An error occurred while trying to follow all`), 'xmark') From 5642bc40bb8d527112833c0c78381e0874f7ec11 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 10 Feb 2026 01:14:46 +0200 Subject: [PATCH 08/59] bump version to v1.117.0 (#9847) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 448330660c..7e81c36c99 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bsky.app", - "version": "1.116.0", + "version": "1.117.0", "private": true, "engines": { "node": ">=20" From b8db36afb04f8489a91543788d8e2ada6b030e52 Mon Sep 17 00:00:00 2001 From: surfdude29 <149612116+surfdude29@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:37:04 +0000 Subject: [PATCH 09/59] Add context for translators for "No one" string (#9844) * add context for translators 'No one' option * update ActivityPrivacySettings to add context for translators * update translation context for 'No one' option --- src/screens/Messages/Settings.tsx | 6 ++++-- src/screens/Settings/ActivityPrivacySettings.tsx | 4 ++-- src/screens/Settings/PrivacyAndSecuritySettings.tsx | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/screens/Messages/Settings.tsx b/src/screens/Messages/Settings.tsx index 253f301343..04e110ad5d 100644 --- a/src/screens/Messages/Settings.tsx +++ b/src/screens/Messages/Settings.tsx @@ -103,10 +103,12 @@ export function MessagesSettingsScreenInner({}: Props) { - No one + No one diff --git a/src/screens/Settings/ActivityPrivacySettings.tsx b/src/screens/Settings/ActivityPrivacySettings.tsx index 988195a36c..c90881d0b4 100644 --- a/src/screens/Settings/ActivityPrivacySettings.tsx +++ b/src/screens/Settings/ActivityPrivacySettings.tsx @@ -126,12 +126,12 @@ export function Inner({ - No one + No one diff --git a/src/screens/Settings/PrivacyAndSecuritySettings.tsx b/src/screens/Settings/PrivacyAndSecuritySettings.tsx index 2e8ffdd61c..19d84e2c01 100644 --- a/src/screens/Settings/PrivacyAndSecuritySettings.tsx +++ b/src/screens/Settings/PrivacyAndSecuritySettings.tsx @@ -156,7 +156,7 @@ function NotificationDeclaration({ case 'mutuals': return Only followers who I follow case 'none': - return No one + return No one case 'followers': default: return Anyone who follows me From efed955003554266510c0422e174a61befcc33ff Mon Sep 17 00:00:00 2001 From: pfrazee <1270099+pfrazee@users.noreply.github.com> Date: Tue, 10 Feb 2026 03:12:38 +0000 Subject: [PATCH 10/59] Nightly source-language update --- src/locale/locales/en/messages.po | 113 ++++++++++++++++-------------- 1 file changed, 59 insertions(+), 54 deletions(-) diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po index e656d26eb8..520091bd29 100644 --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -128,7 +128,7 @@ msgid "{0, plural, other {{1} posts}}" msgstr "" #. Number of users (always at least 25) who have joined Bluesky using a specific starter pack -#: src/screens/StarterPack/StarterPackScreen.tsx:496 +#: src/screens/StarterPack/StarterPackScreen.tsx:499 msgid "{0, plural, other {# people have}} used this starter pack!" msgstr "" @@ -939,8 +939,8 @@ msgstr "" msgid "All" msgstr "" -#: src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx:93 -#: src/screens/StarterPack/StarterPackScreen.tsx:390 +#: src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx:96 +#: src/screens/StarterPack/StarterPackScreen.tsx:393 msgid "All accounts have been followed!" msgstr "" @@ -1105,9 +1105,9 @@ msgid "An error occurred while saving the QR code!" msgstr "" #: src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx:53 -#: src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx:78 +#: src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx:81 #: src/screens/StarterPack/StarterPackScreen.tsx:356 -#: src/screens/StarterPack/StarterPackScreen.tsx:378 +#: src/screens/StarterPack/StarterPackScreen.tsx:381 msgid "An error occurred while trying to follow all" msgstr "" @@ -1327,7 +1327,7 @@ msgstr "" msgid "Are you sure you want to delete this message? The message will be deleted for you, but not for the other participant." msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:664 +#: src/screens/StarterPack/StarterPackScreen.tsx:667 msgid "Are you sure you want to delete this starter pack?" msgstr "" @@ -2238,7 +2238,7 @@ msgstr "" msgid "Community Guidelines" msgstr "" -#: src/screens/Onboarding/StepFinished/index.tsx:325 +#: src/screens/Onboarding/StepFinished/index.tsx:328 msgid "Complete onboarding and start using your account" msgstr "" @@ -2503,7 +2503,7 @@ msgid "Copy host" msgstr "" #: src/components/StarterPack/ShareDialog.tsx:114 -#: src/screens/StarterPack/StarterPackScreen.tsx:624 +#: src/screens/StarterPack/StarterPackScreen.tsx:627 msgid "Copy link" msgstr "" @@ -2528,7 +2528,7 @@ msgstr "" msgid "Copy link to profile" msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:617 +#: src/screens/StarterPack/StarterPackScreen.tsx:620 msgid "Copy link to starter pack" msgstr "" @@ -2808,9 +2808,9 @@ msgstr "" #: src/screens/Messages/components/ChatStatusInfo.tsx:55 #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:274 #: src/screens/Settings/AppPasswords.tsx:212 -#: src/screens/StarterPack/StarterPackScreen.tsx:606 -#: src/screens/StarterPack/StarterPackScreen.tsx:695 -#: src/screens/StarterPack/StarterPackScreen.tsx:767 +#: src/screens/StarterPack/StarterPackScreen.tsx:609 +#: src/screens/StarterPack/StarterPackScreen.tsx:698 +#: src/screens/StarterPack/StarterPackScreen.tsx:770 msgid "Delete" msgstr "" @@ -2882,12 +2882,12 @@ msgstr "" msgid "Delete post" msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:600 -#: src/screens/StarterPack/StarterPackScreen.tsx:758 +#: src/screens/StarterPack/StarterPackScreen.tsx:603 +#: src/screens/StarterPack/StarterPackScreen.tsx:761 msgid "Delete starter pack" msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:661 +#: src/screens/StarterPack/StarterPackScreen.tsx:664 msgid "Delete starter pack?" msgstr "" @@ -2995,8 +2995,8 @@ msgstr "" #: src/lib/moderation/useLabelBehaviorDescription.ts:35 #: src/lib/moderation/useLabelBehaviorDescription.ts:45 #: src/lib/moderation/useLabelBehaviorDescription.ts:71 -#: src/screens/Messages/Settings.tsx:144 -#: src/screens/Messages/Settings.tsx:147 +#: src/screens/Messages/Settings.tsx:146 +#: src/screens/Messages/Settings.tsx:149 #: src/screens/Moderation/index.tsx:384 msgid "Disabled" msgstr "" @@ -3237,7 +3237,7 @@ msgstr "" #: src/screens/Settings/AccountSettings.tsx:145 #: src/screens/Settings/NotificationSettings/ActivityNotificationSettings.tsx:252 -#: src/screens/StarterPack/StarterPackScreen.tsx:595 +#: src/screens/StarterPack/StarterPackScreen.tsx:598 #: src/screens/StarterPack/Wizard/index.tsx:340 #: src/screens/StarterPack/Wizard/index.tsx:345 msgid "Edit" @@ -3318,7 +3318,7 @@ msgstr "" msgid "Edit Profile" msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:587 +#: src/screens/StarterPack/StarterPackScreen.tsx:590 msgid "Edit starter pack" msgstr "" @@ -3454,8 +3454,8 @@ msgstr "" msgid "Enable trending videos in your Discover feed" msgstr "" -#: src/screens/Messages/Settings.tsx:135 -#: src/screens/Messages/Settings.tsx:138 +#: src/screens/Messages/Settings.tsx:137 +#: src/screens/Messages/Settings.tsx:140 #: src/screens/Moderation/index.tsx:382 msgid "Enabled" msgstr "" @@ -3745,7 +3745,7 @@ msgstr "" msgid "Failed to delete post, please try again" msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:729 +#: src/screens/StarterPack/StarterPackScreen.tsx:732 msgid "Failed to delete starter pack" msgstr "" @@ -4028,7 +4028,7 @@ msgstr "" msgid "Filter who you receive notifications from" msgstr "" -#: src/screens/Onboarding/StepFinished/index.tsx:331 +#: src/screens/Onboarding/StepFinished/index.tsx:334 msgid "Finalizing" msgstr "" @@ -4162,12 +4162,12 @@ msgstr "" #: src/components/contacts/screens/ViewMatches.tsx:275 #: src/components/contacts/screens/ViewMatches.tsx:290 #: src/screens/Onboarding/StepSuggestedAccounts/index.tsx:274 -#: src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx:158 -#: src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx:165 +#: src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx:161 +#: src/screens/Onboarding/StepSuggestedStarterpacks/StarterPackCard.tsx:168 #: src/screens/Settings/FindContactsSettings.tsx:443 #: src/screens/Settings/FindContactsSettings.tsx:453 -#: src/screens/StarterPack/StarterPackScreen.tsx:442 -#: src/screens/StarterPack/StarterPackScreen.tsx:450 +#: src/screens/StarterPack/StarterPackScreen.tsx:445 +#: src/screens/StarterPack/StarterPackScreen.tsx:453 msgid "Follow all" msgstr "" @@ -4445,7 +4445,7 @@ msgstr "" #: src/screens/Profile/ErrorState.tsx:62 #: src/screens/Profile/ErrorState.tsx:66 #: src/screens/Profile/ProfileFeed/index.tsx:100 -#: src/screens/StarterPack/StarterPackScreen.tsx:780 +#: src/screens/StarterPack/StarterPackScreen.tsx:783 #: src/view/screens/NotFound.tsx:56 msgid "Go Back" msgstr "" @@ -5137,8 +5137,8 @@ msgstr "" #: src/screens/StarterPack/StarterPackLandingScreen.tsx:210 #: src/screens/StarterPack/StarterPackLandingScreen.tsx:216 -#: src/screens/StarterPack/StarterPackScreen.tsx:468 -#: src/screens/StarterPack/StarterPackScreen.tsx:479 +#: src/screens/StarterPack/StarterPackScreen.tsx:471 +#: src/screens/StarterPack/StarterPackScreen.tsx:482 msgid "Join Bluesky" msgstr "" @@ -5332,7 +5332,7 @@ msgstr "" msgid "Let's get your password reset!" msgstr "" -#: src/screens/Onboarding/StepFinished/index.tsx:333 +#: src/screens/Onboarding/StepFinished/index.tsx:336 msgid "Let's go!" msgstr "" @@ -6135,8 +6135,8 @@ msgstr "" #: src/screens/Login/LoginForm.tsx:353 #: src/screens/Login/SetNewPasswordForm.tsx:182 #: src/screens/Login/SetNewPasswordForm.tsx:188 -#: src/screens/Onboarding/StepFinished/index.tsx:326 -#: src/screens/Onboarding/StepFinished/index.tsx:335 +#: src/screens/Onboarding/StepFinished/index.tsx:329 +#: src/screens/Onboarding/StepFinished/index.tsx:338 #: src/screens/Settings/components/AddAppPasswordDialog.tsx:157 #: src/screens/Settings/components/AddAppPasswordDialog.tsx:165 #: src/screens/Signup/BackNextButtons.tsx:67 @@ -6236,11 +6236,16 @@ msgstr "" msgid "No notifications yet!" msgstr "" -#: src/screens/Messages/Settings.tsx:106 -#: src/screens/Messages/Settings.tsx:109 +#: src/screens/Messages/Settings.tsx:107 +#: src/screens/Messages/Settings.tsx:111 +msgctxt "allow messages from" +msgid "No one" +msgstr "" + #: src/screens/Settings/ActivityPrivacySettings.tsx:129 #: src/screens/Settings/ActivityPrivacySettings.tsx:134 #: src/screens/Settings/PrivacyAndSecuritySettings.tsx:159 +msgctxt "enable for" msgid "No one" msgstr "" @@ -6395,11 +6400,11 @@ msgstr "" msgid "Notification settings" msgstr "" -#: src/screens/Messages/Settings.tsx:128 +#: src/screens/Messages/Settings.tsx:130 msgid "Notification sounds" msgstr "" -#: src/screens/Messages/Settings.tsx:125 +#: src/screens/Messages/Settings.tsx:127 msgid "Notification Sounds" msgstr "" @@ -6614,7 +6619,7 @@ msgstr "" msgid "Open share menu" msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:573 +#: src/screens/StarterPack/StarterPackScreen.tsx:576 msgid "Open starter pack menu" msgstr "" @@ -7894,8 +7899,8 @@ msgstr "" msgid "Report post" msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:637 #: src/screens/StarterPack/StarterPackScreen.tsx:640 +#: src/screens/StarterPack/StarterPackScreen.tsx:643 msgid "Report starter pack" msgstr "" @@ -7957,7 +7962,7 @@ msgstr "" #: src/components/PostControls/RepostButton.tsx:145 #: src/components/PostControls/RepostButton.web.tsx:44 #: src/components/PostControls/RepostButton.web.tsx:104 -#: src/screens/StarterPack/StarterPackScreen.tsx:568 +#: src/screens/StarterPack/StarterPackScreen.tsx:571 msgid "Repost or quote post" msgstr "" @@ -8111,7 +8116,7 @@ msgstr "" #: src/components/Error.tsx:73 #: src/screens/List/ListHiddenScreen.tsx:219 -#: src/screens/StarterPack/StarterPackScreen.tsx:774 +#: src/screens/StarterPack/StarterPackScreen.tsx:777 msgid "Return to previous page" msgstr "" @@ -8735,7 +8740,7 @@ msgstr "" #: src/components/StarterPack/QrCodeDialog.tsx:194 #: src/screens/Hashtag.tsx:142 -#: src/screens/StarterPack/StarterPackScreen.tsx:437 +#: src/screens/StarterPack/StarterPackScreen.tsx:440 #: src/screens/Topic.tsx:103 msgid "Share" msgstr "" @@ -8787,7 +8792,7 @@ msgstr "" msgid "Share this feed" msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:430 +#: src/screens/StarterPack/StarterPackScreen.tsx:433 msgid "Share this starter pack" msgstr "" @@ -8799,8 +8804,8 @@ msgstr "" #: src/components/PostControls/ShareMenu/ShareMenuItems.tsx:121 #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:159 #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:165 -#: src/screens/StarterPack/StarterPackScreen.tsx:618 -#: src/screens/StarterPack/StarterPackScreen.tsx:626 +#: src/screens/StarterPack/StarterPackScreen.tsx:621 +#: src/screens/StarterPack/StarterPackScreen.tsx:629 #: src/view/com/profile/ProfileMenu.tsx:270 #: src/view/com/profile/ProfileMenu.tsx:283 msgid "Share via..." @@ -9026,8 +9031,8 @@ msgstr "" #: src/components/contacts/screens/VerifyNumber.tsx:204 #: src/screens/Onboarding/StepFindContactsIntro/index.tsx:85 #: src/screens/Onboarding/StepFindContactsIntro/index.tsx:89 -#: src/screens/Onboarding/StepFinished/index.tsx:291 -#: src/screens/Onboarding/StepFinished/index.tsx:313 +#: src/screens/Onboarding/StepFinished/index.tsx:294 +#: src/screens/Onboarding/StepFinished/index.tsx:316 #: src/screens/Onboarding/StepSuggestedAccounts/index.tsx:261 #: src/screens/Onboarding/StepSuggestedStarterpacks/index.tsx:104 #: src/screens/StarterPack/Wizard/index.tsx:219 @@ -9039,8 +9044,8 @@ msgstr "" msgid "Skip contact sharing and continue to the app" msgstr "" -#: src/screens/Onboarding/StepFinished/index.tsx:284 -#: src/screens/Onboarding/StepFinished/index.tsx:310 +#: src/screens/Onboarding/StepFinished/index.tsx:287 +#: src/screens/Onboarding/StepFinished/index.tsx:313 msgid "Skip introduction and start using your account" msgstr "" @@ -9206,7 +9211,7 @@ msgstr "" msgid "Starter pack by you" msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:738 +#: src/screens/StarterPack/StarterPackScreen.tsx:741 msgid "Starter pack is invalid" msgstr "" @@ -9603,7 +9608,7 @@ msgstr "" msgid "The server appears to be experiencing issues. Please try again in a few moments." msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:748 +#: src/screens/StarterPack/StarterPackScreen.tsx:751 msgid "The starter pack that you are trying to view is invalid. You may delete this starter pack instead." msgstr "" @@ -10180,7 +10185,7 @@ msgstr "" msgid "Unable to contact your service. Please check your Internet connection." msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:680 +#: src/screens/StarterPack/StarterPackScreen.tsx:683 msgid "Unable to delete" msgstr "" @@ -11275,7 +11280,7 @@ msgstr "" msgid "Yes, deactivate" msgstr "" -#: src/screens/StarterPack/StarterPackScreen.tsx:692 +#: src/screens/StarterPack/StarterPackScreen.tsx:695 msgid "Yes, delete this starter pack" msgstr "" @@ -11374,7 +11379,7 @@ msgstr "" msgid "You can choose whether chat notifications have sound in the chat settings within the app" msgstr "" -#: src/screens/Messages/Settings.tsx:116 +#: src/screens/Messages/Settings.tsx:118 msgid "You can continue ongoing conversations regardless of which setting you choose." msgstr "" From 5ea96736dea4d74049cddb3765c87c2ff8e886c8 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 10 Feb 2026 08:36:27 +0000 Subject: [PATCH 11/59] rm unused @testing-library/jest-native (#9820) --- package.json | 1 - yarn.lock | 17 +++-------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 7e81c36c99..4934691ea9 100644 --- a/package.json +++ b/package.json @@ -242,7 +242,6 @@ "@react-native/eslint-config": "^0.81.5", "@react-native/typescript-config": "^0.81.5", "@sentry/webpack-plugin": "^3.2.2", - "@testing-library/jest-native": "^5.4.3", "@testing-library/react-native": "^13.2.0", "@types/jest": "29.5.14", "@types/lodash.chunk": "^4.2.7", diff --git a/yarn.lock b/yarn.lock index 770b8e9d90..c952dedbd7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7168,17 +7168,6 @@ dependencies: "@tanstack/query-core" "5.25.0" -"@testing-library/jest-native@^5.4.3": - version "5.4.3" - resolved "https://registry.yarnpkg.com/@testing-library/jest-native/-/jest-native-5.4.3.tgz#9334c68eaf45db9eb20d0876728cc5d7fc2c3ea2" - integrity sha512-/sSDGaOuE+PJ1Z9Kp4u7PQScSVVXGud59I/qsBFFJvIbcn4P6yYw6cBnBmbPF+X9aRIsTJRDl6gzw5ZkJNm66w== - dependencies: - chalk "^4.1.2" - jest-diff "^29.0.1" - jest-matcher-utils "^29.0.1" - pretty-format "^29.0.3" - redent "^3.0.0" - "@testing-library/react-native@^13.2.0": version "13.2.0" resolved "https://registry.yarnpkg.com/@testing-library/react-native/-/react-native-13.2.0.tgz#b4f53c69a889728abe8bc3115ba803824bcafe10" @@ -13765,7 +13754,7 @@ jest-config@^29.7.0: slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@^29.0.1, jest-diff@^29.6.3: +jest-diff@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.6.3.tgz#365c6b037ea8e67d2f2af68bc018fc18d44311f0" integrity sha512-3sw+AdWnwH9sSNohMRKA7JiYUJSRr/WS6+sEFfBuhxU5V5GlEVKfvUn8JuMHE0wqKowemR1C2aHy8VtXbaV8dQ== @@ -13910,7 +13899,7 @@ jest-leak-detector@^29.7.0: jest-get-type "^29.6.3" pretty-format "^29.7.0" -jest-matcher-utils@^29.0.1, jest-matcher-utils@^29.6.3: +jest-matcher-utils@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.6.3.tgz#a7574092b635d96a38fa0a22d015fb596b9c2efc" integrity sha512-6ZrMYINZdwduSt5Xu18/n49O1IgXdjsfG7NEZaQws9k69eTKWKcVbJBw/MZsjOZe2sSyJFmuzh8042XWwl54Zg== @@ -16572,7 +16561,7 @@ pretty-error@^4.0.0: lodash "^4.17.20" renderkid "^3.0.0" -pretty-format@^29.0.0, pretty-format@^29.0.3, pretty-format@^29.6.3: +pretty-format@^29.0.0, pretty-format@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.6.3.tgz#d432bb4f1ca6f9463410c3fb25a0ba88e594ace7" integrity sha512-ZsBgjVhFAj5KeK+nHfF1305/By3lechHQSMWCTl8iHSbfOm2TN5nHEtFc/+W7fAyUeCs2n5iow72gld4gW0xDw== From 3cbded0269b9bbb91b0b60a0aa4fb25fb5489d62 Mon Sep 17 00:00:00 2001 From: surfdude29 <149612116+surfdude29@users.noreply.github.com> Date: Tue, 10 Feb 2026 10:41:47 +0000 Subject: [PATCH 12/59] fix typos in drafts NUX alt text (#9832) --- src/components/dialogs/nuxs/DraftsAnnouncement.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/dialogs/nuxs/DraftsAnnouncement.tsx b/src/components/dialogs/nuxs/DraftsAnnouncement.tsx index 4aa358f032..7811921d85 100644 --- a/src/components/dialogs/nuxs/DraftsAnnouncement.tsx +++ b/src/components/dialogs/nuxs/DraftsAnnouncement.tsx @@ -95,7 +95,7 @@ export function DraftsAnnouncement() { ]} alt={_( msg({ - message: `A screenshot of a the post composer with a new button next to the post button that says "Drafts", with a rainbow firework effect. Below, the text in the composer reads "Hey, did you hear the news? Bluesky has drafts now???".`, + message: `A screenshot of the post composer with a new button next to the post button that says "Drafts", with a rainbow firework effect. Below, the text in the composer reads "Hey, did you hear the news? Bluesky has drafts now!!!".`, comment: 'Contains a post that originally appeared in English. Consider translating the post text if it makes sense in your language, and noting that the post was translated from English.', }), From e2058c8ecc2945e9ad0afe2a41ad693f325c8201 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 10 Feb 2026 15:37:48 +0000 Subject: [PATCH 13/59] Update starter pack message to clarify users joined Bluesky (#9849) --- CLAUDE.md | 8 +++++--- src/screens/StarterPack/StarterPackScreen.tsx | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index ea77e350d3..5b0369e6c8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -29,8 +29,9 @@ yarn lint # Run ESLint yarn typecheck # Run TypeScript type checking # Internationalization -yarn intl:extract # Extract translation strings (you don't typically need to run this manually, we have CI for it) -yarn intl:compile # Compile translations for runtime +# DO NOT run these commands - extraction and compilation are handled by CI +yarn intl:extract # Extract translation strings (nightly CI job) +yarn intl:compile # Compile translations for runtime (nightly CI job) # Build yarn build-web # Build web version @@ -299,8 +300,9 @@ function MyComponent() { **Commands:** ```bash +# DO NOT run these commands - extraction and compilation are handled by a nightly CI job yarn intl:extract # Extract new strings to locale files -yarn intl:compile # Compile for runtime (required after changes) +yarn intl:compile # Compile translations for runtime ``` ## State Management diff --git a/src/screens/StarterPack/StarterPackScreen.tsx b/src/screens/StarterPack/StarterPackScreen.tsx index 4e4dd1a372..e4fbc81891 100644 --- a/src/screens/StarterPack/StarterPackScreen.tsx +++ b/src/screens/StarterPack/StarterPackScreen.tsx @@ -501,7 +501,7 @@ function Header({ value={starterPack.joinedAllTimeCount || 0} other="# people have" />{' '} - used this starter pack! + joined Bluesky via this starter pack! From 338016ed5c875387e1bd9dee912753873cbad50e Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 10 Feb 2026 21:01:58 +0000 Subject: [PATCH 14/59] Android sheets edge to edge (#8342) --- modules/bottom-sheet/android/build.gradle | 2 +- .../modules/bottomsheet/BottomSheetView.kt | 200 ++++++++++-------- .../bottomsheet/DialogRootViewGroup.kt | 2 + .../android/src/main/res/values/styles.xml | 20 ++ .../src/BottomSheetNativeComponent.tsx | 1 + .../NotificationPrefs.kt | 3 + .../ExpoReceiveAndroidIntentsModule.kt | 4 +- package.json | 2 +- src/App.native.tsx | 2 +- src/components/Dialog/index.tsx | 10 +- .../verification/VerifierDialog.tsx | 4 +- src/lib/hooks/useEnableKeyboardController.tsx | 107 ---------- src/screens/FindContactsFlowScreen.tsx | 3 - src/screens/Messages/Conversation.tsx | 3 - src/screens/Onboarding/index.tsx | 3 - src/screens/StarterPack/Wizard/index.tsx | 3 - src/screens/Takendown.tsx | 3 - .../composer/photos/ImageAltTextDialog.tsx | 9 +- yarn.lock | 8 +- 19 files changed, 161 insertions(+), 228 deletions(-) create mode 100644 modules/bottom-sheet/android/src/main/res/values/styles.xml delete mode 100644 src/lib/hooks/useEnableKeyboardController.tsx diff --git a/modules/bottom-sheet/android/build.gradle b/modules/bottom-sheet/android/build.gradle index a1d423044b..c4c051b70f 100644 --- a/modules/bottom-sheet/android/build.gradle +++ b/modules/bottom-sheet/android/build.gradle @@ -44,6 +44,6 @@ android { dependencies { implementation project(':expo-modules-core') - implementation 'com.google.android.material:material:1.12.0' + implementation 'com.google.android.material:material:1.13.0' implementation "com.facebook.react:react-native:+" } diff --git a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt index fa42e37d5a..300c338f9f 100644 --- a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt +++ b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/BottomSheetView.kt @@ -5,8 +5,12 @@ import android.util.DisplayMetrics import android.view.View import android.view.ViewGroup import android.view.ViewStructure +import android.view.Window import android.view.accessibility.AccessibilityEvent import android.widget.FrameLayout +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.allViews import com.facebook.react.bridge.LifecycleEventListener import com.facebook.react.bridge.ReactContext @@ -15,6 +19,7 @@ import com.facebook.react.uimanager.UIManagerHelper import com.facebook.react.uimanager.events.EventDispatcher import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog +import com.google.android.material.internal.EdgeToEdgeUtils import expo.modules.kotlin.AppContext import expo.modules.kotlin.viewevent.EventDispatcher import expo.modules.kotlin.views.ExpoView @@ -29,22 +34,26 @@ class BottomSheetView( private lateinit var dialogRootViewGroup: DialogRootViewGroup private var eventDispatcher: EventDispatcher? = null + private var isKeyboardVisible: Boolean = false - private val rawScreenHeight = + private val screenHeight = context.resources.displayMetrics.heightPixels .toFloat() - private val safeScreenHeight = (rawScreenHeight - getNavigationBarHeight()).toFloat() private fun getNavigationBarHeight(): Int { val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android") return if (resourceId > 0) resources.getDimensionPixelSize(resourceId) else 0 } + private fun getStatusBarHeight(): Int { + val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android") + return if (resourceId > 0) resources.getDimensionPixelSize(resourceId) else 0 + } + private val onAttemptDismiss by EventDispatcher() private val onSnapPointChange by EventDispatcher() private val onStateChange by EventDispatcher() - // Props var disableDrag = false set(value) { field = value @@ -56,48 +65,31 @@ class BottomSheetView( field = value this.dialog?.setCancelable(!value) } + var preventExpansion = false var minHeight = 0f set(value) { - field = - if (value < 0) { - 0f - } else { - dpToPx(value) - } + field = if (value < 0) 0f else dpToPx(value) } - var maxHeight = this.safeScreenHeight + var maxHeight = this.screenHeight set(value) { val px = dpToPx(value) - field = - if (px > this.safeScreenHeight) { - this.safeScreenHeight - } else { - px - } + field = if (px > this.screenHeight) this.screenHeight else px } private var isOpen: Boolean = false set(value) { field = value - onStateChange( - mapOf( - "state" to if (value) "open" else "closed", - ), - ) + onStateChange(mapOf("state" to if (value) "open" else "closed")) } private var isOpening: Boolean = false set(value) { field = value if (value) { - onStateChange( - mapOf( - "state" to "opening", - ), - ) + onStateChange(mapOf("state" to "opening")) } } @@ -105,33 +97,21 @@ class BottomSheetView( set(value) { field = value if (value) { - onStateChange( - mapOf( - "state" to "closing", - ), - ) + onStateChange(mapOf("state" to "closing")) } } private var selectedSnapPoint = 0 set(value) { if (field == value) return - field = value - onSnapPointChange( - mapOf( - "snapPoint" to value, - ), - ) + onSnapPointChange(mapOf("snapPoint" to value)) } - // Lifecycle - init { (appContext.reactContext as? ReactContext)?.let { it.addLifecycleEventListener(this) this.eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(it, this.id) - this.dialogRootViewGroup = DialogRootViewGroup(context) this.dialogRootViewGroup.eventDispatcher = this.eventDispatcher } @@ -161,27 +141,55 @@ class BottomSheetView( private fun getHalfExpandedRatio(contentHeight: Float): Float = when { // Full height sheets - contentHeight >= safeScreenHeight -> 0.99f - // Medium height sheets (>50% but <100%) - contentHeight >= safeScreenHeight / 2 -> - this.clampRatio(this.getTargetHeight() / safeScreenHeight) - // Small height sheets (<50%) - else -> - this.clampRatio(this.getTargetHeight() / rawScreenHeight) + contentHeight >= screenHeight -> 0.99f + else -> this.clampRatio(this.getTargetHeight() / screenHeight) } private fun present() { if (this.isOpen || this.isOpening || this.isClosing) return val contentHeight = this.getContentHeight() - val dialog = BottomSheetDialog(context) + + var activityWindow: Window? = null + var currentContext = context + while (currentContext != null) { + if (currentContext is android.app.Activity) { + activityWindow = currentContext.window + break + } + currentContext = (currentContext as? android.content.ContextWrapper)?.baseContext + } + + val originalStatusBarAppearance = + activityWindow?.let { window -> + WindowInsetsControllerCompat(window, window.decorView).isAppearanceLightStatusBars + } + val originalNavBarAppearance = + activityWindow?.let { window -> + WindowInsetsControllerCompat(window, window.decorView).isAppearanceLightNavigationBars + } + + val dialog = BottomSheetDialog(context, R.style.EdgeToEdgeBottomSheetDialogTheme) dialog.setContentView(dialogRootViewGroup) dialog.setCancelable(!preventDismiss) + dialog.setDismissWithAnimation(true) dialog.setOnDismissListener { this.isClosing = true this.destroy() } + dialog.setOnShowListener { + dialog.window?.let { window -> + val insetsController = WindowInsetsControllerCompat(window, window.decorView) + if (originalNavBarAppearance != null) { + insetsController.isAppearanceLightNavigationBars = originalNavBarAppearance + } + if (originalStatusBarAppearance != null) { + EdgeToEdgeUtils.setLightStatusBar(window, originalStatusBarAppearance) + } + } + } + val bottomSheet = dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet) bottomSheet?.let { it.setBackgroundColor(0) @@ -194,7 +202,17 @@ class BottomSheetView( behavior.isDraggable = true behavior.isHideable = true - if (contentHeight >= this.safeScreenHeight || this.minHeight >= this.safeScreenHeight) { + if (preventExpansion) { + behavior.maxHeight = (behavior.halfExpandedRatio * screenHeight).toInt() + } else { + behavior.maxHeight = (screenHeight - getStatusBarHeight()).toInt() + } + + val targetHeight = this.getTargetHeight() + val availableHeight = screenHeight - getStatusBarHeight() - getNavigationBarHeight() + val shouldBeExpanded = targetHeight >= availableHeight + + if (shouldBeExpanded) { behavior.state = BottomSheetBehavior.STATE_EXPANDED this.selectedSnapPoint = 2 } else { @@ -209,18 +227,10 @@ class BottomSheetView( newState: Int, ) { when (newState) { - BottomSheetBehavior.STATE_EXPANDED -> { - selectedSnapPoint = 2 - } - BottomSheetBehavior.STATE_COLLAPSED -> { - selectedSnapPoint = 1 - } - BottomSheetBehavior.STATE_HALF_EXPANDED -> { - selectedSnapPoint = 1 - } - BottomSheetBehavior.STATE_HIDDEN -> { - selectedSnapPoint = 0 - } + BottomSheetBehavior.STATE_EXPANDED -> selectedSnapPoint = 2 + BottomSheetBehavior.STATE_COLLAPSED -> selectedSnapPoint = 1 + BottomSheetBehavior.STATE_HALF_EXPANDED -> selectedSnapPoint = 1 + BottomSheetBehavior.STATE_HIDDEN -> selectedSnapPoint = 0 } } @@ -231,9 +241,26 @@ class BottomSheetView( }, ) } + this.isOpening = true dialog.show() this.dialog = dialog + + ViewCompat.setOnApplyWindowInsetsListener(dialogRootViewGroup) { view, insets -> + val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()) + val bottomSheet = dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet) + val behavior = bottomSheet?.let { BottomSheetBehavior.from(it) } + + val wasKeyboardVisible = isKeyboardVisible + isKeyboardVisible = imeVisible + + if (imeVisible && behavior?.state == BottomSheetBehavior.STATE_HALF_EXPANDED) { + behavior.state = BottomSheetBehavior.STATE_EXPANDED + } else if (!imeVisible && wasKeyboardVisible) { + updateLayout() + } + insets + } } fun updateLayout() { @@ -246,12 +273,24 @@ class BottomSheetView( val currentState = behavior.state val oldRatio = behavior.halfExpandedRatio - var newRatio = getHalfExpandedRatio(contentHeight) + val newRatio = getHalfExpandedRatio(contentHeight) behavior.halfExpandedRatio = newRatio - if (contentHeight > this.safeScreenHeight && behavior.state != BottomSheetBehavior.STATE_EXPANDED) { + if (preventExpansion) { + behavior.maxHeight = (behavior.halfExpandedRatio * screenHeight).toInt() + } + + val targetHeight = this.getTargetHeight() + val availableHeight = screenHeight - getStatusBarHeight() - getNavigationBarHeight() + val shouldBeExpanded = targetHeight >= availableHeight + + if (isKeyboardVisible) { + if (behavior.state != BottomSheetBehavior.STATE_EXPANDED) { + behavior.state = BottomSheetBehavior.STATE_EXPANDED + } + } else if (shouldBeExpanded && behavior.state != BottomSheetBehavior.STATE_EXPANDED && !preventExpansion) { behavior.state = BottomSheetBehavior.STATE_EXPANDED - } else if (contentHeight < this.safeScreenHeight && behavior.state != BottomSheetBehavior.STATE_HALF_EXPANDED) { + } else if (!shouldBeExpanded && behavior.state != BottomSheetBehavior.STATE_HALF_EXPANDED) { behavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED } else if (currentState == BottomSheetBehavior.STATE_HALF_EXPANDED && oldRatio != newRatio) { behavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED @@ -279,25 +318,19 @@ class BottomSheetView( private fun getTargetHeight(): Float { val contentHeight = this.getContentHeight() - val height = - if (contentHeight > maxHeight) { - maxHeight - } else if (contentHeight < minHeight) { - minHeight - } else { - contentHeight - } - return height + return when { + contentHeight > maxHeight -> maxHeight + contentHeight < minHeight -> minHeight + else -> contentHeight + } } - private fun clampRatio(ratio: Float): Float { - if (ratio < 0.01) { - return 0.01f - } else if (ratio > 0.99) { - return 0.99f + private fun clampRatio(ratio: Float): Float = + when { + ratio < 0.01 -> 0.01f + ratio > 0.99 -> 0.99f + else -> ratio } - return ratio - } private fun setDraggable(draggable: Boolean) { val dialog = this.dialog ?: return @@ -322,9 +355,7 @@ class BottomSheetView( // View overrides to pass to DialogRootViewGroup instead override fun dispatchProvideStructure(structure: ViewStructure?) { - if (structure == null) { - return - } + if (structure == null) return dialogRootViewGroup.dispatchProvideStructure(structure) } @@ -363,7 +394,6 @@ class BottomSheetView( // https://stackoverflow.com/questions/11862391/getheight-px-or-dpi fun dpToPx(dp: Float): Float { val displayMetrics = context.resources.displayMetrics - val px = dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT) - return px + return dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT) } } diff --git a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/DialogRootViewGroup.kt b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/DialogRootViewGroup.kt index 60b9aac08c..c43d963888 100644 --- a/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/DialogRootViewGroup.kt +++ b/modules/bottom-sheet/android/src/main/java/expo/modules/bottomsheet/DialogRootViewGroup.kt @@ -52,6 +52,8 @@ class DialogRootViewGroup( if (ReactFeatureFlags.dispatchPointerEvents) { jSPointerDispatcher = JSPointerDispatcher(this) } + + fitsSystemWindows = false } override fun onSizeChanged( diff --git a/modules/bottom-sheet/android/src/main/res/values/styles.xml b/modules/bottom-sheet/android/src/main/res/values/styles.xml new file mode 100644 index 0000000000..b2a4945da7 --- /dev/null +++ b/modules/bottom-sheet/android/src/main/res/values/styles.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx b/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx index bbeab8c469..e4e37b1865 100644 --- a/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx +++ b/modules/bottom-sheet/src/BottomSheetNativeComponent.tsx @@ -175,6 +175,7 @@ function BottomSheetNativeComponentInner({ Platform.OS === 'android' && { borderTopLeftRadius: cornerRadius, borderTopRightRadius: cornerRadius, + overflow: 'hidden', }, extraStyles, ]}> diff --git a/modules/expo-background-notification-handler/android/src/main/java/expo/modules/backgroundnotificationhandler/NotificationPrefs.kt b/modules/expo-background-notification-handler/android/src/main/java/expo/modules/backgroundnotificationhandler/NotificationPrefs.kt index 97b05b4d73..3f63814bcb 100644 --- a/modules/expo-background-notification-handler/android/src/main/java/expo/modules/backgroundnotificationhandler/NotificationPrefs.kt +++ b/modules/expo-background-notification-handler/android/src/main/java/expo/modules/backgroundnotificationhandler/NotificationPrefs.kt @@ -34,12 +34,15 @@ class NotificationPrefs( is Boolean -> { putBoolean(key, value) } + is String -> { putString(key, value) } + is Array<*> -> { putStringSet(key, value.map { it.toString() }.toSet()) } + is Map<*, *> -> { putStringSet(key, value.map { it.toString() }.toSet()) } diff --git a/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt b/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt index 2aaee3b8ec..d7b9e0e468 100644 --- a/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt +++ b/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt @@ -117,7 +117,7 @@ class ExpoReceiveAndroidIntentsModule : Module() { private fun handleImageIntents( uris: List, - text: String? + text: String?, ) { var allParams = "" @@ -145,7 +145,7 @@ class ExpoReceiveAndroidIntentsModule : Module() { private fun handleVideoIntents( uris: List, - text: String? + text: String?, ) { val uri = uris[0] // If there is no extension for the file, substringAfterLast returns the original string - not diff --git a/package.json b/package.json index 4934691ea9..ccf27c7f54 100644 --- a/package.json +++ b/package.json @@ -202,7 +202,7 @@ "react-native-edge-to-edge": "^1.6.0", "react-native-gesture-handler": "~2.28.0", "react-native-get-random-values": "~1.11.0", - "react-native-keyboard-controller": "1.18.5", + "react-native-keyboard-controller": "^1.20.7", "react-native-pager-view": "6.8.0", "react-native-progress": "bluesky-social/react-native-progress", "react-native-qrcode-styled": "^0.3.3", diff --git a/src/App.native.tsx b/src/App.native.tsx index 1568f7b8ae..5de9f82b7b 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -3,6 +3,7 @@ import '#/view/icons' import React, {useEffect, useState} from 'react' import {GestureHandlerRootView} from 'react-native-gesture-handler' +import {KeyboardProvider as KeyboardControllerProvider} from 'react-native-keyboard-controller' import { initialWindowMetrics, SafeAreaProvider, @@ -14,7 +15,6 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import * as Sentry from '@sentry/react-native' -import {KeyboardControllerProvider} from '#/lib/hooks/useEnableKeyboardController' import {Provider as HideBottomBarBorderProvider} from '#/lib/hooks/useHideBottomBarBorder' import {QueryProvider} from '#/lib/react-query' import {s} from '#/lib/styles' diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx index b63ab4f1c6..374dc94cd8 100644 --- a/src/components/Dialog/index.tsx +++ b/src/components/Dialog/index.tsx @@ -11,6 +11,7 @@ import { } from 'react-native' import { KeyboardAwareScrollView, + type KeyboardAwareScrollViewRef, useKeyboardHandler, useReanimatedKeyboardAnimation, } from 'react-native-keyboard-controller' @@ -23,7 +24,6 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {useEnableKeyboardController} from '#/lib/hooks/useEnableKeyboardController' import {ScrollProvider} from '#/lib/ScrollContext' import {logger} from '#/logger' import {useA11y} from '#/state/a11y' @@ -209,10 +209,9 @@ export const ScrollableInner = React.forwardRef( const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext() const insets = useSafeAreaInsets() - useEnableKeyboardController(IS_IOS) - const [keyboardHeight, setKeyboardHeight] = React.useState(0) + // note: iOS-only. keyboard-controller doesn't seem to work inside the sheets on Android useKeyboardHandler( { onEnd: e => { @@ -231,7 +230,6 @@ export const ScrollableInner = React.forwardRef( } paddingBottom = Math.max(paddingBottom, tokens.space._2xl) } else { - paddingBottom += keyboardHeight if (nativeSnapPoint === BottomSheetSnapPoint.Full) { paddingBottom += insets.top } @@ -259,7 +257,7 @@ export const ScrollableInner = React.forwardRef( {paddingBottom}, contentContainerStyle, ]} - ref={ref} + ref={ref as React.Ref} showsVerticalScrollIndicator={IS_ANDROID ? false : undefined} {...props} bounces={nativeSnapPoint === BottomSheetSnapPoint.Full} @@ -289,8 +287,6 @@ export const InnerFlatList = React.forwardRef< const insets = useSafeAreaInsets() const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext() - useEnableKeyboardController(IS_IOS) - const onScroll = (e: ScrollEvent) => { 'worklet' if (!IS_ANDROID) { diff --git a/src/components/verification/VerifierDialog.tsx b/src/components/verification/VerifierDialog.tsx index e7548aa92b..39fb456453 100644 --- a/src/components/verification/VerifierDialog.tsx +++ b/src/components/verification/VerifierDialog.tsx @@ -28,7 +28,7 @@ export function VerifierDialog({ verificationState: FullVerificationState }) { return ( - + { @@ -138,7 +137,6 @@ function Inner({ @@ -232,7 +239,10 @@ function StarterPackList({ onEndReachedThreshold={0.1} ListHeaderComponent={listHeader} ListEmptyComponent={} - style={IS_WEB ? [a.px_md, {minHeight: 500}] : [a.px_2xl, a.pt_lg]} + style={platform({ + web: [a.px_2xl, {minHeight: 500}], + native: [a.px_2xl, a.pt_lg], + })} /> ) } @@ -240,66 +250,54 @@ function StarterPackList({ function StarterPackItem({ starterPackWithMembership, targetDid, + subject, }: { starterPackWithMembership: StarterPackWithMembership targetDid: string + subject?: bsky.profile.AnyProfileView }) { const t = useTheme() const ax = useAnalytics() const {_} = useLingui() - const queryClient = useQueryClient() const starterPack = starterPackWithMembership.starterPack const isInPack = !!starterPackWithMembership.listItem - const [isPendingRefresh, setIsPendingRefresh] = useState(false) + const {mutate: addMembership, isPending: isPendingAdd} = + useListMembershipAddMutation({ + subject, + onSuccess: () => { + Toast.show(_(msg`Added to starter pack`)) + }, + onError: err => { + if (!isNetworkError(err)) { + logger.error('Failed to add to starter pack', {safeMessage: err}) + } + Toast.show(_(msg`Failed to add to starter pack`), {type: 'error'}) + }, + }) - const {mutate: addMembership} = useListMembershipAddMutation({ - onSuccess: () => { - Toast.show(_(msg`Added to starter pack`)) - // Use a timeout to wait for the appview to update, matching the pattern - // in list-memberships.ts - setTimeout(() => { - invalidateActorStarterPacksWithMembershipQuery({ - queryClient, - did: targetDid, - }) - setIsPendingRefresh(false) - }, 1e3) - }, - onError: () => { - Toast.show(_(msg`Failed to add to starter pack`), 'xmark') - setIsPendingRefresh(false) - }, - }) + const {mutate: removeMembership, isPending: isPendingRemove} = + useListMembershipRemoveMutation({ + onSuccess: () => { + Toast.show(_(msg`Removed from starter pack`)) + }, + onError: err => { + if (!isNetworkError(err)) { + logger.error('Failed to remove from starter pack', {safeMessage: err}) + } + Toast.show(_(msg`Failed to remove from starter pack`), {type: 'error'}) + }, + }) - const {mutate: removeMembership} = useListMembershipRemoveMutation({ - onSuccess: () => { - Toast.show(_(msg`Removed from starter pack`)) - // Use a timeout to wait for the appview to update, matching the pattern - // in list-memberships.ts - setTimeout(() => { - invalidateActorStarterPacksWithMembershipQuery({ - queryClient, - did: targetDid, - }) - setIsPendingRefresh(false) - }, 1e3) - }, - onError: () => { - Toast.show(_(msg`Failed to remove from starter pack`), 'xmark') - setIsPendingRefresh(false) - }, - }) + const isPending = isPendingAdd || isPendingRemove const handleToggleMembership = () => { - if (!starterPack.list?.uri || isPendingRefresh) return + if (!starterPack.list?.uri || isPending) return const listUri = starterPack.list.uri const starterPackUri = starterPack.uri - setIsPendingRefresh(true) - if (!isInPack) { addMembership({ listUri: listUri, @@ -309,7 +307,6 @@ function StarterPackItem({ } else { if (!starterPackWithMembership.listItem?.uri) { console.error('Cannot remove: missing membership URI') - setIsPendingRefresh(false) return } removeMembership({ @@ -344,7 +341,7 @@ function StarterPackItem({ starterPack.listItemsSample.length > 0 && ( <> p.subject)} @@ -375,8 +372,9 @@ function StarterPackItem({ label={isInPack ? _(msg`Remove`) : _(msg`Add`)} color={isInPack ? 'secondary' : 'primary_subtle'} size="tiny" - disabled={isPendingRefresh} + disabled={isPending} onPress={handleToggleMembership}> + {isPending && } {isInPack ? Remove : Add} diff --git a/src/state/queries/actor-starter-packs.ts b/src/state/queries/actor-starter-packs.ts index d40e054535..97cc3b5e05 100644 --- a/src/state/queries/actor-starter-packs.ts +++ b/src/state/queries/actor-starter-packs.ts @@ -1,13 +1,4 @@ -import { - type AppBskyGraphGetActorStarterPacks, - type AppBskyGraphGetStarterPacksWithMembership, -} from '@atproto/api' -import { - type InfiniteData, - type QueryClient, - type QueryKey, - useInfiniteQuery, -} from '@tanstack/react-query' +import {type QueryClient, useInfiniteQuery} from '@tanstack/react-query' import {useAgent} from '#/state/session' @@ -28,13 +19,7 @@ export function useActorStarterPacksQuery({ }) { const agent = useAgent() - return useInfiniteQuery< - AppBskyGraphGetActorStarterPacks.OutputSchema, - Error, - InfiniteData, - QueryKey, - string | undefined - >({ + return useInfiniteQuery({ queryKey: RQKEY(did), queryFn: async ({pageParam}: {pageParam?: string}) => { const res = await agent.app.bsky.graph.getActorStarterPacks({ @@ -59,13 +44,7 @@ export function useActorStarterPacksWithMembershipsQuery({ }) { const agent = useAgent() - return useInfiniteQuery< - AppBskyGraphGetStarterPacksWithMembership.OutputSchema, - Error, - InfiniteData, - QueryKey, - string | undefined - >({ + return useInfiniteQuery({ queryKey: RQKEY_WITH_MEMBERSHIP(did), queryFn: async ({pageParam}: {pageParam?: string}) => { const res = await agent.app.bsky.graph.getStarterPacksWithMembership({ diff --git a/src/state/queries/list-memberships.ts b/src/state/queries/list-memberships.ts index 410a613ada..dd7fde2482 100644 --- a/src/state/queries/list-memberships.ts +++ b/src/state/queries/list-memberships.ts @@ -14,12 +14,23 @@ * -prf */ -import {AtUri} from '@atproto/api' -import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query' +import { + type AppBskyActorDefs, + type AppBskyGraphGetStarterPacksWithMembership, + AtUri, +} from '@atproto/api' +import { + type InfiniteData, + useMutation, + useQuery, + useQueryClient, +} from '@tanstack/react-query' import {STALE} from '#/state/queries' import {RQKEY as LIST_MEMBERS_RQKEY} from '#/state/queries/list-members' import {useAgent, useSession} from '#/state/session' +import type * as bsky from '#/types/bsky' +import {RQKEY_WITH_MEMBERSHIP as STARTER_PACKS_WITH_MEMBERSHIPS_RKEY} from './actor-starter-packs' // sanity limit is SANITY_PAGE_LIMIT*PAGE_SIZE total records const SANITY_PAGE_LIMIT = 1000 @@ -91,9 +102,14 @@ export function getMembership( } export function useListMembershipAddMutation({ + subject, onSuccess, onError, }: { + /** + * Needed for optimistic update of starter pack query + */ + subject?: bsky.profile.AnyProfileView onSuccess?: (data: {uri: string; cid: string}) => void onError?: (error: Error) => void } = {}) { @@ -151,6 +167,60 @@ export function useListMembershipAddMutation({ queryKey: LIST_MEMBERS_RQKEY(variables.listUri), }) }, 1e3) + + // update WITH_MEMBERSHIPS query + + if (subject) { + queryClient.setQueryData< + InfiniteData + >(STARTER_PACKS_WITH_MEMBERSHIPS_RKEY(variables.actorDid), old => { + if (!old) return old + + return { + ...old, + pages: old.pages.map(page => ({ + ...page, + starterPacksWithMembership: page.starterPacksWithMembership.map( + spWithMembership => { + if ( + spWithMembership.starterPack.list && + spWithMembership.starterPack.list?.uri === variables.listUri + ) { + return { + ...spWithMembership, + starterPack: { + ...spWithMembership.starterPack, + listItemsSample: [ + { + uri: data.uri, + subject: subject as AppBskyActorDefs.ProfileView, + }, + ...(spWithMembership.starterPack.listItemsSample?.filter( + item => item.subject.did !== variables.actorDid, + ) ?? []), + ], + list: { + ...spWithMembership.starterPack.list, + listItemCount: + (spWithMembership.starterPack.list.listItemCount ?? + 0) + 1, + }, + }, + listItem: { + uri: data.uri, + subject: subject as AppBskyActorDefs.ProfileView, + }, + } + } + + return spWithMembership + }, + ), + })), + } + }) + } + onSuccess?.(data) }, onError, @@ -206,6 +276,50 @@ export function useListMembershipRemoveMutation({ queryKey: LIST_MEMBERS_RQKEY(variables.listUri), }) }, 1e3) + + queryClient.setQueryData< + InfiniteData + >(STARTER_PACKS_WITH_MEMBERSHIPS_RKEY(variables.actorDid), old => { + if (!old) return old + + return { + ...old, + pages: old.pages.map(page => ({ + ...page, + starterPacksWithMembership: page.starterPacksWithMembership.map( + spWithMembership => { + if ( + spWithMembership.starterPack.list && + spWithMembership.starterPack.list.uri === variables.listUri + ) { + return { + ...spWithMembership, + starterPack: { + ...spWithMembership.starterPack, + listItemsSample: + spWithMembership.starterPack.listItemsSample?.filter( + item => item.subject.did !== variables.actorDid, + ), + list: { + ...spWithMembership.starterPack.list, + listItemCount: Math.max( + 0, + (spWithMembership.starterPack.list.listItemCount ?? + 1) - 1, + ), + }, + }, + listItem: undefined, + } + } + + return spWithMembership + }, + ), + })), + } + }) + onSuccess?.(data) }, onError, diff --git a/src/view/com/profile/ProfileMenu.tsx b/src/view/com/profile/ProfileMenu.tsx index 8d7846d815..684dcbf0fe 100644 --- a/src/view/com/profile/ProfileMenu.tsx +++ b/src/view/com/profile/ProfileMenu.tsx @@ -329,15 +329,17 @@ let ProfileMenu = ({ )} )} - - - Add to starter packs - - - + {!isSelf && ( + + + Add to starter packs + + + + )} Date: Wed, 11 Feb 2026 09:46:47 -0800 Subject: [PATCH 23/59] Address feedback and lint warnings --- src/view/screens/Profile.tsx | 54 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx index 2f0dc4cc83..dd1450c1c8 100644 --- a/src/view/screens/Profile.tsx +++ b/src/view/screens/Profile.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useMemo} from 'react' +import {useCallback, useEffect, useMemo, useRef, useState} from 'react' import {StyleSheet} from 'react-native' import {SafeAreaView} from 'react-native-safe-area-context' import { @@ -79,45 +79,45 @@ function ProfileScreenInner({route}: Props) { data: resolvedDid, error: resolveError, refetch: refetchDid, - status: didStatus, + isPending: isDidPending, } = useResolveDidQuery(name) const { data: profile, error: profileError, refetch: refetchProfile, isPlaceholderData: isPlaceholderProfile, - status: profileStatus, + isPending: isProfilePending, } = useProfileQuery({ did: resolvedDid, }) - const onPressTryAgain = React.useCallback(() => { + const onPressTryAgain = useCallback(() => { if (resolveError) { - refetchDid() + void refetchDid() } else { - refetchProfile() + void refetchProfile() } }, [resolveError, refetchDid, refetchProfile]) // Apply hard-coded redirects as need - React.useEffect(() => { + useEffect(() => { if (resolveError) { if (name === 'lulaoficial.bsky.social') { console.log('Applying redirect to lula.com.br') - navigate('Profile', {name: 'lula.com.br'}) + void navigate('Profile', {name: 'lula.com.br'}) } } }, [name, resolveError]) // When we open the profile, we want to reset the posts query if we are blocked. - React.useEffect(() => { + useEffect(() => { if (resolvedDid && profile?.viewer?.blockedBy) { resetProfilePostsQueries(queryClient, resolvedDid) } }, [queryClient, profile?.viewer?.blockedBy, resolvedDid]) // Most pushes will happen here, since we will have only placeholder data - if (didStatus === 'pending' || profileStatus === 'pending') { + if (isDidPending || isProfilePending) { return ( @@ -186,20 +186,20 @@ function ProfileScreenLoaded({ did: profile.did, enabled: !!profile.associated?.labeler, }) - const [currentPage, setCurrentPage] = React.useState(0) + const [currentPage, setCurrentPage] = useState(0) const {_} = useLingui() - const [scrollViewTag, setScrollViewTag] = React.useState(null) + const [scrollViewTag, setScrollViewTag] = useState(null) - const postsSectionRef = React.useRef(null) - const repliesSectionRef = React.useRef(null) - const mediaSectionRef = React.useRef(null) - const videosSectionRef = React.useRef(null) - const likesSectionRef = React.useRef(null) - const feedsSectionRef = React.useRef(null) - const listsSectionRef = React.useRef(null) - const starterPacksSectionRef = React.useRef(null) - const labelsSectionRef = React.useRef(null) + const postsSectionRef = useRef(null) + const repliesSectionRef = useRef(null) + const mediaSectionRef = useRef(null) + const videosSectionRef = useRef(null) + const likesSectionRef = useRef(null) + const feedsSectionRef = useRef(null) + const listsSectionRef = useRef(null) + const starterPacksSectionRef = useRef(null) + const labelsSectionRef = useRef(null) useSetTitle(combinedDisplayName(profile)) @@ -315,7 +315,7 @@ function ProfileScreenLoaded({ ) useFocusEffect( - React.useCallback(() => { + useCallback(() => { setMinimalShellMode(false) return listenSoftReset(() => { scrollSectionToTop(currentPage) @@ -601,16 +601,16 @@ function ProfileScreenLoaded({ function useRichText(text: string): [RichTextAPI, boolean] { const agent = useAgent() - const [prevText, setPrevText] = React.useState(text) - const [rawRT, setRawRT] = React.useState(() => new RichTextAPI({text})) - const [resolvedRT, setResolvedRT] = React.useState(null) + const [prevText, setPrevText] = useState(text) + const [rawRT, setRawRT] = useState(() => new RichTextAPI({text})) + const [resolvedRT, setResolvedRT] = useState(null) if (text !== prevText) { setPrevText(text) setRawRT(new RichTextAPI({text})) setResolvedRT(null) // This will queue an immediate re-render } - React.useEffect(() => { + useEffect(() => { let ignore = false async function resolveRTFacets() { // new each time @@ -620,7 +620,7 @@ function useRichText(text: string): [RichTextAPI, boolean] { setResolvedRT(resolvedRT) } } - resolveRTFacets() + void resolveRTFacets() return () => { ignore = true } From 63fbf577d994ae0fd0e0ea9be75dfdfff7b0ddfb Mon Sep 17 00:00:00 2001 From: Spence Pope Date: Wed, 11 Feb 2026 13:11:15 -0500 Subject: [PATCH 24/59] Update src/components/ProgressGuide/List.tsx Co-authored-by: Samuel Newman --- src/components/ProgressGuide/List.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/ProgressGuide/List.tsx b/src/components/ProgressGuide/List.tsx index d7cb4d0f03..4a25e02e79 100644 --- a/src/components/ProgressGuide/List.tsx +++ b/src/components/ProgressGuide/List.tsx @@ -158,6 +158,7 @@ function StackedAvatars({follows}: {follows?: bsky.profile.AnyProfileView[]}) { type="user" size={avatarSize - 2} avatar={follow.avatar} + noBorder /> ))} From 1ec70420e60d5ceaba970624ae7cb9ba1a01693f Mon Sep 17 00:00:00 2001 From: Spence Pope Date: Wed, 11 Feb 2026 13:11:24 -0500 Subject: [PATCH 25/59] Update src/components/ProgressGuide/List.tsx Co-authored-by: Samuel Newman --- src/components/ProgressGuide/List.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ProgressGuide/List.tsx b/src/components/ProgressGuide/List.tsx index 4a25e02e79..8ce57a8436 100644 --- a/src/components/ProgressGuide/List.tsx +++ b/src/components/ProgressGuide/List.tsx @@ -147,11 +147,11 @@ function StackedAvatars({follows}: {follows?: bsky.profile.AnyProfileView[]}) { key={follow.did} style={[ a.rounded_full, + a.border, + t.atoms.border_contrast_low, { marginLeft: i === 0 ? 0 : -overlap, zIndex: TOTAL_AVATARS - i, - borderWidth: 1, - borderColor: t.atoms.bg_contrast_25.backgroundColor, }, ]}> Date: Wed, 11 Feb 2026 13:11:30 -0500 Subject: [PATCH 26/59] Update src/components/ProgressGuide/List.tsx Co-authored-by: Samuel Newman --- src/components/ProgressGuide/List.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ProgressGuide/List.tsx b/src/components/ProgressGuide/List.tsx index 8ce57a8436..e07f3305f2 100644 --- a/src/components/ProgressGuide/List.tsx +++ b/src/components/ProgressGuide/List.tsx @@ -173,14 +173,14 @@ function StackedAvatars({follows}: {follows?: bsky.profile.AnyProfileView[]}) { a.justify_center, a.rounded_full, t.atoms.bg_contrast_300, + a.border, + t.atoms.border_contrast_low, { width: avatarSize, height: avatarSize, marginLeft: followedAvatars.length === 0 && i === 0 ? 0 : -overlap, zIndex: TOTAL_AVATARS - followedAvatars.length - i, - borderWidth: 1, - borderColor: t.atoms.border_contrast_low.borderColor, }, ]}> Date: Wed, 11 Feb 2026 17:41:34 -0600 Subject: [PATCH 27/59] Bump API SDK (#9862) * Bump API SDK * Bump dev-env --- package.json | 4 +- yarn.lock | 275 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 162 insertions(+), 117 deletions(-) diff --git a/package.json b/package.json index ccf27c7f54..0c49dc24da 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "icons:optimize": "svgo -f ./assets/icons" }, "dependencies": { - "@atproto/api": "^0.18.20", + "@atproto/api": "^0.18.21", "@bitdrift/react-native": "^0.6.8", "@braintree/sanitize-url": "^6.0.2", "@bsky.app/alf": "^0.1.6", @@ -229,7 +229,7 @@ "zod": "^3.20.2" }, "devDependencies": { - "@atproto/dev-env": "^0.3.208", + "@atproto/dev-env": "^0.3.209", "@babel/core": "^7.26.0", "@babel/preset-env": "^7.26.0", "@babel/runtime": "^7.26.0", diff --git a/yarn.lock b/yarn.lock index f27ce92f8e..4524ecd665 100644 --- a/yarn.lock +++ b/yarn.lock @@ -82,12 +82,12 @@ "@atproto/xrpc" "^0.7.6" "@atproto/xrpc-server" "^0.10.0" -"@atproto/api@^0.18.18": - version "0.18.18" - resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.18.18.tgz#0c02585ea1b0f4a37444b0d8dfbe347c99ea5f64" - integrity sha512-Vg7/sjbwDQZDj8fXtb4E48U4gA+6RC1iSt7onGnH2NyR0E25uds1KnqSKMzqcphdJXrz5GXrgHWc747XPGibzg== +"@atproto/api@^0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.18.20.tgz#3fdbb7b7fae90bd59101970c2b56cc31e8cf417d" + integrity sha512-BZYZkh2VJIFCXEnc/vzKwAwWjAQQTgbNJ8FBxpBK+z+KYh99O0uPCsRYKoCQsRrnkgrhzdU9+g2G+7zanTIGbw== dependencies: - "@atproto/common-web" "^0.4.14" + "@atproto/common-web" "^0.4.15" "@atproto/lexicon" "^0.6.1" "@atproto/syntax" "^0.4.3" "@atproto/xrpc" "^0.7.7" @@ -96,12 +96,12 @@ tlds "^1.234.0" zod "^3.23.8" -"@atproto/api@^0.18.19", "@atproto/api@^0.18.20": - version "0.18.20" - resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.18.20.tgz#3fdbb7b7fae90bd59101970c2b56cc31e8cf417d" - integrity sha512-BZYZkh2VJIFCXEnc/vzKwAwWjAQQTgbNJ8FBxpBK+z+KYh99O0uPCsRYKoCQsRrnkgrhzdU9+g2G+7zanTIGbw== +"@atproto/api@^0.18.21": + version "0.18.21" + resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.18.21.tgz#19dbea422de22e7f5253f1c5475e3588c3a9d4a0" + integrity sha512-s35MIJerGT/pKe2xJtKKswqlIr/ola2r2iURBKBL0Mk1OKe6jP4YvTMh1N2d2PEANFzNNTbKoDaLfJPo2Uvc/w== dependencies: - "@atproto/common-web" "^0.4.15" + "@atproto/common-web" "^0.4.16" "@atproto/lexicon" "^0.6.1" "@atproto/syntax" "^0.4.3" "@atproto/xrpc" "^0.7.7" @@ -128,23 +128,23 @@ multiformats "^9.9.0" uint8arrays "3.0.0" -"@atproto/bsky@^0.0.214": - version "0.0.214" - resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.214.tgz#54183957e323fe0800606acdcc3137acadf6672e" - integrity sha512-Fn+o3WcaX57EmcLoUdcViY4wU2UzfbyNlS/qFQu+1clADtL3pthylwTJgwUU73cZE+7MILZPfTzhQTc15snR9A== +"@atproto/bsky@^0.0.215": + version "0.0.215" + resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.215.tgz#df566ccc7bc77d27dd2f9506c96739352b395cef" + integrity sha512-1X9G4L8boh9naCtXzorFYm8VskE1xLOJslthR16Hd4uH+ryOEVxN0BLk16OP86qy00hU6VNvyGkDqBthUyy62w== dependencies: "@atproto-labs/fetch-node" "^0.2.0" "@atproto-labs/xrpc-utils" "^0.0.24" - "@atproto/api" "^0.18.20" - "@atproto/common" "^0.5.10" + "@atproto/api" "^0.18.21" + "@atproto/common" "^0.5.11" "@atproto/crypto" "^0.4.5" "@atproto/did" "^0.3.0" - "@atproto/identity" "^0.4.10" + "@atproto/identity" "^0.4.11" "@atproto/lexicon" "^0.6.1" "@atproto/repo" "^0.8.12" "@atproto/sync" "^0.1.39" "@atproto/syntax" "^0.4.3" - "@atproto/xrpc-server" "^0.10.11" + "@atproto/xrpc-server" "^0.10.12" "@bufbuild/protobuf" "^1.5.0" "@connectrpc/connect" "^1.1.4" "@connectrpc/connect-express" "^1.1.4" @@ -194,7 +194,7 @@ pino-http "^8.2.1" typed-emitter "^2.1.0" -"@atproto/common-web@^0.4.13", "@atproto/common-web@^0.4.14", "@atproto/common-web@^0.4.4", "@atproto/common-web@^0.4.7": +"@atproto/common-web@^0.4.13", "@atproto/common-web@^0.4.4", "@atproto/common-web@^0.4.7": version "0.4.14" resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.4.14.tgz#77545d454add08d735af00ffc29dd6abf1ab77b3" integrity sha512-rMU8Q+kpyPpirUS9OqT7aOD1hxKa+diem3vc7BA0lOkj0tU6wcAxegxmbPZ8JaOsR7SSYhP/jCt/5wbT4qqkuQ== @@ -214,6 +214,16 @@ "@atproto/syntax" "^0.4.3" zod "^3.23.8" +"@atproto/common-web@^0.4.16": + version "0.4.16" + resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.4.16.tgz#1bee6073ee7a102ea6c47a512a8f6992c683012e" + integrity sha512-Ufvaff5JgxUyUyTAG0/3o7ltpy3lnZ1DvLjyAnvAf+hHfiK7OMQg+8byr+orN+KP9MtIQaRTsCgYPX+PxMKUoA== + dependencies: + "@atproto/lex-data" "^0.0.11" + "@atproto/lex-json" "^0.0.11" + "@atproto/syntax" "^0.4.3" + zod "^3.23.8" + "@atproto/common@0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.1.0.tgz#4216a8fef5b985ab62ac21252a0f8ca0f4a0f210" @@ -246,14 +256,14 @@ multiformats "^9.9.0" pino "^8.21.0" -"@atproto/common@^0.5.10": - version "0.5.10" - resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.5.10.tgz#f0d6b7e012b3dd3991d7e2975e26913d4f41e90f" - integrity sha512-A1+4W3JmjZIgmtJFLJBAaoVruZhRL0ANtyjZ91aJR4rjHcZuaQ+v4IFR1UcE6yyTATacLdBk6ADy8OtxXzq14g== +"@atproto/common@^0.5.11": + version "0.5.11" + resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.5.11.tgz#88499978d3b29c451e7ad9a71f9d2f89446e89f6" + integrity sha512-WRlT4s+wv80WdQuzkQub9D5vTD82O8dH2p91u4b+x3O17q5IQbmA3Lj+1NICINNSy2voqloqAWdqXEkRfdlAPw== dependencies: - "@atproto/common-web" "^0.4.15" - "@atproto/lex-cbor" "^0.0.10" - "@atproto/lex-data" "^0.0.10" + "@atproto/common-web" "^0.4.16" + "@atproto/lex-cbor" "^0.0.11" + "@atproto/lex-data" "^0.0.11" iso-datestring-validator "^2.2.2" multiformats "^9.9.0" pino "^8.21.0" @@ -278,23 +288,23 @@ "@noble/hashes" "^1.6.1" uint8arrays "3.0.0" -"@atproto/dev-env@^0.3.208": - version "0.3.208" - resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.208.tgz#01d07d4b1ef2404adb07bdddf324393989231a52" - integrity sha512-ttx+MIT21iFICW7sZNaFJoCPlxZAqgFy1ztOEn1ebW2MkJzsNHSq2oQC8MHxmpbYEOMPekTXC2iMHW6PYVQJxQ== +"@atproto/dev-env@^0.3.209": + version "0.3.209" + resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.209.tgz#0df234a7feab7628ad376773de0e8bd612fb7f2a" + integrity sha512-i4IVqoyCAqULNeye9xpo5YVfrNjFQjGwAJZ4QAA26L9LuFlXmudnAX17KOCMvmJiPgtRe2ofIy6h+ZJ6qm52tQ== dependencies: - "@atproto/api" "^0.18.20" - "@atproto/bsky" "^0.0.214" + "@atproto/api" "^0.18.21" + "@atproto/bsky" "^0.0.215" "@atproto/bsync" "^0.0.23" - "@atproto/common-web" "^0.4.15" + "@atproto/common-web" "^0.4.16" "@atproto/crypto" "^0.4.5" - "@atproto/identity" "^0.4.10" + "@atproto/identity" "^0.4.11" "@atproto/lexicon" "^0.6.1" - "@atproto/ozone" "^0.1.162" - "@atproto/pds" "^0.4.207" + "@atproto/ozone" "^0.1.163" + "@atproto/pds" "^0.4.209" "@atproto/sync" "^0.1.39" "@atproto/syntax" "^0.4.3" - "@atproto/xrpc-server" "^0.10.11" + "@atproto/xrpc-server" "^0.10.12" "@did-plc/lib" "^0.0.1" "@did-plc/server" "^0.0.1" dotenv "^16.0.3" @@ -319,6 +329,14 @@ "@atproto/common-web" "^0.4.4" "@atproto/crypto" "^0.4.4" +"@atproto/identity@^0.4.11": + version "0.4.11" + resolved "https://registry.yarnpkg.com/@atproto/identity/-/identity-0.4.11.tgz#9622496499919cb2c05d21ab1ba45132dd1e3b52" + integrity sha512-/xXPPojR0PRD0pqoEPmgKMeclUCrkaMKfFGFkssAmXSuT39aCtiibxNqvhp+S2jOdeM6rKrs2QgH91OCGvwPcg== + dependencies: + "@atproto/common-web" "^0.4.16" + "@atproto/crypto" "^0.4.5" + "@atproto/jwk-jose@^0.1.11": version "0.1.11" resolved "https://registry.yarnpkg.com/@atproto/jwk-jose/-/jwk-jose-0.1.11.tgz#ef64bce940a66e267fc3cf0db8df4dbd062bb28a" @@ -343,22 +361,22 @@ "@atproto/lex-data" "0.0.9" tslib "^2.8.1" -"@atproto/lex-cbor@^0.0.10": - version "0.0.10" - resolved "https://registry.yarnpkg.com/@atproto/lex-cbor/-/lex-cbor-0.0.10.tgz#712abc4fedef4854c341e32d0fd1608e45616984" - integrity sha512-5RtV90iIhRNCXXvvETd3KlraV8XGAAAgOmiszUb+l8GySDU/sGk7AlVvArFfXnj/S/GXJq8DP6IaUxCw/sPASA== +"@atproto/lex-cbor@^0.0.11": + version "0.0.11" + resolved "https://registry.yarnpkg.com/@atproto/lex-cbor/-/lex-cbor-0.0.11.tgz#7a464a2032eb61a1dfc254bae1e2759c8279d6a6" + integrity sha512-A7ETtPsEsJ/VuPJOFw4bPNTKxHvFN1JbTQ2NjLuisd3ry7fVxgMpo/qGXsUQsAh/I/uziGbhpNqdS6GnI2p/Wg== dependencies: - "@atproto/lex-data" "^0.0.10" + "@atproto/lex-data" "^0.0.11" tslib "^2.8.1" -"@atproto/lex-client@^0.0.11": - version "0.0.11" - resolved "https://registry.yarnpkg.com/@atproto/lex-client/-/lex-client-0.0.11.tgz#b8e8d0da81ed27f1093d0a1e1c7fdb994394e323" - integrity sha512-2DCidAlhATtZc1Z11PUd+C98BiW/Od4pWtDlQSAxkjHSC/56ZwuSkZQVx27ISk1HldfKVc9qUvQWA9nhmrxYIw== +"@atproto/lex-client@^0.0.12": + version "0.0.12" + resolved "https://registry.yarnpkg.com/@atproto/lex-client/-/lex-client-0.0.12.tgz#87be8075746e32dafc3d23f282e53daadb50ea66" + integrity sha512-ef4jQQ7SOtBsXr+Gf1UHuBfCiAGYZxO5PCCXl3eT4ObO83SROtIf7pyO06jBQI/IZChSVsXqXsgakR0aru6lYQ== dependencies: - "@atproto/lex-data" "^0.0.10" - "@atproto/lex-json" "^0.0.10" - "@atproto/lex-schema" "^0.0.11" + "@atproto/lex-data" "^0.0.11" + "@atproto/lex-json" "^0.0.11" + "@atproto/lex-schema" "^0.0.12" tslib "^2.8.1" "@atproto/lex-data@0.0.9": @@ -381,12 +399,22 @@ uint8arrays "3.0.0" unicode-segmenter "^0.14.0" -"@atproto/lex-document@^0.0.12": - version "0.0.12" - resolved "https://registry.yarnpkg.com/@atproto/lex-document/-/lex-document-0.0.12.tgz#18e0ca344101bb742a2930f663473e0213721f52" - integrity sha512-+no+ZXyCNdOdjkOj6a4n4WHAQzZz3M6VJTwx7IQQC2+to41/4fFr6k8U1y3Jtq2lYcbHqapkJj3RGIxzFcrtwA== +"@atproto/lex-data@^0.0.11": + version "0.0.11" + resolved "https://registry.yarnpkg.com/@atproto/lex-data/-/lex-data-0.0.11.tgz#de98894a80ff907f9cd6c3faa561d3a16e21dd8d" + integrity sha512-4+KTtHdqwlhiTKA7D4SACea4jprsNpCQsNALW09wsZ6IHhCDGO5tr1cmV+QnLYe3G3mu1E1yXHXbPUHrUUDT/A== dependencies: - "@atproto/lex-schema" "^0.0.11" + multiformats "^9.9.0" + tslib "^2.8.1" + uint8arrays "3.0.0" + unicode-segmenter "^0.14.0" + +"@atproto/lex-document@^0.0.13": + version "0.0.13" + resolved "https://registry.yarnpkg.com/@atproto/lex-document/-/lex-document-0.0.13.tgz#fcf794addf6cb328c78d4393e91ec0050a43c623" + integrity sha512-LWsBsKIbyuG7jFObTtnCFQNYHxWWVpVVspqv6UtnS/QsaCyCMg1GIz5vlgi8QBnmGvaPiQxIzGt6mERpTvEXpg== + dependencies: + "@atproto/lex-schema" "^0.0.12" core-js "^3" tslib "^2.8.1" @@ -406,27 +434,35 @@ "@atproto/lex-data" "^0.0.10" tslib "^2.8.1" -"@atproto/lex-resolver@^0.0.13": - version "0.0.13" - resolved "https://registry.yarnpkg.com/@atproto/lex-resolver/-/lex-resolver-0.0.13.tgz#6407b813001d3a3f9e4048197755deccb3cc6f62" - integrity sha512-CcqCE6W3ZVMVzAihatpVbXLxO15mtvddzRzovIJ9QxBTpUmtkdmIk9/gle0oAsRToTJYQy2a6dwAmnAosxP/XQ== +"@atproto/lex-json@^0.0.11": + version "0.0.11" + resolved "https://registry.yarnpkg.com/@atproto/lex-json/-/lex-json-0.0.11.tgz#56be96a4d2366113da3911020cedfb0fb97fbb4f" + integrity sha512-2IExAoQ4KsR5fyPa1JjIvtR316PvdgRH/l3BVGLBd3cSxM3m5MftIv1B6qZ9HjNiK60SgkWp0mi9574bTNDhBQ== + dependencies: + "@atproto/lex-data" "^0.0.11" + tslib "^2.8.1" + +"@atproto/lex-resolver@^0.0.14": + version "0.0.14" + resolved "https://registry.yarnpkg.com/@atproto/lex-resolver/-/lex-resolver-0.0.14.tgz#8bc32e49c231bc29ca0d1ea927b33d7a21447de3" + integrity sha512-jBkYRmMKap2OM1zm0VDvs7Heuf3pGjw9xJEHQx1ohkMmM5f+cHPS40RQ8x8SNE+Vl9gMuOrgmgKyPDIuYSIBTw== dependencies: "@atproto-labs/did-resolver" "^0.2.6" "@atproto/crypto" "^0.4.5" - "@atproto/lex-client" "^0.0.11" - "@atproto/lex-data" "^0.0.10" - "@atproto/lex-document" "^0.0.12" - "@atproto/lex-schema" "^0.0.11" + "@atproto/lex-client" "^0.0.12" + "@atproto/lex-data" "^0.0.11" + "@atproto/lex-document" "^0.0.13" + "@atproto/lex-schema" "^0.0.12" "@atproto/repo" "^0.8.12" "@atproto/syntax" "^0.4.3" tslib "^2.8.1" -"@atproto/lex-schema@^0.0.11": - version "0.0.11" - resolved "https://registry.yarnpkg.com/@atproto/lex-schema/-/lex-schema-0.0.11.tgz#7ff8a1e94971cb750cacaa40e30f546a64db0acd" - integrity sha512-1vLUPQIMeawKP6ehSx2RiqaJDkiseFTXyUk3C4PaoFCktaH8FgVgPVKgUSSy02m1pxVMKnsOBV5psKeN53HG+Q== +"@atproto/lex-schema@^0.0.12": + version "0.0.12" + resolved "https://registry.yarnpkg.com/@atproto/lex-schema/-/lex-schema-0.0.12.tgz#3519b1e4040503e1e6e5a47df1012660f4c38d8c" + integrity sha512-l1RNYmqNwIEjgMEjC9i2o6FLsUFdpAc610xQYK/CRxN31cRzY0lAJ2GFbp2GZ4rRAD3FGYCXid6gZ42KsieUcw== dependencies: - "@atproto/lex-data" "^0.0.10" + "@atproto/lex-data" "^0.0.11" "@atproto/syntax" "^0.4.3" tslib "^2.8.1" @@ -441,7 +477,7 @@ multiformats "^9.9.0" zod "^3.23.8" -"@atproto/oauth-provider-api@0.3.7", "@atproto/oauth-provider-api@^0.3.7": +"@atproto/oauth-provider-api@0.3.7": version "0.3.7" resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-api/-/oauth-provider-api-0.3.7.tgz#7b911256536a72dbba6f38081a200836a3ab50b8" integrity sha512-7yU9vuQFt/hy4NzlDtn+LuhIGvVKkhgWAkCmopnseMPBw6oGPT90uOsTxMkVGtHuKVvBSz7hOXoELXpnZq3gDQ== @@ -449,41 +485,41 @@ "@atproto/jwk" "0.6.0" "@atproto/oauth-types" "0.6.2" -"@atproto/oauth-provider-frontend@^0.2.8": - version "0.2.8" - resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-frontend/-/oauth-provider-frontend-0.2.8.tgz#97f6dc33257b0f846229839dd74f606528f49846" - integrity sha512-wHypQrsbwE6LUlyDADfiJfOH5pDAHWm4l/v1dwkQhRndOai7L+knsbdLAOZVXuz6bRs7oV2Frb3mSS03OS4Gdw== +"@atproto/oauth-provider-frontend@0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-frontend/-/oauth-provider-frontend-0.2.9.tgz#68486c0d9710a1325a02a303a6b22c733239b219" + integrity sha512-m1NhqC7ydEpF5ELV13CxkgCawyMX8wbAXls/4af3Tsz3IOkdM6zPgQeYK7Zj+7Nywjml4mZTkJ8rZiT6O9+5sw== optionalDependencies: "@atproto/oauth-provider-api" "0.3.7" -"@atproto/oauth-provider-ui@^0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-ui/-/oauth-provider-ui-0.4.2.tgz#4edd41c71fd1bf5aaa1df219fb8a20c0b8d90738" - integrity sha512-j3Afu23JYy68GY8L4t/cTEZz1PnrvxLrjiG/nPhXPURZbCnqZ1puIU+HRVCBJfqKyCwaWthXgUjwaL+SFlPGKA== +"@atproto/oauth-provider-ui@0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-ui/-/oauth-provider-ui-0.4.3.tgz#c80b076c2d2a7cc45e45866796f09b959bcf1c03" + integrity sha512-BLNZmtOwoHu2qk/Oi6dUR8TcXQaJre6wgW8YjkW5bKf+Vftn3PGzh8bKgr1fQZDYweZ6AF148imA2OzVSAaLHQ== optionalDependencies: "@atproto/oauth-provider-api" "0.3.7" -"@atproto/oauth-provider@^0.15.7": - version "0.15.7" - resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.15.7.tgz#fc5bd420984dac60f726949d2473bbdb3ddff991" - integrity sha512-rsPez44TJGVC5vFdwSTfSOLIIG5O1JF8NXLe1BjjsUbzRuflN6TyM6HyfBJVsnOVF2bOq6W6xPcnBFUJHCSyUQ== +"@atproto/oauth-provider@^0.15.9": + version "0.15.9" + resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.15.9.tgz#3ec21380711e34f4303a0782ecfffffb8080f144" + integrity sha512-nuyOVw5piS/iEk7xKEtdulRbcFZ7HBB0gPXL62z5IpxmluEvLem/VLqsntj2OK/mtP6xhnIfFHP5pb5+PnLuYQ== dependencies: "@atproto-labs/fetch" "^0.2.3" "@atproto-labs/fetch-node" "^0.2.0" "@atproto-labs/pipe" "^0.1.1" "@atproto-labs/simple-store" "^0.3.0" "@atproto-labs/simple-store-memory" "^0.1.4" - "@atproto/common" "^0.5.10" + "@atproto/common" "^0.5.11" "@atproto/did" "^0.3.0" "@atproto/jwk" "^0.6.0" "@atproto/jwk-jose" "^0.1.11" - "@atproto/lex-document" "^0.0.12" - "@atproto/lex-resolver" "^0.0.13" - "@atproto/oauth-provider-api" "^0.3.7" - "@atproto/oauth-provider-frontend" "^0.2.8" - "@atproto/oauth-provider-ui" "^0.4.2" + "@atproto/lex-document" "^0.0.13" + "@atproto/lex-resolver" "^0.0.14" + "@atproto/oauth-provider-api" "0.3.7" + "@atproto/oauth-provider-frontend" "0.2.9" + "@atproto/oauth-provider-ui" "0.4.3" "@atproto/oauth-scopes" "^0.3.1" - "@atproto/oauth-types" "^0.6.2" + "@atproto/oauth-types" "^0.6.3" "@atproto/syntax" "^0.4.3" "@hapi/accept" "^6.0.3" "@hapi/address" "^5.1.1" @@ -505,7 +541,7 @@ "@atproto/did" "^0.3.0" "@atproto/syntax" "^0.4.3" -"@atproto/oauth-types@0.6.2", "@atproto/oauth-types@^0.6.2": +"@atproto/oauth-types@0.6.2": version "0.6.2" resolved "https://registry.yarnpkg.com/@atproto/oauth-types/-/oauth-types-0.6.2.tgz#d829fae63421dcea7ac703e84460175d2f8d9299" integrity sha512-2cuboM4RQBCYR8NQC5uGRkW6KgCgKyq/B5/+tnMmWZYtZGVUQvsUWQHK/ZiMCnVXbcDNtc/RIEJQJDZ8FXMoxg== @@ -514,20 +550,29 @@ "@atproto/jwk" "0.6.0" zod "^3.23.8" -"@atproto/ozone@^0.1.162": - version "0.1.162" - resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.162.tgz#2c1775c1c45fb03b96087937c7675f7f1825c429" - integrity sha512-UeSbHJ4qHIrWcRelifPm4BFh8PFN7DG9tpKuXSqFjZFG3hO2ZDyBzxV6e9zh7Qg+m2tibdst4Hrk4vyT/7wO6Q== +"@atproto/oauth-types@^0.6.3": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@atproto/oauth-types/-/oauth-types-0.6.3.tgz#4fc996d0af61874830079d1b1bddc7c0774ad6b2" + integrity sha512-jdKuoPknJuh/WjI+mYk7agSbx9mNVMbS6Dr3k1z2YMY2oRiCQjxYBuo4MLKATbxj05nMQaZRWlHRUazoAu5Cng== dependencies: - "@atproto/api" "^0.18.18" - "@atproto/common" "^0.5.9" + "@atproto/did" "^0.3.0" + "@atproto/jwk" "^0.6.0" + zod "^3.23.8" + +"@atproto/ozone@^0.1.163": + version "0.1.163" + resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.163.tgz#7935f9180b6c7f3bd05043d42e14b6055c268596" + integrity sha512-Rz5p0Bf9K3KVo6VuPNe5KTiuJVM5eV7fXSIeWidC1WbDgfEEM8jJu2YRQHvDQq5r95SKKY0gTFYqU6vW0DKSJA== + dependencies: + "@atproto/api" "^0.18.20" + "@atproto/common" "^0.5.11" "@atproto/crypto" "^0.4.5" - "@atproto/identity" "^0.4.10" + "@atproto/identity" "^0.4.11" "@atproto/lexicon" "^0.6.1" "@atproto/syntax" "^0.4.3" "@atproto/ws-client" "^0.0.4" "@atproto/xrpc" "^0.7.7" - "@atproto/xrpc-server" "^0.10.10" + "@atproto/xrpc-server" "^0.10.12" "@did-plc/lib" "^0.0.1" compression "^1.7.4" cors "^2.8.5" @@ -545,30 +590,30 @@ undici "^6.14.1" ws "^8.12.0" -"@atproto/pds@^0.4.207": - version "0.4.207" - resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.207.tgz#20ff3afcf1541b96f016a6843d69d3731b562f19" - integrity sha512-LtzgqeD4aB3O1efzDbhdEopdujB4GG/klLT4N/3v35+0Jpylrkht5Ux2yJGKAqJkzFCfpBdRhNMWpJqS2ssu8A== +"@atproto/pds@^0.4.209": + version "0.4.209" + resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.209.tgz#eb12f325c55692a6487c0620a7754b13f0914fe1" + integrity sha512-jW9dnrrqj65u6FZoj/idIez+idGgYBG4KGVB75i7pqrRkE1a91Bj5MXX60JfIQ0VY9YpfBthSnJG9Pzz5OzA/Q== dependencies: "@atproto-labs/fetch-node" "^0.2.0" "@atproto-labs/simple-store" "^0.3.0" "@atproto-labs/simple-store-memory" "^0.1.4" "@atproto-labs/simple-store-redis" "^0.0.1" "@atproto-labs/xrpc-utils" "^0.0.24" - "@atproto/api" "^0.18.19" + "@atproto/api" "^0.18.21" "@atproto/aws" "^0.2.31" - "@atproto/common" "^0.5.10" + "@atproto/common" "^0.5.11" "@atproto/crypto" "^0.4.5" - "@atproto/identity" "^0.4.10" - "@atproto/lex-cbor" "^0.0.10" - "@atproto/lex-data" "^0.0.10" + "@atproto/identity" "^0.4.11" + "@atproto/lex-cbor" "^0.0.11" + "@atproto/lex-data" "^0.0.11" "@atproto/lexicon" "^0.6.1" - "@atproto/oauth-provider" "^0.15.7" + "@atproto/oauth-provider" "^0.15.9" "@atproto/oauth-scopes" "^0.3.1" "@atproto/repo" "^0.8.12" "@atproto/syntax" "^0.4.3" "@atproto/xrpc" "^0.7.7" - "@atproto/xrpc-server" "^0.10.11" + "@atproto/xrpc-server" "^0.10.12" "@did-plc/lib" "^0.0.4" "@hapi/address" "^5.1.1" better-sqlite3 "^10.0.0" @@ -642,7 +687,7 @@ "@atproto/common" "^0.5.3" ws "^8.12.0" -"@atproto/xrpc-server@^0.10.0", "@atproto/xrpc-server@^0.10.10", "@atproto/xrpc-server@^0.10.3": +"@atproto/xrpc-server@^0.10.0", "@atproto/xrpc-server@^0.10.3": version "0.10.10" resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.10.10.tgz#69d1a3ce8278a6b49286a5df33ebc204d42129ed" integrity sha512-USDjOZGiletqzuWHC3Q2fk30hJDk4uYt6KPgvnZidShCouTf3hzwJZ8d2eOKOofSjGXW+GC0QYp7fYJFn6lZ2Q== @@ -661,15 +706,15 @@ ws "^8.12.0" zod "^3.23.8" -"@atproto/xrpc-server@^0.10.11": - version "0.10.11" - resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.10.11.tgz#cd6f880ebb6a913db2925a23aa0ef0b05f5b02fd" - integrity sha512-7XR+n1G4j1PO33slr2Agl+lmTXbEQzk5iaCJmrcsfTC/0BbCHqSSbm+WHduz3EH4dfFioZsnDo1UesCF0EQEtg== +"@atproto/xrpc-server@^0.10.12": + version "0.10.12" + resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.10.12.tgz#6b88c9af5d301302e5e177b5f982a3494e734d78" + integrity sha512-HuciFHxvQfWtvq+dmH3vK9uXii49vqkJgZFLcHums1xMvLvNBY5bgtUBdpQdsdEuq8B4DTuanZRs+z3zGariyg== dependencies: - "@atproto/common" "^0.5.10" + "@atproto/common" "^0.5.11" "@atproto/crypto" "^0.4.5" - "@atproto/lex-cbor" "^0.0.10" - "@atproto/lex-data" "^0.0.10" + "@atproto/lex-cbor" "^0.0.11" + "@atproto/lex-data" "^0.0.11" "@atproto/lexicon" "^0.6.1" "@atproto/ws-client" "^0.0.4" "@atproto/xrpc" "^0.7.7" From 93d2f3a8dbd78a23dcbe3642897474d0f37168e2 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Wed, 11 Feb 2026 23:51:19 +0000 Subject: [PATCH 28/59] Germ DM button (#9848) * germ link (wip) * add todos * just yeet declaration for now * ensure not proxied * allow undo delete * tweak styles * ignore unknown values * tweak styles * fix boolean logic * skip IAB * fix mutationFn * add link warning interstitial * Logging and metrics * Little more error handling * Update copy --------- Co-authored-by: Eric Bailey --- assets/images/germ_logo.webp | Bin 0 -> 7840 bytes src/analytics/metrics/types.ts | 5 + src/components/dialogs/LinkWarning.tsx | 19 +- .../Profile/Header/ProfileHeaderStandard.tsx | 5 + src/screens/Profile/components/GermButton.tsx | 334 ++++++++++++++++++ src/state/session/index.tsx | 2 +- 6 files changed, 362 insertions(+), 3 deletions(-) create mode 100644 assets/images/germ_logo.webp create mode 100644 src/screens/Profile/components/GermButton.tsx diff --git a/assets/images/germ_logo.webp b/assets/images/germ_logo.webp new file mode 100644 index 0000000000000000000000000000000000000000..a85048381ac71eee1131022b862b807875f6ad85 GIT binary patch literal 7840 zcmZ{pWl$Wz(ykW?4#6!1w_w5DJ-FNA4!bx6cXxMpTihkMyGzjE?iTdR`OdAnb${Ic z)iu>K(^cKiTO%qzBqh^`0RT-2Q6&u}ZqlfK{!9@d8;b4@>JCaUUOG>fs;H2xxY5$B z78B9T_K$Nu0{vy1LI3;tntOy->f`rKp(_%oX1fca#O?~GDD8Kz9L1N9V4~i;@C|0d>$PdR z!jb+$TyDjT=1sbqBY36gU$QQ>N!%P>$QR@KuOjLz>qLVZ0=6+#N1w71J2A2|c%O%K z4NKuL4C9eVpWA3CG)=W$ktPI#B%(L2vhfjBwJA~*7h9}9oERn}F9)-kQ$6InIJ4~S zKu>jLfi2)3Lltxnk7t32=ECn+R7^9hZG-=&eW^z6kU2S!<1|9pf@uKB6J~t(JyEn; z-_E;4ME)6e5LB?fNhrN;n^|QN%SQB$ojJunJ4g@SjR0Akr(JBV0g|N*^nqw2|z5MTFiu(C*{2iFX~he^je@ z<+2p57^84=&YbzHZqVk>0^?p~Mkh9AW`v}k+=Z?4v)UScc(LgM5sIgWdUmeeVzir0KNt&OY2y8EsL{ zWQeHpe@2))&n;50t$!m}Id#WYg9B`rDt04$npwSg1LkiBB#LHdf@535+E3PqX5-|f z{KirEqM4dv_DGRa|&f;)Hi4^VeRh3XBE(~f(78E7ow#_RZDfmBQTBm{4hQI0fY|J6DW z4Yi~B`wdrZ@K;IM6ylAtIQxP$%uRimE)K%OY;3f;b*xkcLVn?}x())lUHmTKlqkc% z7E`8>HhG@w2(c@%1#Q;Y)-wSIY&I9J;cwk$%zvyj{)ab4)%B$xFvrh4sD`zD+9oq4 zRSdmUDtn(@8yHMTBZn3+Z@3;o6v1z)Zuxp ziPLJ{80dzgvJS1^xy$371-g@auV#r=UuE4cd7}F{K+~i*mr>z*BA|4hW~y z5!Y(rn?s&nW6NEhn=Xj@46{bUL8_xZ?vyaP3|O+wg%@QoAa*MkQ_Ef<7OEu_>wBC+ zwMJSJk5*f|DV#L;+8%Q0-H+ATUS(lb)Q# zXG%muUKOq8icp?O0$bQT7l+h3<&}Bn!2LTb#*yA_O&|CN6G-{*-A`f}DK3);=fZgfV zt!O@#>cm34u+53t<2Xuaezcl$)@sHFnnW%?v;)`2j=0n7QQ!nzpx5tN^nvbU><0Vk zzcr<3@p9W<%DH3)jsqKl&CN{Cgn>{^_CDz6zNk3OhJ*7@r2;CEgU1-7__@y|ABQ?R zfDN8Czl4j#ljK@SpZkzq#R0t#-L9bu3G+2eOIMl#7i>xMiiX$$?lznk>&p?rRW)N2 zTs903qx*y-vaO_vJDEOBrk+?b{e>H_BcaC};?(@MAUP+-TKRPQC2I0+$k*(WdlDK8 zWJ7Z0N4GweY&BLrgwu5fI`y^u4uMP8MFTONOblweW7?FipluRw{3=47rkRWE%BTU0 zCJWUOvL&cie<8|sQm)6u3Ap^PA&qI&&v~g9r0Wp1iVV=ub$|o3tXjv>!d_!Tl|Fi- z$WT%83~28KveW#H4I$}7*CoU`?{hSJ%q183*LXc?NwUKV#TQ8!Qsw0=co7NytPY30 zr#44Bgt~{A2(6v@yVv*&4>)0~C{c$VW=X*q^gQ`+$aXGe|6*jmHIougP`eq;{aLNT z=!T-l%LMh_sj9iNtiaR>^k_$#GK>^?c(Zlt;5ksbc9b0m1t2tFm!YVsUY;nZdN89Q z*^y|$D5{N(v*^za($q zbp4t@W|)VvIKGvZy>2-X;6W*S)>HauAuI}DC;w^Hm8kY;NtkJSS0#P zJa%5OLW9NMOKO65977q@-rO8~obI@&XL>5#%U3JZ@@oOPzg&$4OBy^`N(SKmssh&1 zPgiXVI|uHodNLDgjYR45^}?{@AhSUd$Ba$#@(yX(!`~!I(?=H`RV+YZ$H`91J-`~< zGajp9Y^9BC0?)qRycd))5cRcXXae^8wiZH%|7q(t#By7;P}hy@wE00xr~hE_2(f%++vGIG@VdK@RAH_Kx2vxkfn}3@x_4IzT?A)|r_F!;D{azN*%Z1ZouR+Rjz)8wQqafbMtBUXGIf44CRrfFX*3Wp zjT5w|OGIj!_)p4qlMlNhQ(TN3lezvp<%m(oeBdx_z>#qg1tC-`gM2pZS;AR9v=&y_ zN6HMAFxNl%*cdH=Izc5Ic!oC&!f27C_l5=E3r)QSsKehSi!~;(RLkHbEi>JAQnPSq zI{Lv|CtF#if`ggTDD%Yfvg1F?jd2nH>EZ&E2Q7c8$cT&<^Sf1)R9LPIc)^ncr_inT zHENw)CO)@sjOK1#v57~tIP;pv`XdH%?4JJUHflI(JjO#*Lzh&n%7?)3=eeA}AitU@ zCRv&#XPiETil~lZ&Z=C~`5+-^)m%u8TIcBp%112tc|d|=@l)jJO`Sh2a3)YPfaY?; z^^Zges5YEzAC0iBBF6S&q}MPXBFQV$B@j}e{H3LODjvM|tB3P$y!V_)%$=i5^@op( zakUEL%7I`GTcNLscU3rxCy^UrlUl5UYMNyU^fJmv$c80YHhIsGh?S!>WOh4%Lij5N zGyT*9Ng0l+OqPccRRsncZAQj#6*;>wZ<@;qZ$%|`?vmm{xLg*$s=o9=kI38_ip*xTSV4RRg|AmdiDF zk>Y$yK1sm)b53lz7yXbNL)sh>TC+6+NeH>_s>4<+urG4l?;Ynxn!m9zxAnTM+gr&U z6WrBeU%(pokm6F2m^SPeWr|)=7JEO5W`29#0X7AW$!W?3J6NGZEh1aUkiZM9##7o+ z=R3Y0w23f^N4|RtHMS6a8x`GoqT0lq(w zr?!h~p3Y8K@Ug;8q&?ZV8WwY)FjGTLm6<#kY&~C3;WSUcMZg3hsp-^Q@l8CuUI#?@@PE!w5D${xwW8X%mQhhmT$uu?d1EV;UwZA9h{!jr8y*vzC9if1#2&E3d;7k(UAB0zzhSk>>t%d-ck7+H z|JLGhRN{CgNpoE~jFhRKXi_=U4ZZUwQZHarF6}2sOfU94q^PKo9&^NY_tZ!=UAVTetGQHcq-%9Kok9+12uE!v5pZT`kn&jQ zr&81`Bv1r*LU17L1*V5WI;!MJzKbo`vMcgkl&*?I$Qz? z2rekbIBEg_(WmIr)DC z^Wxz<++|Dg=k_%??1#eAdi7igYHs*!E?)A^X5GSd_w9vCbYJ6JnDbW6{_Y(ra<|H* zccA!u4&ja(Oc6ucN)Ad;rlOKot>K#i;5ooOM0xhJ}Z5t!QS!zR49%x8JnYr<1xbqqUzalL>0bHUr zHj=nuQfdhC&Y`t!wo+Y~c&Xi0tzs=L)L#1VE~$2g75@I6QD2UK(0}sp;zNfNfl4Vn zg`{gvg%~5!hqQNegA?*gi3{ZbSe>czT9slk{HaPF^e2dtCWgH(<2SfJ{Td18155Eh z5<-BKXcjp4vjMbI^&hY^zoYD4_$Jrit{2}s1@lep+T!MUaiG2O=Eib*_gat>3EQALT@vhY5~+8nZnP`> zNg_TlHKj=IWjKrYM^f?XF34Y0*DZz@S=?6t_)W=e5g!5Uh0bO(^_V3it91!*cM(s> zQ(`Ye@*?=o{N}PY@0kPP@ zhrg%cog&OqaMrFKnW+=TWDH>>x1VP!kr*^IX>SD_OI)c#l|6TB10ahXePXpZ6LvpT zS$mK}`tIKib_nvHQ>A%an|4BgXRm!8IIMe2Sev{(0jg;UmkQ$UX7^DKK|iFHPFf_^ z*jwJZ+m;1JE4wzhdMipf%b072#o?QVTe-7~n8Ny!_ruh}&77hznQpw0o@gPyw)>e_h3jvDih&6~9pRz8s zy`NMVh05TSMzE5M$sOI@&ix~&kJFk6XajxY6D-HKPUQFipbU(t+$;lI;reLK%#=c& zZmzIX+2l{oRoF~xbSuA{*lnI^vg*SERm4y@c?0i<*SGM2P{Suot<{QbrFxpa>QyYB zexyLx4t!*j>-*u5lVb>Z1vJ!UJ9Q{@P?qPBfJ{t1mB|>k#%_lJ23)?8rwB~LlUx-> zVxDSA&*(SI4&=O+=rC;Y^u8ry{zMAO^}4*t+g4(iLPPAjTs{|XJFCpI33)tB%{WgE zS8l8{8H{S1F}_dE4kh`?G723(ds=`=(EGQh7p`ki^qU=_QcLY00t&8$RGSX!_{hK}UggO9@?QJ+j)ix*36XuVM1j=vnA!}iyuB&PiTz7J~2 zAD!ndsj$UDhmGZoJ)1KUC(-*!D($3SPU0?B`r+D~gvZjy%;)nKZQNJGEG%~q(HX&X z@7m3_Y+v%#;_JZqKSn~1TN`lqx;#u0DF8o!l>{}qH~WMgW9tr5rL5m%O*N}%BxO|e zK(sGf<0<0~cQ}e`Y;%;P(VZ5VuK~?v(A3e0OkCvQs0~ZO<&Wa^yrhVwu=Fgg0mJ&& z4*5tgMjhVoz9F*30v-$?9`LCJ-mfS*!_-IHpOoLGzG%C zPa74}fe*&)-Lr1WuxpG6w5>V9N}N@FdHZ@3 zG88#-pNO437ZO^2 #b-;s`mQ+1g~Ar(x2^)#OM1HxwPV2_dmcaKGL$X0K$Aavag%~}Qs z&Dd@#TLqOaDt1$OU!+J_YWC<_6_MTXjX&3;|GQo)e*Da#^Q-?&v%}|+=Es1DIQeDm z#{#pfUr8CBiF_K3I|&hV1?86XmJc0ji&`Zw!^EcJA6rL(+m3u!IqMNY0dJ}CTDVpq^o`h zP~XWcn0R`8>*gzRVfx#X#=e1ok!Qp z6LR$ucY+zu%O9u~9y4AuYZ?KH$`(~t7PgNJSUtrXV0fbb%0puzP_HbO*Hsv&!T#6j zuFR2wX0EC^R`AvVKVLa#p>vh~+(^WE{8!nV>8r^i1_6WPaINX5W;}#$j^>^Weop0; zF=C5F!fn$VSb_5zaFpK4yNl=y06{rQ{)i=L{)g(-9zR9j%-P=8x{c{J;F|ERxLc;^ITHGHfo!=`I#;}k1Y8^_I{?tOP*}cxu_$*5~42xsVaj6s6^~7Z`rs9qKjMcEPITMu*;qvdbQXzE!nI zqNZ$=a3Gd4cZ|z*7>dti4kXIz)b={#3JlhGc_Q_~fcZ5DosjF^rV#Ca$~wso^JV@mnB|FaWkEWCKGH zlQCIu&`CZW{)U;yPI=aBUz9Z+`5xbi-puYCr|>bb?gd>;3YpOQb1^DzTk42f=!R+E z1V2)`3R2A|HTi4q-RCt{C7ows&9+Fk(@pA88O>4t_{2K&=Yj(~uYcc3Wwk^Lt2LeR z(=m05v6zR}6MBKx$B=n2s>#LzwCAO zq!}Bjn6Xto7gp8ik!K2|C0g--lncqrT$Ep9=ua=??Kx;HN4GS zF5R>JxY!xd3atyr0-F*K(`G4J;(%C+KV^OHo`KP0-r5Frzl@2LzBbelpzMvNRQD156tfUIWAAbx%Bvp^{kU8F`dHrC zs7~7%XXXhKzoDm;c=CKMH|>uTMpHURpV7UrVc&OAA-PuJXv zRv}BP)hw2Lmw-B_tIcMMiAaCNhw+P}IVP2Ho&NjZr))2Z>R9IAscUTsU{;@}>_9C2 zwtDoXd9!n6>I(7SwWsLVV?o3;m$*W^0T=xVcZ^Iv#wqm@8z;yaIkM~U8)XO$Qym^B z#SByh&zVz0fF!>|iK8dcu_nv!jLp*B4>KNGU~Xa;oMc!Y0054n#k`jaz_$&QP^7aKyIcP@x zWL7H?Vl?lBucqctyN5wO<{_w63_uk^G3Q0~M7%4eJ(FtFiHY;PC2HCvQEqgmT|lzx z&J7|LMRRp|i6hDPwb;fKo>2IAxbzsz(f}pHN!6J-28CiVu_%e4l9^%1+ANZW29$mM zYk+8T+?-dy4__vzg*VJ@kk;AR0_jH%gf7XtZWDA<;WQSV7W)x{PnNvG$w#`aW{7ny z5LN{(rUgnkDj@xBQDw3eQ#0Dxc0leHMf#hZrH7I{YmY>H&Yydx7-lC-@1|zm+fpA) z*uq+vR?Ril({;<%nQn+~ZV&#l(3m>uYf|c2DRc!YzZFQa@=jz8dVTFy%&GaMo3 z6Tc$f^K!xb)tpEvJzwl;A9^2Pi&{Nc#iUPO+phxvK#fcv%8X&e*A;po40>mY+OUZZ z&%)UT`^1%^ha5=-)9<09;}xn%`)J}z3=CVGkuKKSa8^QA-^h@YTjAk?zC=)8tL1&8 m=#XQx@WsoZCD2|i9A?ArTW7wtKQ{bttKlgr^AKG9^Zy6naywlB literal 0 HcmV?d00001 diff --git a/src/analytics/metrics/types.ts b/src/analytics/metrics/types.ts index 97b7fcfe09..65f2a5d39f 100644 --- a/src/analytics/metrics/types.ts +++ b/src/analytics/metrics/types.ts @@ -875,4 +875,9 @@ export type Events = { 'liveEvents:unhideAllFeedBanners': { context: LiveEventFeedMetricContext } + + 'profile:associated:germ:click-to-chat': {} + 'profile:associated:germ:click-self-info': {} + 'profile:associated:germ:self-disconnect': {} + 'profile:associated:germ:self-reconnect': {} } diff --git a/src/components/dialogs/LinkWarning.tsx b/src/components/dialogs/LinkWarning.tsx index 74be78f9d3..181d411ce4 100644 --- a/src/components/dialogs/LinkWarning.tsx +++ b/src/components/dialogs/LinkWarning.tsx @@ -22,12 +22,27 @@ export function LinkWarningDialog() { webOptions={{alignCenter: true}} onClose={linkWarningDialogControl.clear}> - + ) } -function InAppBrowserConsentInner({ +export function CustomLinkWarningDialog({ + control, + link, +}: { + control: Dialog.DialogControlProps + link?: {href: string; displayText: string; share?: boolean} +}) { + return ( + + + + + ) +} + +function LinkWarningDialogInner({ link, }: { link?: {href: string; displayText: string; share?: boolean} diff --git a/src/screens/Profile/Header/ProfileHeaderStandard.tsx b/src/screens/Profile/Header/ProfileHeaderStandard.tsx index 6467756d4e..c60fcd032a 100644 --- a/src/screens/Profile/Header/ProfileHeaderStandard.tsx +++ b/src/screens/Profile/Header/ProfileHeaderStandard.tsx @@ -39,6 +39,7 @@ import * as Toast from '#/components/Toast' import {Text} from '#/components/Typography' import {VerificationCheckButton} from '#/components/verification/VerificationCheckButton' import {IS_IOS} from '#/env' +import {GermButton} from '../components/GermButton' import {EditProfileDialog} from './EditProfileDialog' import {ProfileHeaderHandle} from './Handle' import {ProfileHeaderMetrics} from './Metrics' @@ -163,6 +164,10 @@ let ProfileHeaderStandard = ({ ) : undefined} + {profile.associated?.germ && ( + + )} + {!isMe && !isBlockedUser && shouldShowKnownFollowers(profile.viewer?.knownFollowers) && ( diff --git a/src/screens/Profile/components/GermButton.tsx b/src/screens/Profile/components/GermButton.tsx new file mode 100644 index 0000000000..c5af7d536e --- /dev/null +++ b/src/screens/Profile/components/GermButton.tsx @@ -0,0 +1,334 @@ +import {Platform, View} from 'react-native' +import {Image} from 'expo-image' +import { + type AppBskyActorDefs, + type AppBskyActorGetProfile, + type AtpAgent, +} from '@atproto/api' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {useMutation, useQueryClient} from '@tanstack/react-query' + +import {until} from '#/lib/async/until' +import {isNetworkError} from '#/lib/strings/errors' +import {RQKEY} from '#/state/queries/profile' +import {useAgent, useSession} from '#/state/session' +import {atoms as a, useTheme, web} from '#/alf' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {CustomLinkWarningDialog} from '#/components/dialogs/LinkWarning' +import {ArrowTopRight_Stroke2_Corner0_Rounded as ArrowTopRightIcon} from '#/components/icons/Arrow' +import {Link} from '#/components/Link' +import {Loader} from '#/components/Loader' +import * as Toast from '#/components/Toast' +import {Text} from '#/components/Typography' +import {useAnalytics} from '#/analytics' +import type * as bsky from '#/types/bsky' + +export function GermButton({ + germ, + profile, +}: { + germ: AppBskyActorDefs.ProfileAssociatedGerm + profile: bsky.profile.AnyProfileView +}) { + const t = useTheme() + const ax = useAnalytics() + const {_} = useLingui() + const {currentAccount} = useSession() + const linkWarningControl = Dialog.useDialogControl() + + // exclude `none` and all unknown values + if ( + !(germ.showButtonTo === 'everyone' || germ.showButtonTo === 'usersIFollow') + ) { + return null + } + + if (currentAccount?.did === profile.did) { + return + } + + if (germ.showButtonTo === 'usersIFollow' && !profile.viewer?.followedBy) { + return null + } + + const url = constructGermUrl(germ, profile, currentAccount?.did) + + if (!url) { + return null + } + + return ( + <> + { + ax.metric('profile:associated:germ:click-to-chat', {}) + if (isCustomGermDomain(url)) { + evt.preventDefault() + linkWarningControl.open() + return false + } + }} + label={_(msg`Open Germ DM`)} + overridePresentation={false} + shouldProxy={false} + style={[ + t.atoms.bg_contrast_50, + a.rounded_full, + a.self_start, + {padding: 6}, + ]}> + + + Germ DM + + + + + + ) +} + +function GermLogo({size}: {size: 'small' | 'large'}) { + return ( + + ) +} + +function GermSelfButton({did}: {did: string}) { + const t = useTheme() + const ax = useAnalytics() + const {_} = useLingui() + const selfExplanationDialogControl = Dialog.useDialogControl() + const agent = useAgent() + const queryClient = useQueryClient() + + const {mutate: deleteDeclaration, isPending} = useMutation({ + mutationFn: async () => { + const previousRecord = await agent.com.germnetwork.declaration + .get({ + repo: did, + rkey: 'self', + }) + .then(res => res.value) + .catch(() => null) + + await agent.com.germnetwork.declaration.delete({ + repo: did, + rkey: 'self', + }) + + await whenAppViewReady(agent, did, res => !res.data.associated?.germ) + + return previousRecord + }, + onSuccess: previousRecord => { + ax.metric('profile:associated:germ:self-disconnect', {}) + + async function undo() { + if (!previousRecord) return + try { + await agent.com.germnetwork.declaration.put( + { + repo: did, + rkey: 'self', + }, + previousRecord, + ) + await whenAppViewReady(agent, did, res => !!res.data.associated?.germ) + await queryClient.refetchQueries({queryKey: RQKEY(did)}) + + Toast.show(_(msg`Germ DM reconnected`)) + ax.metric('profile:associated:germ:self-reconnect', {}) + } catch (e: any) { + Toast.show( + _(msg`Failed to reconnect Germ DM. Error: ${e?.message}`), + { + type: 'error', + }, + ) + if (!isNetworkError(e)) { + ax.logger.error('Failed to reconnect Germ DM link', { + safeMessage: e, + }) + } + } + } + + selfExplanationDialogControl.close(() => { + void queryClient.refetchQueries({queryKey: RQKEY(did)}) + Toast.show( + + + + Germ DM disconnected + + {previousRecord && ( + void undo()}> + Undo + + )} + , + ) + }) + }, + onError: error => { + Toast.show( + _(msg`Failed to disconnect Germ DM. Error: ${error?.message}`), + { + type: 'error', + }, + ) + if (!isNetworkError(error)) { + ax.logger.error('Failed to disconnect Germ DM link', { + safeMessage: error, + }) + } + }, + }) + + return ( + <> + + + + + + + + + Germ DM Link + + + + + + This button lets others open the Germ DM app to send you a + message. You can manage its visibility from the Germ DM app, or + you can disconnect your Bluesky account from Germ DM altogether by + clicking the button below. + + + + + + + + + + ) +} + +function constructGermUrl( + declaration: AppBskyActorDefs.ProfileAssociatedGerm, + profile: bsky.profile.AnyProfileView, + viewerDid?: string, +) { + try { + const urlp = new URL(declaration.messageMeUrl) + + if (urlp.pathname.endsWith('/')) { + urlp.pathname = urlp.pathname.slice(0, -1) + } + + urlp.pathname += `/${platform()}` + + if (viewerDid) { + urlp.hash = `#${profile.did}+${viewerDid}` + } else { + urlp.hash = `#${profile.did}` + } + + return urlp.toString() + } catch { + return null + } +} + +function isCustomGermDomain(url: string) { + try { + const urlp = new URL(url) + return urlp.hostname !== 'landing.ger.mx' + } catch { + return false + } +} + +function platform() { + switch (Platform.OS) { + case 'ios': + return 'iOS' + case 'android': + return 'android' + default: + return 'web' + } +} + +async function whenAppViewReady( + agent: AtpAgent, + actor: string, + fn: (res: AppBskyActorGetProfile.Response) => boolean, +) { + await until( + 5, // 5 tries + 1e3, // 1s delay between tries + fn, + () => agent.app.bsky.actor.getProfile({actor}), + ) +} diff --git a/src/state/session/index.tsx b/src/state/session/index.tsx index 4a70fc4c09..e63e180a4e 100644 --- a/src/state/session/index.tsx +++ b/src/state/session/index.tsx @@ -430,7 +430,7 @@ export function useRequireAuth() { const {signinDialogControl} = useGlobalDialogsControlContext() return useCallback( - (fn: () => void) => { + (fn: () => unknown) => { if (hasSession) { fn() } else { From 8c4820b1f1054f72289b50a0e16fa9737c0c28e9 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Thu, 12 Feb 2026 01:52:22 +0000 Subject: [PATCH 29/59] [Web] Fix splash flicker and add animation (#9860) * manually hide non-React splash logo * tweak comment * animate out splash --- bskyweb/templates/base.html | 8 +-- src/App.web.tsx | 123 ++++++++++++++++++------------------ src/Splash.web.tsx | 96 ++++++++++++++++++++++++---- web/index.html | 8 +-- 4 files changed, 151 insertions(+), 84 deletions(-) diff --git a/bskyweb/templates/base.html b/bskyweb/templates/base.html index 0c4a91df6b..e33479e697 100644 --- a/bskyweb/templates/base.html +++ b/bskyweb/templates/base.html @@ -148,11 +148,11 @@ {%- block body_all %} +
+ + +
-
- - -
+
+ + +
-
- - -
From cbac380c9696f60e23d8aab50b8fa021dcb4b091 Mon Sep 17 00:00:00 2001 From: surfdude29 <149612116+surfdude29@users.noreply.github.com> Date: Thu, 12 Feb 2026 01:55:54 +0000 Subject: [PATCH 30/59] Add profile error messages to cleanError (#9842) --- src/lib/strings/errors.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lib/strings/errors.ts b/src/lib/strings/errors.ts index a706597144..e68cadeda2 100644 --- a/src/lib/strings/errors.ts +++ b/src/lib/strings/errors.ts @@ -30,6 +30,18 @@ export function cleanError(str: any): string { if (str.includes('Bad token scope') || str.includes('Bad token method')) { return t`This feature is not available while using an App Password. Please sign in with your main password.` } + if (str.includes('Account has been suspended')) { + return t`Account has been suspended` + } + if (str.includes('Account is deactivated')) { + return t`Account is deactivated` + } + if (str.includes('Profile not found')) { + return t`Profile not found` + } + if (str.includes('Unable to resolve handle')) { + return t`Unable to resolve handle` + } if (str.startsWith('Error: ')) { return str.slice('Error: '.length) } From 6d68a5bd212dd4eeee816828ffe4e27601cdd7f3 Mon Sep 17 00:00:00 2001 From: pfrazee <1270099+pfrazee@users.noreply.github.com> Date: Thu, 12 Feb 2026 03:12:33 +0000 Subject: [PATCH 31/59] Nightly source-language update --- src/locale/locales/en/messages.po | 302 ++++++++++++++++++------------ 1 file changed, 184 insertions(+), 118 deletions(-) diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po index cb66d55f57..49beb8aee9 100644 --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -132,7 +132,7 @@ msgstr "" msgid "{0, plural, other {# people have}} joined Bluesky via this starter pack!" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:361 +#: src/components/dialogs/StarterPackDialog.tsx:358 msgid "{0, plural, other {+# more}}" msgstr "" @@ -643,6 +643,14 @@ msgctxt "toast" msgid "Account followed" msgstr "" +#: src/lib/strings/errors.ts:34 +msgid "Account has been suspended" +msgstr "" + +#: src/lib/strings/errors.ts:37 +msgid "Account is deactivated" +msgstr "" + #: src/components/PostControls/PostMenu/PostMenuItems.tsx:446 #: src/view/com/profile/ProfileMenu.tsx:158 msgctxt "toast" @@ -670,8 +678,8 @@ msgstr "" msgid "Account removed from quick access" msgstr "" -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:84 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:290 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:85 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:295 #: src/view/com/profile/ProfileMenu.tsx:172 msgctxt "toast" msgid "Account unblocked" @@ -704,8 +712,8 @@ msgstr "" #: src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx:169 #: src/components/dialogs/MutedWords.tsx:333 -#: src/components/dialogs/StarterPackDialog.tsx:375 -#: src/components/dialogs/StarterPackDialog.tsx:381 +#: src/components/dialogs/StarterPackDialog.tsx:372 +#: src/components/dialogs/StarterPackDialog.tsx:379 #: src/view/com/modals/UserAddRemoveLists.tsx:235 msgid "Add" msgstr "" @@ -835,8 +843,8 @@ msgstr "" msgid "Add this feed to your feeds" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:343 -#: src/view/com/profile/ProfileMenu.tsx:346 +#: src/view/com/profile/ProfileMenu.tsx:345 +#: src/view/com/profile/ProfileMenu.tsx:348 msgid "Add to lists" msgstr "" @@ -844,9 +852,9 @@ msgstr "" msgid "Add to saved posts" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:176 -#: src/view/com/profile/ProfileMenu.tsx:334 -#: src/view/com/profile/ProfileMenu.tsx:337 +#: src/components/dialogs/StarterPackDialog.tsx:182 +#: src/view/com/profile/ProfileMenu.tsx:335 +#: src/view/com/profile/ProfileMenu.tsx:338 msgid "Add to starter packs" msgstr "" @@ -863,7 +871,7 @@ msgstr "" msgid "Added to list" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:259 +#: src/components/dialogs/StarterPackDialog.tsx:270 msgid "Added to starter pack" msgstr "" @@ -1435,7 +1443,7 @@ msgstr "" msgid "Before creating a post or replying, you must first verify your email." msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:71 +#: src/components/dialogs/StarterPackDialog.tsx:70 #: src/components/StarterPack/ProfileStarterPacks.tsx:263 #: src/components/StarterPack/ProfileStarterPacks.tsx:273 #: src/view/screens/Profile.tsx:351 @@ -1482,8 +1490,8 @@ msgid "Birthday" msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:821 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:190 -#: src/view/com/profile/ProfileMenu.tsx:551 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:195 +#: src/view/com/profile/ProfileMenu.tsx:553 msgid "Block" msgstr "" @@ -1493,13 +1501,13 @@ msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:708 #: src/screens/Messages/components/RequestButtons.tsx:144 #: src/screens/Messages/components/RequestButtons.tsx:146 -#: src/view/com/profile/ProfileMenu.tsx:457 -#: src/view/com/profile/ProfileMenu.tsx:464 +#: src/view/com/profile/ProfileMenu.tsx:459 +#: src/view/com/profile/ProfileMenu.tsx:466 msgid "Block account" msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:816 -#: src/view/com/profile/ProfileMenu.tsx:534 +#: src/view/com/profile/ProfileMenu.tsx:536 msgid "Block Account?" msgstr "" @@ -1551,7 +1559,7 @@ msgid "Blocked Accounts" msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:818 -#: src/view/com/profile/ProfileMenu.tsx:546 +#: src/view/com/profile/ProfileMenu.tsx:548 msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you." msgstr "" @@ -1567,7 +1575,7 @@ msgstr "" msgid "Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you." msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:543 +#: src/view/com/profile/ProfileMenu.tsx:545 msgid "Blocking will not prevent labels from being applied on your account, but it will stop this account from replying in your threads or interacting with you." msgstr "" @@ -1601,7 +1609,7 @@ msgstr "" msgid "Bluesky is an open network where you can choose your own provider. If you're new here, we recommend sticking with the default Bluesky Social option." msgstr "" -#: src/components/ProgressGuide/List.tsx:103 +#: src/components/ProgressGuide/List.tsx:108 msgid "Bluesky is better with friends!" msgstr "" @@ -2104,7 +2112,7 @@ msgstr "" #: src/components/dialogs/nuxs/LiveNowBetaDialog.tsx:190 #: src/components/dialogs/nuxs/LiveNowBetaDialog.tsx:198 #: src/components/dialogs/SearchablePeopleList.tsx:295 -#: src/components/dialogs/StarterPackDialog.tsx:179 +#: src/components/dialogs/StarterPackDialog.tsx:185 #: src/components/dms/AfterReportDialog.tsx:93 #: src/components/dms/AfterReportDialog.tsx:98 #: src/components/dms/AfterReportDialog.tsx:208 @@ -2477,8 +2485,8 @@ msgstr "" msgid "Copy App Password" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:494 -#: src/view/com/profile/ProfileMenu.tsx:497 +#: src/view/com/profile/ProfileMenu.tsx:496 +#: src/view/com/profile/ProfileMenu.tsx:499 msgid "Copy at:// URI" msgstr "" @@ -2493,8 +2501,8 @@ msgid "Copy code" msgstr "" #: src/screens/Settings/components/ChangeHandleDialog.tsx:502 -#: src/view/com/profile/ProfileMenu.tsx:503 -#: src/view/com/profile/ProfileMenu.tsx:506 +#: src/view/com/profile/ProfileMenu.tsx:505 +#: src/view/com/profile/ProfileMenu.tsx:508 msgid "Copy DID" msgstr "" @@ -2594,8 +2602,8 @@ msgid "Could not load feed" msgstr "" #: src/screens/ProfileList/components/ErrorScreen.tsx:26 -#: src/screens/ProfileList/index.tsx:79 -#: src/screens/ProfileList/index.tsx:101 +#: src/screens/ProfileList/index.tsx:80 +#: src/screens/ProfileList/index.tsx:102 msgid "Could not load list" msgstr "" @@ -2629,8 +2637,8 @@ msgstr "" #. Text on button to create a new starter pack #. Text on button to create a new starter pack -#: src/components/dialogs/StarterPackDialog.tsx:112 -#: src/components/dialogs/StarterPackDialog.tsx:201 +#: src/components/dialogs/StarterPackDialog.tsx:111 +#: src/components/dialogs/StarterPackDialog.tsx:208 #: src/components/StarterPack/ProfileStarterPacks.tsx:328 msgid "Create" msgstr "" @@ -2711,8 +2719,8 @@ msgstr "" msgid "Create report for {0}" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:107 -#: src/components/dialogs/StarterPackDialog.tsx:196 +#: src/components/dialogs/StarterPackDialog.tsx:106 +#: src/components/dialogs/StarterPackDialog.tsx:203 msgid "Create starter pack" msgstr "" @@ -3025,6 +3033,11 @@ msgstr "" msgid "Discard post?" msgstr "" +#: src/screens/Profile/components/GermButton.tsx:260 +#: src/screens/Profile/components/GermButton.tsx:267 +msgid "Disconnect Germ DM" +msgstr "" + #: src/screens/Settings/components/PwiOptOut.tsx:87 #: src/screens/Settings/components/PwiOptOut.tsx:91 msgid "Discourage apps from showing my account to logged-out users" @@ -3052,7 +3065,7 @@ msgstr "" msgid "Dismiss error" msgstr "" -#: src/components/ProgressGuide/List.tsx:67 +#: src/components/ProgressGuide/List.tsx:73 msgid "Dismiss getting started guide" msgstr "" @@ -3279,8 +3292,8 @@ msgstr "" msgid "Edit list details" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:357 -#: src/view/com/profile/ProfileMenu.tsx:377 +#: src/view/com/profile/ProfileMenu.tsx:359 +#: src/view/com/profile/ProfileMenu.tsx:379 msgid "Edit live status" msgstr "" @@ -3309,12 +3322,12 @@ msgstr "" #: src/screens/Profile/Header/EditProfileDialog.tsx:268 #: src/screens/Profile/Header/EditProfileDialog.tsx:274 #: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:295 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:324 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:329 msgid "Edit profile" msgstr "" #: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:298 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:326 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:331 msgid "Edit Profile" msgstr "" @@ -3524,7 +3537,7 @@ msgstr "" msgid "Enter your username and password" msgstr "" -#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:146 +#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:148 msgid "Enters full screen" msgstr "" @@ -3710,7 +3723,7 @@ msgstr "" msgid "Failed to add emoji reaction" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:271 +#: src/components/dialogs/StarterPackDialog.tsx:276 msgid "Failed to add to starter pack" msgstr "" @@ -3749,6 +3762,10 @@ msgstr "" msgid "Failed to delete starter pack" msgstr "" +#: src/screens/Profile/components/GermButton.tsx:194 +msgid "Failed to disconnect Germ DM. Error: {0}" +msgstr "" + #: src/screens/Onboarding/StepSuggestedAccounts/index.tsx:133 msgid "Failed to follow all suggested accounts, please try again" msgstr "" @@ -3823,6 +3840,10 @@ msgstr "" msgid "Failed to pin post" msgstr "" +#: src/screens/Profile/components/GermButton.tsx:162 +msgid "Failed to reconnect Germ DM. Error: {0}" +msgstr "" + #: src/screens/Settings/FindContactsSettings.tsx:487 msgid "Failed to remove data due to a network error, please check your internet connection." msgstr "" @@ -3836,7 +3857,7 @@ msgstr "" msgid "Failed to remove emoji reaction" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:290 +#: src/components/dialogs/StarterPackDialog.tsx:289 msgid "Failed to remove from starter pack" msgstr "" @@ -4126,7 +4147,7 @@ msgstr "" #: src/components/ProfileHoverCard/index.web.tsx:497 #: src/components/ProfileHoverCard/index.web.tsx:508 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:152 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:381 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:386 #: src/screens/VideoFeed/index.tsx:874 #: src/view/com/notifications/NotificationFeedItem.tsx:841 #: src/view/com/notifications/NotificationFeedItem.tsx:848 @@ -4134,7 +4155,7 @@ msgid "Follow" msgstr "" #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:139 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:369 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:374 msgid "Follow {0}" msgstr "" @@ -4146,11 +4167,11 @@ msgstr "" msgid "Follow 10 accounts" msgstr "" -#: src/components/ProgressGuide/List.tsx:60 +#: src/components/ProgressGuide/List.tsx:66 msgid "Follow 10 people to get started" msgstr "" -#: src/components/ProgressGuide/List.tsx:102 +#: src/components/ProgressGuide/List.tsx:107 msgid "Follow 7 accounts" msgstr "" @@ -4178,7 +4199,7 @@ msgstr "" #. User is not following this account, click to follow back #: src/components/ProfileCard.tsx:553 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:150 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:379 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:384 #: src/view/com/notifications/NotificationFeedItem.tsx:841 #: src/view/com/notifications/NotificationFeedItem.tsx:848 msgid "Follow back" @@ -4223,7 +4244,7 @@ msgstr "" #: src/components/ProfileHoverCard/index.web.tsx:496 #: src/components/ProfileHoverCard/index.web.tsx:507 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:155 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:377 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:382 #: src/screens/VideoFeed/index.tsx:872 #: src/view/com/notifications/NotificationFeedItem.tsx:819 #: src/view/com/notifications/NotificationFeedItem.tsx:836 @@ -4237,7 +4258,7 @@ msgid "Following" msgstr "" #: src/components/ProfileCard.tsx:509 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:244 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:249 #: src/view/com/notifications/NotificationFeedItem.tsx:772 msgid "Following {0}" msgstr "" @@ -4339,6 +4360,24 @@ msgstr "" msgid "Generate a starter pack" msgstr "" +#: src/screens/Profile/components/GermButton.tsx:85 +#: src/screens/Profile/components/GermButton.tsx:223 +msgid "Germ DM" +msgstr "" + +#: src/screens/Profile/components/GermButton.tsx:181 +msgid "Germ DM disconnected" +msgstr "" + +#: src/screens/Profile/components/GermButton.tsx:232 +#: src/screens/Profile/components/GermButton.tsx:237 +msgid "Germ DM Link" +msgstr "" + +#: src/screens/Profile/components/GermButton.tsx:158 +msgid "Germ DM reconnected" +msgstr "" + #: src/view/shell/Drawer.tsx:374 msgid "Get help" msgstr "" @@ -4421,8 +4460,8 @@ msgstr "" msgid "Glorification of violence" msgstr "" -#: src/components/dialogs/LinkWarning.tsx:111 -#: src/components/dialogs/LinkWarning.tsx:117 +#: src/components/dialogs/LinkWarning.tsx:126 +#: src/components/dialogs/LinkWarning.tsx:132 #: src/components/Layout/Header/index.tsx:128 #: src/components/moderation/ScreenHider.tsx:160 #: src/components/moderation/ScreenHider.tsx:169 @@ -4471,8 +4510,8 @@ msgstr "" msgid "Go Home" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:358 -#: src/view/com/profile/ProfileMenu.tsx:379 +#: src/view/com/profile/ProfileMenu.tsx:360 +#: src/view/com/profile/ProfileMenu.tsx:381 msgid "Go live" msgstr "" @@ -4483,8 +4522,8 @@ msgstr "" msgid "Go Live" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:355 -#: src/view/com/profile/ProfileMenu.tsx:375 +#: src/view/com/profile/ProfileMenu.tsx:357 +#: src/view/com/profile/ProfileMenu.tsx:377 msgid "Go live (disabled)" msgstr "" @@ -4529,6 +4568,11 @@ msgstr "" msgid "Going live is currently disabled for your account" msgstr "" +#: src/screens/Profile/components/GermButton.tsx:251 +#: src/screens/Profile/components/GermButton.tsx:256 +msgid "Got it" +msgstr "" + #: src/lib/moderation/useGlobalLabelStrings.ts:46 #: src/lib/moderation/useGlobalLabelStrings.ts:50 #: src/view/com/composer/labels/LabelsBtn.tsx:200 @@ -5284,6 +5328,10 @@ msgstr "" msgid "Learn more about what is public on Bluesky." msgstr "" +#: src/screens/Profile/components/GermButton.tsx:210 +msgid "Learn more about your Germ DM link" +msgstr "" + #: src/components/ageAssurance/AgeAssuranceAdmonition.tsx:89 msgid "Learn more in your <0>account settings." msgstr "" @@ -5314,8 +5362,8 @@ msgstr "" msgid "Leave them all unselected to see any language." msgstr "" -#: src/components/dialogs/LinkWarning.tsx:67 -#: src/components/dialogs/LinkWarning.tsx:75 +#: src/components/dialogs/LinkWarning.tsx:82 +#: src/components/dialogs/LinkWarning.tsx:90 msgid "Leaving Bluesky" msgstr "" @@ -5356,7 +5404,7 @@ msgstr "" msgid "Like ({0, plural, one {# like} other {# likes}})" msgstr "" -#: src/components/ProgressGuide/List.tsx:96 +#: src/components/ProgressGuide/List.tsx:101 msgid "Like 10 posts" msgstr "" @@ -5473,7 +5521,7 @@ msgstr "" msgid "List has been hidden" msgstr "" -#: src/screens/ProfileList/index.tsx:172 +#: src/screens/ProfileList/index.tsx:176 msgid "List Hidden" msgstr "" @@ -5643,7 +5691,7 @@ msgstr "" msgid "Make one for me" msgstr "" -#: src/components/dialogs/LinkWarning.tsx:85 +#: src/components/dialogs/LinkWarning.tsx:100 msgid "Make sure this is where you intend to go!" msgstr "" @@ -5870,7 +5918,7 @@ msgstr "" msgid "Music" msgstr "" -#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:167 +#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:169 #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VolumeControl.tsx:97 msgctxt "video" msgid "Mute" @@ -5883,8 +5931,8 @@ msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:689 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:695 -#: src/view/com/profile/ProfileMenu.tsx:436 -#: src/view/com/profile/ProfileMenu.tsx:443 +#: src/view/com/profile/ProfileMenu.tsx:438 +#: src/view/com/profile/ProfileMenu.tsx:445 msgid "Mute account" msgstr "" @@ -6014,7 +6062,7 @@ msgid "Nevermind, create a handle for me" msgstr "" #: src/screens/Search/modules/ExploreTrendingTopics.tsx:193 -#: src/view/com/profile/ProfileMenu.tsx:391 +#: src/view/com/profile/ProfileMenu.tsx:393 msgid "New" msgstr "" @@ -6081,8 +6129,8 @@ msgid "New password" msgstr "" #: src/screens/Profile/ProfileFeed/index.tsx:250 -#: src/screens/ProfileList/index.tsx:246 -#: src/screens/ProfileList/index.tsx:284 +#: src/screens/ProfileList/index.tsx:250 +#: src/screens/ProfileList/index.tsx:299 #: src/view/screens/Feeds.tsx:552 #: src/view/screens/Notifications.tsx:166 #: src/view/screens/Profile.tsx:594 @@ -6107,7 +6155,7 @@ msgstr "" msgid "New posts from {firstAuthorName} and {additionalAuthorsCount, plural, one {{formattedAuthorsCount} other} other {{formattedAuthorsCount} others}}" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:193 +#: src/components/dialogs/StarterPackDialog.tsx:200 msgid "New starter pack" msgstr "" @@ -6211,7 +6259,7 @@ msgid "No lists" msgstr "" #: src/components/ProfileCard.tsx:531 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:269 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:274 #: src/view/com/notifications/NotificationFeedItem.tsx:792 msgid "No longer following {0}" msgstr "" @@ -6373,7 +6421,7 @@ msgstr "" msgid "Not ready to hit post? Keep your best ideas in Drafts until the timing is just right." msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:558 +#: src/view/com/profile/ProfileMenu.tsx:560 msgid "Note about sharing" msgstr "" @@ -6586,6 +6634,10 @@ msgstr "" msgid "Open full emoji list" msgstr "" +#: src/screens/Profile/components/GermButton.tsx:74 +msgid "Open Germ DM" +msgstr "" + #: src/components/Post/Embed/ExternalEmbed/index.tsx:79 msgid "Open link to {niceUrl}" msgstr "" @@ -6703,7 +6755,7 @@ msgstr "" msgid "Opens image picker" msgstr "" -#: src/components/dialogs/LinkWarning.tsx:97 +#: src/components/dialogs/LinkWarning.tsx:112 msgid "Opens link {0}" msgstr "" @@ -6846,7 +6898,7 @@ msgstr "" msgid "Password updated!" msgstr "" -#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:151 +#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:153 #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx:385 msgid "Pause" msgstr "" @@ -6859,7 +6911,7 @@ msgstr "" msgid "Pause video" msgstr "" -#: src/screens/ProfileList/index.tsx:166 +#: src/screens/ProfileList/index.tsx:168 #: src/screens/Search/SearchResults.tsx:72 #: src/screens/StarterPack/StarterPackScreen.tsx:192 msgid "People" @@ -6960,7 +7012,7 @@ msgstr "" msgid "Pinned to your feeds" msgstr "" -#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:151 +#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:153 #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx:386 msgid "Play" msgstr "" @@ -6986,7 +7038,7 @@ msgstr "" msgid "Plays or pauses the GIF" msgstr "" -#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:152 +#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:154 msgid "Plays or pauses the video" msgstr "" @@ -7256,7 +7308,7 @@ msgstr "" #: src/components/activity-notifications/SubscribeProfileDialog.tsx:250 #: src/components/activity-notifications/SubscribeProfileDialog.tsx:262 -#: src/screens/ProfileList/index.tsx:166 +#: src/screens/ProfileList/index.tsx:168 #: src/screens/Settings/NotificationSettings/ActivityNotificationSettings.tsx:216 #: src/screens/StarterPack/StarterPackScreen.tsx:194 #: src/view/screens/Profile.tsx:234 @@ -7275,11 +7327,11 @@ msgstr "" msgid "Posts, Replies" msgstr "" -#: src/components/dialogs/LinkWarning.tsx:73 +#: src/components/dialogs/LinkWarning.tsx:88 msgid "Potentially misleading link" msgstr "" -#: src/components/dialogs/LinkWarning.tsx:66 +#: src/components/dialogs/LinkWarning.tsx:81 msgid "Potentially misleading link warning" msgstr "" @@ -7380,6 +7432,10 @@ msgstr "" msgid "Profile" msgstr "" +#: src/lib/strings/errors.ts:40 +msgid "Profile not found" +msgstr "" + #: src/screens/Profile/Header/EditProfileDialog.tsx:189 msgctxt "toast" msgid "Profile updated" @@ -7601,8 +7657,8 @@ msgstr "" #: src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx:171 #: src/components/dialogs/MutedWords.tsx:443 -#: src/components/dialogs/StarterPackDialog.tsx:375 -#: src/components/dialogs/StarterPackDialog.tsx:381 +#: src/components/dialogs/StarterPackDialog.tsx:372 +#: src/components/dialogs/StarterPackDialog.tsx:379 #: src/components/FeedCard.tsx:375 #: src/components/StarterPack/Wizard/WizardListCard.tsx:105 #: src/components/StarterPack/Wizard/WizardListCard.tsx:112 @@ -7726,8 +7782,8 @@ msgstr "" #: src/components/verification/VerificationRemovePrompt.tsx:46 #: src/components/verification/VerificationsDialog.tsx:249 -#: src/view/com/profile/ProfileMenu.tsx:409 -#: src/view/com/profile/ProfileMenu.tsx:412 +#: src/view/com/profile/ProfileMenu.tsx:411 +#: src/view/com/profile/ProfileMenu.tsx:414 msgid "Remove verification" msgstr "" @@ -7757,7 +7813,7 @@ msgstr "" msgid "Removed from saved posts" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:278 +#: src/components/dialogs/StarterPackDialog.tsx:283 msgid "Removed from starter pack" msgstr "" @@ -7862,8 +7918,8 @@ msgstr "" msgid "Report" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:476 -#: src/view/com/profile/ProfileMenu.tsx:479 +#: src/view/com/profile/ProfileMenu.tsx:478 +#: src/view/com/profile/ProfileMenu.tsx:481 msgid "Report account" msgstr "" @@ -8758,7 +8814,7 @@ msgstr "" msgid "Share a fun fact!" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:563 +#: src/view/com/profile/ProfileMenu.tsx:565 msgid "Share anyway" msgstr "" @@ -8767,8 +8823,8 @@ msgstr "" msgid "Share author DID" msgstr "" -#: src/components/dialogs/LinkWarning.tsx:96 -#: src/components/dialogs/LinkWarning.tsx:104 +#: src/components/dialogs/LinkWarning.tsx:111 +#: src/components/dialogs/LinkWarning.tsx:119 #: src/components/StarterPack/ShareDialog.tsx:114 #: src/components/StarterPack/ShareDialog.tsx:123 msgid "Share link" @@ -9437,7 +9493,7 @@ msgstr "" msgid "Task complete - 10 likes!" msgstr "" -#: src/components/ProgressGuide/List.tsx:97 +#: src/components/ProgressGuide/List.tsx:102 msgid "Teach our algorithm what you like" msgstr "" @@ -9522,9 +9578,9 @@ msgstr "" msgid "That's everything!" msgstr "" -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:186 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:394 -#: src/view/com/profile/ProfileMenu.tsx:539 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:191 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:399 +#: src/view/com/profile/ProfileMenu.tsx:541 msgid "The account will be able to interact with you after unblocking." msgstr "" @@ -9707,10 +9763,10 @@ msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:450 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:116 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:127 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:88 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:253 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:279 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:294 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:89 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:258 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:284 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:299 #: src/view/com/profile/ProfileMenu.tsx:152 #: src/view/com/profile/ProfileMenu.tsx:162 #: src/view/com/profile/ProfileMenu.tsx:176 @@ -9789,6 +9845,10 @@ msgstr "" msgid "This author has chosen to make their posts visible only to people who are signed in." msgstr "" +#: src/screens/Profile/components/GermButton.tsx:242 +msgid "This button lets others open the Germ DM app to send you a message. You can manage its visibility from the Germ DM app, or you can disconnect your Bluesky account from Germ DM altogether by clicking the button below." +msgstr "" + #: src/screens/Messages/components/MessageListError.tsx:18 msgid "This chat was disconnected" msgstr "" @@ -9897,7 +9957,7 @@ msgstr "" msgid "This labeler hasn't declared what labels it publishes, and may not be active." msgstr "" -#: src/components/dialogs/LinkWarning.tsx:79 +#: src/components/dialogs/LinkWarning.tsx:94 msgid "This link is taking you to the following website:" msgstr "" @@ -9941,7 +10001,7 @@ msgstr "" msgid "This post's author has disabled quote posts." msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:560 +#: src/view/com/profile/ProfileMenu.tsx:562 msgid "This profile is only visible to logged-in users. It won't be visible to people who aren't signed in." msgstr "" @@ -10070,7 +10130,7 @@ msgstr "" msgid "Toggle to enable or disable adult content" msgstr "" -#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:169 +#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:171 msgid "Toggles the sound" msgstr "" @@ -10189,6 +10249,10 @@ msgstr "" msgid "Unable to delete" msgstr "" +#: src/lib/strings/errors.ts:43 +msgid "Unable to resolve handle" +msgstr "" + #: src/screens/Settings/Settings.tsx:523 msgid "Unapply Pull Request" msgstr "" @@ -10209,30 +10273,30 @@ msgstr "" #: src/components/dms/MessagesListBlockedFooter.tsx:104 #: src/components/dms/MessagesListBlockedFooter.tsx:112 #: src/components/dms/MessagesListBlockedFooter.tsx:119 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:190 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:337 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:397 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:195 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:342 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:402 #: src/screens/ProfileList/components/Header.tsx:165 #: src/screens/ProfileList/components/Header.tsx:172 -#: src/view/com/profile/ProfileMenu.tsx:551 +#: src/view/com/profile/ProfileMenu.tsx:553 msgid "Unblock" msgstr "" -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:341 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:346 msgctxt "action" msgid "Unblock" msgstr "" #: src/components/dms/ConvoMenu.tsx:261 #: src/components/dms/ConvoMenu.tsx:264 -#: src/view/com/profile/ProfileMenu.tsx:456 -#: src/view/com/profile/ProfileMenu.tsx:462 +#: src/view/com/profile/ProfileMenu.tsx:458 +#: src/view/com/profile/ProfileMenu.tsx:464 msgid "Unblock account" msgstr "" -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:184 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:392 -#: src/view/com/profile/ProfileMenu.tsx:533 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:189 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:397 +#: src/view/com/profile/ProfileMenu.tsx:535 msgid "Unblock Account?" msgstr "" @@ -10252,6 +10316,8 @@ msgstr "" #: src/features/liveEvents/components/LiveEventFeedOptionsMenu.tsx:78 #: src/features/liveEvents/components/SidebarLiveEventFeedsBanner.tsx:39 #: src/features/liveEvents/components/SidebarLiveEventFeedsBanner.tsx:45 +#: src/screens/Profile/components/GermButton.tsx:184 +#: src/screens/Profile/components/GermButton.tsx:185 msgid "Undo" msgstr "" @@ -10265,7 +10331,7 @@ msgstr "" msgid "Undo repost ({0, plural, one {# repost} other {# reposts}})" msgstr "" -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:368 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:373 msgid "Unfollow {0}" msgstr "" @@ -10311,7 +10377,7 @@ msgstr "" msgid "Unlike ({0, plural, one {# like} other {# likes}})" msgstr "" -#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:166 +#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:168 #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VolumeControl.tsx:96 msgctxt "video" msgid "Unmute" @@ -10329,8 +10395,8 @@ msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:688 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:694 -#: src/view/com/profile/ProfileMenu.tsx:435 -#: src/view/com/profile/ProfileMenu.tsx:441 +#: src/view/com/profile/ProfileMenu.tsx:437 +#: src/view/com/profile/ProfileMenu.tsx:443 msgid "Unmute account" msgstr "" @@ -10646,8 +10712,8 @@ msgstr "" #: src/components/verification/VerificationCreatePrompt.tsx:84 #: src/components/verification/VerificationCreatePrompt.tsx:86 -#: src/view/com/profile/ProfileMenu.tsx:419 -#: src/view/com/profile/ProfileMenu.tsx:422 +#: src/view/com/profile/ProfileMenu.tsx:421 +#: src/view/com/profile/ProfileMenu.tsx:424 msgid "Verify account" msgstr "" @@ -10728,8 +10794,8 @@ msgstr "" msgid "Version {0}" msgstr "" -#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:84 -#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:145 +#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:86 +#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:147 msgid "Video" msgstr "" @@ -10774,7 +10840,7 @@ msgstr "" msgid "Video uploaded" msgstr "" -#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:84 +#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx:86 msgid "Video: {0}" msgstr "" @@ -10918,8 +10984,8 @@ msgstr "" msgid "Violent or threatening content" msgstr "" -#: src/components/dialogs/LinkWarning.tsx:96 -#: src/components/dialogs/LinkWarning.tsx:106 +#: src/components/dialogs/LinkWarning.tsx:111 +#: src/components/dialogs/LinkWarning.tsx:121 msgid "Visit site" msgstr "" @@ -11090,7 +11156,7 @@ msgstr "" msgid "We're sorry, but based on your device's location, you are currently located in a region that requires age assurance." msgstr "" -#: src/screens/ProfileList/index.tsx:87 +#: src/screens/ProfileList/index.tsx:88 msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "" @@ -11494,7 +11560,7 @@ msgstr "" msgid "You have no lists." msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:101 +#: src/components/dialogs/StarterPackDialog.tsx:100 msgid "You have no starter packs." msgstr "" From c46219bc4d55104e0cb90813f8ae89a25a6d3f09 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Thu, 12 Feb 2026 15:07:26 +0000 Subject: [PATCH 32/59] Fix keyboard flicker when selecting a draft in composer (#9864) --- src/view/com/composer/drafts/DraftsListDialog.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/view/com/composer/drafts/DraftsListDialog.tsx b/src/view/com/composer/drafts/DraftsListDialog.tsx index 0ee587a434..138337c8c0 100644 --- a/src/view/com/composer/drafts/DraftsListDialog.tsx +++ b/src/view/com/composer/drafts/DraftsListDialog.tsx @@ -1,5 +1,5 @@ import {useCallback, useEffect, useMemo} from 'react' -import {View} from 'react-native' +import {Keyboard, View} from 'react-native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -54,6 +54,12 @@ export function DraftsListDialog({ const handleSelectDraft = useCallback( (summary: DraftSummary) => { + // Dismiss keyboard immediately to prevent flicker. Without this, + // the text input regains focus (showing the keyboard) after the + // drafts sheet closes, then loses it again when the post component + // remounts with the draft content, causing a show-hide-show cycle -sfn + Keyboard.dismiss() + control.close(() => { onSelectDraft(summary) }) From 2f156bb9067bd968a089426a85dfa07a39ff07a7 Mon Sep 17 00:00:00 2001 From: Spence Pope Date: Thu, 12 Feb 2026 10:24:38 -0500 Subject: [PATCH 33/59] [APP-1833] Handle errors on saving a draft over char limit (#9850) * show composer error if draft over char limit * adjust cancel discarding if over the limit * use richtext for validation * don't allow saving a draft that can't actually be saved * account for 1k chars * update discard sheet * show composer error if draft over char limit * adjust cancel discarding if over the limit * use richtext for validation * don't allow saving a draft that can't actually be saved * account for 1k chars * update discard sheet * pr comment fixes * pluralization --- src/lib/constants.ts | 2 + src/view/com/composer/Composer.tsx | 140 ++++++++++++++---- src/view/com/composer/drafts/DraftItem.tsx | 1 + src/view/com/composer/drafts/DraftsButton.tsx | 54 ++++--- 4 files changed, 148 insertions(+), 49 deletions(-) diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 96e1d8e2e8..ba19765d47 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -62,6 +62,8 @@ export const MAX_DESCRIPTION = 256 export const MAX_GRAPHEME_LENGTH = 300 +export const MAX_DRAFT_GRAPHEME_LENGTH = 1000 + export const MAX_DM_GRAPHEME_LENGTH = 1000 // Recommended is 100 per: https://www.w3.org/WAI/GL/WCAG20/tests/test3.html diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index 425440609b..53d50bca8a 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -45,6 +45,7 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context' import * as FileSystem from 'expo-file-system' import {type ImagePickerAsset} from 'expo-image-picker' import { + AppBskyDraftCreateDraft, AppBskyUnspeccedDefs, type AppBskyUnspeccedGetPostThreadV2, AtUri, @@ -62,6 +63,7 @@ import {useAppState} from '#/lib/appState' import {retry} from '#/lib/async/retry' import {until} from '#/lib/async/until' import { + MAX_DRAFT_GRAPHEME_LENGTH, MAX_GRAPHEME_LENGTH, SUPPORTED_MIME_TYPES, type SupportedMimeTypes, @@ -275,6 +277,13 @@ export const ComposePost = ({ ) const thread = composerState.thread + + // Clear error when composer content changes, but only if all posts are + // back within the character limit. + const allPostsWithinLimit = thread.posts.every( + post => post.richtext.graphemeLength <= MAX_DRAFT_GRAPHEME_LENGTH, + ) + const activePost = thread.posts[composerState.activePostIndex] const nextPost: PostDraft | undefined = thread.posts[composerState.activePostIndex + 1] @@ -543,7 +552,36 @@ export const ComposePost = ({ revokeAllMediaUrls() }, [closeComposer, queryClient]) + const getDraftSaveError = React.useCallback( + (e: unknown): string => { + if (e instanceof AppBskyDraftCreateDraft.DraftLimitReachedError) { + return _(msg`You've reached the maximum number of drafts`) + } + return _(msg`Failed to save draft`) + }, + [_], + ) + + const validateDraftTextOrError = React.useCallback((): boolean => { + const tooLong = composerState.thread.posts.some( + post => post.richtext.graphemeLength > MAX_DRAFT_GRAPHEME_LENGTH, + ) + if (tooLong) { + setError( + _( + msg`One or more posts are too long to save as a draft. ${plural(MAX_DRAFT_GRAPHEME_LENGTH, {one: 'The maximum number of characters is # character.', other: 'The maximum number of characters is # characters.'})}`, + ), + ) + return false + } + return true + }, [composerState.thread.posts, _]) + const handleSaveDraft = React.useCallback(async () => { + setError('') + if (!validateDraftTextOrError()) { + return + } const isNewDraft = !composerState.draftId try { const result = await saveDraft({ @@ -569,18 +607,44 @@ export const ComposePost = ({ onClose() } catch (e) { logger.error('Failed to save draft', {error: e}) - setError(_(msg`Failed to save draft`)) + setError(getDraftSaveError(e)) } - }, [saveDraft, composerState, composerDispatch, onClose, _, ax]) + }, [ + saveDraft, + composerState, + composerDispatch, + onClose, + ax, + validateDraftTextOrError, + getDraftSaveError, + ]) // Save without closing - for use by DraftsButton - const saveCurrentDraft = React.useCallback(async () => { - const result = await saveDraft({ - composerState, - existingDraftId: composerState.draftId, - }) - composerDispatch({type: 'mark_saved', draftId: result.draftId}) - }, [saveDraft, composerState, composerDispatch]) + const saveCurrentDraft = React.useCallback(async (): Promise<{ + success: boolean + }> => { + setError('') + if (!validateDraftTextOrError()) { + return {success: false} + } + try { + const result = await saveDraft({ + composerState, + existingDraftId: composerState.draftId, + }) + composerDispatch({type: 'mark_saved', draftId: result.draftId}) + return {success: true} + } catch (e) { + setError(getDraftSaveError(e)) + return {success: false} + } + }, [ + saveDraft, + composerState, + composerDispatch, + validateDraftTextOrError, + getDraftSaveError, + ]) // Handle discard action - fires metric and closes composer const handleDiscard = React.useCallback(() => { @@ -1090,6 +1154,7 @@ export const ComposePost = ({ isEmpty={isComposerEmpty} isDirty={composerState.isDirty} isEditingDraft={!!composerState.draftId} + canSaveDraft={allPostsWithinLimit} textLength={thread.posts[0].richtext.text.length}> {missingAltError && } - {composerState.draftId ? ( - Save changes? + {allPostsWithinLimit ? ( + composerState.draftId ? ( + Save changes? + ) : ( + Save draft? + ) ) : ( - Save draft? + Discard post? )} - {composerState.draftId ? ( - - You have unsaved changes to this draft, would you like to - save them? - + {allPostsWithinLimit ? ( + composerState.draftId ? ( + + You have unsaved changes to this draft, would you like to + save them? + + ) : ( + + Would you like to save this as a draft to edit later? + + ) ) : ( - - Would you like to save this as a draft to edit later? - + You can only save drafts up to 1000 characters. )} - + {allPostsWithinLimit && ( + + )} - + )} @@ -1416,6 +1491,7 @@ function ComposerTopBar({ isEmpty, isDirty, isEditingDraft, + canSaveDraft, textLength, topBarAnimatedStyle, children, @@ -1429,11 +1505,12 @@ function ComposerTopBar({ onCancel: () => void onPublish: () => void onSelectDraft: (draft: DraftSummary) => void - onSaveDraft: () => Promise + onSaveDraft: () => Promise<{success: boolean}> onDiscard: () => void isEmpty: boolean isDirty: boolean isEditingDraft: boolean + canSaveDraft: boolean textLength: number topBarAnimatedStyle: StyleProp children?: React.ReactNode @@ -1481,6 +1558,7 @@ function ComposerTopBar({ isEmpty={isEmpty} isDirty={isDirty} isEditingDraft={isEditingDraft} + canSaveDraft={canSaveDraft} textLength={textLength} /> )} diff --git a/src/view/com/composer/drafts/DraftItem.tsx b/src/view/com/composer/drafts/DraftItem.tsx index 964afe1180..16274acbf4 100644 --- a/src/view/com/composer/drafts/DraftItem.tsx +++ b/src/view/com/composer/drafts/DraftItem.tsx @@ -98,6 +98,7 @@ export function DraftItem({ {!!post.text.trim().length && ( void - onSaveDraft: () => Promise + onSaveDraft: () => Promise<{success: boolean}> onDiscard: () => void isEmpty: boolean isDirty: boolean isEditingDraft: boolean + canSaveDraft: boolean textLength: number }) { const {_} = useLingui() @@ -44,8 +46,10 @@ export function DraftsButton({ } const handleSaveAndOpen = async () => { - await onSaveDraft() - draftsDialogControl.open() + const {success} = await onSaveDraft() + if (success) { + draftsDialogControl.open() + } } const handleDiscardAndOpen = () => { @@ -83,37 +87,51 @@ export function DraftsButton({ - {isEditingDraft ? ( - Save changes? + {canSaveDraft ? ( + isEditingDraft ? ( + Save changes? + ) : ( + Save draft? + ) ) : ( - Save draft? + Discard draft? )} - {isEditingDraft ? ( - - You have unsaved changes. Would you like to save them before - viewing your drafts? - + {canSaveDraft ? ( + isEditingDraft ? ( + + You have unsaved changes. Would you like to save them before + viewing your drafts? + + ) : ( + + Would you like to save this as a draft before viewing your + drafts? + + ) ) : ( - Would you like to save this as a draft before viewing your drafts? + You can only save drafts up to 1000 characters. Would you like to + discard this post before viewing your drafts? )} - + {canSaveDraft && ( + + )} - + From 82fea6da7d57b62105211742ac67598a41db4653 Mon Sep 17 00:00:00 2001 From: Spence Pope Date: Thu, 12 Feb 2026 14:34:50 -0500 Subject: [PATCH 34/59] [APP-1846] Remove trending post counts until we can improve accuracy (#9867) --- .../Search/modules/ExploreTrendingTopics.tsx | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/screens/Search/modules/ExploreTrendingTopics.tsx b/src/screens/Search/modules/ExploreTrendingTopics.tsx index 693c4710c3..9eaa493b00 100644 --- a/src/screens/Search/modules/ExploreTrendingTopics.tsx +++ b/src/screens/Search/modules/ExploreTrendingTopics.tsx @@ -1,7 +1,7 @@ import {useMemo} from 'react' import {Pressable, View} from 'react-native' import {type AppBskyUnspeccedDefs, moderateProfile} from '@atproto/api' -import {msg, plural, Trans} from '@lingui/macro' +import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useModerationOpts} from '#/state/preferences/moderation-opts' @@ -9,7 +9,6 @@ import {useTrendingSettings} from '#/state/preferences/trending' import {useGetTrendsQuery} from '#/state/queries/trending/useGetTrendsQuery' import {useTrendingConfig} from '#/state/service-config' import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder' -import {formatCount} from '#/view/com/util/numeric/format' import {atoms as a, useGutters, useTheme, type ViewStyleProp, web} from '#/alf' import {AvatarStack} from '#/components/AvatarStack' import {type Props as SVGIconProps} from '#/components/icons/common' @@ -65,7 +64,7 @@ export function TrendRow({ onPress?: () => void }) { const t = useTheme() - const {_, i18n} = useLingui() + const {_} = useLingui() const gutters = useGutters([0, 'base']) const category = useCategoryDisplayName(trend?.category || 'other') @@ -74,13 +73,6 @@ export function TrendRow({ (1000 * 60 * 60), ) const badgeType = trend.status === 'hot' ? 'hot' : age < 2 ? 'new' : age - const postCount = trend.postCount - ? _( - plural(trend.postCount, { - other: `${formatCount(i18n, trend.postCount)} posts`, - }), - ) - : null const actors = useModerateTrendingActors(trend.actors) @@ -132,8 +124,6 @@ export function TrendRow({ web(a.leading_snug), ]} numberOfLines={1}> - {postCount} - {postCount && category && <> · } {category} From 795428971dda0774c4541416398a48c2beb7e385 Mon Sep 17 00:00:00 2001 From: pfrazee <1270099+pfrazee@users.noreply.github.com> Date: Fri, 13 Feb 2026 03:12:46 +0000 Subject: [PATCH 35/59] Nightly source-language update --- src/locale/locales/en/messages.po | 199 ++++++++++++++++-------------- 1 file changed, 109 insertions(+), 90 deletions(-) diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po index 49beb8aee9..2b527d77d2 100644 --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -89,7 +89,7 @@ msgstr "" msgid "{0, plural, one {#mo} other {#mo}}" msgstr "" -#: src/view/com/composer/drafts/DraftItem.tsx:142 +#: src/view/com/composer/drafts/DraftItem.tsx:143 msgid "{0, plural, one {1 more post} other {# more posts}}" msgstr "" @@ -123,10 +123,6 @@ msgstr "" msgid "{0, plural, one {save} other {saves}}" msgstr "" -#: src/screens/Search/modules/ExploreTrendingTopics.tsx:79 -msgid "{0, plural, other {{1} posts}}" -msgstr "" - #. Number of users (always at least 25) who have joined Bluesky using a specific starter pack #: src/screens/StarterPack/StarterPackScreen.tsx:499 msgid "{0, plural, other {# people have}} joined Bluesky via this starter pack!" @@ -448,12 +444,12 @@ msgid "{profileName} joined Bluesky using a starter pack {timeAgoString} ago" msgstr "" #. The trending topic rank, i.e. "1. March Madness", "2. The Bachelor" -#: src/screens/Search/modules/ExploreTrendingTopics.tsx:108 +#: src/screens/Search/modules/ExploreTrendingTopics.tsx:100 msgid "{rank}." msgstr "" #. trending topic time spent trending. should be as short as possible to fit in a pill -#: src/screens/Search/modules/ExploreTrendingTopics.tsx:200 +#: src/screens/Search/modules/ExploreTrendingTopics.tsx:190 msgid "{type}h ago" msgstr "" @@ -766,11 +762,11 @@ msgstr "" msgid "Add another account" msgstr "" -#: src/view/com/composer/Composer.tsx:1241 +#: src/view/com/composer/Composer.tsx:1316 msgid "Add another post" msgstr "" -#: src/view/com/composer/Composer.tsx:1900 +#: src/view/com/composer/Composer.tsx:1978 msgid "Add another post to thread" msgstr "" @@ -1356,7 +1352,7 @@ msgstr "" msgid "Are you sure you want to remove this from your feeds?" msgstr "" -#: src/view/com/composer/Composer.tsx:1380 +#: src/view/com/composer/Composer.tsx:1455 msgid "Are you sure you'd like to discard this post?" msgstr "" @@ -1417,8 +1413,8 @@ msgstr "" #: src/screens/Settings/components/ChangePasswordDialog.tsx:281 #: src/screens/Signup/BackNextButtons.tsx:41 #: src/screens/StarterPack/Wizard/index.tsx:321 -#: src/view/com/composer/drafts/DraftsListDialog.tsx:80 #: src/view/com/composer/drafts/DraftsListDialog.tsx:86 +#: src/view/com/composer/drafts/DraftsListDialog.tsx:92 msgid "Back" msgstr "" @@ -1708,7 +1704,7 @@ msgstr "" msgid "Browse starter pack {displayName}" msgstr "" -#: src/screens/Search/modules/ExploreTrendingTopics.tsx:90 +#: src/screens/Search/modules/ExploreTrendingTopics.tsx:82 msgid "Browse topic {0}" msgstr "" @@ -1798,8 +1794,8 @@ msgstr "" #: src/screens/Settings/Settings.tsx:305 #: src/screens/Takendown.tsx:101 #: src/screens/Takendown.tsx:104 -#: src/view/com/composer/Composer.tsx:1449 -#: src/view/com/composer/Composer.tsx:1461 +#: src/view/com/composer/Composer.tsx:1526 +#: src/view/com/composer/Composer.tsx:1538 #: src/view/com/composer/photos/EditImageDialog.web.tsx:43 #: src/view/com/composer/photos/EditImageDialog.web.tsx:52 #: src/view/shell/desktop/LeftNav.tsx:213 @@ -2202,7 +2198,7 @@ msgstr "" msgid "Closes password update alert" msgstr "" -#: src/view/com/composer/Composer.tsx:1458 +#: src/view/com/composer/Composer.tsx:1535 msgid "Closes post composer and discards post draft" msgstr "" @@ -2259,7 +2255,7 @@ msgstr "" msgid "Compose new post" msgstr "" -#: src/view/com/composer/Composer.tsx:1344 +#: src/view/com/composer/Composer.tsx:1419 msgid "Compose posts up to {0, plural, other {# characters}} in length" msgstr "" @@ -2267,11 +2263,11 @@ msgstr "" msgid "Compose reply" msgstr "" -#: src/view/com/composer/Composer.tsx:2298 +#: src/view/com/composer/Composer.tsx:2376 msgid "Compressing GIF..." msgstr "" -#: src/view/com/composer/Composer.tsx:2300 +#: src/view/com/composer/Composer.tsx:2378 msgid "Compressing video..." msgstr "" @@ -2886,7 +2882,7 @@ msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:746 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:748 -#: src/view/com/composer/Composer.tsx:1354 +#: src/view/com/composer/Composer.tsx:1429 msgid "Delete post" msgstr "" @@ -3011,11 +3007,11 @@ msgstr "" #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:92 #: src/screens/Profile/Header/EditProfileDialog.tsx:82 -#: src/view/com/composer/Composer.tsx:1149 -#: src/view/com/composer/Composer.tsx:1187 -#: src/view/com/composer/Composer.tsx:1387 -#: src/view/com/composer/drafts/DraftItem.tsx:241 -#: src/view/com/composer/drafts/DraftsButton.tsx:112 +#: src/view/com/composer/Composer.tsx:1214 +#: src/view/com/composer/Composer.tsx:1262 +#: src/view/com/composer/Composer.tsx:1462 +#: src/view/com/composer/drafts/DraftItem.tsx:242 +#: src/view/com/composer/drafts/DraftsButton.tsx:130 msgid "Discard" msgstr "" @@ -3024,12 +3020,14 @@ msgstr "" msgid "Discard changes?" msgstr "" -#: src/view/com/composer/Composer.tsx:1147 -#: src/view/com/composer/drafts/DraftItem.tsx:238 +#: src/view/com/composer/Composer.tsx:1212 +#: src/view/com/composer/drafts/DraftItem.tsx:239 +#: src/view/com/composer/drafts/DraftsButton.tsx:97 msgid "Discard draft?" msgstr "" -#: src/view/com/composer/Composer.tsx:1379 +#: src/view/com/composer/Composer.tsx:1229 +#: src/view/com/composer/Composer.tsx:1454 msgid "Discard post?" msgstr "" @@ -3061,7 +3059,7 @@ msgstr "" msgid "Dismiss banner" msgstr "" -#: src/view/com/composer/Composer.tsx:2219 +#: src/view/com/composer/Composer.tsx:2297 msgid "Dismiss error" msgstr "" @@ -3194,9 +3192,9 @@ msgid "Doxxing" msgstr "" #: src/components/dialogs/nuxs/DraftsAnnouncement.tsx:118 -#: src/view/com/composer/drafts/DraftsButton.tsx:65 -#: src/view/com/composer/drafts/DraftsButton.tsx:74 -#: src/view/com/composer/drafts/DraftsListDialog.tsx:112 +#: src/view/com/composer/drafts/DraftsButton.tsx:69 +#: src/view/com/composer/drafts/DraftsButton.tsx:78 +#: src/view/com/composer/drafts/DraftsListDialog.tsx:118 msgid "Drafts" msgstr "" @@ -3541,11 +3539,11 @@ msgstr "" msgid "Enters full screen" msgstr "" -#: src/screens/Search/modules/ExploreTrendingTopics.tsx:233 +#: src/screens/Search/modules/ExploreTrendingTopics.tsx:223 msgid "Entertainment" msgstr "" -#: src/view/com/composer/Composer.tsx:2318 +#: src/view/com/composer/Composer.tsx:2396 #: src/view/com/util/error/ErrorScreen.tsx:42 msgid "Error" msgstr "" @@ -3869,7 +3867,7 @@ msgstr "" msgid "Failed to resolve location. Please try again." msgstr "" -#: src/view/com/composer/Composer.tsx:572 +#: src/view/com/composer/Composer.tsx:560 msgid "Failed to save draft" msgstr "" @@ -4448,7 +4446,7 @@ msgstr "" msgid "GIF" msgstr "" -#: src/view/com/composer/Composer.tsx:2323 +#: src/view/com/composer/Composer.tsx:2401 msgid "GIF uploaded" msgstr "" @@ -4852,7 +4850,7 @@ msgstr "" msgid "Hosting provider" msgstr "" -#: src/screens/Search/modules/ExploreTrendingTopics.tsx:188 +#: src/screens/Search/modules/ExploreTrendingTopics.tsx:178 msgid "Hot" msgstr "" @@ -5170,7 +5168,7 @@ msgstr "" msgid "It's just you right now! Add more people to your starter pack by searching above." msgstr "" -#: src/view/com/composer/Composer.tsx:2238 +#: src/view/com/composer/Composer.tsx:2316 msgid "Job ID: {0}" msgstr "" @@ -5195,6 +5193,11 @@ msgstr "" msgid "Journalism" msgstr "" +#: src/view/com/composer/Composer.tsx:1266 +#: src/view/com/composer/drafts/DraftsButton.tsx:134 +msgid "Keep editing" +msgstr "" + #: src/components/activity-notifications/SubscribeProfileDialog.tsx:223 msgid "Keep me posted" msgstr "" @@ -5734,11 +5737,11 @@ msgid "Media" msgstr "" #. Example: "Media stored on John's iPhone" -#: src/view/com/composer/drafts/DraftItem.tsx:118 +#: src/view/com/composer/drafts/DraftItem.tsx:119 msgid "Media stored on {0}" msgstr "" -#: src/view/com/composer/drafts/DraftItem.tsx:116 +#: src/view/com/composer/drafts/DraftItem.tsx:117 msgid "Media stored on another device" msgstr "" @@ -5820,7 +5823,7 @@ msgstr "" msgid "Misleading" msgstr "" -#: src/view/com/composer/drafts/DraftItem.tsx:130 +#: src/view/com/composer/drafts/DraftItem.tsx:131 msgid "Missing media" msgstr "" @@ -5896,7 +5899,7 @@ msgid "More languages..." msgstr "" #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:143 -#: src/view/com/composer/drafts/DraftItem.tsx:189 +#: src/view/com/composer/drafts/DraftItem.tsx:190 #: src/view/com/profile/ProfileMenu.tsx:242 #: src/view/com/profile/ProfileMenu.tsx:249 msgid "More options" @@ -6061,7 +6064,7 @@ msgstr "" msgid "Nevermind, create a handle for me" msgstr "" -#: src/screens/Search/modules/ExploreTrendingTopics.tsx:193 +#: src/screens/Search/modules/ExploreTrendingTopics.tsx:183 #: src/view/com/profile/ProfileMenu.tsx:393 msgid "New" msgstr "" @@ -6171,7 +6174,7 @@ msgid "Newest replies first" msgstr "" #: src/lib/interests.ts:67 -#: src/screens/Search/modules/ExploreTrendingTopics.tsx:235 +#: src/screens/Search/modules/ExploreTrendingTopics.tsx:225 msgid "News" msgstr "" @@ -6224,7 +6227,7 @@ msgstr "" msgid "No DNS Panel" msgstr "" -#: src/view/com/composer/drafts/DraftsListDialog.tsx:136 +#: src/view/com/composer/drafts/DraftsListDialog.tsx:142 msgid "No drafts yet" msgstr "" @@ -6540,11 +6543,11 @@ msgstr "" msgid "Onboarding reset" msgstr "" -#: src/view/com/composer/Composer.tsx:707 +#: src/view/com/composer/Composer.tsx:771 msgid "One or more GIFs is missing alt text." msgstr "" -#: src/view/com/composer/Composer.tsx:704 +#: src/view/com/composer/Composer.tsx:768 msgid "One or more images is missing alt text." msgstr "" @@ -6556,7 +6559,11 @@ msgstr "" msgid "One or more of your selected files are too large. Maximum size is 100 MB." msgstr "" -#: src/view/com/composer/Composer.tsx:714 +#: src/view/com/composer/Composer.tsx:572 +msgid "One or more posts are too long to save as a draft. {MAX_DRAFT_GRAPHEME_LENGTH, plural, one {The maximum number of characters is # character.} other {The maximum number of characters is # characters.}}" +msgstr "" + +#: src/view/com/composer/Composer.tsx:778 msgid "One or more videos is missing alt text." msgstr "" @@ -6617,7 +6624,7 @@ msgid "Open drawer menu" msgstr "" #: src/screens/Messages/components/MessageInput.web.tsx:181 -#: src/view/com/composer/Composer.tsx:1885 +#: src/view/com/composer/Composer.tsx:1963 msgid "Open emoji picker" msgstr "" @@ -6729,7 +6736,7 @@ msgstr "" msgid "Opens device gallery to select up to {MAX_IMAGES, plural, other {# images}}, or a single video or GIF." msgstr "" -#: src/view/com/composer/Composer.tsx:1886 +#: src/view/com/composer/Composer.tsx:1964 msgid "Opens emoji picker" msgstr "" @@ -7203,7 +7210,7 @@ msgid "Please write your message below:" msgstr "" #: src/lib/interests.ts:70 -#: src/screens/Search/modules/ExploreTrendingTopics.tsx:229 +#: src/screens/Search/modules/ExploreTrendingTopics.tsx:219 msgid "Politics" msgstr "" @@ -7216,7 +7223,7 @@ msgctxt "description" msgid "Post" msgstr "" -#: src/view/com/composer/Composer.tsx:1532 +#: src/view/com/composer/Composer.tsx:1610 msgctxt "action" msgid "Post" msgstr "" @@ -7231,7 +7238,7 @@ msgstr "" msgid "Post a video" msgstr "" -#: src/view/com/composer/Composer.tsx:1530 +#: src/view/com/composer/Composer.tsx:1608 msgctxt "action" msgid "Post All" msgstr "" @@ -7407,11 +7414,11 @@ msgstr "" msgid "Privacy violation of a minor" msgstr "" -#: src/view/com/composer/Composer.tsx:2312 +#: src/view/com/composer/Composer.tsx:2390 msgid "Processing GIF..." msgstr "" -#: src/view/com/composer/Composer.tsx:2314 +#: src/view/com/composer/Composer.tsx:2392 msgid "Processing video..." msgstr "" @@ -7454,22 +7461,22 @@ msgid "Public, sharable lists of users to mute or block in bulk." msgstr "" #. Accessibility label for button to publish a single post -#: src/view/com/composer/Composer.tsx:1515 +#: src/view/com/composer/Composer.tsx:1593 msgid "Publish post" msgstr "" #. Accessibility label for button to publish multiple posts in a thread -#: src/view/com/composer/Composer.tsx:1508 +#: src/view/com/composer/Composer.tsx:1586 msgid "Publish posts" msgstr "" #. Accessibility label for button to publish multiple replies in a thread -#: src/view/com/composer/Composer.tsx:1493 +#: src/view/com/composer/Composer.tsx:1571 msgid "Publish replies" msgstr "" #. Accessibility label for button to publish a single reply -#: src/view/com/composer/Composer.tsx:1500 +#: src/view/com/composer/Composer.tsx:1578 msgid "Publish reply" msgstr "" @@ -7509,7 +7516,7 @@ msgstr "" #: src/components/PostControls/RepostButton.tsx:198 #: src/components/PostControls/RepostButton.web.tsx:85 #: src/components/PostControls/RepostButton.web.tsx:92 -#: src/view/com/composer/drafts/DraftItem.tsx:136 +#: src/view/com/composer/drafts/DraftItem.tsx:137 msgid "Quote post" msgstr "" @@ -7870,7 +7877,7 @@ msgstr "" msgid "Replies to this post are disabled." msgstr "" -#: src/view/com/composer/Composer.tsx:1528 +#: src/view/com/composer/Composer.tsx:1606 msgctxt "action" msgid "Reply" msgstr "" @@ -8226,23 +8233,23 @@ msgstr "" #: src/components/activity-notifications/SubscribeProfileDialog.tsx:200 #: src/screens/SavedFeeds.tsx:116 #: src/screens/SavedFeeds.tsx:120 -#: src/view/com/composer/Composer.tsx:1180 -#: src/view/com/composer/drafts/DraftsButton.tsx:107 +#: src/view/com/composer/Composer.tsx:1254 +#: src/view/com/composer/drafts/DraftsButton.tsx:124 msgid "Save changes" msgstr "" -#: src/view/com/composer/Composer.tsx:1158 -#: src/view/com/composer/drafts/DraftsButton.tsx:87 +#: src/view/com/composer/Composer.tsx:1224 +#: src/view/com/composer/drafts/DraftsButton.tsx:92 msgid "Save changes?" msgstr "" -#: src/view/com/composer/Composer.tsx:1181 -#: src/view/com/composer/drafts/DraftsButton.tsx:107 +#: src/view/com/composer/Composer.tsx:1255 +#: src/view/com/composer/drafts/DraftsButton.tsx:124 msgid "Save draft" msgstr "" -#: src/view/com/composer/Composer.tsx:1160 -#: src/view/com/composer/drafts/DraftsButton.tsx:89 +#: src/view/com/composer/Composer.tsx:1226 +#: src/view/com/composer/drafts/DraftsButton.tsx:94 msgid "Save draft?" msgstr "" @@ -9118,7 +9125,7 @@ msgstr "" msgid "Snoozes the reminder" msgstr "" -#: src/view/com/composer/drafts/DraftsListDialog.tsx:148 +#: src/view/com/composer/drafts/DraftsListDialog.tsx:154 msgid "So many thoughts, you should post one" msgstr "" @@ -9222,7 +9229,7 @@ msgid "Spam or other inauthentic behavior or deception" msgstr "" #: src/lib/interests.ts:72 -#: src/screens/Search/modules/ExploreTrendingTopics.tsx:227 +#: src/screens/Search/modules/ExploreTrendingTopics.tsx:217 msgid "Sports" msgstr "" @@ -9886,7 +9893,7 @@ msgstr "" msgid "This conversation is with a deleted or a deactivated account. Press for options" msgstr "" -#: src/view/com/composer/drafts/DraftItem.tsx:239 +#: src/view/com/composer/drafts/DraftItem.tsx:240 msgid "This draft will be permanently deleted." msgstr "" @@ -9997,7 +10004,7 @@ msgstr "" msgid "This post will be hidden from feeds and threads. This cannot be undone." msgstr "" -#: src/view/com/composer/Composer.tsx:823 +#: src/view/com/composer/Composer.tsx:887 msgid "This post's author has disabled quote posts." msgstr "" @@ -10482,7 +10489,7 @@ msgstr "" msgid "Unsubscribed from list" msgstr "" -#: src/view/com/composer/Composer.tsx:1282 +#: src/view/com/composer/Composer.tsx:1357 msgid "Unsupported video type: {mimeType}" msgstr "" @@ -10552,7 +10559,7 @@ msgstr "" msgid "Upload from Library" msgstr "" -#: src/view/com/composer/Composer.tsx:2305 +#: src/view/com/composer/Composer.tsx:2383 msgid "Uploading GIF..." msgstr "" @@ -10565,7 +10572,7 @@ msgstr "" msgid "Uploading link thumbnail..." msgstr "" -#: src/view/com/composer/Composer.tsx:2307 +#: src/view/com/composer/Composer.tsx:2385 msgid "Uploading video..." msgstr "" @@ -10816,7 +10823,7 @@ msgid "Video from {0}. Tap to play or pause the video" msgstr "" #: src/lib/interests.ts:62 -#: src/screens/Search/modules/ExploreTrendingTopics.tsx:231 +#: src/screens/Search/modules/ExploreTrendingTopics.tsx:221 msgid "Video Games" msgstr "" @@ -10836,7 +10843,7 @@ msgstr "" msgid "Video settings" msgstr "" -#: src/view/com/composer/Composer.tsx:2325 +#: src/view/com/composer/Composer.tsx:2403 msgid "Video uploaded" msgstr "" @@ -10852,7 +10859,7 @@ msgstr "" msgid "Videos must be less than 3 minutes long." msgstr "" -#: src/view/com/composer/Composer.tsx:915 +#: src/view/com/composer/Composer.tsx:979 msgctxt "Action to view the post the user just created" msgid "View" msgstr "" @@ -10909,7 +10916,7 @@ msgstr "" msgid "View more trending videos" msgstr "" -#: src/view/com/composer/Composer.tsx:910 +#: src/view/com/composer/Composer.tsx:974 msgid "View post" msgstr "" @@ -11169,7 +11176,7 @@ msgstr "" msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "" -#: src/view/com/composer/Composer.tsx:820 +#: src/view/com/composer/Composer.tsx:884 msgid "We're sorry! The post you are replying to has been deleted." msgstr "" @@ -11220,7 +11227,7 @@ msgid "What do you want to call your starter pack?" msgstr "" #: src/view/com/auth/SplashScreen.web.tsx:103 -#: src/view/com/composer/Composer.tsx:1242 +#: src/view/com/composer/Composer.tsx:1317 #: src/view/com/feeds/ComposerPrompt.tsx:192 msgid "What's up?" msgstr "" @@ -11297,11 +11304,11 @@ msgstr "" msgid "Would you like to block this user and/or delete this conversation?" msgstr "" -#: src/view/com/composer/drafts/DraftsButton.tsx:100 +#: src/view/com/composer/drafts/DraftsButton.tsx:109 msgid "Would you like to save this as a draft before viewing your drafts?" msgstr "" -#: src/view/com/composer/Composer.tsx:1170 +#: src/view/com/composer/Composer.tsx:1240 msgid "Would you like to save this as a draft to edit later?" msgstr "" @@ -11315,12 +11322,12 @@ msgstr "" msgid "Write a post" msgstr "" -#: src/view/com/composer/Composer.tsx:1342 +#: src/view/com/composer/Composer.tsx:1417 msgid "Write post" msgstr "" #: src/screens/PostThread/components/ThreadComposePrompt.tsx:90 -#: src/view/com/composer/Composer.tsx:1240 +#: src/view/com/composer/Composer.tsx:1315 msgid "Write your reply" msgstr "" @@ -11463,6 +11470,14 @@ msgstr "" msgid "You can now sign in with your new password." msgstr "" +#: src/view/com/composer/Composer.tsx:1245 +msgid "You can only save drafts up to 1000 characters." +msgstr "" + +#: src/view/com/composer/drafts/DraftsButton.tsx:115 +msgid "You can only save drafts up to 1000 characters. Would you like to discard this post before viewing your drafts?" +msgstr "" + #: src/view/com/composer/SelectMediaButton.tsx:431 msgid "You can only select one GIF at a time." msgstr "" @@ -11584,11 +11599,11 @@ msgstr "" msgid "You have temporarily reached the limit for video uploads. Please try again later." msgstr "" -#: src/view/com/composer/Composer.tsx:1165 +#: src/view/com/composer/Composer.tsx:1235 msgid "You have unsaved changes to this draft, would you like to save them?" msgstr "" -#: src/view/com/composer/drafts/DraftsButton.tsx:95 +#: src/view/com/composer/drafts/DraftsButton.tsx:104 msgid "You have unsaved changes. Would you like to save them before viewing your drafts?" msgstr "" @@ -11789,6 +11804,10 @@ msgstr "" msgid "You've reached the end of your feed! Find some more accounts to follow." msgstr "" +#: src/view/com/composer/Composer.tsx:558 +msgid "You've reached the maximum number of drafts" +msgstr "" + #: src/lib/hooks/useCleanError.ts:73 msgid "You've reached the maximum number of requests allowed. Please try again later." msgstr "" @@ -11947,11 +11966,11 @@ msgstr "" msgid "Your password must be at least 8 characters long." msgstr "" -#: src/view/com/composer/Composer.tsx:906 +#: src/view/com/composer/Composer.tsx:970 msgid "Your post was sent" msgstr "" -#: src/view/com/composer/Composer.tsx:903 +#: src/view/com/composer/Composer.tsx:967 msgid "Your posts were sent" msgstr "" @@ -11972,7 +11991,7 @@ msgstr "" msgid "Your profile, posts, feeds, and lists will no longer be visible to other Bluesky users. You can reactivate your account at any time by logging in." msgstr "" -#: src/view/com/composer/Composer.tsx:905 +#: src/view/com/composer/Composer.tsx:969 msgid "Your reply was sent" msgstr "" From c83dddce57bd66ca4c3193d500808eb43223da9f Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Fri, 13 Feb 2026 13:30:10 +0000 Subject: [PATCH 36/59] Bandcamp embed (#9445) --- __tests__/lib/string.test.ts | 24 ++++++++++++++++++ src/components/dialogs/EmbedConsent.tsx | 23 +++++++---------- src/lib/strings/embed-player.ts | 33 +++++++++++++++++++++++++ src/state/persisted/schema.ts | 1 + 4 files changed, 67 insertions(+), 14 deletions(-) diff --git a/__tests__/lib/string.test.ts b/__tests__/lib/string.test.ts index c59c8b3e34..7a20a49a4e 100644 --- a/__tests__/lib/string.test.ts +++ b/__tests__/lib/string.test.ts @@ -437,6 +437,13 @@ describe('parseEmbedPlayerFromUrl', () => { 'https://www.flickr.com/groups/898944@N23/', 'https://www.flickr.com/groups', + + 'https://maxblansjaar.bandcamp.com/album/false-comforts', + 'https://grmnygrmny.bandcamp.com/track/fluid', + 'https://sufjanstevens.bandcamp.com/', + 'https://sufjanstevens.bandcamp.com', + 'https://bandcamp.com/', + 'https://bandcamp.com', ] const outputs = [ @@ -815,6 +822,23 @@ describe('parseEmbedPlayerFromUrl', () => { undefined, undefined, + + { + type: 'bandcamp_album', + source: 'bandcamp', + playerUri: + 'https://bandcamp.com/EmbeddedPlayer/url=https%3A%2F%2Fmaxblansjaar.bandcamp.com%2Falbum%2Ffalse-comforts/size=large/bgcol=ffffff/linkcol=0687f5/minimal=true/transparent=true/', + }, + { + type: 'bandcamp_track', + source: 'bandcamp', + playerUri: + 'https://bandcamp.com/EmbeddedPlayer/url=https%3A%2F%2Fgrmnygrmny.bandcamp.com%2Ftrack%2Ffluid/size=large/bgcol=ffffff/linkcol=0687f5/minimal=true/transparent=true/', + }, + undefined, + undefined, + undefined, + undefined, ] it('correctly grabs the correct id from uri', () => { diff --git a/src/components/dialogs/EmbedConsent.tsx b/src/components/dialogs/EmbedConsent.tsx index a9d96be533..7ffba6f3a7 100644 --- a/src/components/dialogs/EmbedConsent.tsx +++ b/src/components/dialogs/EmbedConsent.tsx @@ -9,7 +9,8 @@ import { externalEmbedLabels, } from '#/lib/strings/embed-player' import {useSetExternalEmbedPref} from '#/state/preferences' -import {atoms as a, useBreakpoints, useTheme} from '#/alf' +import {atoms as a, web} from '#/alf' +import {Admonition} from '#/components/Admonition' import {Button, ButtonText} from '#/components/Button' import * as Dialog from '#/components/Dialog' import {Text} from '#/components/Typography' @@ -24,9 +25,7 @@ export function EmbedConsentDialog({ onAccept: () => void }) { const {_} = useLingui() - const t = useTheme() const setExternalEmbedPref = useSetExternalEmbedPref() - const {gtMobile} = useBreakpoints() const onShowAllPress = useCallback(() => { for (const key of embedPlayerSources) { @@ -52,50 +51,46 @@ export function EmbedConsentDialog({ + style={web({maxWidth: 400})}> - + External Media - + This content is hosted by {externalEmbedLabels[source]}. Do you want to enable external media? - + External media may allow websites to collect information about you and your device. No information is sent or requested until you press the "play" button. - + - - + {IS_WEB && ( + + + + + )} ) } diff --git a/src/screens/Login/ForgotPasswordForm.tsx b/src/screens/Login/ForgotPasswordForm.tsx index d3b5a4f101..8a7ddc628c 100644 --- a/src/screens/Login/ForgotPasswordForm.tsx +++ b/src/screens/Login/ForgotPasswordForm.tsx @@ -1,21 +1,22 @@ import React, {useState} from 'react' -import {ActivityIndicator, Keyboard, View} from 'react-native' +import {Keyboard, View} from 'react-native' import {type ComAtprotoServerDescribeServer} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import * as EmailValidator from 'email-validator' -import {isNetworkError} from '#/lib/strings/errors' -import {cleanError} from '#/lib/strings/errors' +import {cleanError, isNetworkError} from '#/lib/strings/errors' import {logger} from '#/logger' import {Agent} from '#/state/session/agent' -import {atoms as a, useTheme} from '#/alf' -import {Button, ButtonText} from '#/components/Button' +import {atoms as a, useTheme, web} from '#/alf' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {FormError} from '#/components/forms/FormError' import {HostingProvider} from '#/components/forms/HostingProvider' import * as TextField from '#/components/forms/TextField' import {At_Stroke2_Corner0_Rounded as At} from '#/components/icons/At' +import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' +import {IS_WEB} from '#/env' import {FormContainer} from './FormContainer' type ServiceDescription = ComAtprotoServerDescribeServer.OutputSchema @@ -118,43 +119,50 @@ export const ForgotPasswordForm = ({ - - - - {!serviceDescription || isProcessing ? ( - + + {IS_WEB && ( + <> + + + + )} + {!serviceDescription ? ( + ) : ( )} - {!serviceDescription || isProcessing ? ( - - Processing... - - ) : undefined} }) { const {gtMobile} = useBreakpoints() - const t = useTheme() + const gutter = useGutters([0, 'wide']) + return ( + style={[a.gap_md, a.flex_1, !gtMobile && gutter, style]}> {titleText && !gtMobile && ( - - {titleText} - + {titleText} )} {children} diff --git a/src/screens/Login/LoginForm.tsx b/src/screens/Login/LoginForm.tsx index 779e273740..f7ccb5c997 100644 --- a/src/screens/Login/LoginForm.tsx +++ b/src/screens/Login/LoginForm.tsx @@ -1,11 +1,5 @@ -import React, {useRef, useState} from 'react' -import { - ActivityIndicator, - Keyboard, - LayoutAnimation, - type TextInput, - View, -} from 'react-native' +import {useCallback, useRef, useState} from 'react' +import {Keyboard, type TextInput, View} from 'react-native' import { ComAtprotoServerCreateSession, type ComAtprotoServerDescribeServer, @@ -14,14 +8,13 @@ import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useRequestNotificationsPermission} from '#/lib/notifications/notifications' -import {isNetworkError} from '#/lib/strings/errors' -import {cleanError} from '#/lib/strings/errors' +import {cleanError, isNetworkError} from '#/lib/strings/errors' import {createFullHandle} from '#/lib/strings/handles' import {logger} from '#/logger' import {useSetHasCheckedForStarterPack} from '#/state/preferences/used-starter-packs' import {useSessionApi} from '#/state/session' import {useLoggedOutViewControls} from '#/state/shell/logged-out' -import {atoms as a, ios, useTheme} from '#/alf' +import {atoms as a, ios, useTheme, web} from '#/alf' import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {FormError} from '#/components/forms/FormError' import {HostingProvider} from '#/components/forms/HostingProvider' @@ -31,7 +24,7 @@ import {Lock_Stroke2_Corner0_Rounded as Lock} from '#/components/icons/Lock' import {Ticket_Stroke2_Corner0_Rounded as Ticket} from '#/components/icons/Ticket' import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' -import {IS_IOS} from '#/env' +import {IS_IOS, IS_WEB} from '#/env' import {FormContainer} from './FormContainer' type ServiceDescription = ComAtprotoServerDescribeServer.OutputSchema @@ -62,9 +55,11 @@ export const LoginForm = ({ onAttemptFailed: () => void }) => { const t = useTheme() - const [isProcessing, setIsProcessing] = useState(false) - const [isAuthFactorTokenNeeded, setIsAuthFactorTokenNeeded] = - useState(false) + const [isProcessing, setIsProcessing] = useState(false) + const [errorField, setErrorField] = useState< + 'none' | 'identifier' | 'password' | '2fa' + >('none') + const [isAuthFactorTokenNeeded, setIsAuthFactorTokenNeeded] = useState(false) const identifierValueRef = useRef(initialHandle || '') const passwordValueRef = useRef('') const [authFactorToken, setAuthFactorToken] = useState('') @@ -77,26 +72,28 @@ export const LoginForm = ({ const {setShowLoggedOut} = useLoggedOutViewControls() const setHasCheckedForStarterPack = useSetHasCheckedForStarterPack() - const onPressSelectService = React.useCallback(() => { + const onPressSelectService = useCallback(() => { Keyboard.dismiss() }, []) const onPressNext = async () => { if (isProcessing) return Keyboard.dismiss() - LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut) setError('') + setErrorField('none') const identifier = identifierValueRef.current.toLowerCase().trim() const password = passwordValueRef.current if (!identifier) { setError(_(msg`Please enter your username`)) + setErrorField('identifier') return } if (!password) { setError(_(msg`Please enter your password`)) + setErrorField('password') return } @@ -141,7 +138,6 @@ export const LoginForm = ({ requestNotificationsPermission('Login') } catch (e: any) { const errMsg = e.toString() - LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut) setIsProcessing(false) if ( e instanceof ComAtprotoServerCreateSession.AuthFactorTokenRequiredError @@ -154,6 +150,7 @@ export const LoginForm = ({ error: errMsg, }) setError(_(msg`Invalid 2FA confirmation code.`)) + setErrorField('2fa') } else if ( errMsg.includes('Authentication Required') || errMsg.includes('Invalid identifier or password') @@ -178,7 +175,7 @@ export const LoginForm = ({ } return ( - Sign in}> + Log in}> Hosting provider @@ -194,7 +191,7 @@ export const LoginForm = ({ Account - + { identifierValueRef.current = v + if (errorField) setErrorField('none') }} onSubmitEditing={() => { passwordRef.current?.focus() @@ -221,7 +219,7 @@ export const LoginForm = ({ /> - + { passwordValueRef.current = v + if (errorField) setErrorField('none') }} onSubmitEditing={onPressNext} blurOnSubmit={false} // HACK: https://github.com/facebook/react-native/issues/21911#issuecomment-558343069 Keyboard blur behavior is now handled in onSubmitEditing @@ -277,7 +276,7 @@ export const LoginForm = ({ 2FA Confirmation - + { + setAuthFactorToken(text) + if (errorField) setErrorField('none') + }} onSubmitEditing={onPressNext} editable={!isProcessing} accessibilityHint={_( @@ -308,25 +310,24 @@ export const LoginForm = ({ )} - - - + + {IS_WEB && ( + + )} {!serviceDescription && error ? ( ) : !serviceDescription ? ( - <> - - - Connecting... - - + ) : ( diff --git a/src/screens/Login/PasswordUpdatedForm.tsx b/src/screens/Login/PasswordUpdatedForm.tsx index 7418b6d53e..63c80eec52 100644 --- a/src/screens/Login/PasswordUpdatedForm.tsx +++ b/src/screens/Login/PasswordUpdatedForm.tsx @@ -2,7 +2,7 @@ import {View} from 'react-native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {atoms as a, useBreakpoints} from '#/alf' +import {atoms as a, useBreakpoints, web} from '#/alf' import {Button, ButtonText} from '#/components/Button' import {Text} from '#/components/Typography' import {FormContainer} from './FormContainer' @@ -19,18 +19,17 @@ export const PasswordUpdatedForm = ({ - + Password updated! You can now sign in with your new password. - + - - {isProcessing ? ( - - ) : ( - + + {IS_WEB && ( + <> + + + )} - {isProcessing ? ( - - Updating... - - ) : undefined} + + ) diff --git a/src/screens/Login/components/AuthLayout/Header/index.tsx b/src/screens/Login/components/AuthLayout/Header/index.tsx new file mode 100644 index 0000000000..ac7716508a --- /dev/null +++ b/src/screens/Login/components/AuthLayout/Header/index.tsx @@ -0,0 +1,92 @@ +import {useContext} from 'react' +import {type GestureResponderEvent, View} from 'react-native' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {HITSLOP_30} from '#/lib/constants' +import {Logomark} from '#/view/icons/Logomark' +import {atoms as a, platform, useGutters, useTheme} from '#/alf' +import {Button, ButtonIcon, type ButtonProps} from '#/components/Button' +import {ArrowLeft_Stroke2_Corner0_Rounded as ArrowLeft} from '#/components/icons/Arrow' +import { + BUTTON_VISUAL_ALIGNMENT_OFFSET, + Header, + HEADER_SLOT_SIZE, +} from '#/components/Layout' +import {IS_WEB} from '#/env' +import {AuthLayoutNavigationContext} from '../context' + +/** + * This is a simplified version of `Layout.Header` for the auth screens. + */ + +export const Slot = Header.Slot + +export function Outer({children}: {children: React.ReactNode}) { + const t = useTheme() + const gutters = useGutters([0, 'wide']) + + return ( + + {children} + + ) +} + +export function Content({children}: {children?: React.ReactNode}) { + return ( + + {IS_WEB ? children : } + + ) +} + +export function Logo() { + const t = useTheme() + + return +} + +export function BackButton({onPress, style, ...props}: Partial) { + const {_} = useLingui() + const navigation = useContext(AuthLayoutNavigationContext) + + const onPressBack = (evt: GestureResponderEvent) => { + onPress?.(evt) + if (evt.defaultPrevented) return + navigation?.goBack() + } + + return ( + + + + ) +} diff --git a/src/screens/Login/components/AuthLayout/Header/index.web.tsx b/src/screens/Login/components/AuthLayout/Header/index.web.tsx new file mode 100644 index 0000000000..08e9eb0eb3 --- /dev/null +++ b/src/screens/Login/components/AuthLayout/Header/index.web.tsx @@ -0,0 +1,23 @@ +import {type ButtonProps} from '#/components/Button' +import {Header} from '#/components/Layout' + +// TEMP: Web needs a much more comprehensive layout change to support the new design +// so to do this incrementally, we'll do native only and migrate to web later + +export const Slot = Header.Slot + +export function Outer({}: {children: React.ReactNode}) { + return null +} + +export function Content({}: {children?: React.ReactNode}) { + return null +} + +export function Logo() { + return null +} + +export function BackButton({}: Partial) { + return null +} diff --git a/src/screens/Login/components/AuthLayout/context.ts b/src/screens/Login/components/AuthLayout/context.ts new file mode 100644 index 0000000000..871113fcdf --- /dev/null +++ b/src/screens/Login/components/AuthLayout/context.ts @@ -0,0 +1,5 @@ +import {createContext} from 'react' + +export const AuthLayoutNavigationContext = createContext<{ + goBack: () => void +} | null>(null) diff --git a/src/screens/Login/components/AuthLayout/index.tsx b/src/screens/Login/components/AuthLayout/index.tsx new file mode 100644 index 0000000000..2b3629bbd8 --- /dev/null +++ b/src/screens/Login/components/AuthLayout/index.tsx @@ -0,0 +1 @@ +export * as Header from './Header' diff --git a/src/screens/Login/index.tsx b/src/screens/Login/index.tsx index 17dfeb4262..2004317734 100644 --- a/src/screens/Login/index.tsx +++ b/src/screens/Login/index.tsx @@ -18,6 +18,8 @@ import {atoms as a, native} from '#/alf' import {ScreenTransition} from '#/components/ScreenTransition' import {useAnalytics} from '#/analytics' import {ChooseAccountForm} from './ChooseAccountForm' +import * as AuthLayout from './components/AuthLayout' +import {AuthLayoutNavigationContext} from './components/AuthLayout/context' enum Forms { Login, @@ -131,11 +133,14 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => { let content = null let title = '' let description = '' + let goBack = null switch (currentForm) { case Forms.Login: title = _(msg`Sign in`) description = _(msg`Enter your username and password`) + goBack = () => + accounts.length ? gotoForm(Forms.ChooseAccount) : handlePressBack() content = ( void}) => { onAttemptFailed={onAttemptFailed} onAttemptSuccess={onAttemptSuccess} setServiceUrl={setServiceUrl} - onPressBack={() => - accounts.length ? gotoForm(Forms.ChooseAccount) : handlePressBack() - } + onPressBack={goBack} onPressForgotPassword={onPressForgotPassword} onPressRetryConnect={refetchService} /> @@ -157,16 +160,18 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => { case Forms.ChooseAccount: title = _(msg`Sign in`) description = _(msg`Select from an existing account`) + goBack = handlePressBack content = ( ) break case Forms.ForgotPassword: title = _(msg`Forgot Password`) description = _(msg`Let's get your password reset!`) + goBack = () => gotoForm(Forms.Login) content = ( void}) => { serviceDescription={serviceDescription} setError={setError} setServiceUrl={setServiceUrl} - onPressBack={() => gotoForm(Forms.Login)} + onPressBack={goBack} onEmailSent={() => gotoForm(Forms.SetNewPassword)} /> ) @@ -182,12 +187,13 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => { case Forms.SetNewPassword: title = _(msg`Forgot Password`) description = _(msg`Let's get your password reset!`) + goBack = () => gotoForm(Forms.ForgotPassword) content = ( gotoForm(Forms.ForgotPassword)} + onPressBack={goBack} onPasswordSet={() => gotoForm(Forms.PasswordUpdated)} /> ) @@ -201,23 +207,35 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => { break } + const navigation = goBack ? {goBack} : null + return ( - - - - - - {content} - - - - - + + + + + + + + + + + + {content} + + + + + + ) } diff --git a/src/view/com/auth/LoggedOut.tsx b/src/view/com/auth/LoggedOut.tsx index 088ae6679d..b3cf382db2 100644 --- a/src/view/com/auth/LoggedOut.tsx +++ b/src/view/com/auth/LoggedOut.tsx @@ -1,10 +1,14 @@ -import React from 'react' +import {useCallback, useEffect, useState} from 'react' import {View} from 'react-native' import {useSafeAreaInsets} from 'react-native-safe-area-context' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {useQueryClient} from '@tanstack/react-query' import {PressableScale} from '#/lib/custom-animations/PressableScale' +import {STALE} from '#/state/queries' +import {profilesQueryKey} from '#/state/queries/profile' +import {useAgent, useSession} from '#/state/session' import { useLoggedOutView, useLoggedOutViewControls, @@ -35,7 +39,7 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) { const insets = useSafeAreaInsets() const setMinimalShellMode = useSetMinimalShellMode() const {requestedAccountSwitchTo} = useLoggedOutView() - const [screenState, setScreenState] = React.useState(() => { + const [screenState, setScreenState] = useState(() => { if (requestedAccountSwitchTo === 'new') { return ScreenState.S_CreateAccount } else if (requestedAccountSwitchTo === 'starterpack') { @@ -48,11 +52,26 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) { }) const {clearRequestedAccount} = useLoggedOutViewControls() - React.useEffect(() => { + const queryClient = useQueryClient() + const {accounts} = useSession() + const agent = useAgent() + useEffect(() => { + const actors = accounts.map(acc => acc.did) + void queryClient.prefetchQuery({ + queryKey: profilesQueryKey(actors), + staleTime: STALE.MINUTES.FIVE, + queryFn: async () => { + const res = await agent.getProfiles({actors}) + return res.data + }, + }) + }, [accounts, agent, queryClient]) + + useEffect(() => { setMinimalShellMode(true) }, [setMinimalShellMode]) - const onPressDismiss = React.useCallback(() => { + const onPressDismiss = useCallback(() => { if (onDismiss) { onDismiss() } diff --git a/src/view/com/util/layouts/LoggedOutLayout.tsx b/src/view/com/util/layouts/LoggedOutLayout.tsx index 334bf07561..b6a0e8682d 100644 --- a/src/view/com/util/layouts/LoggedOutLayout.tsx +++ b/src/view/com/util/layouts/LoggedOutLayout.tsx @@ -42,11 +42,11 @@ export const LoggedOutLayout = ({ contentContainerStyle={[ {paddingBottom: isKeyboardVisible ? 300 : 0}, ]}> - {children} + {children} ) } else { - return {children} + return {children} } } return ( From b4cb4c4d1363fa5541b16c5958efdb995893896a Mon Sep 17 00:00:00 2001 From: Spence Pope Date: Fri, 13 Feb 2026 16:24:06 -0500 Subject: [PATCH 39/59] Revert "Add --what-to-test to iOS submissions (#9856)" (#9873) --- .github/workflows/build-submit-ios.yml | 7 +------ .github/workflows/bundle-deploy-eas-update.yml | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-submit-ios.yml b/.github/workflows/build-submit-ios.yml index a2576e329a..2ebbd66ec9 100644 --- a/.github/workflows/build-submit-ios.yml +++ b/.github/workflows/build-submit-ios.yml @@ -118,12 +118,7 @@ jobs: fi - name: 🚀 Deploy - env: - PROFILE: ${{ inputs.profile || 'testflight' }} - run: > - eas submit -p ios --non-interactive - --path ios-build/ios/build/Bluesky.ipa - --what-to-test "$([[ "$PROFILE" == "production" ]] && echo "Production build" || echo "TestFlight build")" + run: eas submit -p ios --non-interactive --path ios-build/ios/build/Bluesky.ipa - name: 🪲 Upload dSYM to Sentry run: > diff --git a/.github/workflows/bundle-deploy-eas-update.yml b/.github/workflows/bundle-deploy-eas-update.yml index 46c848b879..ee59cad977 100644 --- a/.github/workflows/bundle-deploy-eas-update.yml +++ b/.github/workflows/bundle-deploy-eas-update.yml @@ -242,7 +242,7 @@ jobs: --local --output build.ipa --non-interactive - name: 🚀 Deploy - run: eas submit -p ios --non-interactive --path build.ipa --what-to-test "TestFlight build" + run: eas submit -p ios --non-interactive --path build.ipa - name: ⬇️ Restore Cache id: get-base-commit From bc001168f34aacde9bf3c32470f8371611266599 Mon Sep 17 00:00:00 2001 From: pfrazee <1270099+pfrazee@users.noreply.github.com> Date: Sat, 14 Feb 2026 03:05:51 +0000 Subject: [PATCH 40/59] Nightly source-language update --- src/locale/locales/en/messages.po | 194 +++++++++++++++--------------- 1 file changed, 96 insertions(+), 98 deletions(-) diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po index 2b527d77d2..29fd965afd 100644 --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -523,7 +523,7 @@ msgstr "" msgid "24 hours" msgstr "" -#: src/screens/Login/LoginForm.tsx:278 +#: src/screens/Login/LoginForm.tsx:277 msgid "2FA Confirmation" msgstr "" @@ -620,7 +620,7 @@ msgid "Accessibility Settings" msgstr "" #: src/Navigation.tsx:402 -#: src/screens/Login/LoginForm.tsx:194 +#: src/screens/Login/LoginForm.tsx:191 #: src/screens/Settings/AccountSettings.tsx:51 #: src/screens/Settings/Settings.tsx:178 #: src/screens/Settings/Settings.tsx:181 @@ -1011,7 +1011,7 @@ msgstr "" msgid "Allows access to direct messages" msgstr "" -#: src/screens/Login/ForgotPasswordForm.tsx:171 +#: src/screens/Login/ForgotPasswordForm.tsx:179 #: src/screens/Settings/components/ChangePasswordDialog.tsx:236 #: src/screens/Settings/components/ChangePasswordDialog.tsx:242 msgid "Already have a code?" @@ -1021,7 +1021,7 @@ msgstr "" msgid "Already have an account?" msgstr "" -#: src/screens/Login/ChooseAccountForm.tsx:44 +#: src/screens/Login/ChooseAccountForm.tsx:45 msgid "Already signed in as @{0}" msgstr "" @@ -1398,14 +1398,14 @@ msgstr "" #: src/components/moderation/LabelsOnMeDialog.tsx:333 #: src/components/moderation/LabelsOnMeDialog.tsx:334 -#: src/screens/Login/ChooseAccountForm.tsx:92 #: src/screens/Login/ChooseAccountForm.tsx:97 -#: src/screens/Login/ForgotPasswordForm.tsx:123 -#: src/screens/Login/ForgotPasswordForm.tsx:129 -#: src/screens/Login/LoginForm.tsx:313 -#: src/screens/Login/LoginForm.tsx:319 -#: src/screens/Login/SetNewPasswordForm.tsx:168 -#: src/screens/Login/SetNewPasswordForm.tsx:174 +#: src/screens/Login/ChooseAccountForm.tsx:101 +#: src/screens/Login/ForgotPasswordForm.tsx:126 +#: src/screens/Login/ForgotPasswordForm.tsx:131 +#: src/screens/Login/LoginForm.tsx:316 +#: src/screens/Login/LoginForm.tsx:321 +#: src/screens/Login/SetNewPasswordForm.tsx:171 +#: src/screens/Login/SetNewPasswordForm.tsx:177 #: src/screens/Messages/components/ChatDisabled.tsx:145 #: src/screens/Messages/components/ChatDisabled.tsx:146 #: src/screens/Profile/Header/Shell.tsx:179 @@ -1971,7 +1971,7 @@ msgstr "" msgid "Check my status" msgstr "" -#: src/screens/Login/LoginForm.tsx:304 +#: src/screens/Login/LoginForm.tsx:306 msgid "Check your email for a sign in code and enter it here." msgstr "" @@ -2306,7 +2306,7 @@ msgid "Confirm your location" msgstr "" #: src/components/dialogs/EmailDialog/components/TokenField.tsx:36 -#: src/screens/Login/LoginForm.tsx:284 +#: src/screens/Login/LoginForm.tsx:283 #: src/screens/Settings/components/ChangePasswordDialog.tsx:186 #: src/screens/Settings/components/ChangePasswordDialog.tsx:190 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:144 @@ -2316,8 +2316,9 @@ msgstr "" msgid "Confirmation code" msgstr "" -#: src/screens/Login/LoginForm.tsx:340 -msgid "Connecting..." +#: src/screens/Login/ForgotPasswordForm.tsx:139 +#: src/screens/Login/LoginForm.tsx:339 +msgid "Connecting to service..." msgstr "" #: src/ageAssurance/components/RedirectOverlay.tsx:296 @@ -3367,7 +3368,7 @@ msgstr "" msgid "Email 2FA enabled" msgstr "" -#: src/screens/Login/ForgotPasswordForm.tsx:93 +#: src/screens/Login/ForgotPasswordForm.tsx:94 msgid "Email address" msgstr "" @@ -3412,7 +3413,7 @@ msgstr "" msgid "Enable" msgstr "" -#: src/components/dialogs/EmbedConsent.tsx:100 +#: src/components/dialogs/EmbedConsent.tsx:95 msgid "Enable {0} only" msgstr "" @@ -3424,8 +3425,8 @@ msgstr "" msgid "Enable email 2FA" msgstr "" -#: src/components/dialogs/EmbedConsent.tsx:81 -#: src/components/dialogs/EmbedConsent.tsx:88 +#: src/components/dialogs/EmbedConsent.tsx:79 +#: src/components/dialogs/EmbedConsent.tsx:85 msgid "Enable external media" msgstr "" @@ -3451,7 +3452,7 @@ msgstr "" msgid "Enable subtitles" msgstr "" -#: src/components/dialogs/EmbedConsent.tsx:93 +#: src/components/dialogs/EmbedConsent.tsx:89 msgid "Enable this source only" msgstr "" @@ -3483,7 +3484,7 @@ msgstr "" msgid "Enter 6-digit code that was sent to your phone number" msgstr "" -#: src/screens/Login/SetNewPasswordForm.tsx:147 +#: src/screens/Login/SetNewPasswordForm.tsx:148 msgid "Enter a password" msgstr "" @@ -3510,11 +3511,11 @@ msgstr "" msgid "Enter the domain you want to use" msgstr "" -#: src/screens/Login/ForgotPasswordForm.tsx:113 +#: src/screens/Login/ForgotPasswordForm.tsx:114 msgid "Enter the email you used to create your account. We'll send you a \"reset code\" so you can set a new password." msgstr "" -#: src/screens/Login/LoginForm.tsx:219 +#: src/screens/Login/LoginForm.tsx:217 msgid "Enter the username or email address you used when you created your account" msgstr "" @@ -3522,16 +3523,16 @@ msgstr "" msgid "Enter your birthdate" msgstr "" -#: src/screens/Login/ForgotPasswordForm.tsx:99 +#: src/screens/Login/ForgotPasswordForm.tsx:100 #: src/screens/Signup/StepInfo/index.tsx:243 msgid "Enter your email address" msgstr "" -#: src/screens/Login/LoginForm.tsx:243 +#: src/screens/Login/LoginForm.tsx:242 msgid "Enter your password" msgstr "" -#: src/screens/Login/index.tsx:138 +#: src/screens/Login/index.tsx:141 msgid "Enter your username and password" msgstr "" @@ -3692,12 +3693,12 @@ msgstr "" msgid "External media" msgstr "" -#: src/components/dialogs/EmbedConsent.tsx:54 -#: src/components/dialogs/EmbedConsent.tsx:58 +#: src/components/dialogs/EmbedConsent.tsx:53 +#: src/components/dialogs/EmbedConsent.tsx:57 msgid "External Media" msgstr "" -#: src/components/dialogs/EmbedConsent.tsx:70 +#: src/components/dialogs/EmbedConsent.tsx:69 #: src/screens/Settings/ExternalMediaPreferences.tsx:43 msgid "External media may allow websites to collect information about you and your device. No information is sent or requested until you press the \"play\" button." msgstr "" @@ -4324,16 +4325,16 @@ msgstr "" msgid "Forget the noise" msgstr "" -#: src/screens/Login/index.tsx:168 -#: src/screens/Login/index.tsx:183 +#: src/screens/Login/index.tsx:172 +#: src/screens/Login/index.tsx:188 msgid "Forgot Password" msgstr "" -#: src/screens/Login/LoginForm.tsx:258 +#: src/screens/Login/LoginForm.tsx:257 msgid "Forgot password?" msgstr "" -#: src/screens/Login/LoginForm.tsx:269 +#: src/screens/Login/LoginForm.tsx:268 msgid "Forgot?" msgstr "" @@ -4463,6 +4464,7 @@ msgstr "" #: src/components/Layout/Header/index.tsx:128 #: src/components/moderation/ScreenHider.tsx:160 #: src/components/moderation/ScreenHider.tsx:169 +#: src/screens/Login/components/AuthLayout/Header/index.tsx:75 #: src/screens/Messages/Inbox.tsx:251 #: src/screens/Profile/ProfileFeed/index.tsx:95 #: src/screens/ProfileList/components/ErrorScreen.tsx:34 @@ -4470,7 +4472,7 @@ msgstr "" #: src/screens/VideoFeed/components/Header.tsx:163 #: src/screens/VideoFeed/index.tsx:1179 #: src/screens/VideoFeed/index.tsx:1183 -#: src/view/com/auth/LoggedOut.tsx:73 +#: src/view/com/auth/LoggedOut.tsx:92 #: src/view/com/profile/ProfileFollowers.tsx:178 #: src/view/com/profile/ProfileFollowers.tsx:179 #: src/view/screens/NotFound.tsx:57 @@ -4548,7 +4550,7 @@ msgstr "" msgid "Go to feed" msgstr "" -#: src/screens/Login/ForgotPasswordForm.tsx:165 +#: src/screens/Login/ForgotPasswordForm.tsx:173 msgid "Go to next" msgstr "" @@ -4845,8 +4847,8 @@ msgstr "" msgid "Host:" msgstr "" -#: src/screens/Login/ForgotPasswordForm.tsx:83 -#: src/screens/Login/LoginForm.tsx:184 +#: src/screens/Login/ForgotPasswordForm.tsx:84 +#: src/screens/Login/LoginForm.tsx:181 msgid "Hosting provider" msgstr "" @@ -5035,11 +5037,11 @@ msgstr "" msgid "Inbox zero!" msgstr "" -#: src/screens/Login/LoginForm.tsx:164 +#: src/screens/Login/LoginForm.tsx:161 msgid "Incorrect username or password" msgstr "" -#: src/screens/Login/SetNewPasswordForm.tsx:133 +#: src/screens/Login/SetNewPasswordForm.tsx:134 msgid "Input code sent to your email for password reset" msgstr "" @@ -5047,7 +5049,7 @@ msgstr "" msgid "Input confirmation code for account deletion" msgstr "" -#: src/screens/Login/SetNewPasswordForm.tsx:159 +#: src/screens/Login/SetNewPasswordForm.tsx:160 msgid "Input new password" msgstr "" @@ -5055,7 +5057,7 @@ msgstr "" msgid "Input password for account deletion" msgstr "" -#: src/screens/Login/LoginForm.tsx:296 +#: src/screens/Login/LoginForm.tsx:298 msgid "Input the code which has been emailed to you" msgstr "" @@ -5083,7 +5085,7 @@ msgstr "" msgid "Introducing saved posts AKA bookmarks" msgstr "" -#: src/screens/Login/LoginForm.tsx:156 +#: src/screens/Login/LoginForm.tsx:152 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:70 msgid "Invalid 2FA confirmation code." msgstr "" @@ -5378,8 +5380,8 @@ msgstr "" msgid "Let me choose" msgstr "" -#: src/screens/Login/index.tsx:169 -#: src/screens/Login/index.tsx:184 +#: src/screens/Login/index.tsx:173 +#: src/screens/Login/index.tsx:189 msgid "Let's get your password reset!" msgstr "" @@ -5649,6 +5651,12 @@ msgstr "" msgid "Log" msgstr "" +#: src/screens/Login/LoginForm.tsx:178 +#: src/screens/Login/LoginForm.tsx:349 +#: src/screens/Login/LoginForm.tsx:355 +msgid "Log in" +msgstr "" + #: src/components/AccountList.tsx:191 msgid "Logged out" msgstr "" @@ -5670,7 +5678,7 @@ msgstr "" msgid "Long press to open tag menu for {0}" msgstr "" -#: src/screens/Login/SetNewPasswordForm.tsx:122 +#: src/screens/Login/SetNewPasswordForm.tsx:123 msgid "Looks like XXXXX-XXXXX" msgstr "" @@ -6046,8 +6054,9 @@ msgstr "" msgid "Navigate to starter pack" msgstr "" -#: src/screens/Login/ForgotPasswordForm.tsx:166 -#: src/screens/Login/LoginForm.tsx:347 +#: src/screens/Login/ForgotPasswordForm.tsx:149 +#: src/screens/Login/ForgotPasswordForm.tsx:174 +#: src/screens/Login/LoginForm.tsx:350 msgid "Navigates to the next screen" msgstr "" @@ -6125,7 +6134,7 @@ msgstr "" msgid "New messages" msgstr "" -#: src/screens/Login/SetNewPasswordForm.tsx:141 +#: src/screens/Login/SetNewPasswordForm.tsx:142 #: src/screens/Settings/components/ChangePasswordDialog.tsx:203 #: src/screens/Settings/components/ChangePasswordDialog.tsx:207 msgid "New password" @@ -6180,12 +6189,10 @@ msgstr "" #: src/components/contacts/screens/ViewMatches.tsx:394 #: src/components/contacts/screens/ViewMatches.tsx:409 -#: src/screens/Login/ForgotPasswordForm.tsx:137 -#: src/screens/Login/ForgotPasswordForm.tsx:143 -#: src/screens/Login/LoginForm.tsx:346 -#: src/screens/Login/LoginForm.tsx:353 -#: src/screens/Login/SetNewPasswordForm.tsx:182 -#: src/screens/Login/SetNewPasswordForm.tsx:188 +#: src/screens/Login/ForgotPasswordForm.tsx:148 +#: src/screens/Login/ForgotPasswordForm.tsx:155 +#: src/screens/Login/SetNewPasswordForm.tsx:185 +#: src/screens/Login/SetNewPasswordForm.tsx:191 #: src/screens/Onboarding/StepFinished/index.tsx:329 #: src/screens/Onboarding/StepFinished/index.tsx:338 #: src/screens/Settings/components/AddAppPasswordDialog.tsx:157 @@ -6364,8 +6371,8 @@ msgstr "" msgid "No Starter Packs yet" msgstr "" -#: src/components/dialogs/EmbedConsent.tsx:104 -#: src/components/dialogs/EmbedConsent.tsx:111 +#: src/components/dialogs/EmbedConsent.tsx:99 +#: src/components/dialogs/EmbedConsent.tsx:106 msgid "No thanks" msgstr "" @@ -6523,7 +6530,7 @@ msgstr "" msgid "OK" msgstr "" -#: src/screens/Login/PasswordUpdatedForm.tsx:37 +#: src/screens/Login/PasswordUpdatedForm.tsx:36 #: src/screens/PostThread/components/ThreadItemAnchor.tsx:705 msgid "Okay" msgstr "" @@ -6770,7 +6777,7 @@ msgstr "" msgid "Opens live status dialog" msgstr "" -#: src/screens/Login/LoginForm.tsx:259 +#: src/screens/Login/LoginForm.tsx:258 msgid "Opens password reset form" msgstr "" @@ -6880,7 +6887,7 @@ msgstr "" msgid "Page Not Found" msgstr "" -#: src/screens/Login/LoginForm.tsx:229 +#: src/screens/Login/LoginForm.tsx:227 #: src/screens/Settings/AccountSettings.tsx:121 #: src/screens/Settings/AccountSettings.tsx:125 #: src/screens/Signup/StepInfo/index.tsx:258 @@ -6897,7 +6904,7 @@ msgstr "" msgid "Password must be at least 8 characters long." msgstr "" -#: src/screens/Login/index.tsx:196 +#: src/screens/Login/index.tsx:202 msgid "Password updated" msgstr "" @@ -7087,7 +7094,7 @@ msgstr "" msgid "Please double-check that you have entered your email address correctly." msgstr "" -#: src/screens/Login/SetNewPasswordForm.tsx:58 +#: src/screens/Login/SetNewPasswordForm.tsx:59 msgid "Please enter a password." msgstr "" @@ -7143,7 +7150,7 @@ msgstr "" msgid "Please enter your new email address." msgstr "" -#: src/screens/Login/LoginForm.tsx:99 +#: src/screens/Login/LoginForm.tsx:95 msgid "Please enter your password" msgstr "" @@ -7151,7 +7158,7 @@ msgstr "" msgid "Please enter your password as well:" msgstr "" -#: src/screens/Login/LoginForm.tsx:94 +#: src/screens/Login/LoginForm.tsx:89 msgid "Please enter your username" msgstr "" @@ -7423,7 +7430,6 @@ msgid "Processing video..." msgstr "" #: src/lib/api/index.ts:60 -#: src/screens/Login/ForgotPasswordForm.tsx:149 msgid "Processing..." msgstr "" @@ -8116,7 +8122,7 @@ msgstr "" msgid "Reset activity subscription nudge" msgstr "" -#: src/screens/Login/SetNewPasswordForm.tsx:116 +#: src/screens/Login/SetNewPasswordForm.tsx:117 msgid "Reset code" msgstr "" @@ -8125,7 +8131,7 @@ msgstr "" msgid "Reset onboarding state" msgstr "" -#: src/screens/Login/ForgotPasswordForm.tsx:80 +#: src/screens/Login/ForgotPasswordForm.tsx:81 msgid "Reset password" msgstr "" @@ -8134,7 +8140,7 @@ msgstr "" msgid "Resync contacts" msgstr "" -#: src/screens/Login/LoginForm.tsx:327 +#: src/screens/Login/LoginForm.tsx:329 msgid "Retries signing in" msgstr "" @@ -8154,8 +8160,8 @@ msgstr "" #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoFallback.tsx:55 #: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoFallback.tsx:58 #: src/components/StarterPack/ProfileStarterPacks.tsx:376 -#: src/screens/Login/LoginForm.tsx:326 -#: src/screens/Login/LoginForm.tsx:333 +#: src/screens/Login/LoginForm.tsx:328 +#: src/screens/Login/LoginForm.tsx:334 #: src/screens/Messages/ChatList.tsx:292 #: src/screens/Messages/components/MessageListError.tsx:25 #: src/screens/Messages/Inbox.tsx:219 @@ -8501,7 +8507,7 @@ msgstr "" msgid "Select a reason" msgstr "" -#: src/screens/Login/ChooseAccountForm.tsx:78 +#: src/screens/Login/ChooseAccountForm.tsx:80 msgid "Select account" msgstr "" @@ -8533,7 +8539,7 @@ msgstr "" msgid "Select duration" msgstr "" -#: src/screens/Login/index.tsx:159 +#: src/screens/Login/index.tsx:162 msgid "Select from an existing account" msgstr "" @@ -8713,7 +8719,7 @@ msgstr "" msgid "Set app icon to {0}" msgstr "" -#: src/screens/Login/SetNewPasswordForm.tsx:106 +#: src/screens/Login/SetNewPasswordForm.tsx:107 msgid "Set new password" msgstr "" @@ -8733,7 +8739,7 @@ msgstr "" msgid "Set your birthdate below and we'll get you back to posting and exploring in no time!" msgstr "" -#: src/screens/Login/ForgotPasswordForm.tsx:107 +#: src/screens/Login/ForgotPasswordForm.tsx:108 msgid "Sets email for password reset" msgstr "" @@ -9012,9 +9018,8 @@ msgstr "" #: src/components/WelcomeModal.tsx:196 #: src/components/WelcomeModal.tsx:208 #: src/screens/Hashtag.tsx:240 -#: src/screens/Login/index.tsx:137 -#: src/screens/Login/index.tsx:158 -#: src/screens/Login/LoginForm.tsx:181 +#: src/screens/Login/index.tsx:140 +#: src/screens/Login/index.tsx:161 #: src/screens/Search/SearchResults.tsx:296 #: src/view/com/auth/SplashScreen.tsx:117 #: src/view/com/auth/SplashScreen.tsx:123 @@ -9033,7 +9038,7 @@ msgstr "" msgid "Sign in as {0}" msgstr "" -#: src/screens/Login/ChooseAccountForm.tsx:82 +#: src/screens/Login/ChooseAccountForm.tsx:85 msgid "Sign in as..." msgstr "" @@ -9086,7 +9091,7 @@ msgid "Sign-in Required" msgstr "" #: src/lib/hooks/useAccountSwitcher.ts:42 -#: src/screens/Login/ChooseAccountForm.tsx:54 +#: src/screens/Login/ChooseAccountForm.tsx:55 msgid "Signed in as @{0}" msgstr "" @@ -9420,6 +9425,8 @@ msgstr "" msgid "Support for this feature in your country has not been enabled yet! Please check back later." msgstr "" +#: src/components/dialogs/SwitchAccount.tsx:46 +#: src/components/dialogs/SwitchAccount.tsx:49 #: src/screens/Settings/Settings.tsx:127 #: src/screens/Settings/Settings.tsx:141 #: src/screens/Settings/Settings.tsx:622 @@ -9427,11 +9434,6 @@ msgstr "" msgid "Switch account" msgstr "" -#: src/components/dialogs/SwitchAccount.tsx:46 -#: src/components/dialogs/SwitchAccount.tsx:49 -msgid "Switch Account" -msgstr "" - #: src/view/shell/desktop/LeftNav.tsx:110 msgid "Switch accounts" msgstr "" @@ -9876,7 +9878,7 @@ msgstr "" msgid "This content has received a general warning from moderators." msgstr "" -#: src/components/dialogs/EmbedConsent.tsx:63 +#: src/components/dialogs/EmbedConsent.tsx:62 msgid "This content is hosted by {0}. Do you want to enable external media?" msgstr "" @@ -10244,10 +10246,10 @@ msgstr "" msgid "Unable to contact your service. Please check your internet connection and try again." msgstr "" -#: src/screens/Login/ForgotPasswordForm.tsx:68 -#: src/screens/Login/index.tsx:94 -#: src/screens/Login/LoginForm.tsx:169 -#: src/screens/Login/SetNewPasswordForm.tsx:81 +#: src/screens/Login/ForgotPasswordForm.tsx:69 +#: src/screens/Login/index.tsx:96 +#: src/screens/Login/LoginForm.tsx:166 +#: src/screens/Login/SetNewPasswordForm.tsx:82 #: src/screens/Signup/index.tsx:88 msgid "Unable to contact your service. Please check your Internet connection." msgstr "" @@ -10528,10 +10530,6 @@ msgctxt "toast" msgid "Updating reply visibility failed" msgstr "" -#: src/screens/Login/SetNewPasswordForm.tsx:194 -msgid "Updating..." -msgstr "" - #: src/screens/Onboarding/StepProfile/index.tsx:298 msgid "Upload a photo instead" msgstr "" @@ -10675,7 +10673,7 @@ msgstr "" msgid "Username must only contain letters (a-z), numbers, and hyphens" msgstr "" -#: src/screens/Login/LoginForm.tsx:202 +#: src/screens/Login/LoginForm.tsx:199 msgid "Username or email address" msgstr "" @@ -11465,7 +11463,7 @@ msgstr "" msgid "You can now choose to be notified when specific people post. If there’s someone you want timely updates from, go to their profile and find the new bell icon near the follow button." msgstr "" -#: src/screens/Login/index.tsx:197 +#: src/screens/Login/index.tsx:203 #: src/screens/Login/PasswordUpdatedForm.tsx:26 msgid "You can now sign in with your new password." msgstr "" @@ -11544,8 +11542,8 @@ msgstr "" msgid "You have completely disabled reply, quote, and mention notifications, so this tab will no longer update. To adjust this, visit your <0>notification settings." msgstr "" -#: src/screens/Login/SetNewPasswordForm.tsx:49 -#: src/screens/Login/SetNewPasswordForm.tsx:95 +#: src/screens/Login/SetNewPasswordForm.tsx:50 +#: src/screens/Login/SetNewPasswordForm.tsx:96 #: src/screens/Settings/components/ChangePasswordDialog.tsx:112 msgid "You have entered an invalid code. It should look like XXXXX-XXXXX." msgstr "" @@ -11726,7 +11724,7 @@ msgstr "" msgid "You will now receive notifications for this thread" msgstr "" -#: src/screens/Login/SetNewPasswordForm.tsx:108 +#: src/screens/Login/SetNewPasswordForm.tsx:109 msgid "You will receive an email with a \"reset code.\" Enter that code here, then enter your new password." msgstr "" @@ -11898,7 +11896,7 @@ msgstr "" msgid "Your email" msgstr "" -#: src/screens/Login/ForgotPasswordForm.tsx:51 +#: src/screens/Login/ForgotPasswordForm.tsx:52 #: src/screens/Settings/components/ChangePasswordDialog.tsx:81 #: src/screens/Signup/state.ts:277 #: src/screens/Signup/StepInfo/index.tsx:131 From 1228306309c3a845f9c1bda196956aac0dbfde60 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Sat, 14 Feb 2026 22:29:59 +0000 Subject: [PATCH 41/59] Fix quote embed clickability in composer on web (#9876) --- src/components/Post/Embed/LazyQuoteEmbed.tsx | 9 +- src/components/Post/Embed/index.tsx | 102 +++++++++++-------- src/view/com/composer/Composer.tsx | 4 +- src/view/com/composer/ComposerReplyTo.tsx | 2 +- 4 files changed, 67 insertions(+), 50 deletions(-) diff --git a/src/components/Post/Embed/LazyQuoteEmbed.tsx b/src/components/Post/Embed/LazyQuoteEmbed.tsx index fdc1c63091..117b88d1d0 100644 --- a/src/components/Post/Embed/LazyQuoteEmbed.tsx +++ b/src/components/Post/Embed/LazyQuoteEmbed.tsx @@ -6,7 +6,13 @@ import {useResolveLinkQuery} from '#/state/queries/resolve-link' import {atoms as a, useTheme} from '#/alf' import {QuoteEmbed} from '#/components/Post/Embed' -export function LazyQuoteEmbed({uri}: {uri: string}) { +export function LazyQuoteEmbed({ + uri, + linkDisabled, +}: { + uri: string + linkDisabled?: boolean +}) { const t = useTheme() const {data} = useResolveLinkQuery(uri) @@ -21,6 +27,7 @@ export function LazyQuoteEmbed({uri}: {uri: string}) { type: 'post', view, }} + linkDisabled={linkDisabled} /> ) : ( & { embed: EmbedType<'post'> viewContext?: QuoteEmbedViewContext + linkDisabled?: boolean }) { const moderationOpts = useModerationOpts() const quote = useMemo<$Typed>( @@ -280,11 +282,48 @@ export function QuoteEmbed({ onIn: onPressIn, onOut: onPressOut, } = useInteractionState() + + const contents = ( + <> + + + + {moderation ? ( + + ) : null} + {richText ? ( + + ) : null} + {quote.embed && ( + + )} + + ) + return ( + onPointerEnter={linkDisabled ? undefined : onPointerEnter} + onPointerLeave={linkDisabled ? undefined : onPointerLeave}> {({active}) => ( <> - {!active && ( + {!active && !linkDisabled && ( )} - - - + {linkDisabled ? ( + + {contents} - {moderation ? ( - - ) : null} - {richText ? ( - - ) : null} - {quote.embed && ( - - )} - + ) : ( + + {contents} + + )} )} diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index 53d50bca8a..ef54c4908f 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -1725,9 +1725,7 @@ function ComposerEmbeds({ - - - + {canRemoveQuote && ( dispatch({type: 'embed_remove_quote'})} diff --git a/src/view/com/composer/ComposerReplyTo.tsx b/src/view/com/composer/ComposerReplyTo.tsx index 462779151f..e534816626 100644 --- a/src/view/com/composer/ComposerReplyTo.tsx +++ b/src/view/com/composer/ComposerReplyTo.tsx @@ -132,7 +132,7 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) { )} {showFull && parsedQuoteEmbed && parsedQuoteEmbed.type === 'post' && ( - + )} From b166d395d9c85f49005b92c05a1f26024f82ffc0 Mon Sep 17 00:00:00 2001 From: pfrazee <1270099+pfrazee@users.noreply.github.com> Date: Sun, 15 Feb 2026 03:11:50 +0000 Subject: [PATCH 42/59] Nightly source-language update --- src/locale/locales/en/messages.po | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po index 29fd965afd..2190d4b60f 100644 --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -766,7 +766,7 @@ msgstr "" msgid "Add another post" msgstr "" -#: src/view/com/composer/Composer.tsx:1978 +#: src/view/com/composer/Composer.tsx:1976 msgid "Add another post to thread" msgstr "" @@ -2263,11 +2263,11 @@ msgstr "" msgid "Compose reply" msgstr "" -#: src/view/com/composer/Composer.tsx:2376 +#: src/view/com/composer/Composer.tsx:2374 msgid "Compressing GIF..." msgstr "" -#: src/view/com/composer/Composer.tsx:2378 +#: src/view/com/composer/Composer.tsx:2376 msgid "Compressing video..." msgstr "" @@ -3060,7 +3060,7 @@ msgstr "" msgid "Dismiss banner" msgstr "" -#: src/view/com/composer/Composer.tsx:2297 +#: src/view/com/composer/Composer.tsx:2295 msgid "Dismiss error" msgstr "" @@ -3544,7 +3544,7 @@ msgstr "" msgid "Entertainment" msgstr "" -#: src/view/com/composer/Composer.tsx:2396 +#: src/view/com/composer/Composer.tsx:2394 #: src/view/com/util/error/ErrorScreen.tsx:42 msgid "Error" msgstr "" @@ -4447,7 +4447,7 @@ msgstr "" msgid "GIF" msgstr "" -#: src/view/com/composer/Composer.tsx:2401 +#: src/view/com/composer/Composer.tsx:2399 msgid "GIF uploaded" msgstr "" @@ -5170,7 +5170,7 @@ msgstr "" msgid "It's just you right now! Add more people to your starter pack by searching above." msgstr "" -#: src/view/com/composer/Composer.tsx:2316 +#: src/view/com/composer/Composer.tsx:2314 msgid "Job ID: {0}" msgstr "" @@ -6631,7 +6631,7 @@ msgid "Open drawer menu" msgstr "" #: src/screens/Messages/components/MessageInput.web.tsx:181 -#: src/view/com/composer/Composer.tsx:1963 +#: src/view/com/composer/Composer.tsx:1961 msgid "Open emoji picker" msgstr "" @@ -6743,7 +6743,7 @@ msgstr "" msgid "Opens device gallery to select up to {MAX_IMAGES, plural, other {# images}}, or a single video or GIF." msgstr "" -#: src/view/com/composer/Composer.tsx:1964 +#: src/view/com/composer/Composer.tsx:1962 msgid "Opens emoji picker" msgstr "" @@ -7421,11 +7421,11 @@ msgstr "" msgid "Privacy violation of a minor" msgstr "" -#: src/view/com/composer/Composer.tsx:2390 +#: src/view/com/composer/Composer.tsx:2388 msgid "Processing GIF..." msgstr "" -#: src/view/com/composer/Composer.tsx:2392 +#: src/view/com/composer/Composer.tsx:2390 msgid "Processing video..." msgstr "" @@ -10557,7 +10557,7 @@ msgstr "" msgid "Upload from Library" msgstr "" -#: src/view/com/composer/Composer.tsx:2383 +#: src/view/com/composer/Composer.tsx:2381 msgid "Uploading GIF..." msgstr "" @@ -10570,7 +10570,7 @@ msgstr "" msgid "Uploading link thumbnail..." msgstr "" -#: src/view/com/composer/Composer.tsx:2385 +#: src/view/com/composer/Composer.tsx:2383 msgid "Uploading video..." msgstr "" @@ -10841,7 +10841,7 @@ msgstr "" msgid "Video settings" msgstr "" -#: src/view/com/composer/Composer.tsx:2403 +#: src/view/com/composer/Composer.tsx:2401 msgid "Video uploaded" msgstr "" From 06fcea988e22662d5d1b90a592ce7e800ebd0756 Mon Sep 17 00:00:00 2001 From: surfdude29 <149612116+surfdude29@users.noreply.github.com> Date: Sun, 15 Feb 2026 19:02:01 +0000 Subject: [PATCH 43/59] 'Log in' to 'Sign in' (#9875) --- src/components/dialogs/BirthDateSettings.tsx | 4 ++-- src/screens/Login/LoginForm.tsx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/dialogs/BirthDateSettings.tsx b/src/components/dialogs/BirthDateSettings.tsx index d94af83f7c..102dd12c89 100644 --- a/src/components/dialogs/BirthDateSettings.tsx +++ b/src/components/dialogs/BirthDateSettings.tsx @@ -72,9 +72,9 @@ export function BirthDateSettingsDialog({ ) : isUsingAppPassword ? ( - Hmm, it looks like you're logged in with an{' '} + Hmm, it looks like you're signed in with an{' '} App Password. To set your - birthdate, you'll need to log in with your main account + birthdate, you'll need to sign in with your main account password, or ask whomever controls this account to do so. diff --git a/src/screens/Login/LoginForm.tsx b/src/screens/Login/LoginForm.tsx index f7ccb5c997..351aaa21b4 100644 --- a/src/screens/Login/LoginForm.tsx +++ b/src/screens/Login/LoginForm.tsx @@ -175,7 +175,7 @@ export const LoginForm = ({ } return ( - Log in}> + Sign in}> Hosting provider @@ -346,13 +346,13 @@ export const LoginForm = ({ ) : ( From 95f9cc1ed5ebd8ff17af9c0185dde61805cbae3c Mon Sep 17 00:00:00 2001 From: pfrazee <1270099+pfrazee@users.noreply.github.com> Date: Mon, 16 Feb 2026 03:11:39 +0000 Subject: [PATCH 44/59] Nightly source-language update --- src/locale/locales/en/messages.po | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po index 2190d4b60f..f350c862a2 100644 --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -4800,7 +4800,7 @@ msgid "Hides the content" msgstr "" #: src/components/dialogs/BirthDateSettings.tsx:74 -msgid "Hmm, it looks like you're logged in with an <0>App Password. To set your birthdate, you'll need to log in with your main account password, or ask whomever controls this account to do so." +msgid "Hmm, it looks like you're signed in with an <0>App Password. To set your birthdate, you'll need to sign in with your main account password, or ask whomever controls this account to do so." msgstr "" #: src/view/com/posts/PostFeedErrorMessage.tsx:124 @@ -5651,12 +5651,6 @@ msgstr "" msgid "Log" msgstr "" -#: src/screens/Login/LoginForm.tsx:178 -#: src/screens/Login/LoginForm.tsx:349 -#: src/screens/Login/LoginForm.tsx:355 -msgid "Log in" -msgstr "" - #: src/components/AccountList.tsx:191 msgid "Logged out" msgstr "" @@ -9020,6 +9014,9 @@ msgstr "" #: src/screens/Hashtag.tsx:240 #: src/screens/Login/index.tsx:140 #: src/screens/Login/index.tsx:161 +#: src/screens/Login/LoginForm.tsx:178 +#: src/screens/Login/LoginForm.tsx:349 +#: src/screens/Login/LoginForm.tsx:355 #: src/screens/Search/SearchResults.tsx:296 #: src/view/com/auth/SplashScreen.tsx:117 #: src/view/com/auth/SplashScreen.tsx:123 From b6b364700e7b0b4a384ba449b2ae6b6b07a5c87e Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Mon, 16 Feb 2026 13:29:59 +0000 Subject: [PATCH 45/59] Make profile description text selectable (#9884) Co-authored-by: Claude Opus 4.6 --- src/screens/Profile/Header/ProfileHeaderStandard.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/screens/Profile/Header/ProfileHeaderStandard.tsx b/src/screens/Profile/Header/ProfileHeaderStandard.tsx index c60fcd032a..9c1c8a662a 100644 --- a/src/screens/Profile/Header/ProfileHeaderStandard.tsx +++ b/src/screens/Profile/Header/ProfileHeaderStandard.tsx @@ -157,6 +157,7 @@ let ProfileHeaderStandard = ({ testID="profileHeaderDescription" style={[a.text_md]} numberOfLines={15} + selectable value={descriptionRT} enableTags authorHandle={profile.handle} From 4ebeb94b41a506817e190daf0c62203e04a421c6 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Mon, 16 Feb 2026 13:30:07 +0000 Subject: [PATCH 46/59] Add Renew menu for expired mute words (#9883) Co-authored-by: Claude Opus 4.6 --- src/components/dialogs/MutedWords.tsx | 133 +++++++++++++++++++++----- 1 file changed, 107 insertions(+), 26 deletions(-) diff --git a/src/components/dialogs/MutedWords.tsx b/src/components/dialogs/MutedWords.tsx index eea54026a6..e674ca212b 100644 --- a/src/components/dialogs/MutedWords.tsx +++ b/src/components/dialogs/MutedWords.tsx @@ -8,6 +8,7 @@ import {logger} from '#/logger' import { usePreferencesQuery, useRemoveMutedWordMutation, + useUpdateMutedWordMutation, useUpsertMutedWordsMutation, } from '#/state/queries/preferences' import { @@ -29,6 +30,7 @@ import {PageText_Stroke2_Corner0_Rounded as PageText} from '#/components/icons/P import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' import {Loader} from '#/components/Loader' +import * as Menu from '#/components/Menu' import * as Prompt from '#/components/Prompt' import {Text} from '#/components/Typography' import {IS_NATIVE} from '#/env' @@ -421,6 +423,7 @@ function MutedWordRow({ const t = useTheme() const {_} = useLingui() const {isPending, mutateAsync: removeMutedWord} = useRemoveMutedWordMutation() + const {mutateAsync: updateMutedWord} = useUpdateMutedWordMutation() const control = Prompt.usePromptControl() const expiryDate = word.expiresAt ? new Date(word.expiresAt) : undefined const isExpired = expiryDate && expiryDate < new Date() @@ -431,6 +434,15 @@ function MutedWordRow({ removeMutedWord(word) }, [removeMutedWord, word, control]) + const renew = (days?: number) => { + updateMutedWord({ + ...word, + expiresAt: days + ? new Date(Date.now() + days * ONE_DAY).toISOString() + : undefined, + }) + } + return ( <> {(expiryDate || word.actorTarget === 'exclude-following') && ( - - - {expiryDate && ( + + {expiryDate && + (isExpired ? ( <> - {isExpired ? ( + Expired - ) : ( - - Expires{' '} - {formatDistance(expiryDate, new Date(), { - addSuffix: true, - })} - - )} + + + {' · '} + + + + {({props}) => ( + + Renew + + )} + + + + Renew duration + + + renew(1)}> + + 24 hours + + + renew(7)}> + + 7 days + + + renew(30)}> + + 30 days + + + renew()}> + + Forever + + + + + - )} - {word.actorTarget === 'exclude-following' && ( - <> - {' • '} - Excludes users you follow - - )} - + ) : ( + + + Expires{' '} + {formatDistance(expiryDate, new Date(), { + addSuffix: true, + })} + + + ))} + {word.actorTarget === 'exclude-following' && ( + + {expiryDate ? ' · ' : ''} + Excludes users you follow + + )} )} From 9b830fd425e936d934e9eec128ebc50ef3e92982 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Mon, 16 Feb 2026 13:39:29 +0000 Subject: [PATCH 47/59] Use scroll position to gate post-created feed refresh (#9881) Co-authored-by: Claude Opus 4.6 --- CLAUDE.md | 1 + src/view/com/posts/PostFeed.tsx | 38 ++++++++++++++++----------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 5b0369e6c8..240c1a4268 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,6 +24,7 @@ yarn android # Run on Android yarn ios # Run on iOS # Testing & Quality +# IMPORTANT: Always use these yarn scripts, never call the underlying tools directly yarn test # Run Jest tests yarn lint # Run ESLint yarn typecheck # Run TypeScript type checking diff --git a/src/view/com/posts/PostFeed.tsx b/src/view/com/posts/PostFeed.tsx index 3c8d25faf8..b79fc1ab32 100644 --- a/src/view/com/posts/PostFeed.tsx +++ b/src/view/com/posts/PostFeed.tsx @@ -1,12 +1,4 @@ -import { - type JSX, - memo, - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from 'react' +import {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react' import { ActivityIndicator, AppState, @@ -220,13 +212,13 @@ let PostFeed = ({ scrollElRef?: ListRef onHasNew?: (v: boolean) => void onScrolledDownChange?: (isScrolledDown: boolean) => void - renderEmptyState: () => JSX.Element - renderEndOfFeed?: () => JSX.Element + renderEmptyState: () => React.ReactElement + renderEndOfFeed?: () => React.ReactElement testID?: string headerOffset?: number progressViewOffset?: number desktopFixedHeightOffset?: number - ListHeaderComponent?: () => JSX.Element + ListHeaderComponent?: () => React.ReactElement extraData?: any savedFeedConfig?: AppBskyActorDefs.SavedFeed initialNumToRender?: number @@ -309,20 +301,26 @@ let PostFeed = ({ } }) + const isScrolledDownRef = useRef(false) + const handleScrolledDownChange = (isScrolledDown: boolean) => { + isScrolledDownRef.current = isScrolledDown + onScrolledDownChange?.(isScrolledDown) + } + const myDid = currentAccount?.did || '' const onPostCreated = useCallback(() => { // NOTE - // only invalidate if there's 1 page - // more than 1 page can trigger some UI freakouts on iOS and android - // -prf + // only invalidate if at the top of the feed + // changing content when scrolled can trigger some UI freakouts on iOS and android + // -sfn if ( - data?.pages.length === 1 && + !isScrolledDownRef.current && (feed === 'following' || feed === `author|${myDid}|posts_and_author_threads`) ) { - queryClient.invalidateQueries({queryKey: RQKEY(feed)}) + void queryClient.invalidateQueries({queryKey: RQKEY(feed)}) } - }, [queryClient, feed, data, myDid]) + }, [queryClient, feed, myDid]) useEffect(() => { return listenPostCreated(onPostCreated) }, [onPostCreated]) @@ -981,7 +979,7 @@ let PostFeed = ({ } } }, - [feedFeedback, feed, liveNowConfig, getPostPosition], + [feedFeedback, feed, liveNowConfig, getPostPosition, ax], ) return ( @@ -1001,7 +999,7 @@ let PostFeed = ({ contentContainerStyle={{ minHeight: Dimensions.get('window').height * 1.5, }} - onScrolledDownChange={onScrolledDownChange} + onScrolledDownChange={handleScrolledDownChange} onEndReached={onEndReached} onEndReachedThreshold={2} // number of posts left to trigger load more removeClippedSubviews={true} From 6be7751769262cc38b67fa70b3030c5537beac9a Mon Sep 17 00:00:00 2001 From: Spence Pope Date: Mon, 16 Feb 2026 08:39:53 -0500 Subject: [PATCH 48/59] have back button dismiss lightbox on web (#9874) --- src/alf/atoms.ts | 16 ++++++++ .../VideoEmbedInner/VideoEmbedInnerWeb.tsx | 14 +------ src/view/com/lightbox/Lightbox.web.tsx | 41 ++++++++++++++++++- 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts index e117b5effc..ffac94a5da 100644 --- a/src/alf/atoms.ts +++ b/src/alf/atoms.ts @@ -108,6 +108,22 @@ export const atoms = { animation: `zoomIn ${EXP_CURVE} 0.3s, fadeIn ${EXP_CURVE} 0.3s`, }), + /** + * Visually hidden but available to screen readers (web). + * Use for live regions or off-screen labels (e.g. "Image 1 of 3"). + */ + sr_only: web({ + position: 'absolute', + width: 1, + height: 1, + padding: 0, + margin: -1, + overflow: 'hidden', + clip: 'rect(0,0,0,0)', + whiteSpace: 'nowrap', + borderWidth: 0, + }), + /** * {@link Layout.SCROLLBAR_OFFSET} */ diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx index 5d14161fe1..37b141132d 100644 --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.tsx @@ -72,19 +72,7 @@ export function VideoEmbedInnerWeb({ loop={loop} /> {embed.alt && ( -
+
{embed.alt}
)} diff --git a/src/view/com/lightbox/Lightbox.web.tsx b/src/view/com/lightbox/Lightbox.web.tsx index 34b88e0aa6..400258e0ee 100644 --- a/src/view/com/lightbox/Lightbox.web.tsx +++ b/src/view/com/lightbox/Lightbox.web.tsx @@ -1,4 +1,4 @@ -import {useCallback, useEffect, useState} from 'react' +import {useCallback, useEffect, useRef, useState} from 'react' import {Pressable, StyleSheet, View} from 'react-native' import {Image} from 'expo-image' import {msg} from '@lingui/macro' @@ -69,7 +69,13 @@ function LightboxContainer({ -
{children}
+
+ {children} +
) @@ -125,6 +131,32 @@ function LightboxGallery({ return () => window.removeEventListener('keydown', onKeyDown) }, [onKeyDown]) + // Push a history entry so the browser back button closes the lightbox + // instead of navigating away from the page. + const closedByPopStateRef = useRef(false) + useEffect(() => { + history.pushState({lightbox: true}, '') + + const handlePopState = () => { + closedByPopStateRef.current = true + onClose() + } + window.addEventListener('popstate', handlePopState) + + return () => { + window.removeEventListener('popstate', handlePopState) + // Only pop our entry if it's still the current one. If navigation + // already pushed a new entry on top, leave the orphaned entry — + // it shares the same URL so traversing through it is harmless. + if ( + !closedByPopStateRef.current && + (history.state as {lightbox?: boolean})?.lightbox + ) { + history.back() + } + } + }, [onClose]) + const delayedFadeInAnim = !reduceMotionEnabled && [ a.fade_in, {animationDelay: '0.2s', animationFillMode: 'both'}, @@ -205,6 +237,11 @@ function LightboxGallery({ ) : null} + {imgs.length > 1 && ( +
+ {_(msg`Image ${index + 1} of ${imgs.length}`)} +
+ )} + + + {error && ( + + {error} + + )} + + + You can also{' '} + + temporarily deactivate + {' '} + your account instead. Your profile, posts, feeds, and lists will + no longer be visible to other Bluesky users. You can reactivate + your account at any time by logging in. + + + + ) + case Step.VERIFY_CODE: + return ( + <> + + + {_(msg`Delete account “${currentHandle}”`)} + + + + Check{' '} + + {currentEmail} + {' '} + for an email with the confirmation code to enter below: + + + + + + Confirmation code + + + + + {emailSentCount > 1 ? ( + + Email sent!{' '} + { + void handleSendEmail() + })}> + Click here to resend. + + + ) : ( + + Don’t see a code?{' '} + { + void handleSendEmail() + })}> + Click here to resend. + + + )}{' '} + + {emailState === EmailState.PENDING ? : null} + + + + + Password + + + + + + + + + + + {error && ( + + {error} + + )} + + ) + case Step.CONFIRM_DELETION: + return ( + <> + + + {_(msg`Are you really, really sure?`)} + + + + This will irreversably delete your Bluesky account{' '} + + {currentHandle} + {' '} + and all associated data. Note that this will affect any other{' '} + + AT Protocol + {' '} + services you use with this account. + + + + + + + + + ) + } +} diff --git a/src/state/modals/index.tsx b/src/state/modals/index.tsx index dab90c0af3..5f023e0680 100644 --- a/src/state/modals/index.tsx +++ b/src/state/modals/index.tsx @@ -11,10 +11,6 @@ export interface UserAddRemoveListsModal { onRemove?: (listUri: string) => void } -export interface DeleteAccountModal { - name: 'delete-account' -} - export interface ContentLanguagesSettingsModal { name: 'content-languages-settings' } @@ -23,9 +19,6 @@ export interface ContentLanguagesSettingsModal { * @deprecated DO NOT ADD NEW MODALS */ export type Modal = - // Account - | DeleteAccountModal - // Curation | ContentLanguagesSettingsModal diff --git a/src/view/com/modals/DeleteAccount.tsx b/src/view/com/modals/DeleteAccount.tsx deleted file mode 100644 index b92a43d686..0000000000 --- a/src/view/com/modals/DeleteAccount.tsx +++ /dev/null @@ -1,342 +0,0 @@ -import React from 'react' -import { - ActivityIndicator, - SafeAreaView, - StyleSheet, - TouchableOpacity, - View, -} from 'react-native' -import {LinearGradient} from 'expo-linear-gradient' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -import {DM_SERVICE_HEADERS} from '#/lib/constants' -import {usePalette} from '#/lib/hooks/usePalette' -import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' -import {cleanError} from '#/lib/strings/errors' -import {colors, gradients, s} from '#/lib/styles' -import {useTheme} from '#/lib/ThemeContext' -import {useModalControls} from '#/state/modals' -import {useAgent, useSession, useSessionApi} from '#/state/session' -import {atoms as a, useTheme as useNewTheme} from '#/alf' -import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' -import {Text as NewText} from '#/components/Typography' -import {IS_ANDROID, IS_WEB} from '#/env' -import {resetToTab} from '../../../Navigation' -import {ErrorMessage} from '../util/error/ErrorMessage' -import {Text} from '../util/text/Text' -import * as Toast from '../util/Toast' -import {ScrollView, TextInput} from './util' - -export const snapPoints = IS_ANDROID ? ['90%'] : ['55%'] - -export function Component({}: {}) { - const pal = usePalette('default') - const theme = useTheme() - const t = useNewTheme() - const {currentAccount} = useSession() - const agent = useAgent() - const {removeAccount} = useSessionApi() - const {_} = useLingui() - const {closeModal} = useModalControls() - const {isMobile} = useWebMediaQueries() - const [isEmailSent, setIsEmailSent] = React.useState(false) - const [confirmCode, setConfirmCode] = React.useState('') - const [password, setPassword] = React.useState('') - const [isProcessing, setIsProcessing] = React.useState(false) - const [error, setError] = React.useState('') - const onPressSendEmail = async () => { - setError('') - setIsProcessing(true) - try { - await agent.com.atproto.server.requestAccountDelete() - setIsEmailSent(true) - } catch (e: any) { - setError(cleanError(e)) - } - setIsProcessing(false) - } - const onPressConfirmDelete = async () => { - if (!currentAccount?.did) { - throw new Error(`DeleteAccount modal: currentAccount.did is undefined`) - } - - setError('') - setIsProcessing(true) - const token = confirmCode.replace(/\s/g, '') - - try { - // inform chat service of intent to delete account - const {success} = await agent.api.chat.bsky.actor.deleteAccount( - undefined, - { - headers: DM_SERVICE_HEADERS, - }, - ) - if (!success) { - throw new Error('Failed to inform chat service of account deletion') - } - await agent.com.atproto.server.deleteAccount({ - did: currentAccount.did, - password, - token, - }) - Toast.show(_(msg`Your account has been deleted`)) - resetToTab('HomeTab') - removeAccount(currentAccount) - closeModal() - } catch (e: any) { - setError(cleanError(e)) - } - setIsProcessing(false) - } - const onCancel = () => { - closeModal() - } - return ( - - - - - - Delete Account{' '} - - " - - - {currentAccount?.handle} - - - " - - - - - {!isEmailSent ? ( - <> - - - For security reasons, we'll need to send a confirmation code to - your email address. - - - {error ? ( - - - - ) : undefined} - {isProcessing ? ( - - - - ) : ( - <> - - - - Send Email - - - - - - Cancel - - - - )} - - - - - - - - You can also temporarily deactivate your account instead, - and reactivate it at any time. - - - - - - ) : ( - <> - {/* TODO: Update this label to be more concise */} - - - Check your inbox for an email with the confirmation code to - enter below: - - - - - Please enter your password as well: - - - {error ? ( - - - - ) : undefined} - {isProcessing ? ( - - - - ) : ( - <> - - - Delete my account - - - - - Cancel - - - - )} - - )} - - - ) -} - -const styles = StyleSheet.create({ - titleContainer: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - flexWrap: 'wrap', - marginTop: 12, - marginBottom: 12, - marginLeft: 20, - marginRight: 20, - }, - titleMobile: { - textAlign: 'center', - }, - titleDesktop: { - textAlign: 'center', - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - // @ts-ignore only rendered on web - maxWidth: '400px', - }, - description: { - textAlign: 'center', - paddingHorizontal: 22, - marginBottom: 10, - }, - mt20: { - marginTop: 20, - }, - mb20: { - marginBottom: 20, - }, - textInput: { - borderWidth: 1, - borderRadius: 6, - paddingHorizontal: 16, - paddingVertical: 12, - fontSize: 20, - marginHorizontal: 20, - }, - btn: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - borderRadius: 32, - padding: 14, - marginHorizontal: 20, - }, - evilBtn: { - backgroundColor: colors.red4, - }, -}) diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx index 4ebec459dd..a4ace3629f 100644 --- a/src/view/com/modals/Modal.tsx +++ b/src/view/com/modals/Modal.tsx @@ -7,7 +7,6 @@ import {usePalette} from '#/lib/hooks/usePalette' import {useModalControls, useModals} from '#/state/modals' import {FullWindowOverlay} from '#/components/FullWindowOverlay' import {createCustomBackdrop} from '../util/BottomSheetCustomBackdrop' -import * as DeleteAccountModal from './DeleteAccount' import * as ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings' import * as UserAddRemoveListsModal from './UserAddRemoveLists' @@ -45,9 +44,6 @@ export function ModalsContainer() { if (activeModal?.name === 'user-add-remove-lists') { snapPoints = UserAddRemoveListsModal.snapPoints element = - } else if (activeModal?.name === 'delete-account') { - snapPoints = DeleteAccountModal.snapPoints - element = } else if (activeModal?.name === 'content-languages-settings') { snapPoints = ContentLanguagesSettingsModal.snapPoints element = diff --git a/src/view/com/modals/Modal.web.tsx b/src/view/com/modals/Modal.web.tsx index bdf8269925..cb932f4530 100644 --- a/src/view/com/modals/Modal.web.tsx +++ b/src/view/com/modals/Modal.web.tsx @@ -6,7 +6,6 @@ import {usePalette} from '#/lib/hooks/usePalette' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {type Modal as ModalIface} from '#/state/modals' import {useModalControls, useModals} from '#/state/modals' -import * as DeleteAccountModal from './DeleteAccount' import * as ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings' import * as UserAddRemoveLists from './UserAddRemoveLists' @@ -48,8 +47,6 @@ function Modal({modal}: {modal: ModalIface}) { let element if (modal.name === 'user-add-remove-lists') { element = - } else if (modal.name === 'delete-account') { - element = } else if (modal.name === 'content-languages-settings') { element = } else { From a6ba0810b74c1c4c59a52036cf8f7c6cfd17526f Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Mon, 16 Feb 2026 21:09:49 +0000 Subject: [PATCH 54/59] Be more descriptive with video errors, log less (#9886) --- src/lib/strings/errors.ts | 1 + src/view/com/composer/state/video.ts | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/lib/strings/errors.ts b/src/lib/strings/errors.ts index e68cadeda2..4a5c9f09a9 100644 --- a/src/lib/strings/errors.ts +++ b/src/lib/strings/errors.ts @@ -54,6 +54,7 @@ const NETWORK_ERRORS = [ 'Failed to fetch', 'Load failed', 'Upstream service unreachable', + 'NetworkError when attempting to fetch resource', ] export function isNetworkError(e: unknown) { diff --git a/src/view/com/composer/state/video.ts b/src/view/com/composer/state/video.ts index 011bf42c69..05f57beefd 100644 --- a/src/view/com/composer/state/video.ts +++ b/src/view/com/composer/state/video.ts @@ -13,6 +13,7 @@ import { import {type CompressedVideo} from '#/lib/media/video/types' import {uploadVideo} from '#/lib/media/video/upload' import {createVideoAgent} from '#/lib/media/video/util' +import {isNetworkError} from '#/lib/strings/errors' import {logger} from '#/logger' type CaptionsTrack = {lang: string; file: File} @@ -403,7 +404,6 @@ function getUploadErrorMessage(e: unknown, _: I18n['_']): string | null { if (e instanceof AbortError) { return null } - logger.error('Error uploading video', {safeMessage: e}) if (e instanceof ServerError || e instanceof UploadLimitError) { // https://github.com/bluesky-social/tango/blob/lumi/lumi/worker/permissions.go#L77 switch (e.message) { @@ -433,9 +433,20 @@ function getUploadErrorMessage(e: unknown, _: I18n['_']): string | null { return _( msg`The selected video is larger than 100 MB. Please try again with a smaller file.`, ) - default: - return e.message + case 'Confirm your email address to upload videos': + return _(msg`Please confirm your email address to upload videos.`) } } - return _(msg`An error occurred while uploading the video.`) + + if (isNetworkError(e)) { + return _( + msg`An error occurred while uploading the video. Please check your internet connection and try again.`, + ) + } else { + // only log errors if they are unknown (and not network errors) + logger.error('Error uploading video', {safeMessage: e}) + } + + const message = e instanceof Error ? e.message : '' + return _(msg`An error occurred while uploading the video. ${message}`) } From 3b9f0b0a6869ca54ec46a6c53b67daf68fdc263e Mon Sep 17 00:00:00 2001 From: surfdude29 <149612116+surfdude29@users.noreply.github.com> Date: Mon, 16 Feb 2026 21:10:57 +0000 Subject: [PATCH 55/59] Add plural formatting for several strings (#9576) --- .../PostControls/PostMenu/PostMenuItems.tsx | 7 +++---- src/screens/Signup/StepInfo/index.tsx | 18 +++++++++--------- .../com/composer/videos/SubtitleDialog.tsx | 7 +++++-- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/components/PostControls/PostMenu/PostMenuItems.tsx b/src/components/PostControls/PostMenu/PostMenuItems.tsx index 0dc204534c..2ed462a134 100644 --- a/src/components/PostControls/PostMenu/PostMenuItems.tsx +++ b/src/components/PostControls/PostMenu/PostMenuItems.tsx @@ -13,7 +13,7 @@ import { AtUri, type RichText as RichTextAPI, } from '@atproto/api' -import {msg} from '@lingui/macro' +import {msg, plural} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useNavigation} from '@react-navigation/native' @@ -384,9 +384,8 @@ let PostMenuItems = ({ if (e instanceof MaxHiddenRepliesError) { Toast.show( _( - msg({ - message: `You can hide a maximum of ${MAX_HIDDEN_REPLIES} replies.`, - context: 'toast', + plural(MAX_HIDDEN_REPLIES, { + other: 'You can hide a maximum of # replies.', }), ), ) diff --git a/src/screens/Signup/StepInfo/index.tsx b/src/screens/Signup/StepInfo/index.tsx index be679613d5..e1d20ca73f 100644 --- a/src/screens/Signup/StepInfo/index.tsx +++ b/src/screens/Signup/StepInfo/index.tsx @@ -1,6 +1,6 @@ import React, {useRef} from 'react' import {type TextInput, View} from 'react-native' -import {msg, Trans} from '@lingui/macro' +import {msg, Plural, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import * as EmailValidator from 'email-validator' import type tldts from 'tldts' @@ -312,15 +312,15 @@ export function StepInfo({ {!isOverAppMinAccessAge ? ( - - You must be {MIN_ACCESS_AGE} years of age or older - to create an account. - + ) : ( - - You must be {aaRegionConfig.minAccessAge} years of - age or older to create an account in your region. - + )} {IS_NATIVE && diff --git a/src/view/com/composer/videos/SubtitleDialog.tsx b/src/view/com/composer/videos/SubtitleDialog.tsx index 0f2a97d95d..f0f01bdce2 100644 --- a/src/view/com/composer/videos/SubtitleDialog.tsx +++ b/src/view/com/composer/videos/SubtitleDialog.tsx @@ -1,6 +1,6 @@ import {useCallback, useState} from 'react' import {Keyboard, type StyleProp, View, type ViewStyle} from 'react-native' -import {msg, Trans} from '@lingui/macro' +import {msg, Plural, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {MAX_ALT_TEXT} from '#/lib/constants' @@ -134,7 +134,10 @@ function SubtitleDialogInner({ a.leading_snug, a.mt_md, ]}> - Alt text must be less than {MAX_ALT_TEXT} characters. + )} From 82f42e734c50b34de31e8aff1e7ced248ab6e96f Mon Sep 17 00:00:00 2001 From: surfdude29 <149612116+surfdude29@users.noreply.github.com> Date: Mon, 16 Feb 2026 21:12:26 +0000 Subject: [PATCH 56/59] Wrap interaction counts with `Trans` to add translation flexibility (#9036) --- .../components/ThreadItemAnchor.tsx | 60 +++++++++++-------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/src/screens/PostThread/components/ThreadItemAnchor.tsx b/src/screens/PostThread/components/ThreadItemAnchor.tsx index 27fcaf0fa8..643f926f1b 100644 --- a/src/screens/PostThread/components/ThreadItemAnchor.tsx +++ b/src/screens/PostThread/components/ThreadItemAnchor.tsx @@ -452,14 +452,16 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({ - - {formatPostStatCount(post.repostCount)} - {' '} - + + + {formatPostStatCount(post.repostCount)} + {' '} + + ) : null} @@ -470,14 +472,16 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({ - - {formatPostStatCount(post.quoteCount)} - {' '} - + + + {formatPostStatCount(post.quoteCount)} + {' '} + + ) : null} @@ -486,10 +490,12 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({ - - {formatPostStatCount(post.likeCount)} - {' '} - + + + {formatPostStatCount(post.likeCount)} + {' '} + + ) : null} @@ -497,10 +503,16 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({ - - {formatPostStatCount(post.bookmarkCount)} - {' '} - + + + {formatPostStatCount(post.bookmarkCount)} + {' '} + + ) : null} From 29bc0f1372879427340b26e9c287d38bed830c9a Mon Sep 17 00:00:00 2001 From: DS Boyce <260543580+ds-boyce@users.noreply.github.com> Date: Mon, 16 Feb 2026 13:29:25 -0800 Subject: [PATCH 57/59] Add optional props to Prompt.Action (#9887) --- src/components/Prompt.tsx | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/components/Prompt.tsx b/src/components/Prompt.tsx index cdafa85c7e..e538e6bc71 100644 --- a/src/components/Prompt.tsx +++ b/src/components/Prompt.tsx @@ -4,8 +4,14 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {atoms as a, useTheme, type ViewStyleProp, web} from '#/alf' -import {Button, type ButtonColor, ButtonText} from '#/components/Button' +import { + Button, + type ButtonColor, + ButtonIcon, + ButtonText, +} from '#/components/Button' import * as Dialog from '#/components/Dialog' +import {type Props as SVGIconProps} from '#/components/icons/common' import {Text} from '#/components/Typography' import {type BottomSheetViewProps} from '../../modules/bottom-sheet' @@ -126,7 +132,7 @@ export function Cancel({ ) } From 7c08bba6cf7b235dc7a739d67bec9f6bc5dcdd7d Mon Sep 17 00:00:00 2001 From: DS Boyce <260543580+ds-boyce@users.noreply.github.com> Date: Mon, 16 Feb 2026 16:23:27 -0800 Subject: [PATCH 58/59] Use Prompt.Action for delete account buttons (#9889) --- .../components/DeleteAccountDialog.tsx | 41 ++++++++----------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/src/screens/Settings/components/DeleteAccountDialog.tsx b/src/screens/Settings/components/DeleteAccountDialog.tsx index fccf2f83a5..d52629c38b 100644 --- a/src/screens/Settings/components/DeleteAccountDialog.tsx +++ b/src/screens/Settings/components/DeleteAccountDialog.tsx @@ -10,7 +10,6 @@ import {logger} from '#/logger' import {useAgent, useSession, useSessionApi} from '#/state/session' import {atoms as a, useTheme, web} from '#/alf' import {Admonition} from '#/components/Admonition' -import {Button, ButtonIcon, ButtonText} from '#/components/Button' import {type DialogOuterProps} from '#/components/Dialog' import { isValidCode, @@ -197,16 +196,12 @@ function DeleteAccountDialogInner({ - + {error && ( @@ -314,14 +309,13 @@ function DeleteAccountDialogInner({ - + cta={_(msg`Delete my account`)} + shouldCloseOnPress={false} + onPress={handleDeleteAccount} + /> {error && ( @@ -340,7 +334,7 @@ function DeleteAccountDialogInner({ - This will irreversably delete your Bluesky account{' '} + This will irreversibly delete your Bluesky account{' '} {currentHandle} {' '} @@ -356,13 +350,12 @@ function DeleteAccountDialogInner({ - + cta={_(msg`Yes, delete my account`)} + shouldCloseOnPress={false} + onPress={handleConfirmDeletion} + /> From e67d81f269f0cafeefe0338014587bfff3e5d6f5 Mon Sep 17 00:00:00 2001 From: pfrazee <1270099+pfrazee@users.noreply.github.com> Date: Tue, 17 Feb 2026 03:09:32 +0000 Subject: [PATCH 59/59] Nightly source-language update --- src/locale/locales/en/messages.po | 829 ++++++++++++++++-------------- 1 file changed, 433 insertions(+), 396 deletions(-) diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po index f350c862a2..eb8baf16bd 100644 --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -103,26 +103,10 @@ msgstr "" msgid "{0, plural, one {following} other {following}}" msgstr "" -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:492 -msgid "{0, plural, one {like} other {likes}}" -msgstr "" - #: src/screens/Profile/Header/Metrics.tsx:58 msgid "{0, plural, one {post} other {posts}}" msgstr "" -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:476 -msgid "{0, plural, one {quote} other {quotes}}" -msgstr "" - -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:458 -msgid "{0, plural, one {repost} other {reposts}}" -msgstr "" - -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:503 -msgid "{0, plural, one {save} other {saves}}" -msgstr "" - #. Number of users (always at least 25) who have joined Bluesky using a specific starter pack #: src/screens/StarterPack/StarterPackScreen.tsx:499 msgid "{0, plural, other {# people have}} joined Bluesky via this starter pack!" @@ -132,6 +116,10 @@ msgstr "" msgid "{0, plural, other {+# more}}" msgstr "" +#: src/screens/Signup/StepInfo/index.tsx:320 +msgid "{0, plural, other {You must be # years of age or older to create an account in your region.}}" +msgstr "" + #: src/lib/strings/time.ts:13 msgctxt "date and time formatted like this: [time] · [date]" msgid "{0} · {1}" @@ -142,12 +130,12 @@ msgid "{0} (Account)" msgstr "" #. Pattern: {wordValue} in tags -#: src/components/dialogs/MutedWords.tsx:481 +#: src/components/dialogs/MutedWords.tsx:493 msgid "{0} <0>in <1>tags" msgstr "" #. Pattern: {wordValue} in text, tags -#: src/components/dialogs/MutedWords.tsx:470 +#: src/components/dialogs/MutedWords.tsx:482 msgid "{0} <0>in <1>text & tags" msgstr "" @@ -155,7 +143,7 @@ msgstr "" msgid "{0} following" msgstr "" -#: src/components/live/LiveStatusDialog.tsx:79 +#: src/features/liveNow/components/LiveStatusDialog.tsx:79 msgid "{0} is live" msgstr "" @@ -410,11 +398,11 @@ msgstr "" msgid "{handle} can't be messaged" msgstr "" -#: src/components/live/utils.ts:15 +#: src/features/liveNow/utils.ts:15 msgid "{hours, plural, one {# hour {minutesString}} other {# hours {minutesString}}}" msgstr "" -#: src/components/live/utils.ts:19 +#: src/features/liveNow/utils.ts:19 msgid "{hours, plural, one {# hour} other {# hours}}" msgstr "" @@ -423,7 +411,19 @@ msgstr "" msgid "{joinedAllTimeCount, plural, other {# users have}} joined!" msgstr "" -#: src/components/live/utils.ts:10 +#: src/view/com/composer/videos/SubtitleDialog.tsx:137 +msgid "{MAX_ALT_TEXT, plural, other {Alt text must be less than # characters.}}" +msgstr "" + +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:387 +msgid "{MAX_HIDDEN_REPLIES, plural, other {You can hide a maximum of # replies.}}" +msgstr "" + +#: src/screens/Signup/StepInfo/index.tsx:315 +msgid "{MIN_ACCESS_AGE, plural, other {You must be # years of age or older to create an account.}}" +msgstr "" + +#: src/features/liveNow/utils.ts:10 msgid "{minutes, plural, one {# minute} other {# minutes}}" msgstr "" @@ -489,6 +489,26 @@ msgstr "" msgid "<0>{0} {1, plural, one {following} other {following}}" msgstr "" +#. Like count display, the <0> tags enclose the number of likes in bold (will never be 0) +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:493 +msgid "<0>{0} {1, plural, one {like} other {likes}}" +msgstr "" + +#. Quote count display, the <0> tags enclose the number of quotes in bold (will never be 0) +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:475 +msgid "<0>{0} {1, plural, one {quote} other {quotes}}" +msgstr "" + +#. Repost count display, the <0> tags enclose the number of reposts in bold (will never be 0) +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:455 +msgid "<0>{0} {1, plural, one {repost} other {reposts}}" +msgstr "" + +#. Save count display, the <0> tags enclose the number of saves in bold (will never be 0) +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:506 +msgid "<0>{0} {1, plural, one {save} other {saves}}" +msgstr "" + #: src/screens/StarterPack/Wizard/index.tsx:509 #: src/screens/StarterPack/Wizard/index.tsx:563 msgid "<0>{0} and<1> <2>{1} are included in your starter pack" @@ -519,7 +539,9 @@ msgstr "" msgid "⚠Invalid Handle" msgstr "" -#: src/components/dialogs/MutedWords.tsx:198 +#: src/components/dialogs/MutedWords.tsx:200 +#: src/components/dialogs/MutedWords.tsx:549 +#: src/components/dialogs/MutedWords.tsx:552 msgid "24 hours" msgstr "" @@ -527,11 +549,15 @@ msgstr "" msgid "2FA Confirmation" msgstr "" -#: src/components/dialogs/MutedWords.tsx:237 +#: src/components/dialogs/MutedWords.tsx:239 +#: src/components/dialogs/MutedWords.tsx:563 +#: src/components/dialogs/MutedWords.tsx:566 msgid "30 days" msgstr "" -#: src/components/dialogs/MutedWords.tsx:222 +#: src/components/dialogs/MutedWords.tsx:224 +#: src/components/dialogs/MutedWords.tsx:556 +#: src/components/dialogs/MutedWords.tsx:559 msgid "7 days" msgstr "" @@ -627,14 +653,14 @@ msgstr "" msgid "Account" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:423 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:422 #: src/screens/Messages/components/RequestButtons.tsx:91 -#: src/view/com/profile/ProfileMenu.tsx:182 +#: src/view/com/profile/ProfileMenu.tsx:181 msgctxt "toast" msgid "Account blocked" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:195 +#: src/view/com/profile/ProfileMenu.tsx:194 msgctxt "toast" msgid "Account followed" msgstr "" @@ -647,8 +673,8 @@ msgstr "" msgid "Account is deactivated" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:446 -#: src/view/com/profile/ProfileMenu.tsx:158 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:445 +#: src/view/com/profile/ProfileMenu.tsx:157 msgctxt "toast" msgid "Account muted" msgstr "" @@ -675,19 +701,19 @@ msgid "Account removed from quick access" msgstr "" #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:85 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:295 -#: src/view/com/profile/ProfileMenu.tsx:172 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:296 +#: src/view/com/profile/ProfileMenu.tsx:171 msgctxt "toast" msgid "Account unblocked" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:207 +#: src/view/com/profile/ProfileMenu.tsx:206 msgctxt "toast" msgid "Account unfollowed" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:436 -#: src/view/com/profile/ProfileMenu.tsx:148 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:435 +#: src/view/com/profile/ProfileMenu.tsx:147 msgctxt "toast" msgid "Account unmuted" msgstr "" @@ -707,7 +733,7 @@ msgid "Activity notifications" msgstr "" #: src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx:169 -#: src/components/dialogs/MutedWords.tsx:333 +#: src/components/dialogs/MutedWords.tsx:335 #: src/components/dialogs/StarterPackDialog.tsx:372 #: src/components/dialogs/StarterPackDialog.tsx:379 #: src/view/com/modals/UserAddRemoveLists.tsx:235 @@ -727,7 +753,7 @@ msgstr "" msgid "Add a content warning" msgstr "" -#: src/components/live/GoLiveDialog.tsx:106 +#: src/features/liveNow/components/GoLiveDialog.tsx:107 msgid "Add a temporary live status to your profile. When someone clicks on your avatar, they’ll see information about your live event." msgstr "" @@ -798,11 +824,11 @@ msgstr "" msgid "Add more details (optional)" msgstr "" -#: src/components/dialogs/MutedWords.tsx:326 +#: src/components/dialogs/MutedWords.tsx:328 msgid "Add mute word with chosen settings" msgstr "" -#: src/components/dialogs/MutedWords.tsx:117 +#: src/components/dialogs/MutedWords.tsx:119 msgid "Add muted words and tags" msgstr "" @@ -839,8 +865,8 @@ msgstr "" msgid "Add this feed to your feeds" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:345 -#: src/view/com/profile/ProfileMenu.tsx:348 +#: src/view/com/profile/ProfileMenu.tsx:344 +#: src/view/com/profile/ProfileMenu.tsx:347 msgid "Add to lists" msgstr "" @@ -849,8 +875,8 @@ msgid "Add to saved posts" msgstr "" #: src/components/dialogs/StarterPackDialog.tsx:182 -#: src/view/com/profile/ProfileMenu.tsx:335 -#: src/view/com/profile/ProfileMenu.tsx:338 +#: src/view/com/profile/ProfileMenu.tsx:334 +#: src/view/com/profile/ProfileMenu.tsx:337 msgid "Add to starter packs" msgstr "" @@ -929,7 +955,7 @@ msgid "Age assurance inquiry was submitted" msgstr "" #: src/ageAssurance/components/NoAccessScreen.tsx:352 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:201 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:219 msgid "Age assurance only takes a few minutes" msgstr "" @@ -1049,10 +1075,6 @@ msgstr "" msgid "Alt text describes images for blind and low-vision users, and helps give context to everyone." msgstr "" -#: src/view/com/composer/videos/SubtitleDialog.tsx:137 -msgid "Alt text must be less than {MAX_ALT_TEXT} characters." -msgstr "" - #: src/view/com/composer/GifAltText.tsx:179 #: src/view/com/composer/photos/ImageAltTextDialog.tsx:143 msgid "Alt text will be truncated. {MAX_ALT_TEXT, plural, other {Limit: {0} characters.}}" @@ -1071,7 +1093,7 @@ msgstr "" msgid "An error occurred" msgstr "" -#: src/view/com/composer/state/video.ts:399 +#: src/view/com/composer/state/video.ts:400 msgid "An error occurred while compressing the video." msgstr "" @@ -1115,8 +1137,12 @@ msgstr "" msgid "An error occurred while trying to follow all" msgstr "" -#: src/view/com/composer/state/video.ts:440 -msgid "An error occurred while uploading the video." +#: src/view/com/composer/state/video.ts:451 +msgid "An error occurred while uploading the video. {message}" +msgstr "" + +#: src/view/com/composer/state/video.ts:443 +msgid "An error occurred while uploading the video. Please check your internet connection and try again." msgstr "" #: src/components/contacts/screens/PhoneInput.tsx:119 @@ -1270,12 +1296,12 @@ msgstr "" msgid "Appeal \"{0}\" label" msgstr "" -#: src/components/live/GoLiveDisabledDialog.tsx:92 +#: src/features/liveNow/components/GoLiveDisabledDialog.tsx:92 msgid "Appeal livestream suspension" msgstr "" -#: src/components/live/GoLiveDisabledDialog.tsx:82 #: src/components/moderation/LabelsOnMeDialog.tsx:271 +#: src/features/liveNow/components/GoLiveDisabledDialog.tsx:82 #: src/screens/Messages/components/ChatDisabled.tsx:103 msgctxt "toast" msgid "Appeal submitted" @@ -1314,15 +1340,19 @@ msgstr "" msgid "Apply Pull Request" msgstr "" -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:674 +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:686 msgid "Archived from {0}" msgstr "" -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:643 -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:683 +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:655 +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:695 msgid "Archived post" msgstr "" +#: src/screens/Settings/components/DeleteAccountDialog.tsx:333 +msgid "Are you really, really sure?" +msgstr "" + #: src/screens/Settings/AppPasswords.tsx:209 msgid "Are you sure you want to delete the app password \"{0}\"?" msgstr "" @@ -1356,7 +1386,7 @@ msgstr "" msgid "Are you sure you'd like to discard this post?" msgstr "" -#: src/components/dialogs/MutedWords.tsx:438 +#: src/components/dialogs/MutedWords.tsx:450 msgid "Are you sure?" msgstr "" @@ -1372,8 +1402,8 @@ msgstr "" msgid "Artistic or non-erotic nudity." msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:558 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:560 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:557 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:559 msgid "Assign topic for algo" msgstr "" @@ -1485,25 +1515,25 @@ msgstr "" msgid "Birthday" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:821 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:195 -#: src/view/com/profile/ProfileMenu.tsx:553 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:820 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:196 +#: src/view/com/profile/ProfileMenu.tsx:552 msgid "Block" msgstr "" #: src/components/dms/ConvoMenu.tsx:261 #: src/components/dms/ConvoMenu.tsx:264 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:706 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:708 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:705 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:707 #: src/screens/Messages/components/RequestButtons.tsx:144 #: src/screens/Messages/components/RequestButtons.tsx:146 -#: src/view/com/profile/ProfileMenu.tsx:459 -#: src/view/com/profile/ProfileMenu.tsx:466 +#: src/view/com/profile/ProfileMenu.tsx:458 +#: src/view/com/profile/ProfileMenu.tsx:465 msgid "Block account" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:816 -#: src/view/com/profile/ProfileMenu.tsx:536 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:815 +#: src/view/com/profile/ProfileMenu.tsx:535 msgid "Block Account?" msgstr "" @@ -1554,8 +1584,8 @@ msgstr "" msgid "Blocked Accounts" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:818 -#: src/view/com/profile/ProfileMenu.tsx:548 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:817 +#: src/view/com/profile/ProfileMenu.tsx:547 msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you." msgstr "" @@ -1571,7 +1601,7 @@ msgstr "" msgid "Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you." msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:545 +#: src/view/com/profile/ProfileMenu.tsx:544 msgid "Blocking will not prevent labels from being applied on your account, but it will stop this account from replying in your threads or interacting with you." msgstr "" @@ -1584,7 +1614,7 @@ msgstr "" msgid "Bluesky" msgstr "" -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:699 +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:711 msgid "Bluesky cannot confirm the authenticity of the claimed date." msgstr "" @@ -1772,14 +1802,14 @@ msgstr "" #: src/components/dialogs/InAppBrowserConsent.tsx:104 #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:274 #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:282 -#: src/components/live/GoLiveDialog.tsx:246 -#: src/components/live/GoLiveDialog.tsx:252 #: src/components/Menu/index.tsx:352 #: src/components/PostControls/RepostButton.tsx:209 -#: src/components/Prompt.tsx:130 -#: src/components/Prompt.tsx:132 +#: src/components/Prompt.tsx:136 +#: src/components/Prompt.tsx:138 #: src/features/liveEvents/components/LiveEventFeedOptionsMenu.tsx:151 #: src/features/liveEvents/components/LiveEventFeedOptionsMenu.tsx:156 +#: src/features/liveNow/components/GoLiveDialog.tsx:247 +#: src/features/liveNow/components/GoLiveDialog.tsx:253 #: src/lib/media/picker.tsx:38 #: src/screens/Deactivated.tsx:149 #: src/screens/Profile/Header/EditProfileDialog.tsx:218 @@ -1802,17 +1832,6 @@ msgstr "" msgid "Cancel" msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:170 -#: src/view/com/modals/DeleteAccount.tsx:278 -msgctxt "action" -msgid "Cancel" -msgstr "" - -#: src/view/com/modals/DeleteAccount.tsx:166 -#: src/view/com/modals/DeleteAccount.tsx:274 -msgid "Cancel account deletion" -msgstr "" - #: src/components/PostControls/RepostButton.tsx:204 msgid "Cancel quote post" msgstr "" @@ -1832,7 +1851,7 @@ msgstr "" msgid "Cannot interact with a blocked user" msgstr "" -#: src/view/com/composer/videos/SubtitleDialog.tsx:152 +#: src/view/com/composer/videos/SubtitleDialog.tsx:155 msgid "Captions (.vtt)" msgstr "" @@ -1966,6 +1985,10 @@ msgstr "" msgid "Chats" msgstr "" +#: src/screens/Settings/components/DeleteAccountDialog.tsx:235 +msgid "Check <0>{currentEmail} for an email with the confirmation code to enter below:" +msgstr "" + #: src/screens/SignupQueued.tsx:78 #: src/screens/SignupQueued.tsx:82 msgid "Check my status" @@ -1975,10 +1998,6 @@ msgstr "" msgid "Check your email for a sign in code and enter it here." msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:213 -msgid "Check your inbox for an email with the confirmation code to enter below:" -msgstr "" - #: src/components/moderation/ReportDialog/utils/useReportOptions.ts:161 msgid "Child safety" msgstr "" @@ -2114,8 +2133,6 @@ msgstr "" #: src/components/dms/AfterReportDialog.tsx:208 #: src/components/dms/AfterReportDialog.tsx:213 #: src/components/dms/EmojiPopup.android.tsx:58 -#: src/components/live/EditLiveDialog.tsx:215 -#: src/components/live/EditLiveDialog.tsx:221 #: src/components/NewskieDialog.tsx:167 #: src/components/NewskieDialog.tsx:173 #: src/components/Post/Embed/VideoEmbed/GifPresentationControls.tsx:106 @@ -2126,6 +2143,8 @@ msgstr "" #: src/components/verification/VerifierDialog.tsx:145 #: src/components/WhoCanReply.tsx:235 #: src/components/WhoCanReply.tsx:242 +#: src/features/liveNow/components/EditLiveDialog.tsx:216 +#: src/features/liveNow/components/EditLiveDialog.tsx:222 #: src/screens/Settings/components/ChangePasswordDialog.tsx:287 #: src/screens/Settings/components/ChangePasswordDialog.tsx:292 #: src/view/com/composer/select-language/PostLanguageSelectDialog.tsx:335 @@ -2176,7 +2195,7 @@ msgid "Close image" msgstr "" #: src/view/com/lightbox/Lightbox.web.tsx:66 -#: src/view/com/lightbox/Lightbox.web.tsx:219 +#: src/view/com/lightbox/Lightbox.web.tsx:256 msgid "Close image viewer" msgstr "" @@ -2283,8 +2302,8 @@ msgstr "" msgid "Configured in <0>moderation settings." msgstr "" -#: src/components/Prompt.tsx:171 -#: src/components/Prompt.tsx:174 +#: src/components/Prompt.tsx:195 +#: src/components/Prompt.tsx:198 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:185 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:188 msgid "Confirm" @@ -2294,25 +2313,20 @@ msgstr "" msgid "Confirm content language settings" msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:264 -msgid "Confirm delete account" -msgstr "" - #: src/ageAssurance/components/NoAccessScreen.tsx:366 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:97 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:115 #: src/components/dialogs/DeviceLocationRequestDialog.tsx:40 #: src/components/dialogs/DeviceLocationRequestDialog.tsx:105 msgid "Confirm your location" msgstr "" -#: src/components/dialogs/EmailDialog/components/TokenField.tsx:36 +#: src/components/dialogs/EmailDialog/components/TokenField.tsx:38 #: src/screens/Login/LoginForm.tsx:283 #: src/screens/Settings/components/ChangePasswordDialog.tsx:186 #: src/screens/Settings/components/ChangePasswordDialog.tsx:190 +#: src/screens/Settings/components/DeleteAccountDialog.tsx:246 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:144 #: src/screens/Settings/components/DisableEmail2FADialog.tsx:150 -#: src/view/com/modals/DeleteAccount.tsx:220 -#: src/view/com/modals/DeleteAccount.tsx:226 msgid "Confirmation code" msgstr "" @@ -2327,11 +2341,15 @@ msgid "Connection issue" msgstr "" #: src/ageAssurance/components/NoAccessScreen.tsx:303 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:140 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:158 #: src/components/ageAssurance/AgeAssuranceAppealDialog.tsx:30 msgid "Contact our moderation team" msgstr "" +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:99 +msgid "Contact our support team" +msgstr "" + #: src/components/ageAssurance/AgeAssuranceInitDialog.tsx:155 #: src/screens/Signup/index.tsx:233 #: src/screens/Signup/index.tsx:236 @@ -2482,8 +2500,8 @@ msgstr "" msgid "Copy App Password" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:496 -#: src/view/com/profile/ProfileMenu.tsx:499 +#: src/view/com/profile/ProfileMenu.tsx:495 +#: src/view/com/profile/ProfileMenu.tsx:498 msgid "Copy at:// URI" msgstr "" @@ -2498,8 +2516,8 @@ msgid "Copy code" msgstr "" #: src/screens/Settings/components/ChangeHandleDialog.tsx:502 -#: src/view/com/profile/ProfileMenu.tsx:505 -#: src/view/com/profile/ProfileMenu.tsx:508 +#: src/view/com/profile/ProfileMenu.tsx:504 +#: src/view/com/profile/ProfileMenu.tsx:507 msgid "Copy DID" msgstr "" @@ -2528,8 +2546,8 @@ msgstr "" msgid "Copy link to post" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:270 -#: src/view/com/profile/ProfileMenu.tsx:281 +#: src/view/com/profile/ProfileMenu.tsx:269 +#: src/view/com/profile/ProfileMenu.tsx:280 msgid "Copy link to profile" msgstr "" @@ -2547,8 +2565,8 @@ msgstr "" msgid "Copy post at:// URI" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:513 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:515 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:512 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:514 msgid "Copy post text" msgstr "" @@ -2809,7 +2827,7 @@ msgid "Default icons" msgstr "" #: src/components/dms/MessageContextMenu.tsx:199 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:765 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:764 #: src/screens/Messages/components/ChatStatusInfo.tsx:55 #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:274 #: src/screens/Settings/AppPasswords.tsx:212 @@ -2824,8 +2842,9 @@ msgstr "" msgid "Delete account" msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:101 -msgid "Delete Account <0>\"<1>{0}<2>\"" +#: src/screens/Settings/components/DeleteAccountDialog.tsx:185 +#: src/screens/Settings/components/DeleteAccountDialog.tsx:232 +msgid "Delete account “{currentHandle}”" msgstr "" #: src/screens/Settings/AppPasswords.tsx:186 @@ -2877,12 +2896,12 @@ msgstr "" msgid "Delete message for me" msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:267 +#: src/screens/Settings/components/DeleteAccountDialog.tsx:315 msgid "Delete my account" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:746 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:748 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:745 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:747 #: src/view/com/composer/Composer.tsx:1429 msgid "Delete post" msgstr "" @@ -2900,7 +2919,7 @@ msgstr "" msgid "Delete this list?" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:760 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:759 msgid "Delete this post?" msgstr "" @@ -2935,12 +2954,12 @@ msgstr "" msgid "Descriptive alt text" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:650 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:660 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:649 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:659 msgid "Detach quote" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:796 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:795 msgid "Detach quote post?" msgstr "" @@ -3104,7 +3123,7 @@ msgstr "" msgid "DNS Panel" msgstr "" -#: src/components/dialogs/MutedWords.tsx:307 +#: src/components/dialogs/MutedWords.tsx:309 msgid "Do not apply this mute word to users you follow" msgstr "" @@ -3120,6 +3139,10 @@ msgstr "" msgid "Don't have a code or need a new one? <0>Click here." msgstr "" +#: src/screens/Settings/components/DeleteAccountDialog.tsx:273 +msgid "Don’t see a code? <0>Click here to resend." +msgstr "" + #: src/components/dialogs/EmailDialog/components/ResendEmailText.tsx:37 msgid "Don't see an email? <0>Click here to resend." msgstr "" @@ -3129,7 +3152,7 @@ msgstr "" msgid "Don't show again" msgstr "" -#: src/components/ageAssurance/useAgeAssuranceCopy.ts:17 +#: src/components/ageAssurance/useAgeAssuranceCopy.ts:26 msgid "Don't worry! All existing messages and settings are saved and will be available after you verify you're an adult." msgstr "" @@ -3152,8 +3175,8 @@ msgstr "" #: src/view/com/composer/labels/LabelsBtn.tsx:222 #: src/view/com/composer/labels/LabelsBtn.tsx:229 #: src/view/com/composer/select-language/PostLanguageSelectDialog.tsx:303 -#: src/view/com/composer/videos/SubtitleDialog.tsx:188 -#: src/view/com/composer/videos/SubtitleDialog.tsx:199 +#: src/view/com/composer/videos/SubtitleDialog.tsx:191 +#: src/view/com/composer/videos/SubtitleDialog.tsx:202 msgid "Done" msgstr "" @@ -3203,11 +3226,11 @@ msgstr "" msgid "Drop to add images" msgstr "" -#: src/components/ageAssurance/useAgeAssuranceCopy.ts:11 +#: src/components/ageAssurance/useAgeAssuranceCopy.ts:20 msgid "Due to laws in your region, certain features on Bluesky are currently restricted until you're able to verify you're an adult." msgstr "" -#: src/components/dialogs/MutedWords.tsx:158 +#: src/components/dialogs/MutedWords.tsx:160 msgid "Duration:" msgstr "" @@ -3276,8 +3299,8 @@ msgstr "" msgid "Edit image" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:727 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:740 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:726 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:739 msgid "Edit interaction settings" msgstr "" @@ -3291,8 +3314,8 @@ msgstr "" msgid "Edit list details" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:359 -#: src/view/com/profile/ProfileMenu.tsx:379 +#: src/view/com/profile/ProfileMenu.tsx:358 +#: src/view/com/profile/ProfileMenu.tsx:378 msgid "Edit live status" msgstr "" @@ -3321,12 +3344,12 @@ msgstr "" #: src/screens/Profile/Header/EditProfileDialog.tsx:268 #: src/screens/Profile/Header/EditProfileDialog.tsx:274 #: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:295 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:329 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:330 msgid "Edit profile" msgstr "" #: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:298 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:331 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:332 msgid "Edit Profile" msgstr "" @@ -3380,6 +3403,10 @@ msgstr "" msgid "Email sent!" msgstr "" +#: src/screens/Settings/components/DeleteAccountDialog.tsx:262 +msgid "Email sent! <0>Click here to resend." +msgstr "" + #: src/components/dialogs/EmailDialog/screens/Verify.tsx:182 msgid "Email verification complete!" msgstr "" @@ -3476,7 +3503,7 @@ msgstr "" msgid "End of feed" msgstr "" -#: src/view/com/composer/videos/SubtitleDialog.tsx:178 +#: src/view/com/composer/videos/SubtitleDialog.tsx:181 msgid "Ensure you have selected a language for each subtitle file." msgstr "" @@ -3488,8 +3515,8 @@ msgstr "" msgid "Enter a password" msgstr "" -#: src/components/dialogs/MutedWords.tsx:132 -#: src/components/dialogs/MutedWords.tsx:133 +#: src/components/dialogs/MutedWords.tsx:134 +#: src/components/dialogs/MutedWords.tsx:135 msgid "Enter a word or tag" msgstr "" @@ -3529,6 +3556,7 @@ msgid "Enter your email address" msgstr "" #: src/screens/Login/LoginForm.tsx:242 +#: src/screens/Settings/components/DeleteAccountDialog.tsx:297 msgid "Enter your password" msgstr "" @@ -3597,11 +3625,11 @@ msgstr "" msgid "Everything else" msgstr "" -#: src/components/dialogs/MutedWords.tsx:316 +#: src/components/dialogs/MutedWords.tsx:318 msgid "Exclude users you follow" msgstr "" -#: src/components/dialogs/MutedWords.tsx:521 +#: src/components/dialogs/MutedWords.tsx:603 msgid "Excludes users you follow" msgstr "" @@ -3609,11 +3637,7 @@ msgstr "" msgid "Exit fullscreen" msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:275 -msgid "Exits account deletion process" -msgstr "" - -#: src/view/com/lightbox/Lightbox.web.tsx:192 +#: src/view/com/lightbox/Lightbox.web.tsx:224 msgid "Expand alt text" msgstr "" @@ -3641,11 +3665,11 @@ msgstr "" msgid "Experimental" msgstr "" -#: src/components/dialogs/MutedWords.tsx:507 +#: src/components/dialogs/MutedWords.tsx:518 msgid "Expired" msgstr "" -#: src/components/dialogs/MutedWords.tsx:509 +#: src/components/dialogs/MutedWords.tsx:587 msgid "Expires {0}" msgstr "" @@ -3654,7 +3678,7 @@ msgstr "" msgid "Expires in {0}" msgstr "" -#: src/components/live/EditLiveDialog.tsx:130 +#: src/features/liveNow/components/EditLiveDialog.tsx:131 msgid "Expires in {0} at {1}" msgstr "" @@ -3895,8 +3919,8 @@ msgstr "" msgid "Failed to send email, please try again." msgstr "" -#: src/components/live/GoLiveDisabledDialog.tsx:76 #: src/components/moderation/LabelsOnMeDialog.tsx:265 +#: src/features/liveNow/components/GoLiveDisabledDialog.tsx:76 #: src/screens/Messages/components/ChatDisabled.tsx:99 msgid "Failed to submit appeal, please try again." msgstr "" @@ -4146,7 +4170,7 @@ msgstr "" #: src/components/ProfileHoverCard/index.web.tsx:497 #: src/components/ProfileHoverCard/index.web.tsx:508 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:152 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:386 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:387 #: src/screens/VideoFeed/index.tsx:874 #: src/view/com/notifications/NotificationFeedItem.tsx:841 #: src/view/com/notifications/NotificationFeedItem.tsx:848 @@ -4154,7 +4178,7 @@ msgid "Follow" msgstr "" #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:139 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:374 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:375 msgid "Follow {0}" msgstr "" @@ -4174,8 +4198,8 @@ msgstr "" msgid "Follow 7 accounts" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:313 -#: src/view/com/profile/ProfileMenu.tsx:324 +#: src/view/com/profile/ProfileMenu.tsx:312 +#: src/view/com/profile/ProfileMenu.tsx:323 msgid "Follow account" msgstr "" @@ -4198,7 +4222,7 @@ msgstr "" #. User is not following this account, click to follow back #: src/components/ProfileCard.tsx:553 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:150 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:384 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:385 #: src/view/com/notifications/NotificationFeedItem.tsx:841 #: src/view/com/notifications/NotificationFeedItem.tsx:848 msgid "Follow back" @@ -4243,7 +4267,7 @@ msgstr "" #: src/components/ProfileHoverCard/index.web.tsx:496 #: src/components/ProfileHoverCard/index.web.tsx:507 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:155 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:382 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:383 #: src/screens/VideoFeed/index.tsx:872 #: src/view/com/notifications/NotificationFeedItem.tsx:819 #: src/view/com/notifications/NotificationFeedItem.tsx:836 @@ -4257,7 +4281,7 @@ msgid "Following" msgstr "" #: src/components/ProfileCard.tsx:509 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:249 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:250 #: src/view/com/notifications/NotificationFeedItem.tsx:772 msgid "Following {0}" msgstr "" @@ -4300,8 +4324,8 @@ msgstr "" msgid "For organizational accounts, use the birthdate of the person who is responsible for the account." msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:125 -msgid "For security reasons, we'll need to send a confirmation code to your email address." +#: src/screens/Settings/components/DeleteAccountDialog.tsx:188 +msgid "For security reasons, we’ll need to send a confirmation code to your email address <0>{currentEmail}." msgstr "" #: src/screens/Settings/components/AddAppPasswordDialog.tsx:208 @@ -4317,7 +4341,9 @@ msgstr "" msgid "For You" msgstr "" -#: src/components/dialogs/MutedWords.tsx:183 +#: src/components/dialogs/MutedWords.tsx:185 +#: src/components/dialogs/MutedWords.tsx:570 +#: src/components/dialogs/MutedWords.tsx:573 msgid "Forever" msgstr "" @@ -4510,24 +4536,24 @@ msgstr "" msgid "Go Home" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:360 -#: src/view/com/profile/ProfileMenu.tsx:381 +#: src/view/com/profile/ProfileMenu.tsx:359 +#: src/view/com/profile/ProfileMenu.tsx:380 msgid "Go live" msgstr "" -#: src/components/live/GoLiveDialog.tsx:98 -#: src/components/live/GoLiveDialog.tsx:103 -#: src/components/live/GoLiveDialog.tsx:231 -#: src/components/live/GoLiveDialog.tsx:240 +#: src/features/liveNow/components/GoLiveDialog.tsx:99 +#: src/features/liveNow/components/GoLiveDialog.tsx:104 +#: src/features/liveNow/components/GoLiveDialog.tsx:232 +#: src/features/liveNow/components/GoLiveDialog.tsx:241 msgid "Go Live" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:357 -#: src/view/com/profile/ProfileMenu.tsx:377 +#: src/view/com/profile/ProfileMenu.tsx:356 +#: src/view/com/profile/ProfileMenu.tsx:376 msgid "Go live (disabled)" msgstr "" -#: src/components/live/GoLiveDialog.tsx:173 +#: src/features/liveNow/components/GoLiveDialog.tsx:174 msgid "Go live for" msgstr "" @@ -4564,7 +4590,7 @@ msgstr "" msgid "Go to user's profile" msgstr "" -#: src/components/live/GoLiveDisabledDialog.tsx:104 +#: src/features/liveNow/components/GoLiveDisabledDialog.tsx:104 msgid "Going live is currently disabled for your account" msgstr "" @@ -4712,7 +4738,7 @@ msgstr "" #: src/components/moderation/ContentHider.tsx:219 #: src/components/moderation/LabelPreference.tsx:140 #: src/components/moderation/PostHider.tsx:139 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:776 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:775 #: src/lib/moderation/useLabelBehaviorDescription.ts:18 #: src/lib/moderation/useLabelBehaviorDescription.ts:23 #: src/lib/moderation/useLabelBehaviorDescription.ts:28 @@ -4739,18 +4765,18 @@ msgstr "" msgid "Hide lists" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:607 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:613 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:606 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:612 msgid "Hide post for me" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:624 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:634 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:623 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:633 msgid "Hide reply for everyone" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:606 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:612 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:605 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:611 msgid "Hide reply for me" msgstr "" @@ -4763,12 +4789,12 @@ msgstr "" msgid "Hide this event" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:771 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:770 msgid "Hide this post?" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:771 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:806 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:770 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:805 msgid "Hide this reply?" msgstr "" @@ -4896,10 +4922,14 @@ msgstr "" msgid "I'm on Bluesky as {0} - come find me! https://bsky.app/download" msgstr "" -#: src/view/com/lightbox/Lightbox.web.tsx:194 +#: src/view/com/lightbox/Lightbox.web.tsx:226 msgid "If alt text is long, toggles alt text expanded state" msgstr "" +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:93 +msgid "If you are 18 years of age or older and want to try again, click the button below and use a different verification method if one is available in your region. If you have questions or concerns, <0>our support team can help." +msgstr "" + #: src/screens/Signup/StepInfo/index.tsx:349 msgid "If you are not yet an adult according to the laws of your country, your parent or legal guardian must read these Terms on your behalf." msgstr "" @@ -4928,7 +4958,7 @@ msgstr "" msgid "If you need to update your email, <0>click here." msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:762 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:761 msgid "If you remove this post, you won't be able to recover it." msgstr "" @@ -4957,6 +4987,10 @@ msgstr "" msgid "Image" msgstr "" +#: src/view/com/lightbox/Lightbox.web.tsx:242 +msgid "Image {0} of {1}" +msgstr "" + #: src/screens/Settings/AboutSettings.tsx:62 msgid "Image cache cleared" msgstr "" @@ -4971,6 +5005,10 @@ msgstr "" msgid "Image saved" msgstr "" +#: src/view/com/lightbox/Lightbox.web.tsx:75 +msgid "Image viewer" +msgstr "" + #: src/lib/media/save-image.ts:51 msgid "Images cannot be saved unless permission is granted to access your photo library." msgstr "" @@ -5045,18 +5083,10 @@ msgstr "" msgid "Input code sent to your email for password reset" msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:228 -msgid "Input confirmation code for account deletion" -msgstr "" - #: src/screens/Login/SetNewPasswordForm.tsx:160 msgid "Input new password" msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:247 -msgid "Input password for account deletion" -msgstr "" - #: src/screens/Login/LoginForm.tsx:298 msgid "Input the code which has been emailed to you" msgstr "" @@ -5094,7 +5124,7 @@ msgstr "" msgid "Invalid handle. Please try a different one." msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:395 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:394 msgctxt "toast" msgid "Invalid interaction settings." msgstr "" @@ -5150,7 +5180,7 @@ msgid "Invites, but personal" msgstr "" #: src/ageAssurance/components/NoAccessScreen.tsx:363 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:94 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:112 msgid "Is your location not accurate? <0>Tap here to confirm your location." msgstr "" @@ -5252,12 +5282,12 @@ msgid "Larger" msgstr "" #: src/ageAssurance/components/NoAccessScreen.tsx:346 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:195 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:213 msgid "Last initiated {timeAgo} ago" msgstr "" #: src/ageAssurance/components/NoAccessScreen.tsx:344 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:193 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:211 msgid "Last initiated just now" msgstr "" @@ -5304,6 +5334,10 @@ msgstr "" msgid "Learn more about self hosting your PDS." msgstr "" +#: src/screens/Settings/components/DeleteAccountDialog.tsx:343 +msgid "Learn more about the AT Protocol." +msgstr "" + #: src/components/moderation/ContentHider.tsx:168 #: src/components/moderation/ContentHider.tsx:234 msgid "Learn more about the moderation applied to this content" @@ -5470,7 +5504,7 @@ msgstr "" msgid "Likes of your reposts notifications" msgstr "" -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:485 +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:489 msgid "Likes on this post" msgstr "" @@ -5577,7 +5611,7 @@ msgid "Lists blocking this user:" msgstr "" #. Live status indicator on avatar. Should be extremely short, not much space for more than 4 characters -#: src/components/live/LiveIndicator.tsx:46 +#: src/features/liveNow/components/LiveIndicator.tsx:46 msgid "LIVE" msgstr "" @@ -5604,14 +5638,14 @@ msgstr "" msgid "Live events appear occasionally when something exciting is happening. If you'd like, you can hide this particular event, or all events for this placement in your app interface." msgstr "" -#: src/components/live/LiveStatusDialog.tsx:228 +#: src/features/liveNow/components/LiveStatusDialog.tsx:228 msgid "Live feature is in beta" msgstr "" -#: src/components/live/EditLiveDialog.tsx:147 -#: src/components/live/EditLiveDialog.tsx:151 -#: src/components/live/GoLiveDialog.tsx:129 -#: src/components/live/GoLiveDialog.tsx:133 +#: src/features/liveNow/components/EditLiveDialog.tsx:148 +#: src/features/liveNow/components/EditLiveDialog.tsx:152 +#: src/features/liveNow/components/GoLiveDialog.tsx:130 +#: src/features/liveNow/components/GoLiveDialog.tsx:134 msgid "Live link" msgstr "" @@ -5709,7 +5743,7 @@ msgstr "" msgid "Manage verification settings" msgstr "" -#: src/components/dialogs/MutedWords.tsx:108 +#: src/components/dialogs/MutedWords.tsx:110 msgid "Manage your muted words and tags" msgstr "" @@ -5902,8 +5936,8 @@ msgstr "" #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:143 #: src/view/com/composer/drafts/DraftItem.tsx:190 -#: src/view/com/profile/ProfileMenu.tsx:242 -#: src/view/com/profile/ProfileMenu.tsx:249 +#: src/view/com/profile/ProfileMenu.tsx:241 +#: src/view/com/profile/ProfileMenu.tsx:248 msgid "More options" msgstr "" @@ -5934,10 +5968,10 @@ msgstr "" msgid "Mute {tag}" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:689 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:695 -#: src/view/com/profile/ProfileMenu.tsx:438 -#: src/view/com/profile/ProfileMenu.tsx:445 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:688 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:694 +#: src/view/com/profile/ProfileMenu.tsx:437 +#: src/view/com/profile/ProfileMenu.tsx:444 msgid "Mute account" msgstr "" @@ -5951,7 +5985,7 @@ msgstr "" msgid "Mute conversation" msgstr "" -#: src/components/dialogs/MutedWords.tsx:258 +#: src/components/dialogs/MutedWords.tsx:260 msgid "Mute in:" msgstr "" @@ -5963,37 +5997,37 @@ msgstr "" msgid "Mute these accounts?" msgstr "" -#: src/components/dialogs/MutedWords.tsx:190 +#: src/components/dialogs/MutedWords.tsx:192 msgid "Mute this word for 24 hours" msgstr "" -#: src/components/dialogs/MutedWords.tsx:229 +#: src/components/dialogs/MutedWords.tsx:231 msgid "Mute this word for 30 days" msgstr "" -#: src/components/dialogs/MutedWords.tsx:214 +#: src/components/dialogs/MutedWords.tsx:216 msgid "Mute this word for 7 days" msgstr "" -#: src/components/dialogs/MutedWords.tsx:263 +#: src/components/dialogs/MutedWords.tsx:265 msgid "Mute this word in post text and tags" msgstr "" -#: src/components/dialogs/MutedWords.tsx:279 +#: src/components/dialogs/MutedWords.tsx:281 msgid "Mute this word in tags only" msgstr "" -#: src/components/dialogs/MutedWords.tsx:175 +#: src/components/dialogs/MutedWords.tsx:177 msgid "Mute this word until you unmute it" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:573 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:577 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:572 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:576 msgid "Mute thread" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:587 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:589 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:586 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:588 msgid "Mute words & tags" msgstr "" @@ -6068,7 +6102,7 @@ msgid "Nevermind, create a handle for me" msgstr "" #: src/screens/Search/modules/ExploreTrendingTopics.tsx:183 -#: src/view/com/profile/ProfileMenu.tsx:393 +#: src/view/com/profile/ProfileMenu.tsx:392 msgid "New" msgstr "" @@ -6199,7 +6233,7 @@ msgstr "" msgid "Next" msgstr "" -#: src/view/com/lightbox/Lightbox.web.tsx:179 +#: src/view/com/lightbox/Lightbox.web.tsx:211 msgid "Next image" msgstr "" @@ -6232,7 +6266,7 @@ msgstr "" msgid "No drafts yet" msgstr "" -#: src/components/live/EditLiveDialog.tsx:139 +#: src/features/liveNow/components/EditLiveDialog.tsx:140 msgid "No expiry set" msgstr "" @@ -6248,7 +6282,7 @@ msgstr "" msgid "No followers yet" msgstr "" -#: src/components/live/LinkPreview.tsx:63 +#: src/features/liveNow/components/LinkPreview.tsx:63 msgid "No image" msgstr "" @@ -6263,7 +6297,7 @@ msgid "No lists" msgstr "" #: src/components/ProfileCard.tsx:531 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:274 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:275 #: src/view/com/notifications/NotificationFeedItem.tsx:792 msgid "No longer following {0}" msgstr "" @@ -6425,7 +6459,7 @@ msgstr "" msgid "Not ready to hit post? Keep your best ideas in Drafts until the timing is just right." msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:560 +#: src/view/com/profile/ProfileMenu.tsx:559 msgid "Note about sharing" msgstr "" @@ -6525,7 +6559,7 @@ msgid "OK" msgstr "" #: src/screens/Login/PasswordUpdatedForm.tsx:36 -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:705 +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:717 msgid "Okay" msgstr "" @@ -6670,8 +6704,8 @@ msgstr "" msgid "Open post options menu" msgstr "" -#: src/components/live/LiveStatusDialog.tsx:202 -#: src/components/live/LiveStatusDialog.tsx:212 +#: src/features/liveNow/components/LiveStatusDialog.tsx:202 +#: src/features/liveNow/components/LiveStatusDialog.tsx:212 msgid "Open profile" msgstr "" @@ -6792,7 +6826,7 @@ msgstr "" msgid "Opens this profile" msgstr "" -#: src/components/dialogs/MutedWords.tsx:304 +#: src/components/dialogs/MutedWords.tsx:306 msgid "Options:" msgstr "" @@ -6884,9 +6918,8 @@ msgstr "" #: src/screens/Login/LoginForm.tsx:227 #: src/screens/Settings/AccountSettings.tsx:121 #: src/screens/Settings/AccountSettings.tsx:125 +#: src/screens/Settings/components/DeleteAccountDialog.tsx:290 #: src/screens/Signup/StepInfo/index.tsx:258 -#: src/view/com/modals/DeleteAccount.tsx:239 -#: src/view/com/modals/DeleteAccount.tsx:246 msgid "Password" msgstr "" @@ -6998,8 +7031,8 @@ msgstr "" msgid "Pin to Home" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:481 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:488 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:480 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:487 msgid "Pin to your profile" msgstr "" @@ -7083,6 +7116,10 @@ msgstr "" msgid "Please complete the verification captcha." msgstr "" +#: src/view/com/composer/state/video.ts:437 +msgid "Please confirm your email address to upload videos." +msgstr "" + #: src/components/ageAssurance/AgeAssuranceInitDialog.tsx:101 #: src/screens/Signup/StepInfo/index.tsx:142 msgid "Please double-check that you have entered your email address correctly." @@ -7111,7 +7148,7 @@ msgstr "" msgid "Please enter a valid email address." msgstr "" -#: src/components/dialogs/MutedWords.tsx:86 +#: src/components/dialogs/MutedWords.tsx:88 msgid "Please enter a valid word, tag, or phrase to mute" msgstr "" @@ -7148,10 +7185,6 @@ msgstr "" msgid "Please enter your password" msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:235 -msgid "Please enter your password as well:" -msgstr "" - #: src/screens/Login/LoginForm.tsx:89 msgid "Please enter your username" msgstr "" @@ -7164,7 +7197,7 @@ msgstr "" msgid "Please explain why you think your chats were incorrectly disabled" msgstr "" -#: src/components/live/GoLiveDisabledDialog.tsx:123 +#: src/features/liveNow/components/GoLiveDisabledDialog.tsx:123 msgid "Please explain why you think your Go Live access was incorrectly disabled." msgstr "" @@ -7323,7 +7356,7 @@ msgstr "" msgid "Posts" msgstr "" -#: src/components/dialogs/MutedWords.tsx:120 +#: src/components/dialogs/MutedWords.tsx:122 msgid "Posts can be muted based on their text, their tags, or both. We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." msgstr "" @@ -7366,7 +7399,7 @@ msgstr "" msgid "Preview" msgstr "" -#: src/view/com/lightbox/Lightbox.web.tsx:158 +#: src/view/com/lightbox/Lightbox.web.tsx:190 msgid "Previous image" msgstr "" @@ -7542,7 +7575,7 @@ msgstr "" msgid "Quotes" msgstr "" -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:469 +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:471 msgid "Quotes of this post" msgstr "" @@ -7554,8 +7587,8 @@ msgstr "" msgid "Rate limit exceeded. Please try again later." msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:649 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:659 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:648 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:658 msgid "Re-attach quote" msgstr "" @@ -7663,7 +7696,7 @@ msgid "Reload conversations" msgstr "" #: src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx:171 -#: src/components/dialogs/MutedWords.tsx:443 +#: src/components/dialogs/MutedWords.tsx:455 #: src/components/dialogs/StarterPackDialog.tsx:372 #: src/components/dialogs/StarterPackDialog.tsx:379 #: src/components/FeedCard.tsx:375 @@ -7752,12 +7785,12 @@ msgstr "" msgid "Remove image" msgstr "" -#: src/components/live/EditLiveDialog.tsx:226 -#: src/components/live/EditLiveDialog.tsx:233 +#: src/features/liveNow/components/EditLiveDialog.tsx:227 +#: src/features/liveNow/components/EditLiveDialog.tsx:234 msgid "Remove live status" msgstr "" -#: src/components/dialogs/MutedWords.tsx:530 +#: src/components/dialogs/MutedWords.tsx:611 msgid "Remove mute word from your list" msgstr "" @@ -7770,7 +7803,7 @@ msgstr "" msgid "Remove repost" msgstr "" -#: src/view/com/composer/videos/SubtitleDialog.tsx:282 +#: src/view/com/composer/videos/SubtitleDialog.tsx:285 msgid "Remove subtitle file" msgstr "" @@ -7789,8 +7822,8 @@ msgstr "" #: src/components/verification/VerificationRemovePrompt.tsx:46 #: src/components/verification/VerificationsDialog.tsx:249 -#: src/view/com/profile/ProfileMenu.tsx:411 -#: src/view/com/profile/ProfileMenu.tsx:414 +#: src/view/com/profile/ProfileMenu.tsx:410 +#: src/view/com/profile/ProfileMenu.tsx:413 msgid "Remove verification" msgstr "" @@ -7834,6 +7867,18 @@ msgstr "" msgid "Removed verification" msgstr "" +#: src/components/dialogs/MutedWords.tsx:539 +msgid "Renew" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:545 +msgid "Renew duration" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:529 +msgid "Renew mute word" +msgstr "" + #: src/view/com/posts/FeedShutdownMsg.tsx:129 #: src/view/com/posts/FeedShutdownMsg.tsx:133 msgid "Replace with Discover" @@ -7921,12 +7966,12 @@ msgstr "" #: src/components/dms/MessageContextMenu.tsx:165 #: src/components/dms/MessagesListBlockedFooter.tsx:85 #: src/components/dms/MessagesListBlockedFooter.tsx:92 -#: src/components/live/LiveStatusDialog.tsx:250 +#: src/features/liveNow/components/LiveStatusDialog.tsx:250 msgid "Report" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:478 -#: src/view/com/profile/ProfileMenu.tsx:481 +#: src/view/com/profile/ProfileMenu.tsx:477 +#: src/view/com/profile/ProfileMenu.tsx:480 msgid "Report account" msgstr "" @@ -7957,8 +8002,8 @@ msgstr "" msgid "Report message" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:715 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:717 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:714 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:716 msgid "Report post" msgstr "" @@ -7984,8 +8029,8 @@ msgstr "" msgid "Report this list" msgstr "" -#: src/components/live/LiveStatusDialog.tsx:233 #: src/components/moderation/ReportDialog/copy.ts:19 +#: src/features/liveNow/components/LiveStatusDialog.tsx:233 msgid "Report this livestream" msgstr "" @@ -8086,6 +8131,8 @@ msgid "Required in your region" msgstr "" #: src/components/dialogs/EmailDialog/components/ResendEmailText.tsx:40 +#: src/screens/Settings/components/DeleteAccountDialog.tsx:265 +#: src/screens/Settings/components/DeleteAccountDialog.tsx:276 msgid "Resend" msgstr "" @@ -8204,9 +8251,9 @@ msgstr "" #: src/components/dialogs/lists/CreateOrEditListDialog.tsx:307 #: src/components/dialogs/PostInteractionSettingsDialog.tsx:665 #: src/components/dialogs/PostInteractionSettingsDialog.tsx:670 -#: src/components/live/EditLiveDialog.tsx:202 -#: src/components/live/EditLiveDialog.tsx:209 #: src/components/StarterPack/QrCodeDialog.tsx:206 +#: src/features/liveNow/components/EditLiveDialog.tsx:203 +#: src/features/liveNow/components/EditLiveDialog.tsx:210 #: src/screens/Profile/Header/EditProfileDialog.tsx:236 #: src/screens/Profile/Header/EditProfileDialog.tsx:250 #: src/screens/SavedFeeds.tsx:120 @@ -8402,8 +8449,8 @@ msgstr "" msgid "Search my posts" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:292 -#: src/view/com/profile/ProfileMenu.tsx:295 +#: src/view/com/profile/ProfileMenu.tsx:291 +#: src/view/com/profile/ProfileMenu.tsx:294 msgid "Search posts" msgstr "" @@ -8529,7 +8576,7 @@ msgstr "" msgid "Select content languages" msgstr "" -#: src/components/live/GoLiveDialog.tsx:178 +#: src/features/liveNow/components/GoLiveDialog.tsx:179 msgid "Select duration" msgstr "" @@ -8553,7 +8600,7 @@ msgstr "" msgid "Select GIF \"{0}\"" msgstr "" -#: src/components/dialogs/MutedWords.tsx:147 +#: src/components/dialogs/MutedWords.tsx:149 msgid "Select how long to mute this word for." msgstr "" @@ -8563,7 +8610,7 @@ msgstr "" msgid "Select language" msgstr "" -#: src/view/com/composer/videos/SubtitleDialog.tsx:269 +#: src/view/com/composer/videos/SubtitleDialog.tsx:272 msgid "Select language..." msgstr "" @@ -8601,7 +8648,7 @@ msgstr "" msgid "Select up to 3 languages used in this post" msgstr "" -#: src/components/dialogs/MutedWords.tsx:247 +#: src/components/dialogs/MutedWords.tsx:249 msgid "Select what content this mute word should apply to." msgstr "" @@ -8650,15 +8697,10 @@ msgstr "" #: src/components/dialogs/EmailDialog/screens/Manage2FA/Disable.tsx:174 #: src/components/dialogs/EmailDialog/screens/Manage2FA/Disable.tsx:181 #: src/components/dialogs/EmailDialog/screens/Verify.tsx:302 -#: src/view/com/modals/DeleteAccount.tsx:145 +#: src/screens/Settings/components/DeleteAccountDialog.tsx:201 msgid "Send email" msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:158 -msgctxt "action" -msgid "Send Email" -msgstr "" - #: src/view/shell/Drawer.tsx:363 msgid "Send feedback" msgstr "" @@ -8697,10 +8739,6 @@ msgstr "" msgid "Send via direct message" msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:147 -msgid "Sends email with confirmation code for account deletion" -msgstr "" - #: src/components/contacts/screens/PhoneInput.tsx:282 msgid "Sent to our phone number verification provider Plivo" msgstr "" @@ -8821,7 +8859,7 @@ msgstr "" msgid "Share a fun fact!" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:565 +#: src/view/com/profile/ProfileMenu.tsx:564 msgid "Share anyway" msgstr "" @@ -8869,8 +8907,8 @@ msgstr "" #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:165 #: src/screens/StarterPack/StarterPackScreen.tsx:621 #: src/screens/StarterPack/StarterPackScreen.tsx:629 -#: src/view/com/profile/ProfileMenu.tsx:270 -#: src/view/com/profile/ProfileMenu.tsx:283 +#: src/view/com/profile/ProfileMenu.tsx:269 +#: src/view/com/profile/ProfileMenu.tsx:282 msgid "Share via..." msgstr "" @@ -8917,8 +8955,8 @@ msgstr "" msgid "Show customization options" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:544 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:546 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:543 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:545 msgid "Show less like this" msgstr "" @@ -8939,8 +8977,8 @@ msgstr "" msgid "Show More" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:536 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:538 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:535 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:537 msgid "Show more like this" msgstr "" @@ -8966,8 +9004,8 @@ msgstr "" msgid "Show replies as" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:623 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:633 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:622 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:632 msgid "Show reply for everyone" msgstr "" @@ -8994,7 +9032,7 @@ msgstr "" msgid "Show when you’re live" msgstr "" -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:645 +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:657 msgid "Shows information about when this post was created" msgstr "" @@ -9056,8 +9094,8 @@ msgstr "" msgid "Sign in to Bluesky or create a new account" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:522 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:524 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:521 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:523 msgid "Sign in to view post" msgstr "" @@ -9200,8 +9238,8 @@ msgstr "" msgid "Sorry, we're unable to load account suggestions at this time." msgstr "" -#: src/App.native.tsx:137 -#: src/App.web.tsx:113 +#: src/App.native.tsx:142 +#: src/App.web.tsx:118 msgid "Sorry! Your session expired. Please sign in again." msgstr "" @@ -9326,10 +9364,10 @@ msgstr "" #: src/components/ageAssurance/AgeAssuranceAppealDialog.tsx:119 #: src/components/ageAssurance/AgeAssuranceAppealDialog.tsx:125 -#: src/components/live/GoLiveDisabledDialog.tsx:138 -#: src/components/live/GoLiveDisabledDialog.tsx:139 #: src/components/moderation/LabelsOnMeDialog.tsx:342 #: src/components/moderation/LabelsOnMeDialog.tsx:343 +#: src/features/liveNow/components/GoLiveDisabledDialog.tsx:138 +#: src/features/liveNow/components/GoLiveDisabledDialog.tsx:139 #: src/screens/Messages/components/ChatDisabled.tsx:154 #: src/screens/Messages/components/ChatDisabled.tsx:155 msgid "Submit" @@ -9453,7 +9491,7 @@ msgstr "" msgid "System log" msgstr "" -#: src/components/dialogs/MutedWords.tsx:287 +#: src/components/dialogs/MutedWords.tsx:289 msgid "Tags only" msgstr "" @@ -9536,12 +9574,12 @@ msgstr "" msgid "Terms of Service" msgstr "" -#: src/components/dialogs/MutedWords.tsx:271 +#: src/components/dialogs/MutedWords.tsx:273 msgid "Text & tags" msgstr "" -#: src/components/live/GoLiveDisabledDialog.tsx:121 #: src/components/moderation/LabelsOnMeDialog.tsx:306 +#: src/features/liveNow/components/GoLiveDisabledDialog.tsx:121 #: src/screens/Messages/components/ChatDisabled.tsx:120 msgid "Text input field" msgstr "" @@ -9555,7 +9593,7 @@ msgid "Thanks, you have successfully verified your email address. You can close msgstr "" #: src/ageAssurance/components/NoAccessScreen.tsx:392 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:123 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:141 msgid "Thanks! You're all set." msgstr "" @@ -9584,9 +9622,9 @@ msgstr "" msgid "That's everything!" msgstr "" -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:191 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:399 -#: src/view/com/profile/ProfileMenu.tsx:541 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:192 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:400 +#: src/view/com/profile/ProfileMenu.tsx:540 msgid "The account will be able to interact with you after unblocking." msgstr "" @@ -9640,7 +9678,7 @@ msgstr "" msgid "The following labels were applied to your content." msgstr "" -#: src/components/live/GoLiveDialog.tsx:160 +#: src/features/liveNow/components/GoLiveDialog.tsx:161 msgid "The following services are enabled for your account: {allowedServices}" msgstr "" @@ -9648,8 +9686,8 @@ msgstr "" msgid "The following settings will be used as your defaults when creating new posts. You can edit these for a specific post from the composer." msgstr "" -#: src/components/ageAssurance/useAgeAssuranceCopy.ts:14 -msgid "The laws in your location require you to verify you're an adult to access certain features. Tap to learn more." +#: src/components/ageAssurance/useAgeAssuranceCopy.ts:23 +msgid "The laws in your region require you to verify you're an adult to access certain features. Tap to learn more." msgstr "" #: src/view/com/composer/select-language/SuggestedLanguage.tsx:119 @@ -9660,7 +9698,7 @@ msgstr "" msgid "The Privacy Policy has been moved to <0/>" msgstr "" -#: src/view/com/composer/state/video.ts:395 +#: src/view/com/composer/state/video.ts:396 #: src/view/com/composer/state/video.ts:434 msgid "The selected video is larger than 100 MB. Please try again with a smaller file." msgstr "" @@ -9733,7 +9771,7 @@ msgid "There was an issue fetching notifications. Tap here to try again." msgstr "" #: src/screens/Search/Explore.tsx:988 -#: src/view/com/posts/PostFeed.tsx:757 +#: src/view/com/posts/PostFeed.tsx:758 msgid "There was an issue fetching posts. Tap here to try again." msgstr "" @@ -9764,21 +9802,21 @@ msgstr "" msgid "There was an issue updating your feeds, please check your internet connection and try again." msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:427 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:440 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:450 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:426 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:439 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:449 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:116 #: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:127 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:89 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:258 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:284 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:299 -#: src/view/com/profile/ProfileMenu.tsx:152 -#: src/view/com/profile/ProfileMenu.tsx:162 -#: src/view/com/profile/ProfileMenu.tsx:176 -#: src/view/com/profile/ProfileMenu.tsx:186 -#: src/view/com/profile/ProfileMenu.tsx:199 -#: src/view/com/profile/ProfileMenu.tsx:211 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:259 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:285 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:300 +#: src/view/com/profile/ProfileMenu.tsx:151 +#: src/view/com/profile/ProfileMenu.tsx:161 +#: src/view/com/profile/ProfileMenu.tsx:175 +#: src/view/com/profile/ProfileMenu.tsx:185 +#: src/view/com/profile/ProfileMenu.tsx:198 +#: src/view/com/profile/ProfileMenu.tsx:210 msgid "There was an issue! {0}" msgstr "" @@ -9841,7 +9879,7 @@ msgstr "" msgid "This appeal will be sent to <0>{sourceName}." msgstr "" -#: src/components/live/GoLiveDisabledDialog.tsx:113 +#: src/features/liveNow/components/GoLiveDisabledDialog.tsx:113 #: src/screens/Messages/components/ChatDisabled.tsx:116 msgid "This appeal will be sent to Bluesky's moderation service." msgstr "" @@ -9946,8 +9984,8 @@ msgstr "" msgid "This is an empty state" msgstr "" -#: src/components/live/EditLiveDialog.tsx:176 -#: src/components/live/GoLiveDialog.tsx:153 +#: src/features/liveNow/components/EditLiveDialog.tsx:177 +#: src/features/liveNow/components/GoLiveDialog.tsx:154 msgid "This is not a valid link" msgstr "" @@ -9983,7 +10021,7 @@ msgstr "" msgid "This moderation service is unavailable. See below for more details. If this issue persists, contact us." msgstr "" -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:686 +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:698 msgid "This post claims to have been created on <0>{0}, but was first seen by Bluesky on <1>{1}." msgstr "" @@ -9999,7 +10037,7 @@ msgstr "" msgid "This post was deleted by its author" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:773 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:772 msgid "This post will be hidden from feeds and threads. This cannot be undone." msgstr "" @@ -10007,11 +10045,11 @@ msgstr "" msgid "This post's author has disabled quote posts." msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:562 +#: src/view/com/profile/ProfileMenu.tsx:561 msgid "This profile is only visible to logged-in users. It won't be visible to people who aren't signed in." msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:808 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:807 msgid "This reply will be sorted into a hidden section at the bottom of your thread and will mute notifications for subsequent replies - both for yourself and others." msgstr "" @@ -10019,7 +10057,7 @@ msgstr "" msgid "This service has not provided terms of service or a privacy policy." msgstr "" -#: src/components/live/queries.ts:40 +#: src/features/liveNow/index.tsx:182 msgid "This service is not supported while the Live feature is in beta. Allowed services: {formatted}." msgstr "" @@ -10068,15 +10106,19 @@ msgstr "" msgid "This user isn't following anyone." msgstr "" -#: src/components/dialogs/MutedWords.tsx:440 +#: src/components/dialogs/MutedWords.tsx:452 msgid "This will delete \"{0}\" from your muted words. You can always add it back later." msgstr "" +#: src/screens/Settings/components/DeleteAccountDialog.tsx:336 +msgid "This will irreversibly delete your Bluesky account <0>{currentHandle} and all associated data. Note that this will affect any other <1>AT Protocol services you use with this account." +msgstr "" + #: src/screens/Settings/Settings.tsx:676 msgid "This will remove @{0} from the quick access list." msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:798 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:797 msgid "This will remove your post from this quote post for all users, and replace it with a placeholder." msgstr "" @@ -10171,10 +10213,10 @@ msgstr "" #: src/components/dms/MessageContextMenu.tsx:136 #: src/components/dms/MessageContextMenu.tsx:138 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:505 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:507 -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:607 -#: src/screens/PostThread/components/ThreadItemAnchor.tsx:610 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:504 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:506 +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:619 +#: src/screens/PostThread/components/ThreadItemAnchor.tsx:622 msgid "Translate" msgstr "" @@ -10279,30 +10321,30 @@ msgstr "" #: src/components/dms/MessagesListBlockedFooter.tsx:104 #: src/components/dms/MessagesListBlockedFooter.tsx:112 #: src/components/dms/MessagesListBlockedFooter.tsx:119 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:195 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:342 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:402 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:196 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:343 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:403 #: src/screens/ProfileList/components/Header.tsx:165 #: src/screens/ProfileList/components/Header.tsx:172 -#: src/view/com/profile/ProfileMenu.tsx:553 +#: src/view/com/profile/ProfileMenu.tsx:552 msgid "Unblock" msgstr "" -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:346 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:347 msgctxt "action" msgid "Unblock" msgstr "" #: src/components/dms/ConvoMenu.tsx:261 #: src/components/dms/ConvoMenu.tsx:264 -#: src/view/com/profile/ProfileMenu.tsx:458 -#: src/view/com/profile/ProfileMenu.tsx:464 +#: src/view/com/profile/ProfileMenu.tsx:457 +#: src/view/com/profile/ProfileMenu.tsx:463 msgid "Unblock account" msgstr "" -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:189 -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:397 -#: src/view/com/profile/ProfileMenu.tsx:535 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:190 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:398 +#: src/view/com/profile/ProfileMenu.tsx:534 msgid "Unblock Account?" msgstr "" @@ -10337,12 +10379,12 @@ msgstr "" msgid "Undo repost ({0, plural, one {# repost} other {# reposts}})" msgstr "" -#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:373 +#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:374 msgid "Unfollow {0}" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:312 -#: src/view/com/profile/ProfileMenu.tsx:322 +#: src/view/com/profile/ProfileMenu.tsx:311 +#: src/view/com/profile/ProfileMenu.tsx:321 msgid "Unfollow account" msgstr "" @@ -10399,10 +10441,10 @@ msgstr "" msgid "Unmute {tag}" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:688 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:694 -#: src/view/com/profile/ProfileMenu.tsx:437 -#: src/view/com/profile/ProfileMenu.tsx:443 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:687 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:693 +#: src/view/com/profile/ProfileMenu.tsx:436 +#: src/view/com/profile/ProfileMenu.tsx:442 msgid "Unmute account" msgstr "" @@ -10415,8 +10457,8 @@ msgstr "" msgid "Unmute list" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:573 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:577 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:572 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:576 msgid "Unmute thread" msgstr "" @@ -10444,8 +10486,8 @@ msgstr "" msgid "Unpin from home" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:480 -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:487 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:479 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:486 msgid "Unpin from profile" msgstr "" @@ -10522,7 +10564,7 @@ msgctxt "toast" msgid "Updating quote attachment failed" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:400 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:399 msgctxt "toast" msgid "Updating reply visibility failed" msgstr "" @@ -10714,13 +10756,13 @@ msgstr "" #: src/components/verification/VerificationCreatePrompt.tsx:84 #: src/components/verification/VerificationCreatePrompt.tsx:86 -#: src/view/com/profile/ProfileMenu.tsx:421 -#: src/view/com/profile/ProfileMenu.tsx:424 +#: src/view/com/profile/ProfileMenu.tsx:420 +#: src/view/com/profile/ProfileMenu.tsx:423 msgid "Verify account" msgstr "" #: src/ageAssurance/components/NoAccessScreen.tsx:329 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:178 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:196 msgid "Verify again" msgstr "" @@ -10748,8 +10790,8 @@ msgstr "" #: src/ageAssurance/components/NoAccessScreen.tsx:317 #: src/ageAssurance/components/NoAccessScreen.tsx:331 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:166 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:180 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:184 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:198 msgid "Verify now" msgstr "" @@ -10801,7 +10843,7 @@ msgstr "" msgid "Video" msgstr "" -#: src/view/com/composer/state/video.ts:357 +#: src/view/com/composer/state/video.ts:358 msgid "Video failed to process" msgstr "" @@ -11013,8 +11055,8 @@ msgstr "" msgid "Warn content and filter from feeds" msgstr "" -#: src/components/live/LiveStatusDialog.tsx:173 -#: src/components/live/LiveStatusDialog.tsx:182 +#: src/features/liveNow/components/LiveStatusDialog.tsx:173 +#: src/features/liveNow/components/LiveStatusDialog.tsx:182 msgid "Watch now" msgstr "" @@ -11154,7 +11196,7 @@ msgid "We're so excited to have you join us!" msgstr "" #: src/ageAssurance/components/NoAccessScreen.tsx:385 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:116 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:134 msgid "We're sorry, but based on your device's location, you are currently located in a region that requires age assurance." msgstr "" @@ -11162,7 +11204,7 @@ msgstr "" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "" -#: src/components/dialogs/MutedWords.tsx:383 +#: src/components/dialogs/MutedWords.tsx:385 msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." msgstr "" @@ -11171,6 +11213,10 @@ msgstr "" msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "" +#: src/components/ageAssurance/AgeRestrictedScreen.tsx:61 +msgid "We're sorry, you cannot access this screen at this time." +msgstr "" + #: src/view/com/composer/Composer.tsx:884 msgid "We're sorry! The post you are replying to has been deleted." msgstr "" @@ -11334,8 +11380,8 @@ msgstr "" msgid "Wrong DID returned from server. Received: {0}" msgstr "" -#: src/components/live/EditLiveDialog.tsx:152 -#: src/components/live/GoLiveDialog.tsx:134 +#: src/features/liveNow/components/EditLiveDialog.tsx:153 +#: src/features/liveNow/components/GoLiveDialog.tsx:135 msgid "www.mylivestream.tv" msgstr "" @@ -11348,15 +11394,19 @@ msgstr "" msgid "Yes, deactivate" msgstr "" +#: src/screens/Settings/components/DeleteAccountDialog.tsx:355 +msgid "Yes, delete my account" +msgstr "" + #: src/screens/StarterPack/StarterPackScreen.tsx:695 msgid "Yes, delete this starter pack" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:801 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:800 msgid "Yes, detach" msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:811 +#: src/components/PostControls/PostMenu/PostMenuItems.tsx:810 msgid "Yes, hide" msgstr "" @@ -11380,12 +11430,12 @@ msgstr "" msgid "You are creating an account on" msgstr "" -#: src/components/live/GoLiveDisabledDialog.tsx:107 +#: src/features/liveNow/components/GoLiveDisabledDialog.tsx:107 msgid "You are currently blocked from using the Go Live feature. To appeal this moderation decision, please submit the form below." msgstr "" #: src/ageAssurance/components/NoAccessScreen.tsx:299 -#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:136 +#: src/components/ageAssurance/AgeAssuranceAccountCard.tsx:154 msgid "You are currently unable to access Bluesky's Age Assurance flow. Please <0>contact our moderation team if you believe this is an error." msgstr "" @@ -11393,12 +11443,12 @@ msgstr "" msgid "You are in line." msgstr "" -#: src/components/live/EditLiveDialog.tsx:118 -#: src/components/live/EditLiveDialog.tsx:123 +#: src/features/liveNow/components/EditLiveDialog.tsx:119 +#: src/features/liveNow/components/EditLiveDialog.tsx:124 msgid "You are Live" msgstr "" -#: src/components/live/queries.ts:208 +#: src/features/liveNow/index.tsx:350 msgid "You are no longer live" msgstr "" @@ -11410,7 +11460,7 @@ msgstr "" msgid "You are not following anyone yet" msgstr "" -#: src/components/live/queries.ts:152 +#: src/features/liveNow/index.tsx:294 msgid "You are now live!" msgstr "" @@ -11430,15 +11480,15 @@ msgstr "" msgid "You can adjust your interests at any time from \"Content and media\" settings." msgstr "" +#: src/screens/Settings/components/DeleteAccountDialog.tsx:213 +msgid "You can also <0>temporarily deactivate your account instead. Your profile, posts, feeds, and lists will no longer be visible to other Bluesky users. You can reactivate your account at any time by logging in." +msgstr "" + #: src/view/com/posts/FollowingEmptyState.tsx:63 #: src/view/com/posts/FollowingEndOfFeed.tsx:64 msgid "You can also discover new Custom Feeds to follow." msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:198 -msgid "You can also temporarily deactivate your account instead, and reactivate it at any time." -msgstr "" - #: src/components/contacts/screens/GetContacts.tsx:249 msgid "You can always opt out and delete your data" msgstr "" @@ -11451,11 +11501,6 @@ msgstr "" msgid "You can continue ongoing conversations regardless of which setting you choose." msgstr "" -#: src/components/PostControls/PostMenu/PostMenuItems.tsx:387 -msgctxt "toast" -msgid "You can hide a maximum of {MAX_HIDDEN_REPLIES} replies." -msgstr "" - #: src/components/dialogs/nuxs/ActivitySubscriptions.tsx:148 msgid "You can now choose to be notified when specific people post. If there’s someone you want timely updates from, go to their profile and find the new bell icon near the follow button." msgstr "" @@ -11535,6 +11580,10 @@ msgstr "" msgid "You have blocked this user. You cannot view their content." msgstr "" +#: src/components/ageAssurance/useAgeAssuranceCopy.ts:17 +msgid "You have completed the Age Assurance process, but based on the results, we cannot be sure that you are 18 years of age or older. Due to laws in your region, certain features on Bluesky must remain restricted until you're able to verify you're an adult." +msgstr "" + #: src/view/screens/Notifications.tsx:297 msgid "You have completely disabled reply, quote, and mention notifications, so this tab will no longer update. To adjust this, visit your <0>notification settings." msgstr "" @@ -11614,7 +11663,7 @@ msgstr "" msgid "You haven't made any custom feeds yet." msgstr "" -#: src/components/dialogs/MutedWords.tsx:403 +#: src/components/dialogs/MutedWords.tsx:405 msgid "You haven't muted any words or tags yet" msgstr "" @@ -11651,14 +11700,6 @@ msgstr "" msgid "You may only add up to 3 feeds" msgstr "" -#: src/screens/Signup/StepInfo/index.tsx:320 -msgid "You must be {0} years of age or older to create an account in your region." -msgstr "" - -#: src/screens/Signup/StepInfo/index.tsx:315 -msgid "You must be {MIN_ACCESS_AGE} years of age or older to create an account." -msgstr "" - #: src/components/dialogs/BirthDateSettings.tsx:178 msgid "You must be at least 13 years old to use Bluesky. Read our <0>Terms of Service for more information." msgstr "" @@ -11667,10 +11708,6 @@ msgstr "" msgid "You must be following at least seven other people to generate a starter pack." msgstr "" -#: src/components/ageAssurance/AgeRestrictedScreen.tsx:61 -msgid "You must complete age assurance in order to access this screen." -msgstr "" - #: src/components/StarterPack/QrCodeDialog.tsx:67 msgid "You must grant access to your photo library to save a QR code" msgstr "" @@ -11827,8 +11864,8 @@ msgstr "" msgid "Your account" msgstr "" -#: src/view/com/modals/DeleteAccount.tsx:84 -msgid "Your account has been deleted" +#: src/screens/Settings/components/DeleteAccountDialog.tsx:130 +msgid "Your account has been deleted, see ya! ✌️" msgstr "" #: src/screens/Takendown.tsx:141 @@ -11949,7 +11986,7 @@ msgstr "" msgid "Your location has been updated." msgstr "" -#: src/components/dialogs/MutedWords.tsx:374 +#: src/components/dialogs/MutedWords.tsx:376 msgid "Your muted words" msgstr ""