Merge branch 'main' into web-layout

This commit is contained in:
Dan Abramov
2023-12-19 02:54:41 +00:00
55 changed files with 1596 additions and 1159 deletions
+7 -3
View File
@@ -292,7 +292,11 @@ function HomeTabNavigator() {
animationDuration: 250,
contentStyle,
}}>
<HomeTab.Screen name="Home" getComponent={() => HomeScreen} />
<HomeTab.Screen
name="Home"
getComponent={() => HomeScreen}
options={{requireAuth: true}}
/>
{commonScreens(HomeTab)}
</HomeTab.Navigator>
)
@@ -402,7 +406,7 @@ const FlatNavigator = () => {
<Flat.Screen
name="Home"
getComponent={() => HomeScreen}
options={{title: title('Home')}}
options={{title: title('Home'), requireAuth: true}}
/>
<Flat.Screen
name="Search"
@@ -412,7 +416,7 @@ const FlatNavigator = () => {
<Flat.Screen
name="Feeds"
getComponent={() => FeedsScreen}
options={{title: title('Feeds')}}
options={{title: title('Feeds'), requireAuth: true}}
/>
<Flat.Screen
name="Notifications"
+41 -24
View File
@@ -1,7 +1,7 @@
import React, {useCallback, useEffect} from 'react'
import {View, StyleSheet} from 'react-native'
import {View, StyleSheet, Image as RNImage} from 'react-native'
import * as SplashScreen from 'expo-splash-screen'
import LinearGradient from 'react-native-linear-gradient'
import {Image} from 'expo-image'
import Animated, {
interpolate,
runOnJS,
@@ -14,6 +14,10 @@ import MaskedView from '@react-native-masked-view/masked-view'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import Svg, {Path, SvgProps} from 'react-native-svg'
// @ts-ignore
import splashImagePointer from '../assets/splash.png'
const splashImageUri = RNImage.resolveAssetSource(splashImagePointer).uri
export const Logo = React.forwardRef(function LogoImpl(props: SvgProps, ref) {
const width = 1000
const height = width * (67 / 64)
@@ -45,7 +49,10 @@ export function Splash(props: React.PropsWithChildren<Props>) {
const intro = useSharedValue(0)
const outroLogo = useSharedValue(0)
const outroApp = useSharedValue(0)
const outroAppOpacity = useSharedValue(0)
const [isAnimationComplete, setIsAnimationComplete] = React.useState(false)
const [isImageLoaded, setIsImageLoaded] = React.useState(false)
const isReady = props.isReady && isImageLoaded
const logoAnimations = useAnimatedStyle(() => {
return {
@@ -56,8 +63,8 @@ export function Splash(props: React.PropsWithChildren<Props>) {
{
scale: interpolate(
outroLogo.value,
[0, 0.06, 0.08, 1],
[1, 0.8, 0.8, 800],
[0, 0.08, 1],
[1, 0.8, 400],
'clamp',
),
},
@@ -70,29 +77,32 @@ export function Splash(props: React.PropsWithChildren<Props>) {
return {
transform: [
{
scale: interpolate(
outroApp.value,
[0, 0.7, 1],
[1.1, 1.1, 1],
'clamp',
),
scale: interpolate(outroApp.value, [0, 1], [1.1, 1], 'clamp'),
},
],
opacity: interpolate(outroApp.value, [0, 0.7, 1], [0, 0, 1], 'clamp'),
opacity: interpolate(
outroAppOpacity.value,
[0, 0.08, 0.15, 1],
[0, 0, 1, 1],
'clamp',
),
}
})
const onFinish = useCallback(() => setIsAnimationComplete(true), [])
useEffect(() => {
if (props.isReady) {
if (isReady) {
// hide on mount
SplashScreen.hideAsync().catch(() => {})
intro.value = withTiming(
1,
{duration: 200, easing: Easing.out(Easing.cubic)},
{duration: 400, easing: Easing.out(Easing.cubic)},
async () => {
// set these values to check animation at specific point
// outroLogo.value = 0.1
// outroApp.value = 0.1
outroLogo.value = withTiming(
1,
{duration: 1200, easing: Easing.in(Easing.cubic)},
@@ -100,24 +110,31 @@ export function Splash(props: React.PropsWithChildren<Props>) {
runOnJS(onFinish)()
},
)
outroApp.value = withTiming(
1,
{duration: 1200, easing: Easing.inOut(Easing.cubic)},
() => {
runOnJS(onFinish)()
},
)
outroApp.value = withTiming(1, {
duration: 1200,
easing: Easing.inOut(Easing.cubic),
})
outroAppOpacity.value = withTiming(1, {
duration: 1200,
easing: Easing.in(Easing.cubic),
})
},
)
}
}, [onFinish, intro, outroLogo, outroApp, props.isReady])
}, [onFinish, intro, outroLogo, outroApp, outroAppOpacity, isReady])
const onLoadEnd = useCallback(() => {
setIsImageLoaded(true)
}, [setIsImageLoaded])
return (
<View style={{flex: 1}}>
{!isAnimationComplete && (
<LinearGradient
colors={['#0A7AFF', '#59B9FF']}
style={[StyleSheet.absoluteFillObject]}
<Image
accessibilityIgnoresInvertColors
onLoadEnd={onLoadEnd}
source={{uri: splashImageUri}}
style={StyleSheet.absoluteFillObject}
/>
)}
-1
View File
@@ -13,7 +13,6 @@ interface TrackPropertiesMap {
'Sign In': {resumedSession: boolean} // CAN BE SERVER
'Create Account': {} // CAN BE SERVER
'Try Create Account': {}
'Create Account Successfully': {}
'Signin:PressedForgotPassword': {}
'Signin:PressedSelectService': {}
// COMPOSER / CREATE POST events
+6
View File
@@ -104,12 +104,18 @@ export async function post(agent: BskyAgent, opts: PostOpts) {
// add image embed if present
if (opts.images?.length) {
logger.info(`Uploading images`, {
count: opts.images.length,
})
const images: AppBskyEmbedImages.Image[] = []
for (const image of opts.images) {
opts.onStateChange?.(`Uploading image #${images.length + 1}...`)
logger.info(`Compressing image`)
await image.compress()
const path = image.compressed?.path ?? image.path
const {width, height} = image.compressed || image
logger.info(`Uploading image`)
const res = await uploadBlob(agent, path, 'image/jpeg')
images.push({
image: res.data.blob,
+139 -103
View File
@@ -75,6 +75,10 @@ msgstr ""
#~ msgid "<0>Note: Your profile and posts will remain publicly available. Third-party apps that display Bluesky content may not respect this setting.</0>"
#~ msgstr ""
#: src/view/com/util/moderation/LabelInfo.tsx:45
msgid "A content warning has been applied to this {0}."
msgstr ""
#: src/lib/hooks/useOTAUpdate.ts:16
msgid "A new version of the app is available. Please update to continue using the app."
msgstr ""
@@ -95,7 +99,7 @@ msgstr ""
#: src/view/com/modals/ListAddRemoveUsers.tsx:264
#: src/view/com/modals/UserAddRemoveLists.tsx:193
#: src/view/screens/ProfileList.tsx:753
#: src/view/screens/ProfileList.tsx:754
msgid "Add"
msgstr ""
@@ -103,7 +107,7 @@ msgstr ""
msgid "Add a content warning"
msgstr ""
#: src/view/screens/ProfileList.tsx:743
#: src/view/screens/ProfileList.tsx:744
msgid "Add a user to this list"
msgstr ""
@@ -126,11 +130,11 @@ msgstr ""
msgid "Add details to report"
msgstr ""
#: src/view/com/composer/Composer.tsx:432
#: src/view/com/composer/Composer.tsx:438
msgid "Add link card"
msgstr ""
#: src/view/com/composer/Composer.tsx:435
#: src/view/com/composer/Composer.tsx:441
msgid "Add link card:"
msgstr ""
@@ -142,7 +146,7 @@ msgstr ""
msgid "Add to Lists"
msgstr ""
#: src/view/screens/ProfileFeed.tsx:275
#: src/view/screens/ProfileFeed.tsx:270
msgid "Add to my feeds"
msgstr ""
@@ -200,15 +204,23 @@ msgstr ""
msgid "App Passwords"
msgstr ""
#: src/view/com/modals/AppealLabel.tsx:65
msgid "Appeal Decision"
#: src/view/com/util/forms/PostDropdownBtn.tsx:207
msgid "Appeal content warning"
msgstr ""
#: src/view/com/util/moderation/LabelInfo.tsx:51
#: src/view/com/modals/AppealLabel.tsx:65
msgid "Appeal Content Warning"
msgstr ""
#: src/view/com/modals/AppealLabel.tsx:65
#~ msgid "Appeal Decision"
#~ msgstr ""
#: src/view/com/util/moderation/LabelInfo.tsx:52
msgid "Appeal this decision"
msgstr ""
#: src/view/com/util/moderation/LabelInfo.tsx:55
#: src/view/com/util/moderation/LabelInfo.tsx:56
msgid "Appeal this decision."
msgstr ""
@@ -224,15 +236,15 @@ msgstr ""
msgid "Are you sure you want to delete the app password \"{name}\"?"
msgstr ""
#: src/view/com/composer/Composer.tsx:141
#: src/view/com/composer/Composer.tsx:142
msgid "Are you sure you'd like to discard this draft?"
msgstr ""
#: src/view/screens/ProfileList.tsx:351
#: src/view/screens/ProfileList.tsx:352
msgid "Are you sure?"
msgstr ""
#: src/view/com/util/forms/PostDropdownBtn.tsx:188
#: src/view/com/util/forms/PostDropdownBtn.tsx:190
msgid "Are you sure? This cannot be undone."
msgstr ""
@@ -244,7 +256,7 @@ msgstr ""
#~ msgid "Ask apps to limit the visibility of my account"
#~ msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:145
#: src/view/com/auth/create/CreateAccount.tsx:141
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
#: src/view/com/auth/login/LoginForm.tsx:249
@@ -275,15 +287,15 @@ msgstr ""
msgid "Block Account"
msgstr ""
#: src/view/screens/ProfileList.tsx:521
#: src/view/screens/ProfileList.tsx:522
msgid "Block accounts"
msgstr ""
#: src/view/screens/ProfileList.tsx:471
#: src/view/screens/ProfileList.tsx:472
msgid "Block list"
msgstr ""
#: src/view/screens/ProfileList.tsx:306
#: src/view/screens/ProfileList.tsx:307
msgid "Block these accounts?"
msgstr ""
@@ -307,7 +319,7 @@ msgstr ""
msgid "Blocked post."
msgstr ""
#: src/view/screens/ProfileList.tsx:308
#: src/view/screens/ProfileList.tsx:309
msgid "Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you."
msgstr ""
@@ -316,7 +328,6 @@ msgid "Blog"
msgstr ""
#: src/view/com/auth/HomeLoggedOutCTA.tsx:31
#: src/view/com/auth/SplashScreen.tsx:26
msgid "Bluesky"
msgstr ""
@@ -362,8 +373,8 @@ msgstr ""
msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
msgstr ""
#: src/view/com/composer/Composer.tsx:279
#: src/view/com/composer/Composer.tsx:282
#: src/view/com/composer/Composer.tsx:285
#: src/view/com/composer/Composer.tsx:288
#: src/view/com/modals/AltImage.tsx:127
#: src/view/com/modals/ChangeEmail.tsx:218
#: src/view/com/modals/ChangeEmail.tsx:220
@@ -542,7 +553,7 @@ msgstr ""
msgid "Confirmation code"
msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:178
#: src/view/com/auth/create/CreateAccount.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:268
msgid "Connecting..."
msgstr ""
@@ -582,11 +593,11 @@ msgstr ""
msgid "Copy"
msgstr ""
#: src/view/screens/ProfileList.tsx:383
#: src/view/screens/ProfileList.tsx:384
msgid "Copy link to list"
msgstr ""
#: src/view/com/util/forms/PostDropdownBtn.tsx:129
#: src/view/com/util/forms/PostDropdownBtn.tsx:131
msgid "Copy link to post"
msgstr ""
@@ -594,7 +605,7 @@ msgstr ""
msgid "Copy link to profile"
msgstr ""
#: src/view/com/util/forms/PostDropdownBtn.tsx:115
#: src/view/com/util/forms/PostDropdownBtn.tsx:117
msgid "Copy post text"
msgstr ""
@@ -602,25 +613,25 @@ msgstr ""
msgid "Copyright Policy"
msgstr ""
#: src/view/screens/ProfileFeed.tsx:98
#: src/view/screens/ProfileFeed.tsx:94
msgid "Could not load feed"
msgstr ""
#: src/view/screens/ProfileList.tsx:829
#: src/view/screens/ProfileList.tsx:830
msgid "Could not load list"
msgstr ""
#: src/view/com/auth/HomeLoggedOutCTA.tsx:62
#: src/view/com/auth/SplashScreen.tsx:41
#: src/view/com/auth/SplashScreen.tsx:46
msgid "Create a new account"
msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:124
#: src/view/com/auth/create/CreateAccount.tsx:120
msgid "Create Account"
msgstr ""
#: src/view/com/auth/HomeLoggedOutCTA.tsx:54
#: src/view/com/auth/SplashScreen.tsx:38
#: src/view/com/auth/SplashScreen.tsx:43
msgid "Create new account"
msgstr ""
@@ -654,8 +665,8 @@ msgstr ""
msgid "Delete app password"
msgstr ""
#: src/view/screens/ProfileList.tsx:350
#: src/view/screens/ProfileList.tsx:410
#: src/view/screens/ProfileList.tsx:351
#: src/view/screens/ProfileList.tsx:411
msgid "Delete List"
msgstr ""
@@ -667,11 +678,11 @@ msgstr ""
msgid "Delete my account…"
msgstr ""
#: src/view/com/util/forms/PostDropdownBtn.tsx:183
#: src/view/com/util/forms/PostDropdownBtn.tsx:185
msgid "Delete post"
msgstr ""
#: src/view/com/util/forms/PostDropdownBtn.tsx:187
#: src/view/com/util/forms/PostDropdownBtn.tsx:189
msgid "Delete this post?"
msgstr ""
@@ -694,11 +705,11 @@ msgstr ""
msgid "Developer Tools"
msgstr ""
#: src/view/com/composer/Composer.tsx:142
#: src/view/com/composer/Composer.tsx:143
msgid "Discard"
msgstr ""
#: src/view/com/composer/Composer.tsx:136
#: src/view/com/composer/Composer.tsx:137
msgid "Discard draft"
msgstr ""
@@ -750,7 +761,7 @@ msgstr ""
msgid "Edit image"
msgstr ""
#: src/view/screens/ProfileList.tsx:398
#: src/view/screens/ProfileList.tsx:399
msgid "Edit list details"
msgstr ""
@@ -858,8 +869,8 @@ msgstr ""
#: src/view/screens/Feeds.tsx:475
#: src/view/screens/Profile.tsx:164
#: src/view/shell/bottom-bar/BottomBar.tsx:163
#: src/view/shell/desktop/LeftNav.tsx:335
#: src/view/shell/bottom-bar/BottomBar.tsx:181
#: src/view/shell/desktop/LeftNav.tsx:339
#: src/view/shell/Drawer.tsx:455
#: src/view/shell/Drawer.tsx:456
msgid "Feeds"
@@ -959,17 +970,17 @@ msgstr ""
msgid "Get Started"
msgstr ""
#: src/view/com/auth/LoggedOut.tsx:70
#: src/view/com/auth/LoggedOut.tsx:71
#: src/view/com/auth/LoggedOut.tsx:81
#: src/view/com/auth/LoggedOut.tsx:82
#: src/view/com/util/moderation/ScreenHider.tsx:123
#: src/view/shell/desktop/LeftNav.tsx:103
msgid "Go back"
msgstr ""
#: src/view/screens/ProfileFeed.tsx:107
#: src/view/screens/ProfileFeed.tsx:112
#: src/view/screens/ProfileList.tsx:838
#: src/view/screens/ProfileList.tsx:843
#: src/view/screens/ProfileFeed.tsx:103
#: src/view/screens/ProfileFeed.tsx:108
#: src/view/screens/ProfileList.tsx:839
#: src/view/screens/ProfileList.tsx:844
msgid "Go Back"
msgstr ""
@@ -1029,14 +1040,14 @@ msgstr ""
#~ msgid "Hmmm, we're having trouble finding this feed. It may have been deleted."
#~ msgstr ""
#: src/view/shell/bottom-bar/BottomBar.tsx:116
#: src/view/shell/desktop/LeftNav.tsx:297
#: src/view/shell/bottom-bar/BottomBar.tsx:137
#: src/view/shell/desktop/LeftNav.tsx:303
#: src/view/shell/Drawer.tsx:379
#: src/view/shell/Drawer.tsx:380
msgid "Home"
msgstr ""
#: src/view/com/pager/FeedsTabBarMobile.tsx:99
#: src/view/com/pager/FeedsTabBarMobile.tsx:96
#: src/view/screens/PreferencesHomeFeed.tsx:95
#: src/view/screens/Settings.tsx:481
msgid "Home Feed Preferences"
@@ -1175,7 +1186,7 @@ msgstr ""
#~ msgid "Light"
#~ msgstr ""
#: src/view/screens/ProfileFeed.tsx:627
#: src/view/screens/ProfileFeed.tsx:577
msgid "Like this feed"
msgstr ""
@@ -1205,7 +1216,7 @@ msgid "List Name"
msgstr ""
#: src/view/screens/Profile.tsx:165
#: src/view/shell/desktop/LeftNav.tsx:372
#: src/view/shell/desktop/LeftNav.tsx:376
#: src/view/shell/Drawer.tsx:471
#: src/view/shell/Drawer.tsx:472
msgid "Lists"
@@ -1245,8 +1256,8 @@ msgid "Login to account that is not listed"
msgstr ""
#: src/view/screens/ProfileFeed.tsx:472
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
msgstr ""
#~ msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
#~ msgstr ""
#: src/view/com/modals/LinkWarning.tsx:63
msgid "Make sure this is where you intend to go!"
@@ -1269,13 +1280,12 @@ msgid "Menu"
msgstr ""
#: src/view/com/posts/FeedErrorMessage.tsx:194
#: src/view/screens/ProfileFeed.tsx:480
msgid "Message from server"
msgstr ""
#: src/view/screens/Moderation.tsx:64
#: src/view/screens/Settings.tsx:563
#: src/view/shell/desktop/LeftNav.tsx:390
#: src/view/shell/desktop/LeftNav.tsx:394
#: src/view/shell/Drawer.tsx:490
#: src/view/shell/Drawer.tsx:491
msgid "Moderation"
@@ -1294,8 +1304,8 @@ msgid "More feeds"
msgstr ""
#: src/view/com/profile/ProfileHeader.tsx:548
#: src/view/screens/ProfileFeed.tsx:365
#: src/view/screens/ProfileList.tsx:582
#: src/view/screens/ProfileFeed.tsx:360
#: src/view/screens/ProfileList.tsx:583
msgid "More options"
msgstr ""
@@ -1307,19 +1317,19 @@ msgstr ""
msgid "Mute Account"
msgstr ""
#: src/view/screens/ProfileList.tsx:509
#: src/view/screens/ProfileList.tsx:510
msgid "Mute accounts"
msgstr ""
#: src/view/screens/ProfileList.tsx:456
#: src/view/screens/ProfileList.tsx:457
msgid "Mute list"
msgstr ""
#: src/view/screens/ProfileList.tsx:269
#: src/view/screens/ProfileList.tsx:270
msgid "Mute these accounts?"
msgstr ""
#: src/view/com/util/forms/PostDropdownBtn.tsx:147
#: src/view/com/util/forms/PostDropdownBtn.tsx:149
msgid "Mute thread"
msgstr ""
@@ -1335,7 +1345,7 @@ msgstr ""
msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private."
msgstr ""
#: src/view/screens/ProfileList.tsx:271
#: src/view/screens/ProfileList.tsx:272
msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them."
msgstr ""
@@ -1376,9 +1386,9 @@ msgstr ""
#: src/view/com/feeds/FeedPage.tsx:200
#: src/view/screens/Feeds.tsx:510
#: src/view/screens/Profile.tsx:353
#: src/view/screens/ProfileFeed.tsx:441
#: src/view/screens/ProfileList.tsx:192
#: src/view/screens/ProfileList.tsx:220
#: src/view/screens/ProfileFeed.tsx:430
#: src/view/screens/ProfileList.tsx:193
#: src/view/screens/ProfileList.tsx:221
#: src/view/shell/desktop/LeftNav.tsx:246
msgid "New post"
msgstr ""
@@ -1387,7 +1397,7 @@ msgstr ""
msgid "New Post"
msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:158
#: src/view/com/auth/create/CreateAccount.tsx:154
#: src/view/com/auth/login/ForgotPasswordForm.tsx:174
#: src/view/com/auth/login/ForgotPasswordForm.tsx:184
#: src/view/com/auth/login/LoginForm.tsx:281
@@ -1407,8 +1417,8 @@ msgstr ""
msgid "No"
msgstr ""
#: src/view/screens/ProfileFeed.tsx:620
#: src/view/screens/ProfileList.tsx:710
#: src/view/screens/ProfileFeed.tsx:570
#: src/view/screens/ProfileList.tsx:711
msgid "No description"
msgstr ""
@@ -1459,8 +1469,8 @@ msgstr ""
#: src/view/screens/Notifications.tsx:109
#: src/view/screens/Notifications.tsx:133
#: src/view/shell/bottom-bar/BottomBar.tsx:187
#: src/view/shell/desktop/LeftNav.tsx:354
#: src/view/shell/bottom-bar/BottomBar.tsx:205
#: src/view/shell/desktop/LeftNav.tsx:358
#: src/view/shell/Drawer.tsx:416
#: src/view/shell/Drawer.tsx:417
msgid "Notifications"
@@ -1474,7 +1484,7 @@ msgstr ""
msgid "Okay"
msgstr ""
#: src/view/com/composer/Composer.tsx:348
#: src/view/com/composer/Composer.tsx:354
msgid "One or more images is missing alt text."
msgstr ""
@@ -1482,7 +1492,7 @@ msgstr ""
msgid "Only {0} can reply."
msgstr ""
#: src/view/com/pager/FeedsTabBarMobile.tsx:79
#: src/view/com/pager/FeedsTabBarMobile.tsx:76
msgid "Open navigation"
msgstr ""
@@ -1594,12 +1604,17 @@ msgstr ""
#: src/view/com/modals/AppealLabel.tsx:72
#: src/view/com/modals/AppealLabel.tsx:75
msgid "Please tell us why you think this decision was incorrect."
msgid "Please tell us why you think this content warning was incorrectly applied!"
msgstr ""
#: src/view/com/composer/Composer.tsx:331
#: src/view/com/modals/AppealLabel.tsx:72
#: src/view/com/modals/AppealLabel.tsx:75
#~ msgid "Please tell us why you think this decision was incorrect."
#~ msgstr ""
#: src/view/com/composer/Composer.tsx:337
#: src/view/com/post-thread/PostThread.tsx:226
#: src/view/screens/PostThread.tsx:78
#: src/view/screens/PostThread.tsx:80
msgid "Post"
msgstr ""
@@ -1651,7 +1666,8 @@ msgstr ""
msgid "Processing..."
msgstr ""
#: src/view/shell/bottom-bar/BottomBar.tsx:229
#: src/view/shell/bottom-bar/BottomBar.tsx:247
#: src/view/shell/desktop/LeftNav.tsx:412
#: src/view/shell/Drawer.tsx:69
#: src/view/shell/Drawer.tsx:525
#: src/view/shell/Drawer.tsx:526
@@ -1718,7 +1734,7 @@ msgstr ""
#: src/view/com/feeds/FeedSourceCard.tsx:105
#: src/view/com/feeds/FeedSourceCard.tsx:172
#: src/view/screens/ProfileFeed.tsx:275
#: src/view/screens/ProfileFeed.tsx:270
msgid "Remove from my feeds"
msgstr ""
@@ -1763,16 +1779,16 @@ msgstr ""
msgid "Report Account"
msgstr ""
#: src/view/screens/ProfileFeed.tsx:295
#: src/view/screens/ProfileFeed.tsx:290
msgid "Report feed"
msgstr ""
#: src/view/screens/ProfileList.tsx:424
#: src/view/screens/ProfileList.tsx:425
msgid "Report List"
msgstr ""
#: src/view/com/modals/report/SendReportButton.tsx:37
#: src/view/com/util/forms/PostDropdownBtn.tsx:165
#: src/view/com/util/forms/PostDropdownBtn.tsx:167
msgid "Report post"
msgstr ""
@@ -1830,8 +1846,8 @@ msgstr ""
msgid "Resets the preferences state"
msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:163
#: src/view/com/auth/create/CreateAccount.tsx:167
#: src/view/com/auth/create/CreateAccount.tsx:171
#: src/view/com/auth/login/LoginForm.tsx:258
#: src/view/com/auth/login/LoginForm.tsx:261
#: src/view/com/util/error/ErrorMessage.tsx:55
@@ -1881,8 +1897,8 @@ msgstr ""
#: src/view/com/util/forms/SearchInput.tsx:64
#: src/view/screens/Search/Search.tsx:401
#: src/view/screens/Search/Search.tsx:567
#: src/view/shell/bottom-bar/BottomBar.tsx:138
#: src/view/shell/desktop/LeftNav.tsx:315
#: src/view/shell/bottom-bar/BottomBar.tsx:159
#: src/view/shell/desktop/LeftNav.tsx:321
#: src/view/shell/desktop/Search.tsx:161
#: src/view/shell/desktop/Search.tsx:170
#: src/view/shell/Drawer.tsx:343
@@ -1894,12 +1910,16 @@ msgstr ""
#~ msgid "Search for posts and users."
#~ msgstr ""
#: src/view/com/auth/LoggedOut.tsx:104
#: src/view/com/auth/LoggedOut.tsx:105
msgid "Search for users"
msgstr ""
#: src/view/com/modals/ChangeEmail.tsx:110
msgid "Security Step Required"
msgstr ""
#: src/view/com/auth/HomeLoggedOutCTA.tsx:39
#: src/view/com/auth/SplashScreen.tsx:29
msgid "See what's next"
msgstr ""
@@ -1973,7 +1993,7 @@ msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your f
msgstr ""
#: src/view/screens/Settings.tsx:277
#: src/view/shell/desktop/LeftNav.tsx:426
#: src/view/shell/desktop/LeftNav.tsx:430
#: src/view/shell/Drawer.tsx:546
#: src/view/shell/Drawer.tsx:547
msgid "Settings"
@@ -1984,12 +2004,12 @@ msgid "Sexual activity or erotic nudity."
msgstr ""
#: src/view/com/profile/ProfileHeader.tsx:338
#: src/view/com/util/forms/PostDropdownBtn.tsx:129
#: src/view/screens/ProfileList.tsx:383
#: src/view/com/util/forms/PostDropdownBtn.tsx:131
#: src/view/screens/ProfileList.tsx:384
msgid "Share"
msgstr ""
#: src/view/screens/ProfileFeed.tsx:307
#: src/view/screens/ProfileFeed.tsx:302
msgid "Share feed"
msgstr ""
@@ -2032,15 +2052,21 @@ msgstr ""
#: src/view/com/auth/HomeLoggedOutCTA.tsx:70
#: src/view/com/auth/login/Login.tsx:98
#: src/view/com/auth/SplashScreen.tsx:49
#: src/view/com/auth/SplashScreen.tsx:54
#: src/view/shell/bottom-bar/BottomBar.tsx:285
#: src/view/shell/bottom-bar/BottomBar.tsx:286
#: src/view/shell/bottom-bar/BottomBar.tsx:288
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:177
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:178
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:180
#: src/view/shell/NavSignupCard.tsx:58
#: src/view/shell/NavSignupCard.tsx:59
msgid "Sign in"
msgstr ""
#: src/view/com/auth/HomeLoggedOutCTA.tsx:78
#: src/view/com/auth/SplashScreen.tsx:52
#: src/view/com/auth/SplashScreen.web.tsx:84
#: src/view/com/auth/SplashScreen.tsx:57
#: src/view/com/auth/SplashScreen.web.tsx:87
msgid "Sign In"
msgstr ""
@@ -2062,6 +2088,12 @@ msgstr ""
msgid "Sign out"
msgstr ""
#: src/view/shell/bottom-bar/BottomBar.tsx:275
#: src/view/shell/bottom-bar/BottomBar.tsx:276
#: src/view/shell/bottom-bar/BottomBar.tsx:278
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:167
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:168
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:170
#: src/view/shell/NavSignupCard.tsx:49
#: src/view/shell/NavSignupCard.tsx:50
#: src/view/shell/NavSignupCard.tsx:52
@@ -2113,11 +2145,11 @@ msgstr ""
msgid "Submit"
msgstr "Submit"
#: src/view/screens/ProfileList.tsx:573
#: src/view/screens/ProfileList.tsx:574
msgid "Subscribe"
msgstr ""
#: src/view/screens/ProfileList.tsx:569
#: src/view/screens/ProfileList.tsx:570
msgid "Subscribe to this list"
msgstr ""
@@ -2192,8 +2224,8 @@ msgid "There was an unexpected issue in the application. Please let us know if t
msgstr ""
#: src/view/com/util/moderation/LabelInfo.tsx:45
msgid "This {0} has been labeled."
msgstr ""
#~ msgid "This {0} has been labeled."
#~ msgstr ""
#: src/view/com/util/moderation/ScreenHider.tsx:88
msgid "This {screenDescription} has been flagged:"
@@ -2227,7 +2259,7 @@ msgstr ""
msgid "This link is taking you to the following website:"
msgstr ""
#: src/view/com/post-thread/PostThreadItem.tsx:124
#: src/view/com/post-thread/PostThreadItem.tsx:123
msgid "This post has been deleted."
msgstr ""
@@ -2252,9 +2284,9 @@ msgstr ""
msgid "Transformations"
msgstr ""
#: src/view/com/post-thread/PostThreadItem.tsx:704
#: src/view/com/post-thread/PostThreadItem.tsx:706
#: src/view/com/post-thread/PostThreadItem.tsx:708
#: src/view/com/util/forms/PostDropdownBtn.tsx:101
#: src/view/com/util/forms/PostDropdownBtn.tsx:103
msgid "Translate"
msgstr ""
@@ -2262,11 +2294,11 @@ msgstr ""
msgid "Try again"
msgstr ""
#: src/view/screens/ProfileList.tsx:471
#: src/view/screens/ProfileList.tsx:472
msgid "Un-block list"
msgstr ""
#: src/view/screens/ProfileList.tsx:456
#: src/view/screens/ProfileList.tsx:457
msgid "Un-mute list"
msgstr ""
@@ -2298,11 +2330,11 @@ msgstr ""
msgid "Unmute Account"
msgstr ""
#: src/view/com/util/forms/PostDropdownBtn.tsx:147
#: src/view/com/util/forms/PostDropdownBtn.tsx:149
msgid "Unmute thread"
msgstr ""
#: src/view/screens/ProfileList.tsx:439
#: src/view/screens/ProfileList.tsx:440
msgid "Unpin moderation list"
msgstr ""
@@ -2351,7 +2383,7 @@ msgstr ""
msgid "Username or email address"
msgstr ""
#: src/view/screens/ProfileList.tsx:737
#: src/view/screens/ProfileList.tsx:738
msgid "Users"
msgstr ""
@@ -2396,7 +2428,7 @@ msgstr ""
msgid "Visit Site"
msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:125
#: src/view/com/auth/create/CreateAccount.tsx:121
msgid "We're so excited to have you join us!"
msgstr ""
@@ -2424,6 +2456,10 @@ msgstr ""
msgid "What is the issue with this {collectionName}?"
msgstr ""
#: src/view/com/auth/SplashScreen.tsx:34
msgid "What's up?"
msgstr ""
#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:78
msgid "Which languages are used in this post?"
msgstr ""
@@ -2445,7 +2481,7 @@ msgstr ""
msgid "Wide"
msgstr ""
#: src/view/com/composer/Composer.tsx:403
#: src/view/com/composer/Composer.tsx:409
msgid "Write post"
msgstr ""
+139 -103
View File
@@ -75,6 +75,10 @@ msgstr "<0>कुछ</0><1>पसंदीदा उपयोगकर्ता
#~ msgid "<0>Note: Your profile and posts will remain publicly available. Third-party apps that display Bluesky content may not respect this setting.</0>"
#~ msgstr ""
#: src/view/com/util/moderation/LabelInfo.tsx:45
msgid "A content warning has been applied to this {0}."
msgstr ""
#: src/lib/hooks/useOTAUpdate.ts:16
msgid "A new version of the app is available. Please update to continue using the app."
msgstr "ऐप का एक नया संस्करण उपलब्ध है. कृपया ऐप का उपयोग जारी रखने के लिए अपडेट करें।"
@@ -95,7 +99,7 @@ msgstr "अकाउंट के विकल्प"
#: src/view/com/modals/ListAddRemoveUsers.tsx:264
#: src/view/com/modals/UserAddRemoveLists.tsx:193
#: src/view/screens/ProfileList.tsx:753
#: src/view/screens/ProfileList.tsx:754
msgid "Add"
msgstr "ऐड करो"
@@ -103,7 +107,7 @@ msgstr "ऐड करो"
msgid "Add a content warning"
msgstr "सामग्री चेतावनी जोड़ें"
#: src/view/screens/ProfileList.tsx:743
#: src/view/screens/ProfileList.tsx:744
msgid "Add a user to this list"
msgstr "इस सूची में किसी को जोड़ें"
@@ -126,11 +130,11 @@ msgstr "विवरण जोड़ें"
msgid "Add details to report"
msgstr "रिपोर्ट करने के लिए विवरण जोड़ें"
#: src/view/com/composer/Composer.tsx:432
#: src/view/com/composer/Composer.tsx:438
msgid "Add link card"
msgstr "लिंक कार्ड जोड़ें"
#: src/view/com/composer/Composer.tsx:435
#: src/view/com/composer/Composer.tsx:441
msgid "Add link card:"
msgstr "लिंक कार्ड जोड़ें:"
@@ -142,7 +146,7 @@ msgstr "अपने डोमेन में निम्नलिखित DN
msgid "Add to Lists"
msgstr "सूचियों में जोड़ें"
#: src/view/screens/ProfileFeed.tsx:275
#: src/view/screens/ProfileFeed.tsx:270
msgid "Add to my feeds"
msgstr "इस फ़ीड को सहेजें"
@@ -200,15 +204,23 @@ msgstr "ऐप पासवर्ड"
msgid "App Passwords"
msgstr "ऐप पासवर्ड"
#: src/view/com/modals/AppealLabel.tsx:65
msgid "Appeal Decision"
#: src/view/com/util/forms/PostDropdownBtn.tsx:207
msgid "Appeal content warning"
msgstr ""
#: src/view/com/util/moderation/LabelInfo.tsx:51
#: src/view/com/modals/AppealLabel.tsx:65
msgid "Appeal Content Warning"
msgstr ""
#: src/view/com/modals/AppealLabel.tsx:65
#~ msgid "Appeal Decision"
#~ msgstr ""
#: src/view/com/util/moderation/LabelInfo.tsx:52
msgid "Appeal this decision"
msgstr ""
#: src/view/com/util/moderation/LabelInfo.tsx:55
#: src/view/com/util/moderation/LabelInfo.tsx:56
msgid "Appeal this decision."
msgstr ""
@@ -224,15 +236,15 @@ msgstr "दिखावट"
msgid "Are you sure you want to delete the app password \"{name}\"?"
msgstr "क्या आप वाकई ऐप पासवर्ड \"{name}\" हटाना चाहते हैं?"
#: src/view/com/composer/Composer.tsx:141
#: src/view/com/composer/Composer.tsx:142
msgid "Are you sure you'd like to discard this draft?"
msgstr "क्या आप वाकई इस ड्राफ्ट को हटाना करना चाहेंगे?"
#: src/view/screens/ProfileList.tsx:351
#: src/view/screens/ProfileList.tsx:352
msgid "Are you sure?"
msgstr "क्या आप वास्तव में इसे करना चाहते हैं?"
#: src/view/com/util/forms/PostDropdownBtn.tsx:188
#: src/view/com/util/forms/PostDropdownBtn.tsx:190
msgid "Are you sure? This cannot be undone."
msgstr "क्या आप वास्तव में इसे करना चाहते हैं? इसे असंपादित नहीं किया जा सकता है।"
@@ -244,7 +256,7 @@ msgstr "कलात्मक या गैर-कामुक नग्नत
#~ msgid "Ask apps to limit the visibility of my account"
#~ msgstr ""
#: src/view/com/auth/create/CreateAccount.tsx:145
#: src/view/com/auth/create/CreateAccount.tsx:141
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
#: src/view/com/auth/login/LoginForm.tsx:249
@@ -275,15 +287,15 @@ msgstr "जन्मदिन:"
msgid "Block Account"
msgstr "खाता ब्लॉक करें"
#: src/view/screens/ProfileList.tsx:521
#: src/view/screens/ProfileList.tsx:522
msgid "Block accounts"
msgstr "खाता ब्लॉक करें"
#: src/view/screens/ProfileList.tsx:471
#: src/view/screens/ProfileList.tsx:472
msgid "Block list"
msgstr ""
#: src/view/screens/ProfileList.tsx:306
#: src/view/screens/ProfileList.tsx:307
msgid "Block these accounts?"
msgstr "खाता ब्लॉक करें?"
@@ -307,7 +319,7 @@ msgstr "अवरुद्ध खाते आपके थ्रेड्स
msgid "Blocked post."
msgstr "ब्लॉक पोस्ट।"
#: src/view/screens/ProfileList.tsx:308
#: src/view/screens/ProfileList.tsx:309
msgid "Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you."
msgstr "अवरोधन सार्वजनिक है. अवरुद्ध खाते आपके थ्रेड्स में उत्तर नहीं दे सकते, आपका उल्लेख नहीं कर सकते, या अन्यथा आपके साथ बातचीत नहीं कर सकते।"
@@ -316,7 +328,6 @@ msgid "Blog"
msgstr ""
#: src/view/com/auth/HomeLoggedOutCTA.tsx:31
#: src/view/com/auth/SplashScreen.tsx:26
msgid "Bluesky"
msgstr "Bluesky"
@@ -362,8 +373,8 @@ msgstr "कैमरा"
msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
msgstr "केवल अक्षर, संख्या, रिक्त स्थान, डैश और अंडरस्कोर हो सकते हैं। कम से कम 4 अक्षर लंबा होना चाहिए, लेकिन 32 अक्षरों से अधिक लंबा नहीं होना चाहिए।।"
#: src/view/com/composer/Composer.tsx:279
#: src/view/com/composer/Composer.tsx:282
#: src/view/com/composer/Composer.tsx:285
#: src/view/com/composer/Composer.tsx:288
#: src/view/com/modals/AltImage.tsx:127
#: src/view/com/modals/ChangeEmail.tsx:218
#: src/view/com/modals/ChangeEmail.tsx:220
@@ -538,7 +549,7 @@ msgstr "खाते को हटा दें"
msgid "Confirmation code"
msgstr "OTP कोड"
#: src/view/com/auth/create/CreateAccount.tsx:178
#: src/view/com/auth/create/CreateAccount.tsx:174
#: src/view/com/auth/login/LoginForm.tsx:268
msgid "Connecting..."
msgstr "कनेक्टिंग ..।"
@@ -578,11 +589,11 @@ msgstr "कॉपी कर ली"
msgid "Copy"
msgstr "कॉपी"
#: src/view/screens/ProfileList.tsx:383
#: src/view/screens/ProfileList.tsx:384
msgid "Copy link to list"
msgstr ""
#: src/view/com/util/forms/PostDropdownBtn.tsx:129
#: src/view/com/util/forms/PostDropdownBtn.tsx:131
msgid "Copy link to post"
msgstr ""
@@ -590,7 +601,7 @@ msgstr ""
msgid "Copy link to profile"
msgstr ""
#: src/view/com/util/forms/PostDropdownBtn.tsx:115
#: src/view/com/util/forms/PostDropdownBtn.tsx:117
msgid "Copy post text"
msgstr "पोस्ट टेक्स्ट कॉपी करें"
@@ -598,25 +609,25 @@ msgstr "पोस्ट टेक्स्ट कॉपी करें"
msgid "Copyright Policy"
msgstr "कॉपीराइट नीति"
#: src/view/screens/ProfileFeed.tsx:98
#: src/view/screens/ProfileFeed.tsx:94
msgid "Could not load feed"
msgstr "फ़ीड लोड नहीं कर सकता"
#: src/view/screens/ProfileList.tsx:829
#: src/view/screens/ProfileList.tsx:830
msgid "Could not load list"
msgstr "सूची लोड नहीं कर सकता"
#: src/view/com/auth/HomeLoggedOutCTA.tsx:62
#: src/view/com/auth/SplashScreen.tsx:41
#: src/view/com/auth/SplashScreen.tsx:46
msgid "Create a new account"
msgstr "नया खाता बनाएं"
#: src/view/com/auth/create/CreateAccount.tsx:124
#: src/view/com/auth/create/CreateAccount.tsx:120
msgid "Create Account"
msgstr "खाता बनाएँ"
#: src/view/com/auth/HomeLoggedOutCTA.tsx:54
#: src/view/com/auth/SplashScreen.tsx:38
#: src/view/com/auth/SplashScreen.tsx:43
msgid "Create new account"
msgstr "नया खाता बनाएं"
@@ -650,8 +661,8 @@ msgstr "खाता हटाएं"
msgid "Delete app password"
msgstr "अप्प पासवर्ड हटाएं"
#: src/view/screens/ProfileList.tsx:350
#: src/view/screens/ProfileList.tsx:410
#: src/view/screens/ProfileList.tsx:351
#: src/view/screens/ProfileList.tsx:411
msgid "Delete List"
msgstr "सूची हटाएँ"
@@ -663,11 +674,11 @@ msgstr "मेरा खाता हटाएं"
msgid "Delete my account…"
msgstr "मेरा खाता हटाएं…"
#: src/view/com/util/forms/PostDropdownBtn.tsx:183
#: src/view/com/util/forms/PostDropdownBtn.tsx:185
msgid "Delete post"
msgstr "पोस्ट को हटाएं"
#: src/view/com/util/forms/PostDropdownBtn.tsx:187
#: src/view/com/util/forms/PostDropdownBtn.tsx:189
msgid "Delete this post?"
msgstr "इस पोस्ट को डीलीट करें?"
@@ -690,11 +701,11 @@ msgstr "देव सर्वर"
msgid "Developer Tools"
msgstr "डेवलपर उपकरण"
#: src/view/com/composer/Composer.tsx:142
#: src/view/com/composer/Composer.tsx:143
msgid "Discard"
msgstr ""
#: src/view/com/composer/Composer.tsx:136
#: src/view/com/composer/Composer.tsx:137
msgid "Discard draft"
msgstr "ड्राफ्ट हटाएं"
@@ -746,7 +757,7 @@ msgstr "प्रत्येक कोड एक बार काम करत
msgid "Edit image"
msgstr "छवि संपादित करें"
#: src/view/screens/ProfileList.tsx:398
#: src/view/screens/ProfileList.tsx:399
msgid "Edit list details"
msgstr "सूची विवरण संपादित करें"
@@ -854,8 +865,8 @@ msgstr "प्रतिक्रिया"
#: src/view/screens/Feeds.tsx:475
#: src/view/screens/Profile.tsx:164
#: src/view/shell/bottom-bar/BottomBar.tsx:163
#: src/view/shell/desktop/LeftNav.tsx:335
#: src/view/shell/bottom-bar/BottomBar.tsx:181
#: src/view/shell/desktop/LeftNav.tsx:339
#: src/view/shell/Drawer.tsx:455
#: src/view/shell/Drawer.tsx:456
msgid "Feeds"
@@ -951,17 +962,17 @@ msgstr "गैलरी"
msgid "Get Started"
msgstr "प्रारंभ करें"
#: src/view/com/auth/LoggedOut.tsx:70
#: src/view/com/auth/LoggedOut.tsx:71
#: src/view/com/auth/LoggedOut.tsx:81
#: src/view/com/auth/LoggedOut.tsx:82
#: src/view/com/util/moderation/ScreenHider.tsx:123
#: src/view/shell/desktop/LeftNav.tsx:103
msgid "Go back"
msgstr "वापस जाओ"
#: src/view/screens/ProfileFeed.tsx:107
#: src/view/screens/ProfileFeed.tsx:112
#: src/view/screens/ProfileList.tsx:838
#: src/view/screens/ProfileList.tsx:843
#: src/view/screens/ProfileFeed.tsx:103
#: src/view/screens/ProfileFeed.tsx:108
#: src/view/screens/ProfileList.tsx:839
#: src/view/screens/ProfileList.tsx:844
msgid "Go Back"
msgstr "वापस जाओ"
@@ -1021,14 +1032,14 @@ msgstr ""
#~ msgid "Hmmm, we're having trouble finding this feed. It may have been deleted."
#~ msgstr ""
#: src/view/shell/bottom-bar/BottomBar.tsx:116
#: src/view/shell/desktop/LeftNav.tsx:297
#: src/view/shell/bottom-bar/BottomBar.tsx:137
#: src/view/shell/desktop/LeftNav.tsx:303
#: src/view/shell/Drawer.tsx:379
#: src/view/shell/Drawer.tsx:380
msgid "Home"
msgstr "होम फीड"
#: src/view/com/pager/FeedsTabBarMobile.tsx:99
#: src/view/com/pager/FeedsTabBarMobile.tsx:96
#: src/view/screens/PreferencesHomeFeed.tsx:95
#: src/view/screens/Settings.tsx:481
msgid "Home Feed Preferences"
@@ -1167,7 +1178,7 @@ msgstr "चित्र पुस्तकालय"
#~ msgid "Light"
#~ msgstr "लाइट मोड"
#: src/view/screens/ProfileFeed.tsx:627
#: src/view/screens/ProfileFeed.tsx:577
msgid "Like this feed"
msgstr "इस फ़ीड को लाइक करो"
@@ -1197,7 +1208,7 @@ msgid "List Name"
msgstr "सूची का नाम"
#: src/view/screens/Profile.tsx:165
#: src/view/shell/desktop/LeftNav.tsx:372
#: src/view/shell/desktop/LeftNav.tsx:376
#: src/view/shell/Drawer.tsx:471
#: src/view/shell/Drawer.tsx:472
msgid "Lists"
@@ -1237,8 +1248,8 @@ msgid "Login to account that is not listed"
msgstr "उस खाते में लॉग इन करें जो सूचीबद्ध नहीं है"
#: src/view/screens/ProfileFeed.tsx:472
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
msgstr ""
#~ msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
#~ msgstr ""
#: src/view/com/modals/LinkWarning.tsx:63
msgid "Make sure this is where you intend to go!"
@@ -1261,13 +1272,12 @@ msgid "Menu"
msgstr "मेनू"
#: src/view/com/posts/FeedErrorMessage.tsx:194
#: src/view/screens/ProfileFeed.tsx:480
msgid "Message from server"
msgstr ""
#: src/view/screens/Moderation.tsx:64
#: src/view/screens/Settings.tsx:563
#: src/view/shell/desktop/LeftNav.tsx:390
#: src/view/shell/desktop/LeftNav.tsx:394
#: src/view/shell/Drawer.tsx:490
#: src/view/shell/Drawer.tsx:491
msgid "Moderation"
@@ -1286,8 +1296,8 @@ msgid "More feeds"
msgstr "अधिक फ़ीड"
#: src/view/com/profile/ProfileHeader.tsx:548
#: src/view/screens/ProfileFeed.tsx:365
#: src/view/screens/ProfileList.tsx:582
#: src/view/screens/ProfileFeed.tsx:360
#: src/view/screens/ProfileList.tsx:583
msgid "More options"
msgstr "अधिक विकल्प"
@@ -1299,19 +1309,19 @@ msgstr "अधिक विकल्प"
msgid "Mute Account"
msgstr "खाता म्यूट करें"
#: src/view/screens/ProfileList.tsx:509
#: src/view/screens/ProfileList.tsx:510
msgid "Mute accounts"
msgstr "खातों को म्यूट करें"
#: src/view/screens/ProfileList.tsx:456
#: src/view/screens/ProfileList.tsx:457
msgid "Mute list"
msgstr ""
#: src/view/screens/ProfileList.tsx:269
#: src/view/screens/ProfileList.tsx:270
msgid "Mute these accounts?"
msgstr "इन खातों को म्यूट करें?"
#: src/view/com/util/forms/PostDropdownBtn.tsx:147
#: src/view/com/util/forms/PostDropdownBtn.tsx:149
msgid "Mute thread"
msgstr "थ्रेड म्यूट करें"
@@ -1327,7 +1337,7 @@ msgstr "म्यूट किए गए खाते"
msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private."
msgstr "म्यूट किए गए खातों की पोस्ट आपके फ़ीड और आपकी सूचनाओं से हटा दी जाती हैं। म्यूट पूरी तरह से निजी हैं."
#: src/view/screens/ProfileList.tsx:271
#: src/view/screens/ProfileList.tsx:272
msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them."
msgstr "म्यूट करना निजी है. म्यूट किए गए खाते आपके साथ इंटरैक्ट कर सकते हैं, लेकिन आप उनकी पोस्ट नहीं देखेंगे या उनसे सूचनाएं प्राप्त नहीं करेंगे।"
@@ -1368,9 +1378,9 @@ msgstr "नया"
#: src/view/com/feeds/FeedPage.tsx:200
#: src/view/screens/Feeds.tsx:510
#: src/view/screens/Profile.tsx:353
#: src/view/screens/ProfileFeed.tsx:441
#: src/view/screens/ProfileList.tsx:192
#: src/view/screens/ProfileList.tsx:220
#: src/view/screens/ProfileFeed.tsx:430
#: src/view/screens/ProfileList.tsx:193
#: src/view/screens/ProfileList.tsx:221
#: src/view/shell/desktop/LeftNav.tsx:246
msgid "New post"
msgstr "नई पोस्ट"
@@ -1379,7 +1389,7 @@ msgstr "नई पोस्ट"
msgid "New Post"
msgstr "नई पोस्ट"
#: src/view/com/auth/create/CreateAccount.tsx:158
#: src/view/com/auth/create/CreateAccount.tsx:154
#: src/view/com/auth/login/ForgotPasswordForm.tsx:174
#: src/view/com/auth/login/ForgotPasswordForm.tsx:184
#: src/view/com/auth/login/LoginForm.tsx:281
@@ -1399,8 +1409,8 @@ msgstr "अगली फोटो"
msgid "No"
msgstr "नहीं"
#: src/view/screens/ProfileFeed.tsx:620
#: src/view/screens/ProfileList.tsx:710
#: src/view/screens/ProfileFeed.tsx:570
#: src/view/screens/ProfileList.tsx:711
msgid "No description"
msgstr "कोई विवरण नहीं"
@@ -1451,8 +1461,8 @@ msgstr ""
#: src/view/screens/Notifications.tsx:109
#: src/view/screens/Notifications.tsx:133
#: src/view/shell/bottom-bar/BottomBar.tsx:187
#: src/view/shell/desktop/LeftNav.tsx:354
#: src/view/shell/bottom-bar/BottomBar.tsx:205
#: src/view/shell/desktop/LeftNav.tsx:358
#: src/view/shell/Drawer.tsx:416
#: src/view/shell/Drawer.tsx:417
msgid "Notifications"
@@ -1466,7 +1476,7 @@ msgstr "अरे नहीं!"
msgid "Okay"
msgstr "ठीक है"
#: src/view/com/composer/Composer.tsx:348
#: src/view/com/composer/Composer.tsx:354
msgid "One or more images is missing alt text."
msgstr "एक या अधिक छवियाँ alt पाठ याद आती हैं।।"
@@ -1474,7 +1484,7 @@ msgstr "एक या अधिक छवियाँ alt पाठ याद
msgid "Only {0} can reply."
msgstr ""
#: src/view/com/pager/FeedsTabBarMobile.tsx:79
#: src/view/com/pager/FeedsTabBarMobile.tsx:76
msgid "Open navigation"
msgstr "ओपन नेविगेशन"
@@ -1586,12 +1596,17 @@ msgstr "कृपया अपना पासवर्ड भी दर्ज
#: src/view/com/modals/AppealLabel.tsx:72
#: src/view/com/modals/AppealLabel.tsx:75
msgid "Please tell us why you think this decision was incorrect."
msgid "Please tell us why you think this content warning was incorrectly applied!"
msgstr ""
#: src/view/com/composer/Composer.tsx:331
#: src/view/com/modals/AppealLabel.tsx:72
#: src/view/com/modals/AppealLabel.tsx:75
#~ msgid "Please tell us why you think this decision was incorrect."
#~ msgstr ""
#: src/view/com/composer/Composer.tsx:337
#: src/view/com/post-thread/PostThread.tsx:226
#: src/view/screens/PostThread.tsx:78
#: src/view/screens/PostThread.tsx:80
msgid "Post"
msgstr "पोस्ट"
@@ -1643,7 +1658,8 @@ msgstr "गोपनीयता नीति"
msgid "Processing..."
msgstr "प्रसंस्करण..."
#: src/view/shell/bottom-bar/BottomBar.tsx:229
#: src/view/shell/bottom-bar/BottomBar.tsx:247
#: src/view/shell/desktop/LeftNav.tsx:412
#: src/view/shell/Drawer.tsx:69
#: src/view/shell/Drawer.tsx:525
#: src/view/shell/Drawer.tsx:526
@@ -1710,7 +1726,7 @@ msgstr "फ़ीड हटाएँ"
#: src/view/com/feeds/FeedSourceCard.tsx:105
#: src/view/com/feeds/FeedSourceCard.tsx:172
#: src/view/screens/ProfileFeed.tsx:275
#: src/view/screens/ProfileFeed.tsx:270
msgid "Remove from my feeds"
msgstr "मेरे फ़ीड से हटाएँ"
@@ -1755,16 +1771,16 @@ msgstr "रिपोर्ट {collectionName}"
msgid "Report Account"
msgstr "रिपोर्ट"
#: src/view/screens/ProfileFeed.tsx:295
#: src/view/screens/ProfileFeed.tsx:290
msgid "Report feed"
msgstr "रिपोर्ट फ़ीड"
#: src/view/screens/ProfileList.tsx:424
#: src/view/screens/ProfileList.tsx:425
msgid "Report List"
msgstr "रिपोर्ट सूची"
#: src/view/com/modals/report/SendReportButton.tsx:37
#: src/view/com/util/forms/PostDropdownBtn.tsx:165
#: src/view/com/util/forms/PostDropdownBtn.tsx:167
msgid "Report post"
msgstr "रिपोर्ट पोस्ट"
@@ -1822,8 +1838,8 @@ msgstr "ऑनबोर्डिंग स्टेट को रीसेट
msgid "Resets the preferences state"
msgstr "प्राथमिकताओं की स्थिति को रीसेट करें"
#: src/view/com/auth/create/CreateAccount.tsx:163
#: src/view/com/auth/create/CreateAccount.tsx:167
#: src/view/com/auth/create/CreateAccount.tsx:171
#: src/view/com/auth/login/LoginForm.tsx:258
#: src/view/com/auth/login/LoginForm.tsx:261
#: src/view/com/util/error/ErrorMessage.tsx:55
@@ -1873,8 +1889,8 @@ msgstr "सहेजे गए फ़ीड"
#: src/view/com/util/forms/SearchInput.tsx:64
#: src/view/screens/Search/Search.tsx:401
#: src/view/screens/Search/Search.tsx:567
#: src/view/shell/bottom-bar/BottomBar.tsx:138
#: src/view/shell/desktop/LeftNav.tsx:315
#: src/view/shell/bottom-bar/BottomBar.tsx:159
#: src/view/shell/desktop/LeftNav.tsx:321
#: src/view/shell/desktop/Search.tsx:161
#: src/view/shell/desktop/Search.tsx:170
#: src/view/shell/Drawer.tsx:343
@@ -1886,12 +1902,16 @@ msgstr "खोज"
#~ msgid "Search for posts and users."
#~ msgstr ""
#: src/view/com/auth/LoggedOut.tsx:104
#: src/view/com/auth/LoggedOut.tsx:105
msgid "Search for users"
msgstr ""
#: src/view/com/modals/ChangeEmail.tsx:110
msgid "Security Step Required"
msgstr "सुरक्षा चरण आवश्यक"
#: src/view/com/auth/HomeLoggedOutCTA.tsx:39
#: src/view/com/auth/SplashScreen.tsx:29
msgid "See what's next"
msgstr "आगे क्या है"
@@ -1965,7 +1985,7 @@ msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your f
msgstr "इस सेटिंग को अपने निम्नलिखित फ़ीड में अपने सहेजे गए फ़ीड के नमूने दिखाने के लिए \"हाँ\" पर सेट करें। यह एक प्रयोगात्मक विशेषता है।।"
#: src/view/screens/Settings.tsx:277
#: src/view/shell/desktop/LeftNav.tsx:426
#: src/view/shell/desktop/LeftNav.tsx:430
#: src/view/shell/Drawer.tsx:546
#: src/view/shell/Drawer.tsx:547
msgid "Settings"
@@ -1976,12 +1996,12 @@ msgid "Sexual activity or erotic nudity."
msgstr "यौन गतिविधि या कामुक नग्नता।।"
#: src/view/com/profile/ProfileHeader.tsx:338
#: src/view/com/util/forms/PostDropdownBtn.tsx:129
#: src/view/screens/ProfileList.tsx:383
#: src/view/com/util/forms/PostDropdownBtn.tsx:131
#: src/view/screens/ProfileList.tsx:384
msgid "Share"
msgstr "शेयर"
#: src/view/screens/ProfileFeed.tsx:307
#: src/view/screens/ProfileFeed.tsx:302
msgid "Share feed"
msgstr ""
@@ -2024,15 +2044,21 @@ msgstr "लोग दिखाएँ"
#: src/view/com/auth/HomeLoggedOutCTA.tsx:70
#: src/view/com/auth/login/Login.tsx:98
#: src/view/com/auth/SplashScreen.tsx:49
#: src/view/com/auth/SplashScreen.tsx:54
#: src/view/shell/bottom-bar/BottomBar.tsx:285
#: src/view/shell/bottom-bar/BottomBar.tsx:286
#: src/view/shell/bottom-bar/BottomBar.tsx:288
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:177
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:178
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:180
#: src/view/shell/NavSignupCard.tsx:58
#: src/view/shell/NavSignupCard.tsx:59
msgid "Sign in"
msgstr "साइन इन करें"
#: src/view/com/auth/HomeLoggedOutCTA.tsx:78
#: src/view/com/auth/SplashScreen.tsx:52
#: src/view/com/auth/SplashScreen.web.tsx:84
#: src/view/com/auth/SplashScreen.tsx:57
#: src/view/com/auth/SplashScreen.web.tsx:87
msgid "Sign In"
msgstr "साइन इन करें"
@@ -2054,6 +2080,12 @@ msgstr "साइन इन करें"
msgid "Sign out"
msgstr "साइन आउट"
#: src/view/shell/bottom-bar/BottomBar.tsx:275
#: src/view/shell/bottom-bar/BottomBar.tsx:276
#: src/view/shell/bottom-bar/BottomBar.tsx:278
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:167
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:168
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:170
#: src/view/shell/NavSignupCard.tsx:49
#: src/view/shell/NavSignupCard.tsx:50
#: src/view/shell/NavSignupCard.tsx:52
@@ -2105,11 +2137,11 @@ msgstr "Storybook"
msgid "Submit"
msgstr ""
#: src/view/screens/ProfileList.tsx:573
#: src/view/screens/ProfileList.tsx:574
msgid "Subscribe"
msgstr "सब्सक्राइब"
#: src/view/screens/ProfileList.tsx:569
#: src/view/screens/ProfileList.tsx:570
msgid "Subscribe to this list"
msgstr "इस सूची को सब्सक्राइब करें"
@@ -2184,8 +2216,8 @@ msgid "There was an unexpected issue in the application. Please let us know if t
msgstr "एप्लिकेशन में एक अप्रत्याशित समस्या थी. कृपया हमें बताएं कि क्या आपके साथ ऐसा हुआ है!"
#: src/view/com/util/moderation/LabelInfo.tsx:45
msgid "This {0} has been labeled."
msgstr ""
#~ msgid "This {0} has been labeled."
#~ msgstr ""
#: src/view/com/util/moderation/ScreenHider.tsx:88
msgid "This {screenDescription} has been flagged:"
@@ -2219,7 +2251,7 @@ msgstr "यह वह सेवा है जो आपको ऑनलाइन
msgid "This link is taking you to the following website:"
msgstr "यह लिंक आपको निम्नलिखित वेबसाइट पर ले जा रहा है:"
#: src/view/com/post-thread/PostThreadItem.tsx:124
#: src/view/com/post-thread/PostThreadItem.tsx:123
msgid "This post has been deleted."
msgstr "इस पोस्ट को हटा दिया गया है।।"
@@ -2244,9 +2276,9 @@ msgstr "ड्रॉपडाउन टॉगल करें"
msgid "Transformations"
msgstr "परिवर्तन"
#: src/view/com/post-thread/PostThreadItem.tsx:704
#: src/view/com/post-thread/PostThreadItem.tsx:706
#: src/view/com/post-thread/PostThreadItem.tsx:708
#: src/view/com/util/forms/PostDropdownBtn.tsx:101
#: src/view/com/util/forms/PostDropdownBtn.tsx:103
msgid "Translate"
msgstr "अनुवाद"
@@ -2254,11 +2286,11 @@ msgstr "अनुवाद"
msgid "Try again"
msgstr "फिर से कोशिश करो"
#: src/view/screens/ProfileList.tsx:471
#: src/view/screens/ProfileList.tsx:472
msgid "Un-block list"
msgstr ""
#: src/view/screens/ProfileList.tsx:456
#: src/view/screens/ProfileList.tsx:457
msgid "Un-mute list"
msgstr ""
@@ -2290,11 +2322,11 @@ msgstr ""
msgid "Unmute Account"
msgstr "अनम्यूट खाता"
#: src/view/com/util/forms/PostDropdownBtn.tsx:147
#: src/view/com/util/forms/PostDropdownBtn.tsx:149
msgid "Unmute thread"
msgstr "थ्रेड को अनम्यूट करें"
#: src/view/screens/ProfileList.tsx:439
#: src/view/screens/ProfileList.tsx:440
msgid "Unpin moderation list"
msgstr ""
@@ -2343,7 +2375,7 @@ msgstr "लोग सूचियाँ"
msgid "Username or email address"
msgstr "यूजर नाम या ईमेल पता"
#: src/view/screens/ProfileList.tsx:737
#: src/view/screens/ProfileList.tsx:738
msgid "Users"
msgstr "यूजर लोग"
@@ -2388,7 +2420,7 @@ msgstr "अवतार देखें"
msgid "Visit Site"
msgstr "साइट पर जाएं"
#: src/view/com/auth/create/CreateAccount.tsx:125
#: src/view/com/auth/create/CreateAccount.tsx:121
msgid "We're so excited to have you join us!"
msgstr "हम आपके हमारी सेवा में शामिल होने को लेकर बहुत उत्साहित हैं!"
@@ -2416,6 +2448,10 @@ msgstr "<0>Bluesky</0> में आपका स्वागत है"
msgid "What is the issue with this {collectionName}?"
msgstr "इस {collectionName} के साथ क्या मुद्दा है?"
#: src/view/com/auth/SplashScreen.tsx:34
msgid "What's up?"
msgstr ""
#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:78
msgid "Which languages are used in this post?"
msgstr "इस पोस्ट में किस भाषा का उपयोग किया जाता है?"
@@ -2437,7 +2473,7 @@ msgstr ""
msgid "Wide"
msgstr "चौड़ा"
#: src/view/com/composer/Composer.tsx:403
#: src/view/com/composer/Composer.tsx:409
msgid "Write post"
msgstr "पोस्ट लिखो"
File diff suppressed because it is too large Load Diff
+1 -45
View File
@@ -161,51 +161,6 @@ export function useFeedSourceInfoQuery({uri}: {uri: string}) {
})
}
export const isFeedPublicQueryKey = ({uri}: {uri: string}) => [
'isFeedPublic',
uri,
]
export function useIsFeedPublicQuery({uri}: {uri: string}) {
return useQuery({
queryKey: isFeedPublicQueryKey({uri}),
queryFn: async ({queryKey}) => {
const [, uri] = queryKey
try {
const res = await getAgent().app.bsky.feed.getFeed({
feed: uri,
limit: 1,
})
return {
isPublic: Boolean(res.data.feed),
error: undefined,
}
} catch (e: any) {
/**
* This should be an `XRPCError`, but I can't safely import from
* `@atproto/xrpc` due to a depdency on node's `crypto` module.
*
* @see https://github.com/bluesky-social/atproto/blob/c17971a2d8e424cc7f10c071d97c07c08aa319cf/packages/xrpc/src/client.ts#L126
*/
if (e?.status === 401) {
return {
isPublic: false,
error: e,
}
}
/*
* Non-401 response means something else went wrong on the server
*/
return {
isPublic: true,
error: e,
}
}
},
})
}
export const useGetPopularFeedsQueryKey = ['getPopularFeeds']
export function useGetPopularFeedsQuery() {
@@ -294,6 +249,7 @@ export function usePinnedFeedsInfos(): {
// these requests can fail, need to filter those out
try {
return await queryClient.fetchQuery({
staleTime: STALE.SECONDS.FIFTEEN,
queryKey: feedSourceInfoQueryKey({uri}),
queryFn: async () => {
const type = getFeedTypeFromUri(uri)
+17 -14
View File
@@ -16,7 +16,7 @@
* 3. Don't call this query's `refetch()` if you're trying to sync latest; call `checkUnread()` instead.
*/
import {useEffect} from 'react'
import {useEffect, useRef} from 'react'
import {AppBskyFeedDefs} from '@atproto/api'
import {
useInfiniteQuery,
@@ -49,6 +49,7 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
const threadMutes = useMutedThreads()
const unreads = useUnreadNotificationsApi()
const enabled = opts?.enabled !== false
const lastPageCountRef = useRef(0)
const query = useInfiniteQuery<
FeedPage,
@@ -104,24 +105,26 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
useEffect(() => {
const {isFetching, hasNextPage, data} = query
let count = 0
let numEmpties = 0
for (const page of data?.pages || []) {
if (!page.items.length) {
numEmpties++
}
count += page.items.length
if (isFetching || !hasNextPage) {
return
}
// avoid double-fires of fetchNextPage()
if (
!isFetching &&
hasNextPage &&
count < PAGE_SIZE &&
numEmpties < 3 &&
(data?.pages.length || 0) < 6
lastPageCountRef.current !== 0 &&
lastPageCountRef.current === data?.pages?.length
) {
return
}
// fetch next page if we haven't gotten a full page of content
let count = 0
for (const page of data?.pages || []) {
count += page.items.length
}
if (count < PAGE_SIZE && (data?.pages.length || 0) < 6) {
query.fetchNextPage()
lastPageCountRef.current = data?.pages?.length || 0
}
}, [query])
+21 -14
View File
@@ -1,4 +1,4 @@
import React, {useCallback, useEffect} from 'react'
import React, {useCallback, useEffect, useRef} from 'react'
import {
AppBskyFeedDefs,
AppBskyFeedPost,
@@ -78,6 +78,7 @@ export interface FeedPageUnselected {
api: FeedAPI
cursor: string | undefined
feed: AppBskyFeedDefs.FeedViewPost[]
fetchedAt: number
}
export interface FeedPage {
@@ -85,6 +86,7 @@ export interface FeedPage {
tuner: FeedTuner | NoopFeedTuner
cursor: string | undefined
slices: FeedPostSlice[]
fetchedAt: number
}
const PAGE_SIZE = 30
@@ -98,11 +100,12 @@ export function usePostFeedQuery(
const feedTuners = useFeedTuners(feedDesc)
const moderationOpts = useModerationOpts()
const enabled = opts?.enabled !== false && Boolean(moderationOpts)
const lastRun = React.useRef<{
const lastRun = useRef<{
data: InfiniteData<FeedPageUnselected>
args: typeof selectArgs
result: InfiniteData<FeedPage>
} | null>(null)
const lastPageCountRef = useRef(0)
// Make sure this doesn't invalidate unless really needed.
const selectArgs = React.useMemo(
@@ -152,6 +155,7 @@ export function usePostFeedQuery(
api,
cursor: res.cursor,
feed: res.feed,
fetchedAt: Date.now(),
}
},
initialPageParam: undefined,
@@ -214,6 +218,7 @@ export function usePostFeedQuery(
api: page.api,
tuner,
cursor: page.cursor,
fetchedAt: page.fetchedAt,
slices: tuner
.tune(page.feed)
.map(slice => {
@@ -279,26 +284,28 @@ export function usePostFeedQuery(
useEffect(() => {
const {isFetching, hasNextPage, data} = query
if (isFetching || !hasNextPage) {
return
}
// avoid double-fires of fetchNextPage()
if (
lastPageCountRef.current !== 0 &&
lastPageCountRef.current === data?.pages?.length
) {
return
}
// fetch next page if we haven't gotten a full page of content
let count = 0
let numEmpties = 0
for (const page of data?.pages || []) {
if (page.slices.length === 0) {
numEmpties++
}
for (const slice of page.slices) {
count += slice.items.length
}
}
if (
!isFetching &&
hasNextPage &&
count < PAGE_SIZE &&
numEmpties < 3 &&
(data?.pages.length || 0) < 6
) {
if (count < PAGE_SIZE && (data?.pages.length || 0) < 6) {
query.fetchNextPage()
lastPageCountRef.current = data?.pages?.length || 0
}
}, [query])
+1 -3
View File
@@ -35,9 +35,7 @@ export function useProfileQuery({did}: {did: string | undefined}) {
// if you remove it, the UI infinite-loops
// -prf
staleTime: isCurrentAccount ? STALE.SECONDS.THIRTY : STALE.MINUTES.FIVE,
refetchInterval: isCurrentAccount
? STALE.SECONDS.THIRTY
: STALE.MINUTES.FIVE,
refetchInterval: STALE.MINUTES.FIVE,
queryKey: RQKEY(did || ''),
queryFn: async () => {
const res = await getAgent().getProfile({actor: did || ''})
+2
View File
@@ -189,6 +189,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
},
logger.DebugContext.session,
)
track('Try Create Account')
const agent = new BskyAgent({service})
@@ -231,6 +232,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
},
logger.DebugContext.session,
)
track('Create Account')
},
[upsertAccount, queryClient],
)
+44 -3
View File
@@ -3,8 +3,9 @@ import {View, Pressable} from 'react-native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
import {useNavigation} from '@react-navigation/native'
import {isIOS} from 'platform/detection'
import {isIOS, isNative} from 'platform/detection'
import {Login} from 'view/com/auth/login/Login'
import {CreateAccount} from 'view/com/auth/create/CreateAccount'
import {ErrorBoundary} from 'view/com/util/ErrorBoundary'
@@ -18,6 +19,9 @@ import {
useLoggedOutView,
useLoggedOutViewControls,
} from '#/state/shell/logged-out'
import {useSession} from '#/state/session'
import {Text} from '#/view/com/util/text/Text'
import {NavigationProp} from 'lib/routes/types'
enum ScreenState {
S_LoginOrCreateAccount,
@@ -26,6 +30,7 @@ enum ScreenState {
}
export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
const {hasSession} = useSession()
const {_} = useLingui()
const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode()
@@ -40,6 +45,8 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
)
const {isMobile} = useWebMediaQueries()
const {clearRequestedAccount} = useLoggedOutViewControls()
const navigation = useNavigation<NavigationProp>()
const isFirstScreen = screenState === ScreenState.S_LoginOrCreateAccount
React.useEffect(() => {
screen('Login')
@@ -53,6 +60,10 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
clearRequestedAccount()
}, [clearRequestedAccount, onDismiss])
const onPressSearch = React.useCallback(() => {
navigation.navigate(`SearchTab`)
}, [navigation])
return (
<View
testID="noSessionView"
@@ -65,7 +76,7 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
},
]}>
<ErrorBoundary>
{onDismiss && (
{onDismiss ? (
<Pressable
accessibilityHint={_(msg`Go back`)}
accessibilityLabel={_(msg`Go back`)}
@@ -88,7 +99,37 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
}}
/>
</Pressable>
)}
) : isNative && !hasSession && isFirstScreen ? (
<Pressable
accessibilityHint={_(msg`Search for users`)}
accessibilityLabel={_(msg`Search for users`)}
accessibilityRole="button"
style={{
flexDirection: 'row',
alignItems: 'center',
gap: 4,
position: 'absolute',
top: 20,
right: 20,
paddingHorizontal: 16,
paddingVertical: 8,
zIndex: 100,
backgroundColor: pal.btn.backgroundColor,
borderRadius: 100,
}}
onPress={onPressSearch}>
<Text type="lg-bold" style={[pal.text]}>
Search{' '}
</Text>
<FontAwesomeIcon
icon="search"
size={16}
style={{
color: String(pal.text.color),
}}
/>
</Pressable>
) : null}
{screenState === ScreenState.S_LoginOrCreateAccount ? (
<SplashScreen
+2 -2
View File
@@ -27,11 +27,11 @@ export const SplashScreen = ({
<Logo width={92} fill="sky" />
<View style={{paddingTop: 40, paddingBottom: 6}}>
<Logotype width={161} />
<Logotype width={161} fill={pal.text.color} />
</View>
<Text type="lg-medium" style={[pal.textLight]}>
<Trans>What's next?</Trans>
<Trans>What's up?</Trans>
</Text>
</View>
<View testID="signinOrCreateAccount" style={styles.btns}>
+1 -1
View File
@@ -63,7 +63,7 @@ export const SplashScreen = ({
<Logo width={92} fill="sky" />
<View style={{paddingTop: 40, paddingBottom: 20}}>
<Logotype width={161} />
<Logotype width={161} fill={pal.text.color} />
</View>
<View testID="signinOrCreateAccount" style={styles.btns}>
+1 -5
View File
@@ -30,7 +30,7 @@ import {Step2} from './Step2'
import {Step3} from './Step3'
export function CreateAccount({onPressBack}: {onPressBack: () => void}) {
const {track, screen} = useAnalytics()
const {screen} = useAnalytics()
const pal = usePalette('default')
const {_} = useLingui()
const [uiState, uiDispatch] = useCreateAccount()
@@ -93,21 +93,17 @@ export function CreateAccount({onPressBack}: {onPressBack: () => void}) {
uiDispatch,
_,
})
track('Create Account')
setBirthDate({birthDate: uiState.birthDate})
if (IS_PROD(uiState.serviceUrl)) {
setSavedFeeds(DEFAULT_PROD_FEEDS)
}
} catch {
// dont need to handle here
} finally {
track('Try Create Account')
}
}
}, [
uiState,
uiDispatch,
track,
onboardingDispatch,
createAccount,
setBirthDate,
+6
View File
@@ -62,6 +62,7 @@ import {useProfileQuery} from '#/state/queries/profile'
import {useComposerControls} from '#/state/shell/composer'
import {emitPostCreated} from '#/state/events'
import {ThreadgateSetting} from '#/state/queries/threadgate'
import {logger} from '#/logger'
type Props = ComposerOpts
export const ComposePost = observer(function ComposePost({
@@ -228,6 +229,11 @@ export const ComposePost = observer(function ComposePost({
})
).uri
} catch (e: any) {
logger.error(e, {
message: `Composer: create post failed`,
hasImages: gallery.size > 0,
})
if (extLink) {
setExtLink({
...extLink,
@@ -215,7 +215,13 @@ export const TextInput = forwardRef(function TextInputImpl(
autoFocus={true}
allowFontScaling
multiline
style={[pal.text, styles.textInput, styles.textInputFormatting]}
numberOfLines={4}
style={[
pal.text,
styles.textInput,
styles.textInputFormatting,
{textAlignVertical: 'top'},
]}
{...props}>
{textDecorated}
</PasteInput>
+1 -1
View File
@@ -29,7 +29,7 @@ import {truncateAndInvalidate} from '#/state/queries/util'
import {TabState, getTabState, getRootNavigation} from '#/lib/routes/helpers'
import {isNative} from '#/platform/detection'
const POLL_FREQ = 30e3 // 30sec
const POLL_FREQ = 60e3 // 60sec
export function FeedPage({
testID,
+3 -3
View File
@@ -62,17 +62,17 @@ export function Component(props: ReportComponentProps) {
<Text
type="2xl-bold"
style={[pal.text, s.textCenter, {paddingBottom: 8}]}>
<Trans>Appeal Decision</Trans>
<Trans>Appeal Content Warning</Trans>
</Text>
<ScrollView>
<View style={[pal.btn, styles.detailsInputContainer]}>
<TextInput
accessibilityLabel={_(msg`Text input field`)}
accessibilityHint={_(
msg`Please tell us why you think this decision was incorrect.`,
msg`Please tell us why you think this content warning was incorrectly applied!`,
)}
placeholder={_(
msg`Please tell us why you think this decision was incorrect.`,
msg`Please tell us why you think this content warning was incorrectly applied!`,
)}
placeholderTextColor={pal.textLight.color}
value={details}
+1 -1
View File
@@ -82,7 +82,7 @@ export function ModalsContainer() {
useEffect(() => {
if (isModalActive) {
bottomSheetRef.current?.expand()
bottomSheetRef.current?.snapToIndex(0)
} else {
bottomSheetRef.current?.close()
}
+6 -8
View File
@@ -42,7 +42,6 @@ import {useComposerControls} from '#/state/shell/composer'
import {useModerationOpts} from '#/state/queries/preferences'
import {Shadow, usePostShadow, POST_TOMBSTONE} from '#/state/cache/post-shadow'
import {ThreadPost} from '#/state/queries/post-thread'
import {LabelInfo} from '../util/moderation/LabelInfo'
import {useSession} from '#/state/session'
import {WhoCanReply} from '../threadgate/WhoCanReply'
@@ -187,6 +186,9 @@ let PostThreadItemLoaded = ({
return makeProfileLink(post.author, 'post', urip.rkey, 'reposted-by')
}, [post.uri, post.author])
const repostsTitle = 'Reposts of this post'
const isSelfLabeledPost =
moderation.decisions.post.cause?.type === 'label' &&
moderation.decisions.post.cause.label.src === currentAccount?.did
const translatorUrl = getTranslatorLink(
record?.text || '',
@@ -332,6 +334,9 @@ let PostThreadItemLoaded = ({
postCid={post.cid}
postUri={post.uri}
record={record}
showAppealLabelItem={
post.author.did === currentAccount?.did && !isSelfLabeledPost
}
style={{
paddingVertical: 6,
paddingHorizontal: 10,
@@ -351,13 +356,6 @@ let PostThreadItemLoaded = ({
includeMute
style={styles.alert}
/>
{post.author.did === currentAccount?.did ? (
<LabelInfo
details={{uri: post.uri, cid: post.cid}}
labels={post.labels}
style={{marginBottom: 8}}
/>
) : null}
{richText?.text ? (
<View
style={[
+22 -4
View File
@@ -27,12 +27,16 @@ import {
import {isWeb} from '#/platform/detection'
import {listenPostCreated} from '#/state/events'
import {useSession} from '#/state/session'
import {STALE} from '#/state/queries'
const LOADING_ITEM = {_reactKey: '__loading__'}
const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
const ERROR_ITEM = {_reactKey: '__error__'}
const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'}
const REFRESH_AFTER = STALE.HOURS.ONE
const CHECK_LATEST_AFTER = STALE.SECONDS.THIRTY
let Feed = ({
feed,
feedParams,
@@ -74,6 +78,7 @@ let Feed = ({
const {currentAccount} = useSession()
const [isPTRing, setIsPTRing] = React.useState(false)
const checkForNewRef = React.useRef<(() => void) | null>(null)
const lastFetchRef = React.useRef<number>(Date.now())
const opts = React.useMemo(
() => ({enabled, ignoreFilterFor}),
@@ -91,6 +96,9 @@ let Feed = ({
fetchNextPage,
} = usePostFeedQuery(feed, feedParams, opts)
const isEmpty = !isFetching && !data?.pages[0]?.slices.length
if (data?.pages[0]) {
lastFetchRef.current = data?.pages[0].fetchedAt
}
const checkForNew = React.useCallback(async () => {
if (!data?.pages[0] || isFetching || !onHasNew || !enabled) {
@@ -130,11 +138,21 @@ let Feed = ({
checkForNewRef.current = checkForNew
}, [checkForNew])
React.useEffect(() => {
if (enabled && checkForNewRef.current) {
// check for new on enable (aka on focus)
checkForNewRef.current()
if (enabled) {
const timeSinceFirstLoad = Date.now() - lastFetchRef.current
if (timeSinceFirstLoad > REFRESH_AFTER) {
// do a full refresh
scrollElRef?.current?.scrollToOffset({offset: 0, animated: false})
queryClient.resetQueries({queryKey: RQKEY(feed)})
} else if (
timeSinceFirstLoad > CHECK_LATEST_AFTER &&
checkForNewRef.current
) {
// check for new on enable (aka on focus)
checkForNewRef.current()
}
}
}, [enabled])
}, [enabled, feed, queryClient, scrollElRef])
React.useEffect(() => {
let cleanup1: () => void | undefined, cleanup2: () => void | undefined
const subscription = AppState.addEventListener('change', nextAppState => {
@@ -31,6 +31,7 @@ let PostDropdownBtn = ({
postUri,
record,
style,
showAppealLabelItem,
}: {
testID: string
postAuthor: AppBskyActorDefs.ProfileViewBasic
@@ -38,6 +39,7 @@ let PostDropdownBtn = ({
postUri: string
record: AppBskyFeedPost.Record
style?: StyleProp<ViewStyle>
showAppealLabelItem?: boolean
}): React.ReactNode => {
const {hasSession, currentAccount} = useSession()
const theme = useTheme()
@@ -198,6 +200,23 @@ let PostDropdownBtn = ({
web: ['far', 'trash-can'],
},
},
showAppealLabelItem && {
label: 'separator',
},
showAppealLabelItem && {
label: _(msg`Appeal content warning`),
onPress() {
openModal({name: 'appeal-label', uri: postUri, cid: postCid})
},
testID: 'postDropdownAppealBtn',
icon: {
ios: {
name: 'exclamationmark.triangle',
},
android: 'ic_menu_report_image',
web: 'circle-exclamation',
},
},
].filter(Boolean) as NativeDropdownItem[]
return (
+2 -1
View File
@@ -43,7 +43,8 @@ export function LabelInfo({
]}>
<Text type="sm" style={pal.text}>
<Trans>
This {'did' in details ? 'account' : 'post'} has been labeled.
A content warning has been applied to this{' '}
{'did' in details ? 'account' : 'post'}.
</Trans>{' '}
</Text>
<Pressable
+3 -6
View File
@@ -10,7 +10,7 @@ import {AppBskyFeedDefs, AppBskyFeedPost} from '@atproto/api'
import {Text} from '../text/Text'
import {PostDropdownBtn} from '../forms/PostDropdownBtn'
import {HeartIcon, HeartIconSolid, CommentBottomArrow} from 'lib/icons'
import {s, colors} from 'lib/styles'
import {s} from 'lib/styles'
import {pluralize} from 'lib/strings/helpers'
import {useTheme} from 'lib/ThemeContext'
import {RepostButton} from './RepostButton'
@@ -180,7 +180,7 @@ let PostCtrls = ({
accessibilityHint=""
hitSlop={big ? HITSLOP_20 : HITSLOP_10}>
{post.viewer?.like ? (
<HeartIconSolid style={styles.ctrlIconLiked} size={big ? 22 : 16} />
<HeartIconSolid style={s.likeColor} size={big ? 22 : 16} />
) : (
<HeartIcon
style={[defaultCtrlColor, big ? styles.mt1 : undefined]}
@@ -193,7 +193,7 @@ let PostCtrls = ({
testID="likeCount"
style={
post.viewer?.like
? [s.bold, s.red3, s.f15, s.ml5]
? [s.bold, s.likeColor, s.f15, s.ml5]
: [defaultCtrlColor, s.f15, s.ml5]
}>
{post.likeCount}
@@ -233,9 +233,6 @@ const styles = StyleSheet.create({
paddingLeft: 5,
paddingRight: 5,
},
ctrlIconLiked: {
color: colors.like,
},
mt1: {
marginTop: 1,
},
+3 -2
View File
@@ -1,7 +1,7 @@
import React from 'react'
import Svg, {Path, SvgProps, PathProps} from 'react-native-svg'
import {colors} from '#/lib/styles'
import {usePalette} from '#/lib/hooks/usePalette'
const ratio = 17 / 64
@@ -9,6 +9,7 @@ export function Logotype({
fill,
...rest
}: {fill?: PathProps['fill']} & SvgProps) {
const pal = usePalette('default')
// @ts-ignore it's fiiiiine
const size = parseInt(rest.width || 32)
@@ -20,7 +21,7 @@ export function Logotype({
width={size}
height={Number(size) * ratio}>
<Path
fill={fill || colors.black}
fill={fill || pal.text.color}
d="M8.478 6.252c1.503.538 2.3 1.78 2.3 3.172 0 2.356-1.576 3.785-4.6 3.785H0V0h5.974c2.875 0 4.267 1.466 4.267 3.413 0 1.3-.594 2.245-1.763 2.839Zm-2.69-4.193H2.504v3.45h3.284c1.28 0 1.967-.667 1.967-1.78 0-1.02-.705-1.67-1.967-1.67Zm-3.284 9.072h3.544c1.41 0 2.17-.65 2.17-1.818 0-1.224-.723-1.837-2.17-1.837H2.504v3.655ZM14.251 13.209h-2.337V0h2.337v13.209ZM22.001 8.998V3.636h2.338v9.573h-2.263v-1.392c-.724 1.076-1.726 1.614-3.006 1.614-2.022 0-3.34-1.224-3.34-3.45V3.636h2.338v5.955c0 1.206.594 1.818 1.8 1.818 1.132 0 2.133-.835 2.133-2.411ZM34.979 8.59v.556h-7.161c.167 1.651 1.076 2.467 2.486 2.467 1.076 0 1.8-.463 2.189-1.372h2.244c-.5 1.947-2.17 3.19-4.452 3.19-1.428 0-2.579-.463-3.45-1.372-.872-.91-1.318-2.115-1.318-3.637 0-1.502.427-2.708 1.299-3.636.872-.909 2.004-1.372 3.432-1.372 1.447 0 2.597.482 3.45 1.428.854.946 1.28 2.208 1.28 3.747Zm-4.75-3.358c-1.28 0-2.17.742-2.393 2.281h4.805c-.204-1.391-1.057-2.281-2.411-2.281ZM40.16 13.469c-2.783 0-4.249-1.095-4.379-3.303h2.282c.13 1.188.724 1.633 2.134 1.633 1.261 0 1.892-.39 1.892-1.15 0-.687-.445-1.02-1.874-1.262l-1.094-.185c-2.097-.353-3.136-1.318-3.136-2.894 0-1.8 1.429-2.894 3.97-2.894 2.728 0 4.138 1.075 4.23 3.246h-2.207c-.056-1.169-.742-1.577-2.023-1.577-1.113 0-1.67.371-1.67 1.113 0 .668.483.965 1.596 1.169l1.206.186c2.32.426 3.32 1.28 3.32 2.912 0 1.93-1.557 3.006-4.247 3.006ZM54.667 13.209h-2.671l-2.783-4.453-1.447 1.447v3.006h-2.3V0h2.3v7.606l3.896-3.97h2.783l-3.618 3.618 3.84 5.955ZM60.772 6.048l.78-2.412H64l-3.692 10.352c-.39 1.057-.872 1.818-1.484 2.245-.612.426-1.484.63-2.634.63-.39 0-.724-.018-1.02-.055V14.97h.89c1.057 0 1.577-.65 1.577-1.54 0-.445-.149-1.094-.446-1.929l-2.746-7.866h2.487l.779 2.393c.575 1.8 1.076 3.58 1.521 5.343.408-1.521.928-3.302 1.54-5.324Z"
/>
</Svg>
+9 -4
View File
@@ -12,6 +12,7 @@ import {FeedPage} from 'view/com/feeds/FeedPage'
import {HomeLoggedOutCTA} from '../com/auth/HomeLoggedOutCTA'
import {useSetMinimalShellMode, useSetDrawerSwipeDisabled} from '#/state/shell'
import {usePreferencesQuery} from '#/state/queries/preferences'
import {usePinnedFeedsInfos, FeedSourceInfo} from '#/state/queries/feed'
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
import {emitSoftReset} from '#/state/events'
import {useSession} from '#/state/session'
@@ -21,6 +22,7 @@ import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
export function HomeScreen(props: Props) {
const {data: preferences} = usePreferencesQuery()
const {feeds: pinnedFeeds} = usePinnedFeedsInfos()
const {isDesktop} = useWebMediaQueries()
const [initialPage, setInitialPage] = React.useState<string | undefined>(
undefined,
@@ -39,11 +41,12 @@ export function HomeScreen(props: Props) {
loadLastActivePage()
}, [])
if (preferences && initialPage !== undefined) {
if (preferences && pinnedFeeds && initialPage !== undefined) {
return (
<HomeScreenReady
{...props}
preferences={preferences}
pinnedFeeds={pinnedFeeds}
initialPage={isDesktop ? 'Following' : initialPage}
/>
)
@@ -58,9 +61,11 @@ export function HomeScreen(props: Props) {
function HomeScreenReady({
preferences,
pinnedFeeds,
initialPage,
}: Props & {
preferences: UsePreferencesQueryResponse
pinnedFeeds: FeedSourceInfo[]
initialPage: string
}) {
const {hasSession} = useSession()
@@ -82,9 +87,9 @@ function HomeScreenReady({
}, [preferences.feeds.pinned, selectedPage])
const customFeeds = React.useMemo(() => {
const pinned = preferences.feeds.pinned
const pinned = pinnedFeeds
const feeds: FeedDescriptor[] = []
for (const uri of pinned) {
for (const {uri} of pinned) {
if (uri.includes('app.bsky.feed.generator')) {
feeds.push(`feedgen|${uri}`)
} else if (uri.includes('app.bsky.graph.list')) {
@@ -92,7 +97,7 @@ function HomeScreenReady({
}
}
return feeds
}, [preferences.feeds.pinned])
}, [pinnedFeeds])
const homeFeedParams = React.useMemo<FeedParams>(() => {
return {
+3 -1
View File
@@ -24,11 +24,13 @@ import {useResolveUriQuery} from '#/state/queries/resolve-uri'
import {ErrorMessage} from '../com/util/error/ErrorMessage'
import {CenteredView} from '../com/util/Views'
import {useComposerControls} from '#/state/shell/composer'
import {useSession} from '#/state/session'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'>
export function PostThreadScreen({route}: Props) {
const queryClient = useQueryClient()
const {_} = useLingui()
const {hasSession} = useSession()
const {fabMinimalShellTransform} = useMinimalShellMode()
const setMinimalShellMode = useSetMinimalShellMode()
const {openComposer} = useComposerControls()
@@ -89,7 +91,7 @@ export function PostThreadScreen({route}: Props) {
/>
)}
</View>
{isMobile && canReply && (
{isMobile && canReply && hasSession && (
<Animated.View
style={[
styles.prompt,
+19 -72
View File
@@ -1,14 +1,14 @@
import React, {useMemo, useCallback} from 'react'
import {Dimensions, StyleSheet, View, ActivityIndicator} from 'react-native'
import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {useNavigation} from '@react-navigation/native'
import {useIsFocused, useNavigation} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query'
import {usePalette} from 'lib/hooks/usePalette'
import {HeartIcon, HeartIconSolid} from 'lib/icons'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {CommonNavigatorParams} from 'lib/routes/types'
import {makeRecordUri} from 'lib/strings/url-helpers'
import {colors, s} from 'lib/styles'
import {s} from 'lib/styles'
import {FeedDescriptor} from '#/state/queries/post-feed'
import {PagerWithHeader} from 'view/com/pager/PagerWithHeader'
import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader'
@@ -42,11 +42,7 @@ import {logger} from '#/logger'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useModalControls} from '#/state/modals'
import {
useFeedSourceInfoQuery,
FeedSourceFeedInfo,
useIsFeedPublicQuery,
} from '#/state/queries/feed'
import {useFeedSourceInfoQuery, FeedSourceFeedInfo} from '#/state/queries/feed'
import {useResolveUriQuery} from '#/state/queries/resolve-uri'
import {
UsePreferencesQueryResponse,
@@ -132,10 +128,8 @@ export function ProfileFeedScreen(props: Props) {
function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) {
const {data: preferences} = usePreferencesQuery()
const {data: info} = useFeedSourceInfoQuery({uri: feedUri})
const {isLoading: isPublicStatusLoading, data: isPublicResponse} =
useIsFeedPublicQuery({uri: feedUri})
if (!preferences || !info || isPublicStatusLoading) {
if (!preferences || !info) {
return (
<CenteredView>
<View style={s.p20}>
@@ -149,7 +143,6 @@ function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) {
<ProfileFeedScreenInner
preferences={preferences}
feedInfo={info as FeedSourceFeedInfo}
isPublicResponse={isPublicResponse}
/>
)
}
@@ -157,11 +150,9 @@ function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) {
export function ProfileFeedScreenInner({
preferences,
feedInfo,
isPublicResponse,
}: {
preferences: UsePreferencesQueryResponse
feedInfo: FeedSourceFeedInfo
isPublicResponse: ReturnType<typeof useIsFeedPublicQuery>['data']
}) {
const {_} = useLingui()
const pal = usePalette('default')
@@ -170,6 +161,7 @@ export function ProfileFeedScreenInner({
const {openComposer} = useComposerControls()
const {track} = useAnalytics()
const feedSectionRef = React.useRef<SectionRef>(null)
const isScreenFocused = useIsFocused()
const {
mutateAsync: saveFeed,
@@ -205,6 +197,9 @@ export function ProfileFeedScreenInner({
useSetTitle(feedInfo?.displayName)
// event handlers
//
const onToggleSaved = React.useCallback(async () => {
try {
Haptics.default()
@@ -398,21 +393,15 @@ export function ProfileFeedScreenInner({
isHeaderReady={true}
renderHeader={renderHeader}
onCurrentPageSelected={onCurrentPageSelected}>
{({headerHeight, scrollElRef, isFocused}) =>
isPublicResponse?.isPublic ? (
<FeedSection
ref={feedSectionRef}
feed={`feedgen|${feedInfo.uri}`}
headerHeight={headerHeight}
scrollElRef={scrollElRef as ListRef}
isFocused={isFocused}
/>
) : (
<CenteredView sideBorders style={[{paddingTop: headerHeight}]}>
<NonPublicFeedMessage rawError={isPublicResponse?.error} />
</CenteredView>
)
}
{({headerHeight, scrollElRef, isFocused}) => (
<FeedSection
ref={feedSectionRef}
feed={`feedgen|${feedInfo.uri}`}
headerHeight={headerHeight}
scrollElRef={scrollElRef as ListRef}
isFocused={isScreenFocused && isFocused}
/>
)}
{({headerHeight, scrollElRef}) => (
<AboutSection
feedOwnerDid={feedInfo.creatorDid}
@@ -446,45 +435,6 @@ export function ProfileFeedScreenInner({
)
}
function NonPublicFeedMessage({rawError}: {rawError?: Error}) {
const pal = usePalette('default')
return (
<View
style={[
pal.border,
{
padding: 18,
borderTopWidth: 1,
minHeight: Dimensions.get('window').height * 1.5,
},
]}>
<View
style={[
pal.viewLight,
{
padding: 12,
borderRadius: 8,
gap: 12,
},
]}>
<Text style={[pal.text]}>
<Trans>
Looks like this feed is only available to users with a Bluesky
account. Please sign up or sign in to view this feed!
</Trans>
</Text>
{rawError?.message && (
<Text style={pal.textLight}>
<Trans>Message from server</Trans>: {rawError.message}
</Text>
)}
</View>
</View>
)
}
interface FeedSectionProps {
feed: FeedDescriptor
headerHeight: number
@@ -519,7 +469,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
<Feed
enabled={isFocused}
feed={feed}
pollInterval={30e3}
pollInterval={60e3}
scrollElRef={scrollElRef}
onHasNew={setHasNew}
onScrolledDownChange={setIsScrolledDown}
@@ -630,7 +580,7 @@ function AboutSection({
onPress={onToggleLiked}
style={{paddingHorizontal: 10}}>
{isLiked ? (
<HeartIconSolid size={19} style={styles.liked} />
<HeartIconSolid size={19} style={s.likeColor} />
) : (
<HeartIcon strokeWidth={3} size={19} style={pal.textLight} />
)}
@@ -673,9 +623,6 @@ const styles = StyleSheet.create({
borderRadius: 50,
marginLeft: 6,
},
liked: {
color: colors.red3,
},
notFoundContainer: {
margin: 10,
paddingHorizontal: 18,
+4 -3
View File
@@ -1,6 +1,6 @@
import React, {useCallback, useMemo} from 'react'
import {ActivityIndicator, Pressable, StyleSheet, View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native'
import {useFocusEffect, useIsFocused} from '@react-navigation/native'
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
import {useNavigation} from '@react-navigation/native'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
@@ -115,6 +115,7 @@ function ProfileListScreenLoaded({
const aboutSectionRef = React.useRef<SectionRef>(null)
const {openModal} = useModalControls()
const isCurateList = list.purpose === 'app.bsky.graph.defs#curatelist'
const isScreenFocused = useIsFocused()
useSetTitle(list.name)
@@ -165,7 +166,7 @@ function ProfileListScreenLoaded({
feed={`list|${uri}`}
scrollElRef={scrollElRef as ListRef}
headerHeight={headerHeight}
isFocused={isFocused}
isFocused={isScreenFocused && isFocused}
/>
)}
{({headerHeight, scrollElRef}) => (
@@ -623,7 +624,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
testID="listFeed"
enabled={isFocused}
feed={feed}
pollInterval={30e3}
pollInterval={60e3}
scrollElRef={scrollElRef}
onHasNew={setHasNew}
onScrolledDownChange={setIsScrolledDown}
+11 -11
View File
@@ -221,18 +221,16 @@ let DrawerContent = ({}: {}): React.ReactNode => {
<NavSignupCard />
)}
{hasSession && <InviteCodes />}
{hasSession && <View style={{height: 10}} />}
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
<HomeMenuItem isActive={isAtHome} onPress={onPressHome} />
{hasSession && (
<NotificationsMenuItem
isActive={isAtNotifications}
onPress={onPressNotifications}
/>
)}
{hasSession && (
{hasSession ? (
<>
<InviteCodes />
<View style={{height: 10}} />
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
<HomeMenuItem isActive={isAtHome} onPress={onPressHome} />
<NotificationsMenuItem
isActive={isAtNotifications}
onPress={onPressNotifications}
/>
<FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
<ListsMenuItem onPress={onPressLists} />
<ModerationMenuItem onPress={onPressModeration} />
@@ -242,6 +240,8 @@ let DrawerContent = ({}: {}): React.ReactNode => {
/>
<SettingsMenuItem onPress={onPressSettings} />
</>
) : (
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
)}
<View style={styles.smallSpacer} />
+4 -4
View File
@@ -5,11 +5,11 @@ import {useLingui} from '@lingui/react'
import {s} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette'
import {DefaultAvatar} from '#/view/com/util/UserAvatar'
import {Text} from '#/view/com/util/text/Text'
import {Button} from '#/view/com/util/forms/Button'
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
import {useCloseAllActiveElements} from '#/state/util'
import {Logo} from '#/view/icons/Logo'
let NavSignupCard = ({}: {}): React.ReactNode => {
const {_} = useLingui()
@@ -35,10 +35,10 @@ let NavSignupCard = ({}: {}): React.ReactNode => {
paddingTop: 6,
marginBottom: 24,
}}>
<DefaultAvatar type="user" size={48} />
<Logo width={48} />
<View style={{paddingTop: 12}}>
<Text type="md" style={[pal.text, s.bold]}>
<View style={{paddingTop: 18}}>
<Text type="md-bold" style={[pal.text]}>
<Trans>Sign up or sign in to join the conversation</Trans>
</Text>
</View>
+108 -47
View File
@@ -23,13 +23,19 @@ import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
import {useNavigationTabState} from 'lib/hooks/useNavigationTabState'
import {UserAvatar} from 'view/com/util/UserAvatar'
import {useLingui} from '@lingui/react'
import {msg} from '@lingui/macro'
import {msg, Trans} from '@lingui/macro'
import {useModalControls} from '#/state/modals'
import {useShellLayout} from '#/state/shell/shell-layout'
import {useUnreadNotifications} from '#/state/queries/notifications/unread'
import {emitSoftReset} from '#/state/events'
import {useSession} from '#/state/session'
import {useProfileQuery} from '#/state/queries/profile'
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
import {useCloseAllActiveElements} from '#/state/util'
import {Button} from '#/view/com/util/forms/Button'
import {s} from 'lib/styles'
import {Logo} from '#/view/icons/Logo'
import {Logotype} from '#/view/icons/Logotype'
type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds'
@@ -46,6 +52,19 @@ export function BottomBar({navigation}: BottomTabBarProps) {
const numUnreadNotifications = useUnreadNotifications()
const {footerMinimalShellTransform} = useMinimalShellMode()
const {data: profile} = useProfileQuery({did: currentAccount?.did})
const {requestSwitchToAccount} = useLoggedOutViewControls()
const closeAllActiveElements = useCloseAllActiveElements()
const showSignIn = React.useCallback(() => {
closeAllActiveElements()
requestSwitchToAccount({requestedAccount: 'none'})
}, [requestSwitchToAccount, closeAllActiveElements])
const showCreateAccount = React.useCallback(() => {
closeAllActiveElements()
requestSwitchToAccount({requestedAccount: 'new'})
// setShowLoggedOut(true)
}, [requestSwitchToAccount, closeAllActiveElements])
const onPressTab = React.useCallback(
(tab: TabOptions) => {
@@ -94,53 +113,52 @@ export function BottomBar({navigation}: BottomTabBarProps) {
onLayout={e => {
footerHeight.value = e.nativeEvent.layout.height
}}>
<Btn
testID="bottomBarHomeBtn"
icon={
isAtHome ? (
<HomeIconSolid
strokeWidth={4}
size={24}
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
/>
) : (
<HomeIcon
strokeWidth={4}
size={24}
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
/>
)
}
onPress={onPressHome}
accessibilityRole="tab"
accessibilityLabel={_(msg`Home`)}
accessibilityHint=""
/>
<Btn
testID="bottomBarSearchBtn"
icon={
isAtSearch ? (
<MagnifyingGlassIcon2Solid
size={25}
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
strokeWidth={1.8}
/>
) : (
<MagnifyingGlassIcon2
size={25}
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
strokeWidth={1.8}
/>
)
}
onPress={onPressSearch}
accessibilityRole="search"
accessibilityLabel={_(msg`Search`)}
accessibilityHint=""
/>
{hasSession && (
{hasSession ? (
<>
<Btn
testID="bottomBarHomeBtn"
icon={
isAtHome ? (
<HomeIconSolid
strokeWidth={4}
size={24}
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
/>
) : (
<HomeIcon
strokeWidth={4}
size={24}
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
/>
)
}
onPress={onPressHome}
accessibilityRole="tab"
accessibilityLabel={_(msg`Home`)}
accessibilityHint=""
/>
<Btn
testID="bottomBarSearchBtn"
icon={
isAtSearch ? (
<MagnifyingGlassIcon2Solid
size={25}
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
strokeWidth={1.8}
/>
) : (
<MagnifyingGlassIcon2
size={25}
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
strokeWidth={1.8}
/>
)
}
onPress={onPressSearch}
accessibilityRole="search"
accessibilityLabel={_(msg`Search`)}
accessibilityHint=""
/>
<Btn
testID="bottomBarFeedsBtn"
icon={
@@ -230,6 +248,49 @@ export function BottomBar({navigation}: BottomTabBarProps) {
accessibilityHint=""
/>
</>
) : (
<>
<View
style={{
width: '100%',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingTop: 14,
paddingBottom: 2,
paddingLeft: 14,
paddingRight: 6,
gap: 8,
}}>
<View style={{flexDirection: 'row', alignItems: 'center', gap: 8}}>
<Logo width={28} />
<View style={{paddingTop: 4}}>
<Logotype width={80} fill={pal.text.color} />
</View>
</View>
<View style={{flexDirection: 'row', alignItems: 'center', gap: 4}}>
<Button
onPress={showCreateAccount}
accessibilityHint={_(msg`Sign up`)}
accessibilityLabel={_(msg`Sign up`)}>
<Text type="md" style={[{color: 'white'}, s.bold]}>
<Trans>Sign up</Trans>
</Text>
</Button>
<Button
type="default"
onPress={showSignIn}
accessibilityHint={_(msg`Sign in`)}
accessibilityLabel={_(msg`Sign in`)}>
<Text type="md" style={[pal.text, s.bold]}>
<Trans>Sign in</Trans>
</Text>
</Button>
</View>
</View>
</>
)}
</Animated.View>
)
+128 -57
View File
@@ -3,6 +3,9 @@ import {usePalette} from 'lib/hooks/usePalette'
import {useNavigationState} from '@react-navigation/native'
import Animated from 'react-native-reanimated'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {getCurrentRoute, isTab} from 'lib/routes/helpers'
import {styles} from './BottomBarStyles'
import {clamp} from 'lib/numbers'
@@ -22,12 +25,33 @@ import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
import {makeProfileLink} from 'lib/routes/links'
import {CommonNavigatorParams} from 'lib/routes/types'
import {useSession} from '#/state/session'
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
import {useCloseAllActiveElements} from '#/state/util'
import {Button} from '#/view/com/util/forms/Button'
import {Text} from '#/view/com/util/text/Text'
import {s} from 'lib/styles'
import {Logo} from '#/view/icons/Logo'
import {Logotype} from '#/view/icons/Logotype'
export function BottomBarWeb() {
const {_} = useLingui()
const {hasSession, currentAccount} = useSession()
const pal = usePalette('default')
const safeAreaInsets = useSafeAreaInsets()
const {footerMinimalShellTransform} = useMinimalShellMode()
const {requestSwitchToAccount} = useLoggedOutViewControls()
const closeAllActiveElements = useCloseAllActiveElements()
const showSignIn = React.useCallback(() => {
closeAllActiveElements()
requestSwitchToAccount({requestedAccount: 'none'})
}, [requestSwitchToAccount, closeAllActiveElements])
const showCreateAccount = React.useCallback(() => {
closeAllActiveElements()
requestSwitchToAccount({requestedAccount: 'new'})
// setShowLoggedOut(true)
}, [requestSwitchToAccount, closeAllActiveElements])
return (
<Animated.View
@@ -39,79 +63,126 @@ export function BottomBarWeb() {
{paddingBottom: clamp(safeAreaInsets.bottom, 15, 30)},
footerMinimalShellTransform,
]}>
<NavItem routeName="Home" href="/">
{({isActive}) => {
const Icon = isActive ? HomeIconSolid : HomeIcon
return (
<Icon
strokeWidth={4}
size={24}
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
/>
)
}}
</NavItem>
<NavItem routeName="Search" href="/search">
{({isActive}) => {
const Icon = isActive
? MagnifyingGlassIcon2Solid
: MagnifyingGlassIcon2
return (
<Icon
size={25}
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
strokeWidth={1.8}
/>
)
}}
</NavItem>
{hasSession && (
{hasSession ? (
<>
<NavItem routeName="Feeds" href="/feeds">
<NavItem routeName="Home" href="/">
{({isActive}) => {
return (
<HashtagIcon
size={22}
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
strokeWidth={isActive ? 4 : 2.5}
/>
)
}}
</NavItem>
<NavItem routeName="Notifications" href="/notifications">
{({isActive}) => {
const Icon = isActive ? BellIconSolid : BellIcon
const Icon = isActive ? HomeIconSolid : HomeIcon
return (
<Icon
strokeWidth={4}
size={24}
strokeWidth={1.9}
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
/>
)
}}
</NavItem>
<NavItem
routeName="Profile"
href={
currentAccount
? makeProfileLink({
did: currentAccount.did,
handle: currentAccount.handle,
})
: '/'
}>
<NavItem routeName="Search" href="/search">
{({isActive}) => {
const Icon = isActive ? UserIconSolid : UserIcon
const Icon = isActive
? MagnifyingGlassIcon2Solid
: MagnifyingGlassIcon2
return (
<Icon
size={28}
strokeWidth={1.5}
style={[styles.ctrlIcon, pal.text, styles.profileIcon]}
size={25}
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
strokeWidth={1.8}
/>
)
}}
</NavItem>
{hasSession && (
<>
<NavItem routeName="Feeds" href="/feeds">
{({isActive}) => {
return (
<HashtagIcon
size={22}
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
strokeWidth={isActive ? 4 : 2.5}
/>
)
}}
</NavItem>
<NavItem routeName="Notifications" href="/notifications">
{({isActive}) => {
const Icon = isActive ? BellIconSolid : BellIcon
return (
<Icon
size={24}
strokeWidth={1.9}
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
/>
)
}}
</NavItem>
<NavItem
routeName="Profile"
href={
currentAccount
? makeProfileLink({
did: currentAccount.did,
handle: currentAccount.handle,
})
: '/'
}>
{({isActive}) => {
const Icon = isActive ? UserIconSolid : UserIcon
return (
<Icon
size={28}
strokeWidth={1.5}
style={[styles.ctrlIcon, pal.text, styles.profileIcon]}
/>
)
}}
</NavItem>
</>
)}
</>
) : (
<>
<View
style={{
width: '100%',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingTop: 14,
paddingBottom: 2,
paddingLeft: 14,
paddingRight: 6,
gap: 8,
}}>
<View style={{flexDirection: 'row', alignItems: 'center', gap: 12}}>
<Logo width={32} />
<View style={{paddingTop: 4}}>
<Logotype width={80} fill={pal.text.color} />
</View>
</View>
<View style={{flexDirection: 'row', alignItems: 'center', gap: 8}}>
<Button
onPress={showCreateAccount}
accessibilityHint={_(msg`Sign up`)}
accessibilityLabel={_(msg`Sign up`)}>
<Text type="md" style={[{color: 'white'}, s.bold]}>
<Trans>Sign up</Trans>
</Text>
</Button>
<Button
type="default"
onPress={showSignIn}
accessibilityHint={_(msg`Sign in`)}
accessibilityLabel={_(msg`Sign in`)}>
<Text type="md" style={[pal.text, s.bold]}>
<Trans>Sign in</Trans>
</Text>
</Button>
</View>
</View>
</>
)}
</Animated.View>
+37 -34
View File
@@ -266,6 +266,10 @@ export function DesktopLeftNav() {
const {isDesktop, isTablet} = useWebMediaQueries()
const numUnread = useUnreadNotifications()
if (!hasSession && !isDesktop) {
return null
}
return (
<View
style={[
@@ -282,40 +286,40 @@ export function DesktopLeftNav() {
</View>
) : null}
<BackBtn />
<NavItem
href="/"
icon={<HomeIcon size={isDesktop ? 24 : 28} style={pal.text} />}
iconFilled={
<HomeIconSolid
strokeWidth={4}
size={isDesktop ? 24 : 28}
style={pal.text}
/>
}
label={_(msg`Home`)}
/>
<NavItem
href="/search"
icon={
<MagnifyingGlassIcon2
strokeWidth={2}
size={isDesktop ? 24 : 26}
style={pal.text}
/>
}
iconFilled={
<MagnifyingGlassIcon2Solid
strokeWidth={2}
size={isDesktop ? 24 : 26}
style={pal.text}
/>
}
label={_(msg`Search`)}
/>
{hasSession && (
<>
<BackBtn />
<NavItem
href="/"
icon={<HomeIcon size={isDesktop ? 24 : 28} style={pal.text} />}
iconFilled={
<HomeIconSolid
strokeWidth={4}
size={isDesktop ? 24 : 28}
style={pal.text}
/>
}
label={_(msg`Home`)}
/>
<NavItem
href="/search"
icon={
<MagnifyingGlassIcon2
strokeWidth={2}
size={isDesktop ? 24 : 26}
style={pal.text}
/>
}
iconFilled={
<MagnifyingGlassIcon2Solid
strokeWidth={2}
size={isDesktop ? 24 : 26}
style={pal.text}
/>
}
label={_(msg`Search`)}
/>
<NavItem
href="/feeds"
icon={
@@ -405,7 +409,7 @@ export function DesktopLeftNav() {
style={pal.text}
/>
}
label="Profile"
label={_(msg`Profile`)}
/>
<NavItem
href="/settings"
@@ -512,7 +516,6 @@ const styles = StyleSheet.create({
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
width: 140,
borderRadius: 24,
paddingTop: 10,
paddingBottom: 12, // visually aligns the text vertically inside the button
+1 -1
View File
@@ -52,7 +52,7 @@ export function DesktopRightNav() {
</Text>
</View>
) : undefined}
<View style={[s.flexRow]}>
<View style={[{flexWrap: 'wrap'}, s.flexRow]}>
{hasSession && (
<>
<TextLink