diff options
Diffstat (limited to 'src/screens')
-rw-r--r-- | src/screens/Messages/ChatList.tsx | 36 | ||||
-rw-r--r-- | src/screens/Profile/Header/Handle.tsx | 2 | ||||
-rw-r--r-- | src/screens/Profile/Header/ProfileHeaderStandard.tsx | 3 | ||||
-rw-r--r-- | src/screens/Profile/Header/Shell.tsx | 5 | ||||
-rw-r--r-- | src/screens/Search/SearchResults.tsx | 65 | ||||
-rw-r--r-- | src/screens/Settings/ContentAndMediaSettings.tsx | 2 | ||||
-rw-r--r-- | src/screens/Settings/Settings.tsx | 52 |
7 files changed, 147 insertions, 18 deletions
diff --git a/src/screens/Messages/ChatList.tsx b/src/screens/Messages/ChatList.tsx index e13f0617b..c37a025cc 100644 --- a/src/screens/Messages/ChatList.tsx +++ b/src/screens/Messages/ChatList.tsx @@ -164,12 +164,18 @@ export function MessagesScreenInner({navigation, route}: Props) { // filter out convos that are actively being left .filter(convo => !leftConvos.includes(convo.id)) + const hasInboxRequests = inboxPreviewConvos?.length > 0 + return [ - { - type: 'INBOX', - count: inboxPreviewConvos.length, - profiles: inboxPreviewConvos.slice(0, 3), - }, + ...(hasInboxRequests + ? [ + { + type: 'INBOX' as const, + count: inboxPreviewConvos.length, + profiles: inboxPreviewConvos.slice(0, 3), + }, + ] + : []), ...conversations.map( convo => ({type: 'CONVERSATION', conversation: convo}) as const, ), @@ -223,16 +229,24 @@ export function MessagesScreenInner({navigation, route}: Props) { return listenSoftReset(onSoftReset) }, [onSoftReset, isScreenFocused]) - // Will always have 1 item - the inbox button - if (conversations.length < 2) { + // NOTE(APiligrim) + // Show empty state only if there are no conversations at all + const actualConversations = conversations.filter( + item => item.type === 'CONVERSATION', + ) + const hasInboxRequests = inboxPreviewConvos?.length > 0 + + if (actualConversations.length === 0) { return ( <Layout.Screen> <Header newChatControl={newChatControl} /> <Layout.Center> - <InboxPreview - count={inboxPreviewConvos.length} - profiles={inboxPreviewConvos} - /> + {hasInboxRequests && ( + <InboxPreview + count={inboxPreviewConvos.length} + profiles={inboxPreviewConvos} + /> + )} {isLoading ? ( <ChatListLoadingPlaceholder /> ) : ( diff --git a/src/screens/Profile/Header/Handle.tsx b/src/screens/Profile/Header/Handle.tsx index cfbf430c4..f52b6d68e 100644 --- a/src/screens/Profile/Header/Handle.tsx +++ b/src/screens/Profile/Header/Handle.tsx @@ -23,7 +23,7 @@ export function ProfileHeaderHandle({ const blockHide = profile.viewer?.blocking || profile.viewer?.blockedBy return ( <View - style={[a.flex_row, a.gap_xs, a.align_center, {maxWidth: '100%'}]} + style={[a.flex_row, a.gap_sm, a.align_center, {maxWidth: '100%'}]} pointerEvents={disableTaps ? 'none' : isIOS ? 'auto' : 'box-none'}> <NewskieDialog profile={profile} disabled={disableTaps} /> {profile.viewer?.followedBy && !blockHide ? ( diff --git a/src/screens/Profile/Header/ProfileHeaderStandard.tsx b/src/screens/Profile/Header/ProfileHeaderStandard.tsx index 5dbf32c57..2f61ba4df 100644 --- a/src/screens/Profile/Header/ProfileHeaderStandard.tsx +++ b/src/screens/Profile/Header/ProfileHeaderStandard.tsx @@ -251,7 +251,7 @@ let ProfileHeaderStandard = ({ <ProfileMenu profile={profile} /> </View> <View - style={[a.flex_col, a.gap_2xs, a.pb_sm, live ? a.pt_sm : a.pt_2xs]}> + style={[a.flex_col, a.gap_xs, a.pb_sm, live ? a.pt_sm : a.pt_2xs]}> <View style={[a.flex_row, a.align_center, a.gap_xs, a.flex_1]}> <Text emoji @@ -261,6 +261,7 @@ let ProfileHeaderStandard = ({ gtMobile ? a.text_4xl : a.text_3xl, a.self_start, a.font_heavy, + a.leading_tight, ]}> {sanitizeDisplayName( profile.displayName || sanitizeHandle(profile.handle), diff --git a/src/screens/Profile/Header/Shell.tsx b/src/screens/Profile/Header/Shell.tsx index 53585c094..27962ba05 100644 --- a/src/screens/Profile/Header/Shell.tsx +++ b/src/screens/Profile/Header/Shell.tsx @@ -229,6 +229,7 @@ let ProfileHeaderShell = ({ size={live.isActive ? 88 : 90} avatar={profile.avatar} moderation={moderation.ui('avatar')} + noBorder /> {live.isActive && <LiveIndicator size="large" />} </Animated.View> @@ -260,7 +261,7 @@ export {ProfileHeaderShell} const styles = StyleSheet.create({ backBtnWrapper: { position: 'absolute', - left: 10, + left: 12, width: 30, height: 30, overflow: 'hidden', @@ -279,7 +280,7 @@ const styles = StyleSheet.create({ }, aviPosition: { position: 'absolute', - top: 110, + top: 104, left: 10, }, avi: { diff --git a/src/screens/Search/SearchResults.tsx b/src/screens/Search/SearchResults.tsx index 6b7a582d5..b626c9329 100644 --- a/src/screens/Search/SearchResults.tsx +++ b/src/screens/Search/SearchResults.tsx @@ -4,11 +4,14 @@ import {type AppBskyFeedDefs} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {usePalette} from '#/lib/hooks/usePalette' import {augmentSearchQuery} from '#/lib/strings/helpers' import {useActorSearch} from '#/state/queries/actor-search' import {usePopularFeedsSearch} from '#/state/queries/feed' import {useSearchPostsQuery} from '#/state/queries/search-posts' import {useSession} from '#/state/session' +import {useLoggedOutViewControls} from '#/state/shell/logged-out' +import {useCloseAllActiveElements} from '#/state/util' import {Pager} from '#/view/com/pager/Pager' import {TabBar} from '#/view/com/pager/TabBar' import {Post} from '#/view/com/post/Post' @@ -17,6 +20,8 @@ import {List} from '#/view/com/util/List' import {atoms as a, useTheme, web} from '#/alf' import * as FeedCard from '#/components/FeedCard' import * as Layout from '#/components/Layout' +import {InlineLinkText} from '#/components/Link' +import {SearchError} from '#/components/SearchError' import {Text} from '#/components/Typography' let SearchResults = ({ @@ -104,7 +109,15 @@ function Loader() { ) } -function EmptyState({message, error}: {message: string; error?: string}) { +function EmptyState({ + message, + error, + children, +}: { + message: string + error?: string + children?: React.ReactNode +}) { const t = useTheme() return ( @@ -132,6 +145,8 @@ function EmptyState({message, error}: {message: string; error?: string}) { </Text> </> )} + + {children} </View> </View> </Layout.Content> @@ -161,6 +176,7 @@ let SearchScreenPostResults = ({ const {_} = useLingui() const {currentAccount} = useSession() const [isPTR, setIsPTR] = useState(false) + const isLoggedin = Boolean(currentAccount?.did) const augmentedQuery = useMemo(() => { return augmentSearchQuery(query || '', {did: currentAccount?.did}) @@ -177,6 +193,8 @@ let SearchScreenPostResults = ({ hasNextPage, } = useSearchPostsQuery({query: augmentedQuery, sort, enabled: active}) + const pal = usePalette('default') + const t = useTheme() const onPullToRefresh = useCallback(async () => { setIsPTR(true) await refetch() @@ -216,6 +234,51 @@ let SearchScreenPostResults = ({ return temp }, [posts, isFetchingNextPage]) + const closeAllActiveElements = useCloseAllActiveElements() + const {requestSwitchToAccount} = useLoggedOutViewControls() + + const showSignIn = () => { + closeAllActiveElements() + requestSwitchToAccount({requestedAccount: 'none'}) + } + + const showCreateAccount = () => { + closeAllActiveElements() + requestSwitchToAccount({requestedAccount: 'new'}) + } + + if (!isLoggedin) { + return ( + <SearchError + title={_(msg`Search is currently unavailable when logged out`)}> + <Text style={[a.text_md, a.text_center, a.leading_snug]}> + <Trans> + <InlineLinkText + style={[pal.link]} + label={_(msg`sign in`)} + to={'#'} + onPress={showSignIn}> + Sign in + </InlineLinkText> + <Text style={t.atoms.text_contrast_medium}> or </Text> + <InlineLinkText + style={[pal.link]} + label={_(msg`create an account`)} + to={'#'} + onPress={showCreateAccount}> + create an account + </InlineLinkText> + <Text> </Text> + <Text style={t.atoms.text_contrast_medium}> + to search for news, sports, politics, and everything else + happening on Bluesky. + </Text> + </Trans> + </Text> + </SearchError> + ) + } + return error ? ( <EmptyState message={_( diff --git a/src/screens/Settings/ContentAndMediaSettings.tsx b/src/screens/Settings/ContentAndMediaSettings.tsx index 10d5b140b..e1144d064 100644 --- a/src/screens/Settings/ContentAndMediaSettings.tsx +++ b/src/screens/Settings/ContentAndMediaSettings.tsx @@ -150,7 +150,7 @@ export function ContentAndMediaSettingsScreen({}: Props) { </Toggle.Item> <Toggle.Item name="show_trending_videos" - label={_(msg`Enable trending videos in your Discover feed.`)} + label={_(msg`Enable trending videos in your Discover feed`)} value={!trendingVideoDisabled} onChange={value => { const hide = Boolean(!value) diff --git a/src/screens/Settings/Settings.tsx b/src/screens/Settings/Settings.tsx index 4d10a9d0d..b712c054c 100644 --- a/src/screens/Settings/Settings.tsx +++ b/src/screens/Settings/Settings.tsx @@ -1,5 +1,5 @@ import {useState} from 'react' -import {LayoutAnimation, Pressable, View} from 'react-native' +import {Alert, LayoutAnimation, Pressable, View} from 'react-native' import {Linking} from 'react-native' import {useReducedMotion} from 'react-native-reanimated' import {type AppBskyActorDefs, moderateProfile} from '@atproto/api' @@ -12,12 +12,14 @@ import {useActorStatus} from '#/lib/actor-status' import {IS_INTERNAL} from '#/lib/app-info' import {HELP_DESK_URL} from '#/lib/constants' import {useAccountSwitcher} from '#/lib/hooks/useAccountSwitcher' +import {useApplyPullRequestOTAUpdate} from '#/lib/hooks/useOTAUpdates' import { type CommonNavigatorParams, type NavigationProp, } from '#/lib/routes/types' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' +import {isIOS, isNative} from '#/platform/detection' import {useProfileShadow} from '#/state/cache/profile-shadow' import * as persisted from '#/state/persisted' import {clearStorage} from '#/state/persisted' @@ -364,6 +366,12 @@ function DevOptions() { const onboardingDispatch = useOnboardingDispatch() const navigation = useNavigation<NavigationProp>() const {mutate: deleteChatDeclarationRecord} = useDeleteActorDeclaration() + const { + tryApplyUpdate, + revertToEmbedded, + isCurrentlyRunningPullRequestDeployment, + currentChannel, + } = useApplyPullRequestOTAUpdate() const [actyNotifNudged, setActyNotifNudged] = useActivitySubscriptionsNudged() const resetOnboarding = async () => { @@ -392,6 +400,30 @@ function DevOptions() { setActyNotifNudged(false) } + const onPressApplyOta = () => { + Alert.prompt( + 'Apply OTA', + 'Enter the channel for the OTA you wish to apply.', + [ + { + style: 'cancel', + text: 'Cancel', + }, + { + style: 'default', + text: 'Apply', + onPress: channel => { + tryApplyUpdate(channel ?? '') + }, + }, + ], + 'plain-text', + isCurrentlyRunningPullRequestDeployment + ? currentChannel + : 'pull-request-', + ) + } + return ( <> <SettingsList.PressableItem @@ -452,6 +484,24 @@ function DevOptions() { <Trans>Clear all storage data (restart after this)</Trans> </SettingsList.ItemText> </SettingsList.PressableItem> + {isIOS ? ( + <SettingsList.PressableItem + onPress={onPressApplyOta} + label={_(msg`Apply Pull Request`)}> + <SettingsList.ItemText> + <Trans>Apply Pull Request</Trans> + </SettingsList.ItemText> + </SettingsList.PressableItem> + ) : null} + {isNative && isCurrentlyRunningPullRequestDeployment ? ( + <SettingsList.PressableItem + onPress={revertToEmbedded} + label={_(msg`Unapply Pull Request`)}> + <SettingsList.ItemText> + <Trans>Unapply Pull Request {currentChannel}</Trans> + </SettingsList.ItemText> + </SettingsList.PressableItem> + ) : null} </> ) } |