, // temp_isStatusValid asserts this
- expiresAt: shadowed.status.expiresAt!, // isStatusStillActive asserts this
- record: shadowed.status.record,
- } satisfies AppBskyActorDefs.StatusView
- } else {
- return {
- status: '',
- isDisabled: false,
- isActive: false,
- record: {},
- } satisfies AppBskyActorDefs.StatusView
- }
- }, [shadowed, config, tick])
-}
-
-export function isStatusStillActive(timeStr: string | undefined) {
- if (!timeStr) return false
- const now = new Date()
- const expiry = parseISO(timeStr)
-
- return isAfter(expiry, now)
-}
-
-/**
- * Validates whether the live status is valid for display in the app. Does NOT
- * validate if the status is valid for the acting user e.g. as they go live.
- */
-export function isStatusValidForViewers(
- status: AppBskyActorDefs.StatusView,
- config: LiveNowConfig,
-) {
- if (status.status !== 'app.bsky.actor.status#live') return false
- if (!status.uri) return false // should not happen, just backwards compat
- try {
- const {host: liveDid} = new AtUri(status.uri)
- if (AppBskyEmbedExternal.isView(status.embed)) {
- const url = new URL(status.embed.external.uri)
- const exception = config.allowedHostsExceptionsByDid.get(liveDid)
- const isValidException = exception ? exception.has(url.hostname) : false
- const isValidForAnyone = config.defaultAllowedHosts.has(url.hostname)
- return isValidException || isValidForAnyone
- } else {
- return false
- }
- } catch {
- return false
- }
-}
diff --git a/src/lib/async/retry.ts b/src/lib/async/retry.ts
index 8a1729091d..479a1cdc12 100644
--- a/src/lib/async/retry.ts
+++ b/src/lib/async/retry.ts
@@ -29,6 +29,7 @@ export async function retry(
export async function networkRetry
(
retries: number,
fn: () => Promise
,
+ delay?: number,
): Promise
{
- return retry(retries, isNetworkError, fn)
+ return retry(retries, isNetworkError, fn, delay)
}
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/lib/hooks/useDebouncedValue.ts b/src/lib/hooks/useDebouncedValue.ts
new file mode 100644
index 0000000000..c8e083b9b3
--- /dev/null
+++ b/src/lib/hooks/useDebouncedValue.ts
@@ -0,0 +1,16 @@
+import {useEffect, useState} from 'react'
+
+/**
+ * Returns a debounced version of the input value that only updates after the
+ * specified delay has passed without any changes to the input value.
+ */
+export function useDebouncedValue(val: T, delayMs: number): T {
+ const [prev, setPrev] = useState(val)
+
+ useEffect(() => {
+ const timeout = setTimeout(() => setPrev(val), delayMs)
+ return () => clearTimeout(timeout)
+ }, [val, delayMs])
+
+ return prev
+}
diff --git a/src/lib/hooks/useEnableKeyboardController.tsx b/src/lib/hooks/useEnableKeyboardController.tsx
deleted file mode 100644
index d55929d0fb..0000000000
--- a/src/lib/hooks/useEnableKeyboardController.tsx
+++ /dev/null
@@ -1,107 +0,0 @@
-import {
- createContext,
- useCallback,
- useContext,
- useEffect,
- useMemo,
- useRef,
-} from 'react'
-import {
- KeyboardProvider,
- useKeyboardController,
-} from 'react-native-keyboard-controller'
-import {useFocusEffect} from '@react-navigation/native'
-
-const KeyboardControllerRefCountContext = createContext<{
- incrementRefCount: () => void
- decrementRefCount: () => void
-}>({
- incrementRefCount: () => {},
- decrementRefCount: () => {},
-})
-KeyboardControllerRefCountContext.displayName =
- 'KeyboardControllerRefCountContext'
-
-export function KeyboardControllerProvider({
- children,
-}: {
- children: React.ReactNode
-}) {
- return (
-
-
- {children}
-
-
- )
-}
-
-function KeyboardControllerProviderInner({
- children,
-}: {
- children: React.ReactNode
-}) {
- const {setEnabled} = useKeyboardController()
- const refCount = useRef(0)
-
- const value = useMemo(
- () => ({
- incrementRefCount: () => {
- refCount.current++
- setEnabled(refCount.current > 0)
- },
- decrementRefCount: () => {
- refCount.current--
- setEnabled(refCount.current > 0)
-
- if (__DEV__ && refCount.current < 0) {
- console.error('KeyboardController ref count < 0')
- }
- },
- }),
- [setEnabled],
- )
-
- return (
-
- {children}
-
- )
-}
-
-export function useEnableKeyboardController(shouldEnable: boolean) {
- const {incrementRefCount, decrementRefCount} = useContext(
- KeyboardControllerRefCountContext,
- )
-
- useEffect(() => {
- if (!shouldEnable) {
- return
- }
- incrementRefCount()
- return () => {
- decrementRefCount()
- }
- }, [shouldEnable, incrementRefCount, decrementRefCount])
-}
-
-/**
- * Like `useEnableKeyboardController`, but using `useFocusEffect`
- */
-export function useEnableKeyboardControllerScreen(shouldEnable: boolean) {
- const {incrementRefCount, decrementRefCount} = useContext(
- KeyboardControllerRefCountContext,
- )
-
- useFocusEffect(
- useCallback(() => {
- if (!shouldEnable) {
- return
- }
- incrementRefCount()
- return () => {
- decrementRefCount()
- }
- }, [shouldEnable, incrementRefCount, decrementRefCount]),
- )
-}
diff --git a/src/lib/strings/embed-player.ts b/src/lib/strings/embed-player.ts
index 951c3318f4..bf396b27ac 100644
--- a/src/lib/strings/embed-player.ts
+++ b/src/lib/strings/embed-player.ts
@@ -24,6 +24,7 @@ export const embedPlayerSources = [
'giphy',
'tenor',
'flickr',
+ 'bandcamp',
] as const
export type EmbedPlayerSource = (typeof embedPlayerSources)[number]
@@ -44,6 +45,8 @@ export type EmbedPlayerType =
| 'giphy_gif'
| 'tenor_gif'
| 'flickr_album'
+ | 'bandcamp_album'
+ | 'bandcamp_track'
export const externalEmbedLabels: Record = {
youtube: 'YouTube',
@@ -56,6 +59,7 @@ export const externalEmbedLabels: Record = {
appleMusic: 'Apple Music',
soundcloud: 'SoundCloud',
flickr: 'Flickr',
+ bandcamp: 'Bandcamp',
}
export interface EmbedPlayerParams {
@@ -459,6 +463,32 @@ export function parseEmbedPlayerFromUrl(
return undefined
}
}
+
+ const bandcampRegex = /^[a-z\d][a-z\d-]{2,}[a-z\d]\.bandcamp\.com$/i
+
+ if (bandcampRegex.test(urlp.hostname)) {
+ const pathComponents = urlp.pathname.split('/')
+ switch (pathComponents[1]) {
+ case 'album':
+ return {
+ type: 'bandcamp_album',
+ source: 'bandcamp',
+ playerUri: `https://bandcamp.com/EmbeddedPlayer/url=${encodeURIComponent(
+ urlp.href,
+ )}/size=large/bgcol=ffffff/linkcol=0687f5/minimal=true/transparent=true/`,
+ }
+ case 'track':
+ return {
+ type: 'bandcamp_track',
+ source: 'bandcamp',
+ playerUri: `https://bandcamp.com/EmbeddedPlayer/url=${encodeURIComponent(
+ urlp.href,
+ )}/size=large/bgcol=ffffff/linkcol=0687f5/minimal=true/transparent=true/`,
+ }
+ default:
+ return undefined
+ }
+ }
}
export function getPlayerAspect({
@@ -498,6 +528,9 @@ export function getPlayerAspect({
return {height: 165}
case 'apple_music_song':
return {height: 150}
+ case 'bandcamp_album':
+ case 'bandcamp_track':
+ return {aspectRatio: 1}
default:
return {aspectRatio: 16 / 9}
}
diff --git a/src/lib/strings/errors.ts b/src/lib/strings/errors.ts
index a706597144..4a5c9f09a9 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)
}
@@ -42,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/locale/locales/en/messages.po b/src/locale/locales/en/messages.po
index 79669e400e..eb8baf16bd 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:143
msgid "{0, plural, one {1 more post} other {# more posts}}"
msgstr ""
@@ -103,39 +103,23 @@ 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 ""
-
-#: 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:496
-msgid "{0, plural, other {# people have}} used this starter pack!"
+#: src/screens/StarterPack/StarterPackScreen.tsx:499
+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 ""
+#: 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}"
@@ -146,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>tags1>0>"
msgstr ""
#. Pattern: {wordValue} in text, tags
-#: src/components/dialogs/MutedWords.tsx:470
+#: src/components/dialogs/MutedWords.tsx:482
msgid "{0} <0>in <1>text & tags1>0>"
msgstr ""
@@ -159,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 ""
@@ -242,7 +226,7 @@ msgid "{DISPLAY_NAME_MAX_GRAPHEMES, plural, other {Display name is too long. The
msgstr ""
#: src/lib/generate-starterpack.ts:104
-#: src/screens/StarterPack/Wizard/index.tsx:202
+#: src/screens/StarterPack/Wizard/index.tsx:199
msgid "{displayName}'s Starter Pack"
msgstr ""
@@ -414,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 ""
@@ -427,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 ""
@@ -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 ""
@@ -475,12 +471,12 @@ msgstr ""
msgid "+{computedTotal}"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:525
+#: src/screens/StarterPack/Wizard/index.tsx:522
msgctxt "profiles"
msgid "<0>{0}, 0><1>{1}, 1>and {2, plural, one {# other} other {# others}} are included in your starter pack"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:578
+#: src/screens/StarterPack/Wizard/index.tsx:575
msgctxt "feeds"
msgid "<0>{0}, 0><1>{1}, 1>and {2, plural, one {# other} other {# others}} are included in your starter pack"
msgstr ""
@@ -493,12 +489,32 @@ msgstr ""
msgid "<0>{0}0> {1, plural, one {following} other {following}}"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:512
-#: src/screens/StarterPack/Wizard/index.tsx:566
+#. 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}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}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}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}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}0> and<1> 1><2>{1} 2>are included in your starter pack"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:559
+#: src/screens/StarterPack/Wizard/index.tsx:556
msgid "<0>{0}0> is included in your starter pack"
msgstr ""
@@ -515,7 +531,7 @@ msgstr ""
msgid "<0>Sign in0><1> or 1><2>create an account2><3> 3><4>to search for news, sports, politics, and everything else happening on Bluesky.4>"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:503
+#: src/screens/StarterPack/Wizard/index.tsx:500
msgid "<0>You0> and<1> 1><2>{0} 2>are included in your starter pack"
msgstr ""
@@ -523,19 +539,25 @@ 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 ""
-#: src/screens/Login/LoginForm.tsx:278
+#: src/screens/Login/LoginForm.tsx:277
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 ""
@@ -581,7 +603,7 @@ msgstr ""
#. 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.
#: src/components/dialogs/nuxs/DraftsAnnouncement.tsx:97
-msgid "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???\"."
+msgid "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!!!\"."
msgstr ""
#: src/Navigation.tsx:535
@@ -624,27 +646,35 @@ 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
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 ""
-#: src/components/PostControls/PostMenu/PostMenuItems.tsx:446
-#: src/view/com/profile/ProfileMenu.tsx:158
+#: 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:445
+#: src/view/com/profile/ProfileMenu.tsx:157
msgctxt "toast"
msgid "Account muted"
msgstr ""
@@ -670,20 +700,20 @@ msgstr ""
msgid "Account removed from quick access"
msgstr ""
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:84
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:290
-#: src/view/com/profile/ProfileMenu.tsx:172
+#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:85
+#: 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 ""
@@ -703,14 +733,14 @@ msgid "Activity notifications"
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/MutedWords.tsx:335
+#: src/components/dialogs/StarterPackDialog.tsx:372
+#: src/components/dialogs/StarterPackDialog.tsx:379
#: src/view/com/modals/UserAddRemoveLists.tsx:235
msgid "Add"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:614
+#: src/screens/StarterPack/Wizard/index.tsx:611
msgid "Add {0} more to continue"
msgstr ""
@@ -723,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 ""
@@ -742,8 +772,8 @@ msgstr ""
#: src/view/com/composer/GifAltText.tsx:211
#: src/view/com/composer/photos/Gallery.tsx:170
#: src/view/com/composer/photos/Gallery.tsx:217
-#: src/view/com/composer/photos/ImageAltTextDialog.tsx:88
#: src/view/com/composer/photos/ImageAltTextDialog.tsx:93
+#: src/view/com/composer/photos/ImageAltTextDialog.tsx:98
msgid "Add alt text"
msgstr ""
@@ -758,11 +788,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:1976
msgid "Add another post to thread"
msgstr ""
@@ -794,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 ""
@@ -819,7 +849,7 @@ msgstr ""
msgid "Add recommended feeds"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:547
+#: src/screens/StarterPack/Wizard/index.tsx:544
msgid "Add some feeds to your starter pack!"
msgstr ""
@@ -835,8 +865,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:344
+#: src/view/com/profile/ProfileMenu.tsx:347
msgid "Add to lists"
msgstr ""
@@ -844,7 +874,7 @@ msgstr ""
msgid "Add to saved posts"
msgstr ""
-#: src/components/dialogs/StarterPackDialog.tsx:176
+#: src/components/dialogs/StarterPackDialog.tsx:182
#: src/view/com/profile/ProfileMenu.tsx:334
#: src/view/com/profile/ProfileMenu.tsx:337
msgid "Add to starter packs"
@@ -863,7 +893,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 ""
@@ -925,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 ""
@@ -939,8 +969,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 ""
@@ -1007,7 +1037,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?"
@@ -1017,11 +1047,11 @@ 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 ""
-#: 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"
@@ -1029,7 +1059,7 @@ msgstr ""
#: src/screens/Settings/AccessibilitySettings.tsx:54
#: src/view/com/composer/GifAltText.tsx:154
-#: src/view/com/composer/photos/ImageAltTextDialog.tsx:117
+#: src/view/com/composer/photos/ImageAltTextDialog.tsx:122
#: src/view/com/composer/videos/SubtitleDialog.tsx:40
#: src/view/com/composer/videos/SubtitleDialog.tsx:58
#: src/view/com/composer/videos/SubtitleDialog.tsx:109
@@ -1037,7 +1067,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 ""
@@ -1045,12 +1075,8 @@ 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:138
+#: src/view/com/composer/photos/ImageAltTextDialog.tsx:143
msgid "Alt text will be truncated. {MAX_ALT_TEXT, plural, other {Limit: {0} characters.}}"
msgstr ""
@@ -1067,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 ""
@@ -1088,7 +1114,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 ""
@@ -1105,14 +1131,18 @@ 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 ""
-#: 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
@@ -1266,23 +1296,23 @@ 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"
msgstr ""
-#: src/screens/Takendown.tsx:114
-#: src/screens/Takendown.tsx:142
+#: src/screens/Takendown.tsx:113
+#: src/screens/Takendown.tsx:139
msgid "Appeal suspension"
msgstr ""
-#: src/screens/Takendown.tsx:117
+#: src/screens/Takendown.tsx:116
msgid "Appeal Suspension"
msgstr ""
@@ -1310,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 ""
@@ -1327,7 +1361,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 ""
@@ -1348,11 +1382,11 @@ 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 ""
-#: src/components/dialogs/MutedWords.tsx:438
+#: src/components/dialogs/MutedWords.tsx:450
msgid "Are you sure?"
msgstr ""
@@ -1368,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 ""
@@ -1394,23 +1428,23 @@ 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
#: src/screens/Settings/components/ChangePasswordDialog.tsx:272
#: src/screens/Settings/components/ChangePasswordDialog.tsx:281
#: src/screens/Signup/BackNextButtons.tsx:41
-#: src/screens/StarterPack/Wizard/index.tsx:324
-#: src/view/com/composer/drafts/DraftsListDialog.tsx:80
+#: src/screens/StarterPack/Wizard/index.tsx:321
#: src/view/com/composer/drafts/DraftsListDialog.tsx:86
+#: src/view/com/composer/drafts/DraftsListDialog.tsx:92
msgid "Back"
msgstr ""
@@ -1435,7 +1469,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
@@ -1453,7 +1487,7 @@ msgstr ""
#: src/components/dms/dialogs/NewChatDialog.tsx:55
#: src/components/dms/MessageProfileButton.tsx:59
#: src/screens/Messages/ChatList.tsx:371
-#: src/screens/Messages/Conversation.tsx:228
+#: src/screens/Messages/Conversation.tsx:225
msgid "Before you can message another user, you must first verify your email."
msgstr ""
@@ -1481,25 +1515,25 @@ msgstr ""
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/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:457
-#: src/view/com/profile/ProfileMenu.tsx:464
+#: 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:534
+#: src/components/PostControls/PostMenu/PostMenuItems.tsx:815
+#: src/view/com/profile/ProfileMenu.tsx:535
msgid "Block Account?"
msgstr ""
@@ -1550,8 +1584,8 @@ msgstr ""
msgid "Blocked Accounts"
msgstr ""
-#: src/components/PostControls/PostMenu/PostMenuItems.tsx:818
-#: src/view/com/profile/ProfileMenu.tsx:546
+#: 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 ""
@@ -1567,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:543
+#: 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 ""
@@ -1580,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 ""
@@ -1601,7 +1635,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 ""
@@ -1617,7 +1651,7 @@ msgstr ""
msgid "Bluesky is more fun with friends. Do you want to invite some of yours? <0/>"
msgstr ""
-#: src/screens/Takendown.tsx:215
+#: src/screens/Takendown.tsx:212
msgid "Bluesky Social Terms of Service"
msgstr ""
@@ -1700,7 +1734,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 ""
@@ -1768,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
@@ -1788,27 +1822,16 @@ msgstr ""
#: src/screens/Settings/components/ChangePasswordDialog.tsx:247
#: src/screens/Settings/components/ChangePasswordDialog.tsx:253
#: src/screens/Settings/Settings.tsx:305
-#: src/screens/Takendown.tsx:102
-#: src/screens/Takendown.tsx:105
-#: src/view/com/composer/Composer.tsx:1449
-#: src/view/com/composer/Composer.tsx:1461
+#: src/screens/Takendown.tsx:101
+#: src/screens/Takendown.tsx:104
+#: 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
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 ""
@@ -1828,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 ""
@@ -1962,19 +1985,19 @@ msgstr ""
msgid "Chats"
msgstr ""
+#: src/screens/Settings/components/DeleteAccountDialog.tsx:235
+msgid "Check <0>{currentEmail}0> 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"
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 ""
-#: 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 ""
@@ -1987,7 +2010,7 @@ msgstr ""
msgid "Choose domain verification method"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:218
+#: src/screens/StarterPack/Wizard/index.tsx:215
msgid "Choose Feeds"
msgstr ""
@@ -1995,7 +2018,7 @@ msgstr ""
msgid "Choose for me"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:214
+#: src/screens/StarterPack/Wizard/index.tsx:211
msgid "Choose People"
msgstr ""
@@ -2104,24 +2127,24 @@ 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
#: 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: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
#: src/components/verification/VerificationsDialog.tsx:145
-#: src/components/verification/VerifierDialog.tsx:147
+#: 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
@@ -2147,7 +2170,7 @@ msgstr ""
#: src/components/ageAssurance/AgeAssuranceInitDialog.tsx:228
#: src/components/dialogs/GifSelect.tsx:263
#: src/components/verification/VerificationsDialog.tsx:137
-#: src/components/verification/VerifierDialog.tsx:139
+#: src/components/verification/VerifierDialog.tsx:138
#: src/view/com/composer/select-language/PostLanguageSelectDialog.tsx:204
#: src/view/com/composer/select-language/PostLanguageSelectDialog.tsx:298
#: src/view/com/composer/select-language/PostLanguageSelectDialog.tsx:330
@@ -2172,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 ""
@@ -2194,7 +2217,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 ""
@@ -2238,7 +2261,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 ""
@@ -2251,7 +2274,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 ""
@@ -2259,11 +2282,11 @@ msgstr ""
msgid "Compose reply"
msgstr ""
-#: src/view/com/composer/Composer.tsx:2298
+#: src/view/com/composer/Composer.tsx:2374
msgid "Compressing GIF..."
msgstr ""
-#: src/view/com/composer/Composer.tsx:2300
+#: src/view/com/composer/Composer.tsx:2376
msgid "Compressing video..."
msgstr ""
@@ -2279,8 +2302,8 @@ msgstr ""
msgid "Configured in <0>moderation settings0>."
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"
@@ -2290,30 +2313,26 @@ 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/screens/Login/LoginForm.tsx:284
+#: 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 ""
-#: 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
@@ -2322,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
@@ -2433,7 +2456,7 @@ msgstr ""
msgid "Continue to next step"
msgstr ""
-#: src/screens/Messages/Conversation.tsx:57
+#: src/screens/Messages/Conversation.tsx:56
msgid "Conversation"
msgstr ""
@@ -2477,8 +2500,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:495
+#: src/view/com/profile/ProfileMenu.tsx:498
msgid "Copy at:// URI"
msgstr ""
@@ -2493,8 +2516,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:504
+#: src/view/com/profile/ProfileMenu.tsx:507
msgid "Copy DID"
msgstr ""
@@ -2503,7 +2526,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 ""
@@ -2523,12 +2546,12 @@ 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 ""
-#: src/screens/StarterPack/StarterPackScreen.tsx:617
+#: src/screens/StarterPack/StarterPackScreen.tsx:620
msgid "Copy link to starter pack"
msgstr ""
@@ -2542,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 ""
@@ -2594,8 +2617,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 +2652,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 +2734,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 ""
@@ -2804,13 +2827,13 @@ 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
-#: 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 ""
@@ -2819,8 +2842,9 @@ msgstr ""
msgid "Delete account"
msgstr ""
-#: src/view/com/modals/DeleteAccount.tsx:101
-msgid "Delete Account <0>\"0><1>{0}1><2>\"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
@@ -2872,22 +2896,22 @@ 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/view/com/composer/Composer.tsx:1354
+#: 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 ""
-#: 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 ""
@@ -2895,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 ""
@@ -2926,16 +2950,16 @@ msgid "Description"
msgstr ""
#: src/view/com/composer/GifAltText.tsx:150
-#: src/view/com/composer/photos/ImageAltTextDialog.tsx:113
+#: src/view/com/composer/photos/ImageAltTextDialog.tsx:118
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 ""
@@ -2995,19 +3019,19 @@ 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 ""
#: 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:239
-#: 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 ""
@@ -3016,15 +3040,22 @@ msgstr ""
msgid "Discard changes?"
msgstr ""
-#: src/view/com/composer/Composer.tsx:1147
-#: src/view/com/composer/drafts/DraftItem.tsx:236
+#: 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 ""
+#: 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"
@@ -3040,7 +3071,7 @@ msgstr ""
msgid "Discover New Feeds"
msgstr ""
-#: src/components/Dialog/index.tsx:379
+#: src/components/Dialog/index.tsx:375
msgid "Dismiss"
msgstr ""
@@ -3048,11 +3079,11 @@ msgstr ""
msgid "Dismiss banner"
msgstr ""
-#: src/view/com/composer/Composer.tsx:2219
+#: src/view/com/composer/Composer.tsx:2295
msgid "Dismiss error"
msgstr ""
-#: src/components/ProgressGuide/List.tsx:67
+#: src/components/ProgressGuide/List.tsx:73
msgid "Dismiss getting started guide"
msgstr ""
@@ -3092,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 ""
@@ -3108,6 +3139,10 @@ msgstr ""
msgid "Don't have a code or need a new one? <0>Click here.0>"
msgstr ""
+#: src/screens/Settings/components/DeleteAccountDialog.tsx:273
+msgid "Don’t see a code? <0>Click here to resend.0>"
+msgstr ""
+
#: src/components/dialogs/EmailDialog/components/ResendEmailText.tsx:37
msgid "Don't see an email? <0>Click here to resend.0>"
msgstr ""
@@ -3117,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 ""
@@ -3140,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 ""
@@ -3159,7 +3194,7 @@ msgstr ""
msgid "Double tap or long press the message to add a reaction"
msgstr ""
-#: src/components/Dialog/index.tsx:380
+#: src/components/Dialog/index.tsx:376
msgid "Double tap to close the dialog"
msgstr ""
@@ -3181,21 +3216,21 @@ 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 ""
-#: 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 ""
-#: 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 ""
@@ -3237,9 +3272,9 @@ msgstr ""
#: src/screens/Settings/AccountSettings.tsx:145
#: src/screens/Settings/NotificationSettings/ActivityNotificationSettings.tsx:252
-#: src/screens/StarterPack/StarterPackScreen.tsx:595
-#: src/screens/StarterPack/Wizard/index.tsx:340
-#: src/screens/StarterPack/Wizard/index.tsx:345
+#: src/screens/StarterPack/StarterPackScreen.tsx:598
+#: src/screens/StarterPack/Wizard/index.tsx:337
+#: src/screens/StarterPack/Wizard/index.tsx:342
msgid "Edit"
msgstr ""
@@ -3264,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 ""
@@ -3279,8 +3314,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:358
+#: src/view/com/profile/ProfileMenu.tsx:378
msgid "Edit live status"
msgstr ""
@@ -3309,16 +3344,16 @@ 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:330
msgid "Edit profile"
msgstr ""
#: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:298
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:326
+#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:332
msgid "Edit Profile"
msgstr ""
-#: src/screens/StarterPack/StarterPackScreen.tsx:587
+#: src/screens/StarterPack/StarterPackScreen.tsx:590
msgid "Edit starter pack"
msgstr ""
@@ -3356,7 +3391,7 @@ msgstr ""
msgid "Email 2FA enabled"
msgstr ""
-#: src/screens/Login/ForgotPasswordForm.tsx:93
+#: src/screens/Login/ForgotPasswordForm.tsx:94
msgid "Email address"
msgstr ""
@@ -3368,6 +3403,10 @@ msgstr ""
msgid "Email sent!"
msgstr ""
+#: src/screens/Settings/components/DeleteAccountDialog.tsx:262
+msgid "Email sent! <0>Click here to resend.0>"
+msgstr ""
+
#: src/components/dialogs/EmailDialog/screens/Verify.tsx:182
msgid "Email verification complete!"
msgstr ""
@@ -3401,7 +3440,7 @@ msgstr ""
msgid "Enable"
msgstr ""
-#: src/components/dialogs/EmbedConsent.tsx:100
+#: src/components/dialogs/EmbedConsent.tsx:95
msgid "Enable {0} only"
msgstr ""
@@ -3413,8 +3452,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 ""
@@ -3440,7 +3479,7 @@ msgstr ""
msgid "Enable subtitles"
msgstr ""
-#: src/components/dialogs/EmbedConsent.tsx:93
+#: src/components/dialogs/EmbedConsent.tsx:89
msgid "Enable this source only"
msgstr ""
@@ -3454,8 +3493,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 ""
@@ -3464,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 ""
@@ -3472,12 +3511,12 @@ 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 ""
-#: 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 ""
@@ -3499,11 +3538,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 ""
@@ -3511,28 +3550,29 @@ 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
+#: src/screens/Settings/components/DeleteAccountDialog.tsx:297
msgid "Enter your password"
msgstr ""
-#: src/screens/Login/index.tsx:138
+#: src/screens/Login/index.tsx:141
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 ""
-#: 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:2394
#: src/view/com/util/error/ErrorScreen.tsx:42
msgid "Error"
msgstr ""
@@ -3585,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 ""
@@ -3597,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 ""
@@ -3629,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 ""
@@ -3642,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 ""
@@ -3657,7 +3693,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 ""
@@ -3681,12 +3717,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 ""
@@ -3710,7 +3746,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 ""
@@ -3726,8 +3762,8 @@ msgstr ""
msgid "Failed to create conversation"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:263
-#: src/screens/StarterPack/Wizard/index.tsx:271
+#: src/screens/StarterPack/Wizard/index.tsx:260
+#: src/screens/StarterPack/Wizard/index.tsx:268
msgid "Failed to create starter pack"
msgstr ""
@@ -3745,10 +3781,14 @@ 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 ""
+#: 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 +3863,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 +3880,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 ""
@@ -3848,7 +3892,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 ""
@@ -3875,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 ""
@@ -3981,7 +4025,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 ""
@@ -4028,7 +4072,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 ""
@@ -4098,7 +4142,7 @@ msgstr ""
msgid "Finding friends..."
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:219
+#: src/screens/StarterPack/Wizard/index.tsx:216
msgid "Finish"
msgstr ""
@@ -4126,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:381
+#: 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
@@ -4134,7 +4178,7 @@ msgid "Follow"
msgstr ""
#: src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx:139
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:369
+#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:375
msgid "Follow {0}"
msgstr ""
@@ -4146,28 +4190,28 @@ 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 ""
-#: 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 ""
#: 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 ""
@@ -4178,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:379
+#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:385
#: src/view/com/notifications/NotificationFeedItem.tsx:841
#: src/view/com/notifications/NotificationFeedItem.tsx:848
msgid "Follow back"
@@ -4223,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:377
+#: 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
@@ -4237,7 +4281,7 @@ msgid "Following"
msgstr ""
#: src/components/ProfileCard.tsx:509
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:244
+#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:250
#: src/view/com/notifications/NotificationFeedItem.tsx:772
msgid "Following {0}"
msgstr ""
@@ -4280,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}0>."
msgstr ""
#: src/screens/Settings/components/AddAppPasswordDialog.tsx:208
@@ -4297,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 ""
@@ -4305,16 +4351,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 ""
@@ -4339,6 +4385,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 ""
@@ -4405,11 +4469,11 @@ 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 ""
-#: src/view/com/composer/Composer.tsx:2323
+#: src/view/com/composer/Composer.tsx:2399
msgid "GIF uploaded"
msgstr ""
@@ -4421,11 +4485,12 @@ 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
+#: 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
@@ -4433,7 +4498,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
@@ -4445,7 +4510,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 ""
@@ -4471,24 +4536,24 @@ 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: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:355
-#: src/view/com/profile/ProfileMenu.tsx:375
+#: 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 ""
@@ -4511,7 +4576,7 @@ msgstr ""
msgid "Go to feed"
msgstr ""
-#: src/screens/Login/ForgotPasswordForm.tsx:165
+#: src/screens/Login/ForgotPasswordForm.tsx:173
msgid "Go to next"
msgstr ""
@@ -4525,10 +4590,15 @@ 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 ""
+#: 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
@@ -4668,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
@@ -4695,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 ""
@@ -4719,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 ""
@@ -4756,7 +4826,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 Password0>. 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 Password0>. 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
@@ -4794,7 +4864,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 ""
@@ -4803,12 +4873,12 @@ 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 ""
-#: src/screens/Search/modules/ExploreTrendingTopics.tsx:188
+#: src/screens/Search/modules/ExploreTrendingTopics.tsx:178
msgid "Hot"
msgstr ""
@@ -4852,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.0>"
+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 ""
@@ -4884,7 +4958,7 @@ msgstr ""
msgid "If you need to update your email, <0>click here0>."
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 ""
@@ -4913,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 ""
@@ -4927,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 ""
@@ -4993,27 +5075,19 @@ 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 ""
-#: src/view/com/modals/DeleteAccount.tsx:228
-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 ""
-#: src/view/com/modals/DeleteAccount.tsx:247
-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 ""
@@ -5041,7 +5115,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 ""
@@ -5050,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 ""
@@ -5106,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.0>"
msgstr ""
@@ -5118,15 +5192,15 @@ msgstr ""
msgid "It's correct"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:492
+#: src/screens/StarterPack/Wizard/index.tsx:489
msgid "It's just <0>{0} 0>right now! Add more people to your starter pack by searching above."
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:487
+#: src/screens/StarterPack/Wizard/index.tsx:484
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:2314
msgid "Job ID: {0}"
msgstr ""
@@ -5137,8 +5211,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 ""
@@ -5151,6 +5225,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 ""
@@ -5203,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 ""
@@ -5219,7 +5298,7 @@ msgid "Latest"
msgstr ""
#: src/components/verification/VerificationsDialog.tsx:167
-#: src/components/verification/VerifierDialog.tsx:135
+#: src/components/verification/VerifierDialog.tsx:134
#: src/screens/Moderation/VerificationSettings.tsx:49
#: src/screens/Profile/Header/EditProfileDialog.tsx:349
#: src/screens/Settings/components/ChangeHandleDialog.tsx:213
@@ -5255,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"
@@ -5284,6 +5367,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.0>"
msgstr ""
@@ -5314,8 +5401,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 ""
@@ -5327,12 +5414,12 @@ 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 ""
-#: src/screens/Onboarding/StepFinished/index.tsx:333
+#: src/screens/Onboarding/StepFinished/index.tsx:336
msgid "Let's go!"
msgstr ""
@@ -5356,7 +5443,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 ""
@@ -5417,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 ""
@@ -5473,7 +5560,7 @@ msgstr ""
msgid "List has been hidden"
msgstr ""
-#: src/screens/ProfileList/index.tsx:172
+#: src/screens/ProfileList/index.tsx:176
msgid "List Hidden"
msgstr ""
@@ -5510,7 +5597,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 ""
@@ -5524,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 ""
@@ -5551,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 ""
@@ -5619,7 +5706,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 ""
@@ -5643,7 +5730,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 ""
@@ -5656,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 ""
@@ -5686,11 +5773,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:119
msgid "Media stored on {0}"
msgstr ""
-#: src/view/com/composer/drafts/DraftItem.tsx:114
+#: src/view/com/composer/drafts/DraftItem.tsx:117
msgid "Media stored on another device"
msgstr ""
@@ -5772,7 +5859,7 @@ msgstr ""
msgid "Misleading"
msgstr ""
-#: src/view/com/composer/drafts/DraftItem.tsx:128
+#: src/view/com/composer/drafts/DraftItem.tsx:131
msgid "Missing media"
msgstr ""
@@ -5848,9 +5935,9 @@ msgid "More languages..."
msgstr ""
#: src/screens/ProfileList/components/MoreOptionsMenu.tsx:143
-#: src/view/com/composer/drafts/DraftItem.tsx:187
-#: src/view/com/profile/ProfileMenu.tsx:242
-#: src/view/com/profile/ProfileMenu.tsx:249
+#: src/view/com/composer/drafts/DraftItem.tsx:190
+#: src/view/com/profile/ProfileMenu.tsx:241
+#: src/view/com/profile/ProfileMenu.tsx:248
msgid "More options"
msgstr ""
@@ -5870,7 +5957,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"
@@ -5881,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:436
-#: src/view/com/profile/ProfileMenu.tsx:443
+#: 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 ""
@@ -5898,7 +5985,7 @@ msgstr ""
msgid "Mute conversation"
msgstr ""
-#: src/components/dialogs/MutedWords.tsx:258
+#: src/components/dialogs/MutedWords.tsx:260
msgid "Mute in:"
msgstr ""
@@ -5910,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 ""
@@ -5995,8 +6082,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 ""
@@ -6013,8 +6101,8 @@ msgstr ""
msgid "Nevermind, create a handle for me"
msgstr ""
-#: src/screens/Search/modules/ExploreTrendingTopics.tsx:193
-#: src/view/com/profile/ProfileMenu.tsx:391
+#: src/screens/Search/modules/ExploreTrendingTopics.tsx:183
+#: src/view/com/profile/ProfileMenu.tsx:392
msgid "New"
msgstr ""
@@ -6074,15 +6162,15 @@ 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"
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 +6195,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 ""
@@ -6123,31 +6211,29 @@ 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 ""
#: 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/Onboarding/StepFinished/index.tsx:326
-#: src/screens/Onboarding/StepFinished/index.tsx:335
+#: 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
#: src/screens/Settings/components/AddAppPasswordDialog.tsx:165
#: src/screens/Signup/BackNextButtons.tsx:67
-#: src/screens/StarterPack/Wizard/index.tsx:211
-#: src/screens/StarterPack/Wizard/index.tsx:215
-#: src/screens/StarterPack/Wizard/index.tsx:393
-#: src/screens/StarterPack/Wizard/index.tsx:400
+#: src/screens/StarterPack/Wizard/index.tsx:208
+#: src/screens/StarterPack/Wizard/index.tsx:212
+#: src/screens/StarterPack/Wizard/index.tsx:390
+#: src/screens/StarterPack/Wizard/index.tsx:397
msgid "Next"
msgstr ""
-#: src/view/com/lightbox/Lightbox.web.tsx:179
+#: src/view/com/lightbox/Lightbox.web.tsx:211
msgid "Next image"
msgstr ""
@@ -6176,11 +6262,11 @@ 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 ""
-#: src/components/live/EditLiveDialog.tsx:139
+#: src/features/liveNow/components/EditLiveDialog.tsx:140
msgid "No expiry set"
msgstr ""
@@ -6196,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 ""
@@ -6211,7 +6297,7 @@ msgid "No lists"
msgstr ""
#: src/components/ProfileCard.tsx:531
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:269
+#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:275
#: src/view/com/notifications/NotificationFeedItem.tsx:792
msgid "No longer following {0}"
msgstr ""
@@ -6236,11 +6322,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 ""
@@ -6308,8 +6399,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 ""
@@ -6350,7 +6441,7 @@ msgstr ""
msgid "None"
msgstr ""
-#: src/screens/FindContactsFlowScreen.tsx:70
+#: src/screens/FindContactsFlowScreen.tsx:67
#: src/screens/Settings/FindContactsSettings.tsx:103
msgid "Not available on this platform."
msgstr ""
@@ -6368,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:558
+#: src/view/com/profile/ProfileMenu.tsx:559
msgid "Note about sharing"
msgstr ""
@@ -6395,11 +6486,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 ""
@@ -6421,7 +6512,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 ""
@@ -6467,8 +6558,8 @@ msgstr ""
msgid "OK"
msgstr ""
-#: src/screens/Login/PasswordUpdatedForm.tsx:37
-#: src/screens/PostThread/components/ThreadItemAnchor.tsx:705
+#: src/screens/Login/PasswordUpdatedForm.tsx:36
+#: src/screens/PostThread/components/ThreadItemAnchor.tsx:717
msgid "Okay"
msgstr ""
@@ -6487,11 +6578,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 ""
@@ -6503,7 +6594,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 ""
@@ -6564,7 +6659,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:1961
msgid "Open emoji picker"
msgstr ""
@@ -6581,6 +6676,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 ""
@@ -6605,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 ""
@@ -6614,7 +6713,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 ""
@@ -6672,7 +6771,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:1962
msgid "Opens emoji picker"
msgstr ""
@@ -6698,7 +6797,7 @@ msgstr ""
msgid "Opens image picker"
msgstr ""
-#: src/components/dialogs/LinkWarning.tsx:97
+#: src/components/dialogs/LinkWarning.tsx:112
msgid "Opens link {0}"
msgstr ""
@@ -6706,7 +6805,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 ""
@@ -6727,7 +6826,7 @@ msgstr ""
msgid "Opens this profile"
msgstr ""
-#: src/components/dialogs/MutedWords.tsx:304
+#: src/components/dialogs/MutedWords.tsx:306
msgid "Options:"
msgstr ""
@@ -6816,12 +6915,11 @@ 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/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 ""
@@ -6833,7 +6931,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 ""
@@ -6841,17 +6939,20 @@ 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/VideoEmbedInnerNative.tsx:153
#: 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 ""
-#: 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"
@@ -6930,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 ""
@@ -6952,8 +7053,7 @@ 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/VideoEmbedInnerNative.tsx:153
#: src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx:386
msgid "Play"
msgstr ""
@@ -6962,7 +7062,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,11 +7075,11 @@ 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 ""
-#: 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 ""
@@ -7012,12 +7116,16 @@ 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."
msgstr ""
-#: src/screens/Login/SetNewPasswordForm.tsx:58
+#: src/screens/Login/SetNewPasswordForm.tsx:59
msgid "Please enter a password."
msgstr ""
@@ -7040,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 ""
@@ -7073,15 +7181,11 @@ 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 ""
-#: src/view/com/modals/DeleteAccount.tsx:235
-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 ""
@@ -7093,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 ""
@@ -7127,7 +7231,7 @@ msgstr ""
msgid "Please use the native app to import your contacts."
msgstr ""
-#: src/screens/FindContactsFlowScreen.tsx:71
+#: src/screens/FindContactsFlowScreen.tsx:68
msgid "Please use the native app to sync your contacts."
msgstr ""
@@ -7140,7 +7244,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 ""
@@ -7153,7 +7257,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 ""
@@ -7168,7 +7272,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 ""
@@ -7245,14 +7349,14 @@ 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
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 ""
@@ -7264,11 +7368,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 ""
@@ -7295,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 ""
@@ -7344,16 +7448,15 @@ msgstr ""
msgid "Privacy violation of a minor"
msgstr ""
-#: src/view/com/composer/Composer.tsx:2312
+#: src/view/com/composer/Composer.tsx:2388
msgid "Processing GIF..."
msgstr ""
-#: src/view/com/composer/Composer.tsx:2314
+#: src/view/com/composer/Composer.tsx:2390
msgid "Processing video..."
msgstr ""
#: src/lib/api/index.ts:60
-#: src/screens/Login/ForgotPasswordForm.tsx:149
msgid "Processing..."
msgstr ""
@@ -7363,12 +7466,16 @@ 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"
msgstr ""
+#: src/lib/strings/errors.ts:40
+msgid "Profile not found"
+msgstr ""
+
#: src/screens/Profile/Header/EditProfileDialog.tsx:189
msgctxt "toast"
msgid "Profile updated"
@@ -7387,22 +7494,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 ""
@@ -7442,7 +7549,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:137
msgid "Quote post"
msgstr ""
@@ -7468,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 ""
@@ -7480,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 ""
@@ -7545,8 +7652,8 @@ msgstr ""
msgid "Real people."
msgstr ""
-#: src/screens/Takendown.tsx:160
-#: src/screens/Takendown.tsx:168
+#: src/screens/Takendown.tsx:157
+#: src/screens/Takendown.tsx:165
msgid "Reason for appeal"
msgstr ""
@@ -7589,9 +7696,9 @@ msgid "Reload conversations"
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/MutedWords.tsx:455
+#: 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
@@ -7678,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 ""
@@ -7696,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 ""
@@ -7715,8 +7822,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:410
+#: src/view/com/profile/ProfileMenu.tsx:413
msgid "Remove verification"
msgstr ""
@@ -7746,7 +7853,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 ""
@@ -7760,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"
@@ -7803,7 +7922,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 ""
@@ -7847,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:476
-#: src/view/com/profile/ProfileMenu.tsx:479
+#: src/view/com/profile/ProfileMenu.tsx:477
+#: src/view/com/profile/ProfileMenu.tsx:480
msgid "Report account"
msgstr ""
@@ -7883,13 +8002,13 @@ 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 ""
-#: src/screens/StarterPack/StarterPackScreen.tsx:637
#: src/screens/StarterPack/StarterPackScreen.tsx:640
+#: src/screens/StarterPack/StarterPackScreen.tsx:643
msgid "Report starter pack"
msgstr ""
@@ -7910,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 ""
@@ -7951,7 +8070,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 ""
@@ -8012,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 ""
@@ -8042,7 +8163,7 @@ msgstr ""
msgid "Reset activity subscription nudge"
msgstr ""
-#: src/screens/Login/SetNewPasswordForm.tsx:116
+#: src/screens/Login/SetNewPasswordForm.tsx:117
msgid "Reset code"
msgstr ""
@@ -8051,7 +8172,7 @@ msgstr ""
msgid "Reset onboarding state"
msgstr ""
-#: src/screens/Login/ForgotPasswordForm.tsx:80
+#: src/screens/Login/ForgotPasswordForm.tsx:81
msgid "Reset password"
msgstr ""
@@ -8060,7 +8181,7 @@ msgstr ""
msgid "Resync contacts"
msgstr ""
-#: src/screens/Login/LoginForm.tsx:327
+#: src/screens/Login/LoginForm.tsx:329
msgid "Retries signing in"
msgstr ""
@@ -8080,8 +8201,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
@@ -8105,7 +8226,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 ""
@@ -8121,7 +8242,7 @@ msgstr ""
msgid "Returns to previous page"
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:325
+#: src/screens/StarterPack/Wizard/index.tsx:322
msgid "Returns to the previous step"
msgstr ""
@@ -8130,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
@@ -8141,8 +8262,8 @@ msgstr ""
#: src/view/com/composer/GifAltText.tsx:202
#: src/view/com/composer/photos/EditImageDialog.web.tsx:62
#: src/view/com/composer/photos/EditImageDialog.web.tsx:75
-#: src/view/com/composer/photos/ImageAltTextDialog.tsx:152
-#: src/view/com/composer/photos/ImageAltTextDialog.tsx:162
+#: src/view/com/composer/photos/ImageAltTextDialog.tsx:157
+#: src/view/com/composer/photos/ImageAltTextDialog.tsx:167
msgid "Save"
msgstr ""
@@ -8159,23 +8280,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 ""
@@ -8202,7 +8323,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"
@@ -8294,7 +8415,7 @@ msgstr ""
msgid "Search for \"{searchText}\""
msgstr ""
-#: src/screens/StarterPack/Wizard/index.tsx:550
+#: src/screens/StarterPack/Wizard/index.tsx:547
msgid "Search for feeds that you want to suggest to others."
msgstr ""
@@ -8328,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 ""
@@ -8427,7 +8548,7 @@ msgstr ""
msgid "Select a reason"
msgstr ""
-#: src/screens/Login/ChooseAccountForm.tsx:78
+#: src/screens/Login/ChooseAccountForm.tsx:80
msgid "Select account"
msgstr ""
@@ -8455,11 +8576,11 @@ msgstr ""
msgid "Select content languages"
msgstr ""
-#: src/components/live/GoLiveDialog.tsx:178
+#: src/features/liveNow/components/GoLiveDialog.tsx:179
msgid "Select duration"
msgstr ""
-#: src/screens/Login/index.tsx:159
+#: src/screens/Login/index.tsx:162
msgid "Select from an existing account"
msgstr ""
@@ -8479,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 ""
@@ -8489,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 ""
@@ -8527,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 ""
@@ -8576,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 ""
@@ -8623,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 ""
@@ -8639,7 +8751,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 ""
@@ -8659,13 +8771,13 @@ 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 ""
#: 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 ""
@@ -8729,7 +8841,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 ""
@@ -8747,7 +8859,7 @@ msgstr ""
msgid "Share a fun fact!"
msgstr ""
-#: src/view/com/profile/ProfileMenu.tsx:563
+#: src/view/com/profile/ProfileMenu.tsx:564
msgid "Share anyway"
msgstr ""
@@ -8756,8 +8868,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"
@@ -8781,7 +8893,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 ""
@@ -8793,10 +8905,10 @@ 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/view/com/profile/ProfileMenu.tsx:270
-#: src/view/com/profile/ProfileMenu.tsx:283
+#: src/screens/StarterPack/StarterPackScreen.tsx:621
+#: src/screens/StarterPack/StarterPackScreen.tsx:629
+#: src/view/com/profile/ProfileMenu.tsx:269
+#: src/view/com/profile/ProfileMenu.tsx:282
msgid "Share via..."
msgstr ""
@@ -8818,7 +8930,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 ""
@@ -8843,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 ""
@@ -8865,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 ""
@@ -8892,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 ""
@@ -8920,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 ""
@@ -8938,9 +9050,11 @@ 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/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
@@ -8959,7 +9073,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 ""
@@ -8980,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 ""
@@ -8990,14 +9104,14 @@ msgstr ""
#: src/screens/Settings/Settings.tsx:304
#: src/screens/SignupQueued.tsx:93
#: src/screens/SignupQueued.tsx:96
-#: src/screens/Takendown.tsx:88
+#: src/screens/Takendown.tsx:87
#: src/view/shell/desktop/LeftNav.tsx:212
#: src/view/shell/desktop/LeftNav.tsx:269
#: src/view/shell/desktop/LeftNav.tsx:272
msgid "Sign out"
msgstr ""
-#: src/screens/Takendown.tsx:91
+#: src/screens/Takendown.tsx:90
msgid "Sign Out"
msgstr ""
@@ -9012,7 +9126,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 ""
@@ -9020,11 +9134,11 @@ 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
+#: src/screens/StarterPack/Wizard/index.tsx:216
msgid "Skip"
msgstr ""
@@ -9033,8 +9147,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 ""
@@ -9051,7 +9165,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 ""
@@ -9087,7 +9201,7 @@ msgstr ""
msgid "Something wasn't quite right with the data you're trying to report. Please contact support."
msgstr ""
-#: src/screens/Messages/Conversation.tsx:144
+#: src/screens/Messages/Conversation.tsx:141
msgid "Something went wrong"
msgstr ""
@@ -9124,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 ""
@@ -9155,7 +9269,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 ""
@@ -9183,7 +9297,7 @@ msgstr ""
#: src/Navigation.tsx:590
#: src/Navigation.tsx:595
-#: src/screens/StarterPack/Wizard/index.tsx:210
+#: src/screens/StarterPack/Wizard/index.tsx:207
msgid "Starter Pack"
msgstr ""
@@ -9200,7 +9314,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 ""
@@ -9250,20 +9364,20 @@ 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"
msgstr ""
-#: src/screens/Takendown.tsx:76
+#: src/screens/Takendown.tsx:75
msgid "Submit appeal"
msgstr ""
-#: src/screens/Takendown.tsx:80
+#: src/screens/Takendown.tsx:79
msgid "Submit Appeal"
msgstr ""
@@ -9346,6 +9460,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
@@ -9353,11 +9469,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 ""
@@ -9380,7 +9491,7 @@ msgstr ""
msgid "System log"
msgstr ""
-#: src/components/dialogs/MutedWords.tsx:287
+#: src/components/dialogs/MutedWords.tsx:289
msgid "Tags only"
msgstr ""
@@ -9426,7 +9537,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 ""
@@ -9463,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 ""
@@ -9482,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 ""
@@ -9494,8 +9605,8 @@ msgstr ""
#: src/screens/StarterPack/StarterPackScreen.tsx:113
#: src/screens/StarterPack/StarterPackScreen.tsx:157
#: src/screens/StarterPack/StarterPackScreen.tsx:158
-#: src/screens/StarterPack/Wizard/index.tsx:117
-#: src/screens/StarterPack/Wizard/index.tsx:127
+#: src/screens/StarterPack/Wizard/index.tsx:116
+#: src/screens/StarterPack/Wizard/index.tsx:126
msgid "That starter pack could not be found."
msgstr ""
@@ -9511,9 +9622,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: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 ""
@@ -9567,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 ""
@@ -9575,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
@@ -9587,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 ""
@@ -9597,7 +9708,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 ""
@@ -9660,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 ""
@@ -9691,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:88
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:253
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:279
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:294
-#: 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:89
+#: 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 ""
@@ -9768,7 +9879,7 @@ msgstr ""
msgid "This appeal will be sent to <0>{sourceName}0>."
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 ""
@@ -9778,6 +9889,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 ""
@@ -9798,7 +9913,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 ""
@@ -9815,7 +9930,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:240
msgid "This draft will be permanently deleted."
msgstr ""
@@ -9869,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 ""
@@ -9886,7 +10001,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 ""
@@ -9906,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}0>, but was first seen by Bluesky on <1>{1}1>."
msgstr ""
@@ -9922,19 +10037,19 @@ 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 ""
-#: src/view/com/composer/Composer.tsx:823
+#: src/view/com/composer/Composer.tsx:887
msgid "This post's author has disabled quote posts."
msgstr ""
-#: src/view/com/profile/ProfileMenu.tsx:560
+#: 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 ""
@@ -9942,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 ""
@@ -9991,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}0> and all associated data. Note that this will affect any other <1>AT Protocol1> 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 ""
@@ -10059,7 +10178,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 ""
@@ -10094,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 ""
@@ -10166,18 +10285,22 @@ 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 ""
-#: src/screens/StarterPack/StarterPackScreen.tsx:680
+#: src/screens/StarterPack/StarterPackScreen.tsx:683
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 ""
@@ -10198,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:190
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:337
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:397
+#: 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:551
+#: src/view/com/profile/ProfileMenu.tsx:552
msgid "Unblock"
msgstr ""
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:341
+#: 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:456
-#: src/view/com/profile/ProfileMenu.tsx:462
+#: src/view/com/profile/ProfileMenu.tsx:457
+#: src/view/com/profile/ProfileMenu.tsx:463
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:190
+#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:398
+#: src/view/com/profile/ProfileMenu.tsx:534
msgid "Unblock Account?"
msgstr ""
@@ -10241,6 +10364,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 ""
@@ -10254,12 +10379,12 @@ msgstr ""
msgid "Undo repost ({0, plural, one {# repost} other {# reposts}})"
msgstr ""
-#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:368
+#: 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 ""
@@ -10300,7 +10425,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"
@@ -10316,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:435
-#: src/view/com/profile/ProfileMenu.tsx:441
+#: 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 ""
@@ -10332,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 ""
@@ -10361,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 ""
@@ -10405,7 +10530,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 ""
@@ -10439,15 +10564,11 @@ 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 ""
-#: src/screens/Login/SetNewPasswordForm.tsx:194
-msgid "Updating..."
-msgstr ""
-
#: src/screens/Onboarding/StepProfile/index.tsx:298
msgid "Upload a photo instead"
msgstr ""
@@ -10475,7 +10596,7 @@ msgstr ""
msgid "Upload from Library"
msgstr ""
-#: src/view/com/composer/Composer.tsx:2305
+#: src/view/com/composer/Composer.tsx:2381
msgid "Uploading GIF..."
msgstr ""
@@ -10488,7 +10609,7 @@ msgstr ""
msgid "Uploading link thumbnail..."
msgstr ""
-#: src/view/com/composer/Composer.tsx:2307
+#: src/view/com/composer/Composer.tsx:2383
msgid "Uploading video..."
msgstr ""
@@ -10591,7 +10712,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 ""
@@ -10635,13 +10756,13 @@ 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: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 ""
@@ -10669,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 ""
@@ -10717,12 +10838,12 @@ 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 ""
-#: src/view/com/composer/state/video.ts:357
+#: src/view/com/composer/state/video.ts:358
msgid "Video failed to process"
msgstr ""
@@ -10739,7 +10860,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 ""
@@ -10759,11 +10880,11 @@ msgstr ""
msgid "Video settings"
msgstr ""
-#: src/view/com/composer/Composer.tsx:2325
+#: src/view/com/composer/Composer.tsx:2401
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 ""
@@ -10775,7 +10896,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 ""
@@ -10832,7 +10953,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 ""
@@ -10907,8 +11028,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 ""
@@ -10934,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 ""
@@ -10959,7 +11080,7 @@ msgstr ""
msgid "We couldn't find any results for that topic."
msgstr ""
-#: src/screens/Messages/Conversation.tsx:145
+#: src/screens/Messages/Conversation.tsx:142
msgid "We couldn't load this conversation"
msgstr ""
@@ -11075,15 +11196,15 @@ 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 ""
-#: 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 ""
-#: 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 ""
@@ -11092,7 +11213,11 @@ 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/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 ""
@@ -11143,7 +11268,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 ""
@@ -11180,7 +11305,7 @@ msgstr ""
msgid "Whoops! Trending videos failed to load."
msgstr ""
-#: src/screens/Takendown.tsx:171
+#: src/screens/Takendown.tsx:168
msgid "Why are you appealing?"
msgstr ""
@@ -11220,11 +11345,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 ""
@@ -11238,12 +11363,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 ""
@@ -11255,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 ""
@@ -11269,15 +11394,19 @@ msgstr ""
msgid "Yes, deactivate"
msgstr ""
-#: src/screens/StarterPack/StarterPackScreen.tsx:692
+#: 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 ""
@@ -11301,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 team0> if you believe this is an error."
msgstr ""
@@ -11314,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 ""
@@ -11331,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 ""
@@ -11351,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 deactivate0> 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 ""
@@ -11368,24 +11497,27 @@ 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 ""
-#: 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 ""
-#: 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 ""
+#: 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 ""
@@ -11448,12 +11580,16 @@ 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 settings0>."
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 ""
@@ -11483,7 +11619,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 ""
@@ -11507,11 +11643,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 ""
@@ -11527,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 ""
@@ -11564,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 Service0> for more information."
msgstr ""
@@ -11580,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 ""
@@ -11634,7 +11758,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 ""
@@ -11712,6 +11836,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 ""
@@ -11736,11 +11864,11 @@ 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:144
+#: src/screens/Takendown.tsx:141
msgid "Your account has been suspended"
msgstr ""
@@ -11752,11 +11880,11 @@ msgstr ""
msgid "Your account repository, containing all public data records, can be downloaded as a \"CAR\" file. This file does not include media embeds, such as images, or your private data, which must be fetched separately."
msgstr ""
-#: src/screens/Takendown.tsx:212
+#: src/screens/Takendown.tsx:209
msgid "Your account was found to be in violation of the <0>Bluesky Social Terms of Service0>. You have been sent an email outlining the specific violation and suspension period, if applicable. You can appeal this decision if you believe it was made in error."
msgstr ""
-#: src/screens/Takendown.tsx:152
+#: src/screens/Takendown.tsx:149
msgid "Your appeal has been submitted. If your appeal succeeds, you will receive an email."
msgstr ""
@@ -11802,7 +11930,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
@@ -11858,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 ""
@@ -11870,11 +11998,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 ""
@@ -11895,7 +12023,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 ""
diff --git a/src/screens/FindContactsFlowScreen.tsx b/src/screens/FindContactsFlowScreen.tsx
index d53472611e..9b9e5b6c74 100644
--- a/src/screens/FindContactsFlowScreen.tsx
+++ b/src/screens/FindContactsFlowScreen.tsx
@@ -4,7 +4,6 @@ import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {usePreventRemove} from '@react-navigation/native'
-import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
import {
type AllNavigatorParams,
type NativeStackScreenProps,
@@ -37,8 +36,6 @@ export function FindContactsFlowScreen({navigation}: Props) {
})
})
- useEnableKeyboardControllerScreen(true)
-
const setMinimalShellMode = useSetMinimalShellMode()
const effect = useCallback(() => {
setMinimalShellMode(true)
diff --git a/src/screens/Login/ChooseAccountForm.tsx b/src/screens/Login/ChooseAccountForm.tsx
index ea9c26ad3b..5eded55c71 100644
--- a/src/screens/Login/ChooseAccountForm.tsx
+++ b/src/screens/Login/ChooseAccountForm.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import {useCallback, useState} from 'react'
import {View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@@ -12,6 +12,7 @@ import {AccountList} from '#/components/AccountList'
import {Button, ButtonText} from '#/components/Button'
import * as TextField from '#/components/forms/TextField'
import {useAnalytics} from '#/analytics'
+import {IS_WEB} from '#/env'
import {FormContainer} from './FormContainer'
export const ChooseAccountForm = ({
@@ -21,14 +22,14 @@ export const ChooseAccountForm = ({
onSelectAccount: (account?: SessionAccount) => void
onPressBack: () => void
}) => {
- const [pendingDid, setPendingDid] = React.useState(null)
+ const [pendingDid, setPendingDid] = useState(null)
const {_} = useLingui()
const ax = useAnalytics()
const {currentAccount} = useSession()
const {resumeSession} = useSessionApi()
const {setShowLoggedOut} = useLoggedOutViewControls()
- const onSelect = React.useCallback(
+ const onSelect = useCallback(
async (account: SessionAccount) => {
if (pendingDid) {
// The session API isn't resilient to race conditions so let's just ignore this.
@@ -54,7 +55,7 @@ export const ChooseAccountForm = ({
Toast.show(_(msg`Signed in as @${account.handle}`))
} catch (e: any) {
logger.error('choose account: initSession failed', {
- message: e.message,
+ message: e instanceof Error ? e.message : 'Unknown error',
})
// Move to login form.
onSelectAccount(account)
@@ -69,6 +70,7 @@ export const ChooseAccountForm = ({
onSelectAccount,
setShowLoggedOut,
_,
+ ax,
],
)
@@ -78,26 +80,29 @@ export const ChooseAccountForm = ({
titleText={Select account }
style={web([a.py_2xl])}>
-
- Sign in as...
-
+ {IS_WEB && (
+
+ Sign in as...
+
+ )}
onSelectAccount()}
pendingDid={pendingDid}
/>
-
-
- {_(msg`Back`)}
-
-
-
+ {IS_WEB && (
+
+
+ {_(msg`Back`)}
+
+
+
+ )}
)
}
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 = ({
-
-
-
- Back
-
-
-
- {!serviceDescription || isProcessing ? (
-
+
+ {IS_WEB && (
+ <>
+
+
+ Back
+
+
+
+ >
+ )}
+ {!serviceDescription ? (
+
+
+ Connecting...
+
) : (
+ onPress={onPressNext}
+ disabled={isProcessing}>
Next
+ {isProcessing && }
)}
- {!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..351aaa21b4 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')
@@ -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 = ({
)}
-
-
-
- Back
-
-
-
+
+ {IS_WEB && (
+
+
+ Back
+
+
+ )}
{!serviceDescription && error ? (
@@ -334,23 +335,24 @@ export const LoginForm = ({
) : !serviceDescription ? (
- <>
-
-
- Connecting...
-
- >
+
+
+ Connecting...
+
) : (
- Next
+ Sign in
{isProcessing && }
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.
-
+
diff --git a/src/screens/Login/SetNewPasswordForm.tsx b/src/screens/Login/SetNewPasswordForm.tsx
index 48e4ff846f..6ba479bcb7 100644
--- a/src/screens/Login/SetNewPasswordForm.tsx
+++ b/src/screens/Login/SetNewPasswordForm.tsx
@@ -1,5 +1,5 @@
import {useState} from 'react'
-import {ActivityIndicator, View} from 'react-native'
+import {View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@@ -7,14 +7,16 @@ import {cleanError, isNetworkError} from '#/lib/strings/errors'
import {checkAndFormatResetCode} from '#/lib/strings/password'
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, web} from '#/alf'
+import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {FormError} from '#/components/forms/FormError'
import * as TextField from '#/components/forms/TextField'
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 {useAnalytics} from '#/analytics'
+import {IS_WEB} from '#/env'
import {FormContainer} from './FormContainer'
export const SetNewPasswordForm = ({
@@ -31,7 +33,6 @@ export const SetNewPasswordForm = ({
onPasswordSet: () => void
}) => {
const {_} = useLingui()
- const t = useTheme()
const ax = useAnalytics()
const [isProcessing, setIsProcessing] = useState(false)
@@ -163,37 +164,34 @@ export const SetNewPasswordForm = ({
-
-
-
- Back
-
-
-
- {isProcessing ? (
-
- ) : (
-
-
- Next
-
-
+
+ {IS_WEB && (
+ <>
+
+
+ Back
+
+
+
+ >
)}
- {isProcessing ? (
-
- Updating...
-
- ) : undefined}
+
+
+
+ Next
+
+ {isProcessing && }
+
)
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/screens/Messages/Conversation.tsx b/src/screens/Messages/Conversation.tsx
index b63cd33908..4a762f6eee 100644
--- a/src/screens/Messages/Conversation.tsx
+++ b/src/screens/Messages/Conversation.tsx
@@ -15,7 +15,6 @@ import {
} from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
-import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import {
type CommonNavigatorParams,
@@ -68,8 +67,6 @@ export function MessagesConversationScreenInner({route}: Props) {
const convoId = route.params.conversation
const {setCurrentConvoId} = useCurrentConvoId()
- useEnableKeyboardControllerScreen(true)
-
useFocusEffect(
useCallback(() => {
setCurrentConvoId(convoId)
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/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/index.tsx b/src/screens/Onboarding/index.tsx
index 25d9173a84..c96ad1fbf1 100644
--- a/src/screens/Onboarding/index.tsx
+++ b/src/screens/Onboarding/index.tsx
@@ -2,7 +2,6 @@ import {useMemo, useReducer} from 'react'
import {View} from 'react-native'
import * as bcp47Match from 'bcp-47-match'
-import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
import {useLanguagePrefs} from '#/state/preferences'
import {
Layout,
@@ -60,8 +59,6 @@ export function Onboarding() {
)
const [contactsFlowState, contactsFlowDispatch] = useFindContactsFlowState()
- useEnableKeyboardControllerScreen(true)
-
return (
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/PostThread/components/ThreadItemAnchor.tsx b/src/screens/PostThread/components/ThreadItemAnchor.tsx
index e475b42de1..643f926f1b 100644
--- a/src/screens/PostThread/components/ThreadItemAnchor.tsx
+++ b/src/screens/PostThread/components/ThreadItemAnchor.tsx
@@ -10,7 +10,6 @@ import {
import {msg, Plural, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
-import {useActorStatus} from '#/lib/actor-status'
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
import {useTranslate} from '#/lib/hooks/useTranslate'
import {makeProfileLink} from '#/lib/routes/links'
@@ -60,6 +59,7 @@ import {Text} from '#/components/Typography'
import {VerificationCheckButton} from '#/components/verification/VerificationCheckButton'
import {WhoCanReply} from '#/components/WhoCanReply'
import {useAnalytics} from '#/analytics'
+import {useActorStatus} from '#/features/liveNow'
import * as bsky from '#/types/bsky'
export function ThreadItemAnchor({
@@ -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}
diff --git a/src/screens/PostThread/components/ThreadItemPost.tsx b/src/screens/PostThread/components/ThreadItemPost.tsx
index ea0d5631bb..4fe78785b8 100644
--- a/src/screens/PostThread/components/ThreadItemPost.tsx
+++ b/src/screens/PostThread/components/ThreadItemPost.tsx
@@ -8,7 +8,6 @@ import {
} from '@atproto/api'
import {Trans} from '@lingui/macro'
-import {useActorStatus} from '#/lib/actor-status'
import {MAX_POST_LINES} from '#/lib/constants'
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
import {makeProfileLink} from '#/lib/routes/links'
@@ -44,6 +43,7 @@ import {RichText} from '#/components/RichText'
import * as Skele from '#/components/Skeleton'
import {SubtleHover} from '#/components/SubtleHover'
import {Text} from '#/components/Typography'
+import {useActorStatus} from '#/features/liveNow'
export type ThreadItemPostProps = {
item: Extract
diff --git a/src/screens/Profile/Header/ProfileHeaderStandard.tsx b/src/screens/Profile/Header/ProfileHeaderStandard.tsx
index 6467756d4e..f2f24edaab 100644
--- a/src/screens/Profile/Header/ProfileHeaderStandard.tsx
+++ b/src/screens/Profile/Header/ProfileHeaderStandard.tsx
@@ -10,7 +10,6 @@ import {
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
-import {useActorStatus} from '#/lib/actor-status'
import {useHaptics} from '#/lib/haptics'
import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {sanitizeHandle} from '#/lib/strings/handles'
@@ -39,6 +38,8 @@ import * as Toast from '#/components/Toast'
import {Text} from '#/components/Typography'
import {VerificationCheckButton} from '#/components/verification/VerificationCheckButton'
import {IS_IOS} from '#/env'
+import {useActorStatus} from '#/features/liveNow'
+import {GermButton} from '../components/GermButton'
import {EditProfileDialog} from './EditProfileDialog'
import {ProfileHeaderHandle} from './Handle'
import {ProfileHeaderMetrics} from './Metrics'
@@ -156,6 +157,7 @@ let ProfileHeaderStandard = ({
testID="profileHeaderDescription"
style={[a.text_md]}
numberOfLines={15}
+ selectable
value={descriptionRT}
enableTags
authorHandle={profile.handle}
@@ -163,6 +165,10 @@ let ProfileHeaderStandard = ({
) : undefined}
+ {profile.associated?.germ && (
+
+ )}
+
{!isMe &&
!isBlockedUser &&
shouldShowKnownFollowers(profile.viewer?.knownFollowers) && (
diff --git a/src/screens/Profile/Header/Shell.tsx b/src/screens/Profile/Header/Shell.tsx
index 8543d45bd1..ae7c146b8c 100644
--- a/src/screens/Profile/Header/Shell.tsx
+++ b/src/screens/Profile/Header/Shell.tsx
@@ -14,7 +14,6 @@ import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native'
-import {useActorStatus} from '#/lib/actor-status'
import {BACK_HITSLOP} from '#/lib/constants'
import {useHaptics} from '#/lib/haptics'
import {type NavigationProp} from '#/lib/routes/types'
@@ -28,13 +27,14 @@ import {atoms as a, platform, useTheme} from '#/alf'
import {Button} from '#/components/Button'
import {useDialogControl} from '#/components/Dialog'
import {ArrowLeft_Stroke2_Corner0_Rounded as ArrowLeftIcon} from '#/components/icons/Arrow'
-import {EditLiveDialog} from '#/components/live/EditLiveDialog'
-import {LiveIndicator} from '#/components/live/LiveIndicator'
-import {LiveStatusDialog} from '#/components/live/LiveStatusDialog'
import {LabelsOnMe} from '#/components/moderation/LabelsOnMe'
import {ProfileHeaderAlerts} from '#/components/moderation/ProfileHeaderAlerts'
import {useAnalytics} from '#/analytics'
import {IS_IOS} from '#/env'
+import {useActorStatus} from '#/features/liveNow'
+import {EditLiveDialog} from '#/features/liveNow/components/EditLiveDialog'
+import {LiveIndicator} from '#/features/liveNow/components/LiveIndicator'
+import {LiveStatusDialog} from '#/features/liveNow/components/LiveStatusDialog'
import {GrowableAvatar} from './GrowableAvatar'
import {GrowableBanner} from './GrowableBanner'
import {StatusBarShadow} from './StatusBarShadow'
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 (
+ <>
+ {
+ ax.metric('profile:associated:germ:click-self-info', {})
+ selfExplanationDialogControl.open()
+ }}
+ style={[
+ t.atoms.bg_contrast_50,
+ a.rounded_full,
+ a.self_start,
+ {padding: 6, paddingRight: 10},
+ ]}>
+
+
+ Germ DM
+
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+ selfExplanationDialogControl.close()}>
+
+ Got it
+
+
+ deleteDeclaration()}
+ disabled={isPending}>
+ {isPending && }
+
+ Disconnect Germ DM
+
+
+
+
+
+ >
+ )
+}
+
+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/screens/ProfileList/index.tsx b/src/screens/ProfileList/index.tsx
index ef40706cd3..bc802335be 100644
--- a/src/screens/ProfileList/index.tsx
+++ b/src/screens/ProfileList/index.tsx
@@ -1,4 +1,4 @@
-import {useCallback, useMemo, useRef} from 'react'
+import {useCallback, useMemo, useRef, useState} from 'react'
import {View} from 'react-native'
import {useAnimatedRef} from 'react-native-reanimated'
import {
@@ -35,12 +35,13 @@ import {PagerWithHeader} from '#/view/com/pager/PagerWithHeader'
import {FAB} from '#/view/com/util/fab/FAB'
import {type ListRef} from '#/view/com/util/List'
import {ListHiddenScreen} from '#/screens/List/ListHiddenScreen'
-import {atoms as a, platform} from '#/alf'
+import {atoms as a, native, platform, useTheme} from '#/alf'
import {useDialogControl} from '#/components/Dialog'
import {ListAddRemoveUsersDialog} from '#/components/dialogs/lists/ListAddRemoveUsersDialog'
import * as Layout from '#/components/Layout'
import {Loader} from '#/components/Loader'
import * as Hider from '#/components/moderation/Hider'
+import {IS_WEB} from '#/env'
import {AboutSection} from './AboutSection'
import {ErrorScreen} from './components/ErrorScreen'
import {Header} from './components/Header'
@@ -149,6 +150,7 @@ function ProfileListScreenLoaded({
moderationOpts: ModerationOpts
preferences: UsePreferencesQueryResponse
}) {
+ const t = useTheme()
const {_} = useLingui()
const queryClient = useQueryClient()
const {openComposer} = useOpenComposer()
@@ -164,6 +166,8 @@ function ProfileListScreenLoaded({
const scrollElRef = useAnimatedRef()
const addUserDialogControl = useDialogControl()
const sectionTitlesCurate = [_(msg`Posts`), _(msg`People`)]
+ // modlist only
+ const [headerHeight, setHeaderHeight] = useState(null)
const moderation = useMemo(() => {
return moderateUserList(list, moderationOpts)
@@ -263,13 +267,24 @@ function ProfileListScreenLoaded({
- {renderHeader()}
-
+ setHeaderHeight(evt.nativeEvent.layout.height)}
+ style={[
+ native([a.absolute, a.z_10, t.atoms.bg]),
+
+ a.border_b,
+ t.atoms.border_contrast_low,
+ ]}>
+ {renderHeader()}
+
+ {headerHeight !== null && (
+
+ )}
openComposer({logContext: 'Fab'})}
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}
diff --git a/src/screens/Settings/AccountSettings.tsx b/src/screens/Settings/AccountSettings.tsx
index 800880ca5c..6b2f5534f0 100644
--- a/src/screens/Settings/AccountSettings.tsx
+++ b/src/screens/Settings/AccountSettings.tsx
@@ -3,7 +3,6 @@ import {useLingui} from '@lingui/react'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {type CommonNavigatorParams} from '#/lib/routes/types'
-import {useModalControls} from '#/state/modals'
import {useSession} from '#/state/session'
import * as SettingsList from '#/screens/Settings/components/SettingsList'
import {atoms as a, useTheme} from '#/alf'
@@ -27,6 +26,7 @@ import * as Layout from '#/components/Layout'
import {ChangeHandleDialog} from './components/ChangeHandleDialog'
import {ChangePasswordDialog} from './components/ChangePasswordDialog'
import {DeactivateAccountDialog} from './components/DeactivateAccountDialog'
+import {DeleteAccountDialog} from './components/DeleteAccountDialog'
import {ExportCarDialog} from './components/ExportCarDialog'
type Props = NativeStackScreenProps
@@ -34,13 +34,13 @@ export function AccountSettingsScreen({}: Props) {
const t = useTheme()
const {_} = useLingui()
const {currentAccount} = useSession()
- const {openModal} = useModalControls()
const emailDialogControl = useEmailDialogControl()
const birthdayControl = useDialogControl()
const changeHandleControl = useDialogControl()
const changePasswordControl = useDialogControl()
const exportCarControl = useDialogControl()
const deactivateAccountControl = useDialogControl()
+ const deleteAccountControl = useDialogControl()
return (
@@ -169,7 +169,7 @@ export function AccountSettingsScreen({}: Props) {
openModal({name: 'delete-account'})}
+ onPress={() => deleteAccountControl.open()}
destructive>
@@ -185,6 +185,10 @@ export function AccountSettingsScreen({}: Props) {
+
)
}
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
diff --git a/src/screens/Settings/Settings.tsx b/src/screens/Settings/Settings.tsx
index 4f6fbb602b..c79386d05b 100644
--- a/src/screens/Settings/Settings.tsx
+++ b/src/screens/Settings/Settings.tsx
@@ -7,7 +7,6 @@ import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
-import {useActorStatus} from '#/lib/actor-status'
import {HELP_DESK_URL} from '#/lib/constants'
import {useAccountSwitcher} from '#/lib/hooks/useAccountSwitcher'
import {useApplyPullRequestOTAUpdate} from '#/lib/hooks/useOTAUpdates'
@@ -70,6 +69,7 @@ import {
} from '#/components/verification/VerificationCheckButton'
import {useAnalytics} from '#/analytics'
import {IS_INTERNAL, IS_IOS, IS_NATIVE} from '#/env'
+import {useActorStatus} from '#/features/liveNow'
import {device, useStorage} from '#/storage'
import {useActivitySubscriptionsNudged} from '#/storage/hooks/activity-subscriptions-nudged'
diff --git a/src/screens/Settings/components/DeleteAccountDialog.tsx b/src/screens/Settings/components/DeleteAccountDialog.tsx
new file mode 100644
index 0000000000..d52629c38b
--- /dev/null
+++ b/src/screens/Settings/components/DeleteAccountDialog.tsx
@@ -0,0 +1,364 @@
+import {useCallback, useRef, useState} from 'react'
+import {type TextInput, View} from 'react-native'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {DM_SERVICE_HEADERS} from '#/lib/constants'
+import {useCleanError} from '#/lib/hooks/useCleanError'
+import {sanitizeHandle} from '#/lib/strings/handles'
+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 {type DialogOuterProps} from '#/components/Dialog'
+import {
+ isValidCode,
+ TokenField,
+} from '#/components/dialogs/EmailDialog/components/TokenField'
+import * as TextField from '#/components/forms/TextField'
+import {Envelope_Stroke2_Corner0_Rounded as Envelope} from '#/components/icons/Envelope'
+import {Lock_Stroke2_Corner0_Rounded as Lock} from '#/components/icons/Lock'
+import {createStaticClick, InlineLinkText} from '#/components/Link'
+import {Loader} from '#/components/Loader'
+import * as Prompt from '#/components/Prompt'
+import * as toast from '#/components/Toast'
+import {Span, Text} from '#/components/Typography'
+import {resetToTab} from '#/Navigation'
+
+const WHITESPACE_RE = /\s/gu
+const PASSWORD_MIN_LENGTH = 8
+
+enum Step {
+ SEND_CODE,
+ VERIFY_CODE,
+ CONFIRM_DELETION,
+}
+
+enum EmailState {
+ DEFAULT,
+ PENDING,
+}
+
+function isPasswordValid(password: string) {
+ return password.length >= PASSWORD_MIN_LENGTH
+}
+
+export function DeleteAccountDialog({
+ control,
+ deactivateDialogControl,
+}: {
+ control: DialogOuterProps['control']
+ deactivateDialogControl: DialogOuterProps['control']
+}) {
+ return (
+
+
+
+ )
+}
+
+function DeleteAccountDialogInner({
+ control,
+ deactivateDialogControl,
+}: {
+ control: DialogOuterProps['control']
+ deactivateDialogControl: DialogOuterProps['control']
+}) {
+ const passwordRef = useRef(null)
+ const t = useTheme()
+ const {_} = useLingui()
+ const cleanError = useCleanError()
+ const agent = useAgent()
+ const {currentAccount} = useSession()
+ const {removeAccount} = useSessionApi()
+
+ const [emailState, setEmailState] = useState(EmailState.DEFAULT)
+ const [emailSentCount, setEmailSentCount] = useState(0)
+ const [step, setStep] = useState(Step.SEND_CODE)
+ const [confirmCode, setConfirmCode] = useState('')
+ const [password, setPassword] = useState('')
+ const [error, setError] = useState('')
+
+ const sendEmail = useCallback(async () => {
+ if (emailState === EmailState.PENDING) {
+ return
+ }
+ try {
+ setEmailState(EmailState.PENDING)
+ await agent.com.atproto.server.requestAccountDelete()
+ setError('')
+ setEmailSentCount(prevCount => prevCount + 1)
+ setStep(Step.VERIFY_CODE)
+ } catch (e: any) {
+ const {clean, raw} = cleanError(e)
+ const error = clean || raw || e
+ setError(error)
+ logger.error(raw || e, {
+ message: 'Failed to send account deletion verification email',
+ })
+ } finally {
+ setEmailState(EmailState.DEFAULT)
+ }
+ }, [agent, cleanError, emailState, setEmailState])
+
+ const confirmDeletion = useCallback(async () => {
+ try {
+ setError('')
+ if (!currentAccount?.did) {
+ throw new Error('Invalid did')
+ }
+ const token = confirmCode.replace(WHITESPACE_RE, '')
+ // 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,
+ })
+ control.close(() => {
+ toast.show(_(msg`Your account has been deleted, see ya! ✌️`))
+ resetToTab('HomeTab')
+ removeAccount(currentAccount)
+ })
+ } catch (e: any) {
+ const {clean, raw} = cleanError(e)
+ const error = clean || raw || e
+ setError(error)
+ logger.error(raw || e, {
+ message: 'Failed to delete account',
+ })
+ setConfirmCode('')
+ setPassword('')
+ setStep(Step.VERIFY_CODE)
+ }
+ }, [
+ _,
+ agent,
+ cleanError,
+ confirmCode,
+ control,
+ currentAccount,
+ password,
+ removeAccount,
+ ])
+
+ const handleDeactivate = useCallback(() => {
+ control.close(() => deactivateDialogControl.open())
+ }, [control, deactivateDialogControl])
+
+ const handleSendEmail = useCallback(() => {
+ void sendEmail()
+ }, [sendEmail])
+
+ const handleSubmitConfirmCode = useCallback(() => {
+ passwordRef.current?.focus()
+ }, [])
+
+ const handleDeleteAccount = useCallback(() => {
+ setStep(Step.CONFIRM_DELETION)
+ }, [setStep])
+
+ const handleConfirmDeletion = useCallback(() => {
+ void confirmDeletion()
+ }, [confirmDeletion])
+
+ const currentHandle = sanitizeHandle(currentAccount?.handle ?? '', '@')
+ const currentEmail = currentAccount?.email ?? '(no email)'
+
+ switch (step) {
+ case Step.SEND_CODE:
+ return (
+ <>
+
+
+ {_(msg`Delete account “${currentHandle}”`)}
+
+
+
+ For security reasons, we’ll need to send a confirmation code to
+ your email address{' '}
+
+ {currentEmail}
+
+ .
+
+
+
+
+
+
+
+ {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 irreversibly 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/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/screens/StarterPack/StarterPackScreen.tsx b/src/screens/StarterPack/StarterPackScreen.tsx
index 4dc9cde927..e4fbc81891 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')
@@ -498,7 +501,7 @@ function Header({
value={starterPack.joinedAllTimeCount || 0}
other="# people have"
/>{' '}
- used this starter pack!
+ joined Bluesky via this starter pack!
diff --git a/src/screens/StarterPack/Wizard/index.tsx b/src/screens/StarterPack/Wizard/index.tsx
index 0e82256619..3382a5d540 100644
--- a/src/screens/StarterPack/Wizard/index.tsx
+++ b/src/screens/StarterPack/Wizard/index.tsx
@@ -16,7 +16,6 @@ import {useFocusEffect, useNavigation} from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {STARTER_PACK_MAX_SIZE} from '#/lib/constants'
-import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name'
import {
type CommonNavigatorParams,
@@ -185,8 +184,6 @@ function WizardInner({
})
}, [navigation])
- useEnableKeyboardControllerScreen(true)
-
useFocusEffect(
React.useCallback(() => {
setMinimalShellMode(true)
diff --git a/src/screens/Takendown.tsx b/src/screens/Takendown.tsx
index 660aecf1a6..4e5e2d2ff4 100644
--- a/src/screens/Takendown.tsx
+++ b/src/screens/Takendown.tsx
@@ -12,7 +12,6 @@ import {
BLUESKY_MOD_SERVICE_HEADERS,
MAX_REPORT_REASON_GRAPHEME_LENGTH,
} from '#/lib/constants'
-import {useEnableKeyboardController} from '#/lib/hooks/useEnableKeyboardController'
import {cleanError} from '#/lib/strings/errors'
import {useAgent, useSession, useSessionApi} from '#/state/session'
import {CharProgress} from '#/view/com/composer/char-progress/CharProgress'
@@ -121,8 +120,6 @@ export function Takendown() {
const webLayout = IS_WEB && gtMobile
- useEnableKeyboardController(true)
-
return (
diff --git a/src/state/appConfig.tsx b/src/state/appConfig.tsx
new file mode 100644
index 0000000000..67b0e553ed
--- /dev/null
+++ b/src/state/appConfig.tsx
@@ -0,0 +1,87 @@
+import {createContext, useContext} from 'react'
+import {QueryClient, useQuery} from '@tanstack/react-query'
+
+import {APP_CONFIG_URL} from '#/env'
+
+const qc = new QueryClient()
+const appConfigQueryKey = ['app-config']
+
+/**
+ * Matches the types defined in our `app-config` worker
+ */
+type AppConfigResponse = {
+ liveNow: {
+ allow: string[]
+ exceptions: {
+ did: string
+ allow: string[]
+ }[]
+ }
+}
+
+export const DEFAULT_APP_CONFIG_RESPONSE: AppConfigResponse = {
+ liveNow: {
+ allow: [],
+ exceptions: [],
+ },
+}
+
+let fetchAppConfigPromise: Promise | undefined
+
+async function fetchAppConfig(): Promise {
+ try {
+ if (!fetchAppConfigPromise) {
+ fetchAppConfigPromise = (async () => {
+ const r = await fetch(`${APP_CONFIG_URL}/config`)
+ if (!r.ok) throw new Error(await r.text())
+ const data = await r.json()
+ return data
+ })()
+ }
+ return await fetchAppConfigPromise
+ } catch (e) {
+ fetchAppConfigPromise = undefined
+ throw e
+ }
+}
+
+const Context = createContext(DEFAULT_APP_CONFIG_RESPONSE)
+
+export function Provider({children}: React.PropsWithChildren<{}>) {
+ const {data} = useQuery(
+ {
+ staleTime: Infinity,
+ queryKey: appConfigQueryKey,
+ refetchInterval: query => {
+ // refetch regularly if fetch failed, otherwise never refetch
+ return query.state.status === 'error' ? 60e3 : Infinity
+ },
+ async queryFn() {
+ return fetchAppConfig()
+ },
+ },
+ qc,
+ )
+ return (
+
+ {children}
+
+ )
+}
+
+export async function prefetchAppConfig() {
+ try {
+ const data = await fetchAppConfig()
+ if (data) {
+ qc.setQueryData(appConfigQueryKey, data)
+ }
+ } catch {}
+}
+
+export function useAppConfig() {
+ const ctx = useContext(Context)
+ if (!ctx) {
+ throw new Error('useAppConfig must be used within a Provider')
+ }
+ return ctx
+}
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/state/persisted/schema.ts b/src/state/persisted/schema.ts
index 4ee4d6e205..d31092ad85 100644
--- a/src/state/persisted/schema.ts
+++ b/src/state/persisted/schema.ts
@@ -106,6 +106,7 @@ const schema = z.object({
appleMusic: z.enum(externalEmbedOptions).optional(),
soundcloud: z.enum(externalEmbedOptions).optional(),
flickr: z.enum(externalEmbedOptions).optional(),
+ bandcamp: z.enum(externalEmbedOptions).optional(),
})
.optional(),
invites: z.object({
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/handle-availability.ts b/src/state/queries/handle-availability.ts
index e3f7a6b741..fb25697c76 100644
--- a/src/state/queries/handle-availability.ts
+++ b/src/state/queries/handle-availability.ts
@@ -6,8 +6,8 @@ import {
BSKY_SERVICE_DID,
PUBLIC_BSKY_SERVICE,
} from '#/lib/constants'
+import {useDebouncedValue} from '#/lib/hooks/useDebouncedValue'
import {createFullHandle} from '#/lib/strings/handles'
-import {useDebouncedValue} from '#/components/live/utils'
import {useAnalytics} from '#/analytics'
import * as bsky from '#/types/bsky'
import {Agent} from '../session/agent'
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/state/queries/preferences/index.ts b/src/state/queries/preferences/index.ts
index 58df94fcc3..e78a5d73f1 100644
--- a/src/state/queries/preferences/index.ts
+++ b/src/state/queries/preferences/index.ts
@@ -200,7 +200,13 @@ export function useSetFeedViewPreferencesMutation() {
})
}
-export function useSetThreadViewPreferencesMutation() {
+export function useSetThreadViewPreferencesMutation({
+ onSuccess,
+ onError,
+}: {
+ onSuccess?: (data: void, variables: Partial) => void
+ onError?: (error: unknown) => void
+}) {
const queryClient = useQueryClient()
const agent = useAgent()
@@ -212,6 +218,8 @@ export function useSetThreadViewPreferencesMutation() {
queryKey: preferencesQueryKey,
})
},
+ onSuccess,
+ onError,
})
}
diff --git a/src/state/queries/preferences/useThreadPreferences.ts b/src/state/queries/preferences/useThreadPreferences.ts
index 7825f4c688..629d1c61b8 100644
--- a/src/state/queries/preferences/useThreadPreferences.ts
+++ b/src/state/queries/preferences/useThreadPreferences.ts
@@ -1,5 +1,6 @@
import {useCallback, useMemo, useRef, useState} from 'react'
import {type AppBskyUnspeccedGetPostThreadV2} from '@atproto/api'
+import {useFocusEffect} from '@react-navigation/native'
import debounce from 'lodash.debounce'
import {useCallOnce} from '#/lib/once'
@@ -70,26 +71,37 @@ export function useThreadPreferences({
}
const userUpdatedPrefs = useRef(false)
- const [isSaving, setIsSaving] = useState(false)
- const {mutateAsync} = useSetThreadViewPreferencesMutation()
+ const {mutate, isPending: isSaving} = useSetThreadViewPreferencesMutation({
+ onSuccess: (_data, prefs) => {
+ ax.metric('thread:preferences:update', {
+ sort: prefs.sort,
+ view: prefs.lab_treeViewEnabled ? 'tree' : 'linear',
+ })
+ },
+ onError: err => {
+ ax.logger.error('useThreadPreferences failed to save', {
+ safeMessage: err,
+ })
+ },
+ })
const savePrefs = useMemo(() => {
- return debounce(async (prefs: ThreadViewPreferences) => {
- try {
- setIsSaving(true)
- await mutateAsync(prefs)
- ax.metric('thread:preferences:update', {
- sort: prefs.sort,
- view: prefs.lab_treeViewEnabled ? 'tree' : 'linear',
- })
- } catch (e) {
- ax.logger.error('useThreadPreferences failed to save', {
- safeMessage: e,
- })
- } finally {
- setIsSaving(false)
+ return debounce(
+ (prefs: ThreadViewPreferences) => {
+ mutate(prefs)
+ },
+ 2e3,
+ {leading: true, trailing: true},
+ )
+ }, [mutate])
+
+ // flush on leave screen
+ useFocusEffect(
+ useCallback(() => {
+ return () => {
+ void savePrefs.flush()
}
- }, 4e3)
- }, [mutateAsync])
+ }, [savePrefs]),
+ )
if (save && userUpdatedPrefs.current) {
savePrefs({
diff --git a/src/state/queries/trending/useTrendingTopics.ts b/src/state/queries/trending/useTrendingTopics.ts
index ca83522733..9cacfd1663 100644
--- a/src/state/queries/trending/useTrendingTopics.ts
+++ b/src/state/queries/trending/useTrendingTopics.ts
@@ -15,14 +15,24 @@ type Response = {
export const DEFAULT_LIMIT = 14
+function dedup(topics: TrendingTopic[]): TrendingTopic[] {
+ const seen = new Set()
+ return topics.filter(t => {
+ if (seen.has(t.link)) return false
+ seen.add(t.link)
+ return true
+ })
+}
+
export const trendingTopicsQueryKey = ['trending-topics']
export function useTrendingTopics() {
const agent = useAgent()
const {data: preferences} = usePreferencesQuery()
- const mutedWords = React.useMemo(() => {
- return preferences?.moderationPrefs?.mutedWords || []
- }, [preferences?.moderationPrefs])
+ const mutedWords = React.useMemo(
+ () => preferences?.moderationPrefs?.mutedWords ?? [],
+ [preferences?.moderationPrefs?.mutedWords],
+ )
return useQuery({
refetchOnWindowFocus: true,
@@ -40,18 +50,22 @@ export function useTrendingTopics() {
select: React.useCallback(
(data: Response) => {
return {
- topics: data.topics.filter(t => {
- return !hasMutedWord({
- mutedWords,
- text: t.topic + ' ' + t.displayName + ' ' + t.description,
- })
- }),
- suggested: data.suggested.filter(t => {
- return !hasMutedWord({
- mutedWords,
- text: t.topic + ' ' + t.displayName + ' ' + t.description,
- })
- }),
+ topics: dedup(
+ data.topics.filter(t => {
+ return !hasMutedWord({
+ mutedWords,
+ text: t.topic + ' ' + t.displayName + ' ' + t.description,
+ })
+ }),
+ ),
+ suggested: dedup(
+ data.suggested.filter(t => {
+ return !hasMutedWord({
+ mutedWords,
+ text: t.topic + ' ' + t.displayName + ' ' + t.description,
+ })
+ }),
+ ),
}
},
[mutedWords],
diff --git a/src/state/service-config.tsx b/src/state/service-config.tsx
index 29fa6bec90..e102cde2f9 100644
--- a/src/state/service-config.tsx
+++ b/src/state/service-config.tsx
@@ -2,28 +2,17 @@ import {createContext, useContext, useMemo} from 'react'
import {useLanguagePrefs} from '#/state/preferences/languages'
import {useServiceConfigQuery} from '#/state/queries/service-config'
-import {useSession} from '#/state/session'
-import {useAnalytics} from '#/analytics'
-import {IS_DEV} from '#/env'
import {device} from '#/storage'
type TrendingContext = {
enabled: boolean
}
-type LiveNowContext = {
- did: string
- domains: string[]
-}[]
-
const TrendingContext = createContext({
enabled: false,
})
TrendingContext.displayName = 'TrendingContext'
-const LiveNowContext = createContext([])
-LiveNowContext.displayName = 'LiveNowContext'
-
const CheckEmailConfirmedContext = createContext(null)
export function Provider({children}: {children: React.ReactNode}) {
@@ -60,19 +49,15 @@ export function Provider({children}: {children: React.ReactNode}) {
return {enabled}
}, [isInitialLoad, config, langPrefs.contentLanguages])
- const liveNow = useMemo(() => config?.liveNow ?? [], [config])
-
// probably true, so default to true when loading
// if the call fails, the query will set it to false for us
const checkEmailConfirmed = config?.checkEmailConfirmed ?? true
return (
-
-
- {children}
-
-
+
+ {children}
+
)
}
@@ -81,55 +66,6 @@ export function useTrendingConfig() {
return useContext(TrendingContext)
}
-const DEFAULT_LIVE_ALLOWED_DOMAINS = [
- 'twitch.tv',
- 'www.twitch.tv',
- 'stream.place',
- 'bluecast.app',
- 'www.bluecast.app',
-]
-export type LiveNowConfig = {
- currentAccountAllowedHosts: Set
- defaultAllowedHosts: Set
- allowedHostsExceptionsByDid: Map>
-}
-export function useLiveNowConfig(): LiveNowConfig {
- const ctx = useContext(LiveNowContext)
- const canGoLive = useCanGoLive()
- const {currentAccount} = useSession()
- return useMemo(() => {
- const defaultAllowedHosts = new Set(DEFAULT_LIVE_ALLOWED_DOMAINS)
- const allowedHostsExceptionsByDid = new Map>()
- for (const live of ctx) {
- allowedHostsExceptionsByDid.set(
- live.did,
- new Set(DEFAULT_LIVE_ALLOWED_DOMAINS.concat(live.domains)),
- )
- }
- if (!currentAccount?.did || !canGoLive)
- return {
- currentAccountAllowedHosts: new Set(),
- defaultAllowedHosts,
- allowedHostsExceptionsByDid,
- }
- const vip = ctx.find(live => live.did === currentAccount.did)
- return {
- currentAccountAllowedHosts: new Set(
- DEFAULT_LIVE_ALLOWED_DOMAINS.concat(vip ? vip.domains : []),
- ),
- defaultAllowedHosts,
- allowedHostsExceptionsByDid,
- }
- }, [ctx, currentAccount, canGoLive])
-}
-
-export function useCanGoLive() {
- const ax = useAnalytics()
- const {hasSession} = useSession()
- if (!hasSession) return false
- return IS_DEV ? true : !ax.features.enabled(ax.features.LiveNowBetaDisable)
-}
-
export function useCheckEmailConfirmed() {
const ctx = useContext(CheckEmailConfirmedContext)
if (ctx === null) {
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 {
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/composer/Composer.tsx b/src/view/com/composer/Composer.tsx
index 1c2f6c209d..ef54c4908f 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 && }
{replyTo ? : undefined}
{thread.posts.map((post, index) => (
-
+
- {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 && (
+
+ )}
-
+
)}
@@ -1320,7 +1395,7 @@ let ComposerPost = React.memo(function ComposerPost({
style={[a.pt_xs]}
richtext={richtext}
placeholder={selectTextInputPlaceholder}
- autoFocus
+ autoFocus={isLastPost}
webForceMinHeight={forceMinHeight}
// To avoid overlap with the close button:
hasRightPadding={isPartOfThread}
@@ -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}
/>
)}
@@ -1647,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' && (
-
+
)}
diff --git a/src/view/com/composer/drafts/DraftItem.tsx b/src/view/com/composer/drafts/DraftItem.tsx
index 4711aa21ea..16274acbf4 100644
--- a/src/view/com/composer/drafts/DraftItem.tsx
+++ b/src/view/com/composer/drafts/DraftItem.tsx
@@ -95,12 +95,15 @@ export function DraftItem({
paddingTop: 20 + a.pt_md.paddingTop,
},
]}>
-
+ {!!post.text.trim().length && (
+
+ )}
{!mediaExistsOnOtherDevice && }
diff --git a/src/view/com/composer/drafts/DraftsButton.tsx b/src/view/com/composer/drafts/DraftsButton.tsx
index 492df895e1..c1675ef2cb 100644
--- a/src/view/com/composer/drafts/DraftsButton.tsx
+++ b/src/view/com/composer/drafts/DraftsButton.tsx
@@ -17,14 +17,16 @@ export function DraftsButton({
isEmpty,
isDirty,
isEditingDraft,
+ canSaveDraft,
textLength,
}: {
onSelectDraft: (draft: DraftSummary) => 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 && (
+
+ )}
-
+
>
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)
})
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/photos/ImageAltTextDialog.tsx b/src/view/com/composer/photos/ImageAltTextDialog.tsx
index 1315eab8c0..1e0b8fa364 100644
--- a/src/view/com/composer/photos/ImageAltTextDialog.tsx
+++ b/src/view/com/composer/photos/ImageAltTextDialog.tsx
@@ -5,6 +5,7 @@ import {msg, Plural, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {MAX_ALT_TEXT} from '#/lib/constants'
+import {useIsKeyboardVisible} from '#/lib/hooks/useIsKeyboardVisible'
import {enforceLen} from '#/lib/strings/helpers'
import {type ComposerImage} from '#/state/gallery'
import {AltTextCounterWrapper} from '#/view/com/composer/AltTextCounterWrapper'
@@ -28,6 +29,7 @@ export const ImageAltTextDialog = ({
image,
onChange,
}: Props): React.ReactNode => {
+ const {height: minHeight} = useWindowDimensions()
const [altText, setAltText] = React.useState(image.alt)
return (
@@ -38,7 +40,8 @@ export const ImageAltTextDialog = ({
...image,
alt: enforceLen(altText, MAX_ALT_TEXT, true),
})
- }}>
+ }}
+ nativeOptions={{minHeight}}>
(() => {
const maxWidth = IS_WEB ? 450 : windim.width
const source = image.transformed ?? image.source
@@ -165,7 +170,7 @@ const ImageAltTextInner = ({
{/* Maybe fix this later -h */}
- {IS_ANDROID ? : null}
+ {IS_ANDROID && isKeyboardVisible ? : null}