diff options
Diffstat (limited to 'src/view/shell/desktop')
-rw-r--r-- | src/view/shell/desktop/Feeds.tsx | 4 | ||||
-rw-r--r-- | src/view/shell/desktop/LeftNav.tsx | 46 | ||||
-rw-r--r-- | src/view/shell/desktop/RightNav.tsx | 37 | ||||
-rw-r--r-- | src/view/shell/desktop/Search.tsx | 104 |
4 files changed, 135 insertions, 56 deletions
diff --git a/src/view/shell/desktop/Feeds.tsx b/src/view/shell/desktop/Feeds.tsx index 93b96e704..a8f5f1c66 100644 --- a/src/view/shell/desktop/Feeds.tsx +++ b/src/view/shell/desktop/Feeds.tsx @@ -21,7 +21,7 @@ export function DesktopFeeds() { }) return ( - <View style={[styles.container, pal.view, pal.border]}> + <View style={[styles.container, pal.view]}> <FeedItem href="/" title="Following" current={route.name === 'Home'} /> {feeds .filter(f => f.displayName !== 'Following') @@ -91,7 +91,5 @@ const styles = StyleSheet.create({ width: 300, paddingHorizontal: 12, paddingVertical: 18, - borderTopWidth: 1, - borderBottomWidth: 1, }, }) diff --git a/src/view/shell/desktop/LeftNav.tsx b/src/view/shell/desktop/LeftNav.tsx index f3c8c1d11..b27898828 100644 --- a/src/view/shell/desktop/LeftNav.tsx +++ b/src/view/shell/desktop/LeftNav.tsx @@ -239,24 +239,26 @@ function ComposeBtn() { return null } return ( - <TouchableOpacity - disabled={isFetchingHandle} - style={[styles.newPostBtn]} - onPress={onPressCompose} - accessibilityRole="button" - accessibilityLabel={_(msg`New post`)} - accessibilityHint=""> - <View style={styles.newPostBtnIconWrapper}> - <ComposeIcon2 - size={19} - strokeWidth={2} - style={styles.newPostBtnLabel} - /> - </View> - <Text type="button" style={styles.newPostBtnLabel}> - <Trans>New Post</Trans> - </Text> - </TouchableOpacity> + <View style={styles.newPostBtnContainer}> + <TouchableOpacity + disabled={isFetchingHandle} + style={styles.newPostBtn} + onPress={onPressCompose} + accessibilityRole="button" + accessibilityLabel={_(msg`New post`)} + accessibilityHint=""> + <View style={styles.newPostBtnIconWrapper}> + <ComposeIcon2 + size={19} + strokeWidth={2} + style={styles.newPostBtnLabel} + /> + </View> + <Text type="button" style={styles.newPostBtnLabel}> + <Trans context="action">New Post</Trans> + </Text> + </TouchableOpacity> + </View> ) } @@ -440,10 +442,11 @@ export function DesktopLeftNav() { const styles = StyleSheet.create({ leftNav: { - position: 'absolute', + // @ts-ignore web only + position: 'fixed', top: 10, // @ts-ignore web only - right: 'calc(50vw + 312px)', + left: 'calc(50vw - 300px - 220px - 20px)', width: 220, // @ts-ignore web only maxHeight: 'calc(100vh - 10px)', @@ -512,6 +515,9 @@ const styles = StyleSheet.create({ fontSize: 14, }, + newPostBtnContainer: { + flexDirection: 'row', + }, newPostBtn: { flexDirection: 'row', alignItems: 'center', diff --git a/src/view/shell/desktop/RightNav.tsx b/src/view/shell/desktop/RightNav.tsx index 8d9961a5f..328c527e4 100644 --- a/src/view/shell/desktop/RightNav.tsx +++ b/src/view/shell/desktop/RightNav.tsx @@ -16,7 +16,7 @@ import {Plural, Trans, msg, plural} from '@lingui/macro' import {useSession} from '#/state/session' import {useInviteCodesQuery} from '#/state/queries/invites' -export function DesktopRightNav() { +export function DesktopRightNav({routeName}: {routeName: string}) { const pal = usePalette('default') const palError = usePalette('error') const {_} = useLingui() @@ -30,12 +30,20 @@ export function DesktopRightNav() { return ( <View style={[styles.rightNav, pal.view]}> <View style={{paddingVertical: 20}}> - <DesktopSearch /> - - {hasSession && ( - <View style={{paddingTop: 18, marginBottom: 18}}> + {routeName === 'Search' ? ( + <View style={{marginBottom: 18}}> <DesktopFeeds /> </View> + ) : ( + <> + <DesktopSearch /> + + {hasSession && ( + <View style={[pal.border, styles.desktopFeedsContainer]}> + <DesktopFeeds /> + </View> + )} + </> )} <View @@ -48,7 +56,7 @@ export function DesktopRightNav() { {isSandbox ? ( <View style={[palError.view, styles.messageLine, s.p10]}> <Text type="md" style={[palError.text, s.bold]}> - SANDBOX. Posts and accounts are not permanent. + <Trans>SANDBOX. Posts and accounts are not permanent.</Trans> </Text> </View> ) : undefined} @@ -169,17 +177,18 @@ function InviteCodes() { const styles = StyleSheet.create({ rightNav: { - position: 'absolute', // @ts-ignore web only - left: 'calc(50vw + 320px)', - width: 304, + position: 'fixed', + // @ts-ignore web only + left: 'calc(50vw + 300px + 20px)', + width: 300, maxHeight: '100%', overflowY: 'auto', }, message: { paddingVertical: 18, - paddingHorizontal: 10, + paddingHorizontal: 12, }, messageLine: { marginBottom: 10, @@ -187,7 +196,7 @@ const styles = StyleSheet.create({ inviteCodes: { borderTopWidth: 1, - paddingHorizontal: 16, + paddingHorizontal: 12, paddingVertical: 12, flexDirection: 'row', }, @@ -196,4 +205,10 @@ const styles = StyleSheet.create({ marginRight: 6, flexShrink: 0, }, + desktopFeedsContainer: { + borderTopWidth: 1, + borderBottomWidth: 1, + marginTop: 18, + marginBottom: 18, + }, }) diff --git a/src/view/shell/desktop/Search.tsx b/src/view/shell/desktop/Search.tsx index 6201f828f..4a9483733 100644 --- a/src/view/shell/desktop/Search.tsx +++ b/src/view/shell/desktop/Search.tsx @@ -29,13 +29,63 @@ import {UserAvatar} from '#/view/com/util/UserAvatar' import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete' import {useModerationOpts} from '#/state/queries/preferences' -export function SearchResultCard({ - profile, +export const MATCH_HANDLE = + /@?([a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(?:\.[a-zA-Z]{2,}))/ + +export function SearchLinkCard({ + label, + to, + onPress, style, +}: { + label: string + to?: string + onPress?: () => void + style?: ViewStyle +}) { + const pal = usePalette('default') + + const inner = ( + <View + style={[pal.border, {paddingVertical: 16, paddingHorizontal: 12}, style]}> + <Text type="md" style={[pal.text]}> + {label} + </Text> + </View> + ) + + if (onPress) { + return ( + <TouchableOpacity + onPress={onPress} + accessibilityLabel={label} + accessibilityHint=""> + {inner} + </TouchableOpacity> + ) + } + + return ( + <Link href={to} asAnchor anchorNoUnderline> + <View + style={[ + pal.border, + {paddingVertical: 16, paddingHorizontal: 12}, + style, + ]}> + <Text type="md" style={[pal.text]}> + {label} + </Text> + </View> + </Link> + ) +} + +export function SearchProfileCard({ + profile, moderation, }: { profile: AppBskyActorDefs.ProfileViewBasic - style: ViewStyle moderation: ProfileModeration }) { const pal = usePalette('default') @@ -50,9 +100,7 @@ export function SearchResultCard({ <View style={[ pal.border, - style, { - borderTopWidth: 1, flexDirection: 'row', alignItems: 'center', gap: 12, @@ -147,6 +195,11 @@ export function DesktopSearch() { navigation.dispatch(StackActions.push('Search', {q: query})) }, [query, navigation, setSearchResults]) + const queryMaybeHandle = React.useMemo(() => { + const match = MATCH_HANDLE.exec(query) + return match && match[1] + }, [query]) + return ( <View style={[styles.container, pal.view]}> <View @@ -169,6 +222,9 @@ export function DesktopSearch() { accessibilityRole="search" accessibilityLabel={_(msg`Search`)} accessibilityHint="" + autoCorrect={false} + autoComplete="off" + autoCapitalize="none" /> {query ? ( <View style={styles.cancelBtn}> @@ -176,7 +232,7 @@ export function DesktopSearch() { onPress={onPressCancelSearch} accessibilityRole="button" accessibilityLabel={_(msg`Cancel search`)} - accessibilityHint="Exits inputting search query" + accessibilityHint={_(msg`Exits inputting search query`)} onAccessibilityEscape={onPressCancelSearch}> <Text type="lg" style={[pal.link]}> <Trans>Cancel</Trans> @@ -195,22 +251,26 @@ export function DesktopSearch() { </View> ) : ( <> - {searchResults.length ? ( - searchResults.map((item, i) => ( - <SearchResultCard - key={item.did} - profile={item} - moderation={moderateProfile(item, moderationOpts)} - style={i === 0 ? {borderTopWidth: 0} : {}} - /> - )) - ) : ( - <View> - <Text style={[pal.textLight, styles.noResults]}> - <Trans>No results found for {query}</Trans> - </Text> - </View> - )} + <SearchLinkCard + label={_(msg`Search for "${query}"`)} + to={`/search?q=${encodeURIComponent(query)}`} + style={{borderBottomWidth: 1}} + /> + + {queryMaybeHandle ? ( + <SearchLinkCard + label={_(msg`Go to @${queryMaybeHandle}`)} + to={`/profile/${queryMaybeHandle}`} + /> + ) : null} + + {searchResults.map(item => ( + <SearchProfileCard + key={item.did} + profile={item} + moderation={moderateProfile(item, moderationOpts)} + /> + ))} </> )} </View> |