diff options
Diffstat (limited to 'src/view/com/util')
-rw-r--r-- | src/view/com/util/Link.tsx | 26 | ||||
-rw-r--r-- | src/view/com/util/PostMeta.tsx | 119 | ||||
-rw-r--r-- | src/view/com/util/UserAvatar.tsx | 54 |
3 files changed, 78 insertions, 121 deletions
diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx index 1dec97e78..454fd7c21 100644 --- a/src/view/com/util/Link.tsx +++ b/src/view/com/util/Link.tsx @@ -6,6 +6,7 @@ import { Platform, StyleProp, TextStyle, + TextProps, View, ViewStyle, TouchableOpacity, @@ -144,7 +145,7 @@ export const TextLink = observer(function TextLink({ numberOfLines?: number lineHeight?: number dataSet?: any -}) { +} & TextProps) { const {...props} = useLinkProps({to: sanitizeUrl(href)}) const store = useStores() const navigation = useNavigation<NavigationProp>() @@ -186,16 +187,7 @@ export const TextLink = observer(function TextLink({ /** * Only acts as a link on desktop web */ -export const DesktopWebTextLink = observer(function DesktopWebTextLink({ - testID, - type = 'md', - style, - href, - text, - numberOfLines, - lineHeight, - ...props -}: { +interface DesktopWebTextLinkProps extends TextProps { testID?: string type?: TypographyVariant style?: StyleProp<TextStyle> @@ -206,7 +198,17 @@ export const DesktopWebTextLink = observer(function DesktopWebTextLink({ accessible?: boolean accessibilityLabel?: string accessibilityHint?: string -}) { +} +export const DesktopWebTextLink = observer(function DesktopWebTextLink({ + testID, + type = 'md', + style, + href, + text, + numberOfLines, + lineHeight, + ...props +}: DesktopWebTextLinkProps) { if (isDesktopWeb) { return ( <TextLink diff --git a/src/view/com/util/PostMeta.tsx b/src/view/com/util/PostMeta.tsx index 628c88722..396b0278d 100644 --- a/src/view/com/util/PostMeta.tsx +++ b/src/view/com/util/PostMeta.tsx @@ -4,12 +4,10 @@ import {Text} from './text/Text' import {DesktopWebTextLink} from './Link' import {ago, niceDate} from 'lib/strings/time' import {usePalette} from 'lib/hooks/usePalette' -import {useStores} from 'state/index' import {UserAvatar} from './UserAvatar' import {observer} from 'mobx-react-lite' -import {FollowButton} from '../profile/FollowButton' -import {FollowState} from 'state/models/cache/my-follows' import {sanitizeDisplayName} from 'lib/strings/display-names' +import {isAndroid, isIOS} from 'platform/detection' interface PostMetaOpts { authorAvatar?: string @@ -18,88 +16,17 @@ interface PostMetaOpts { authorHasWarning: boolean postHref: string timestamp: string - did?: string - showFollowBtn?: boolean } export const PostMeta = observer(function (opts: PostMetaOpts) { const pal = usePalette('default') const displayName = opts.authorDisplayName || opts.authorHandle const handle = opts.authorHandle - const store = useStores() - const isMe = opts.did === store.me.did - const followState = - typeof opts.did === 'string' - ? store.me.follows.getFollowState(opts.did) - : FollowState.Unknown - const [didFollow, setDidFollow] = React.useState(false) - const onToggleFollow = React.useCallback(() => { - setDidFollow(true) - }, [setDidFollow]) - - if ( - opts.showFollowBtn && - !isMe && - (followState === FollowState.NotFollowing || didFollow) && - opts.did - ) { - // two-liner with follow button - return ( - <View style={styles.metaTwoLine}> - <View style={styles.metaTwoLineLeft}> - <View style={styles.metaTwoLineTop}> - <DesktopWebTextLink - type="lg-bold" - style={pal.text} - numberOfLines={1} - lineHeight={1.2} - text={sanitizeDisplayName(displayName)} - href={`/profile/${opts.authorHandle}`} - /> - <Text - type="md" - style={pal.textLight} - lineHeight={1.2} - accessible={false}> - · - </Text> - <DesktopWebTextLink - type="md" - style={[styles.metaItem, pal.textLight]} - lineHeight={1.2} - text={ago(opts.timestamp)} - accessibilityLabel={niceDate(opts.timestamp)} - accessibilityHint="" - href={opts.postHref} - /> - </View> - <DesktopWebTextLink - type="md" - style={[styles.metaItem, pal.textLight]} - lineHeight={1.2} - numberOfLines={1} - text={`@${handle}`} - href={`/profile/${opts.authorHandle}`} - /> - </View> - - <View> - <FollowButton - unfollowedType="default" - did={opts.did} - onToggleFollow={onToggleFollow} - /> - </View> - </View> - ) - } - - // one-liner return ( - <View style={styles.meta}> + <View style={styles.metaOneLine}> {typeof opts.authorAvatar !== 'undefined' && ( - <View style={[styles.metaItem, styles.avatar]}> + <View style={styles.avatar}> <UserAvatar avatar={opts.authorAvatar} size={16} @@ -107,7 +34,7 @@ export const PostMeta = observer(function (opts: PostMetaOpts) { /> </View> )} - <View style={[styles.metaItem, styles.maxWidth]}> + <View style={styles.maxWidth}> <DesktopWebTextLink type="lg-bold" style={pal.text} @@ -128,12 +55,18 @@ export const PostMeta = observer(function (opts: PostMetaOpts) { href={`/profile/${opts.authorHandle}`} /> </View> - <Text type="md" style={pal.textLight} lineHeight={1.2} accessible={false}> - · - </Text> + {!isAndroid && ( + <Text + type="md" + style={pal.textLight} + lineHeight={1.2} + accessible={false}> + · + </Text> + )} <DesktopWebTextLink type="md" - style={[styles.metaItem, pal.textLight]} + style={pal.textLight} lineHeight={1.2} text={ago(opts.timestamp)} accessibilityLabel={niceDate(opts.timestamp)} @@ -145,32 +78,16 @@ export const PostMeta = observer(function (opts: PostMetaOpts) { }) const styles = StyleSheet.create({ - meta: { + metaOneLine: { flexDirection: 'row', paddingBottom: 2, - }, - metaTwoLine: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - width: '100%', - paddingBottom: 4, - }, - metaTwoLineLeft: { - flex: 1, - paddingRight: 40, - }, - metaTwoLineTop: { - flexDirection: 'row', - alignItems: 'baseline', - }, - metaItem: { - paddingRight: 5, + gap: 4, }, avatar: { alignSelf: 'center', }, maxWidth: { - maxWidth: '80%', + flex: isAndroid ? 1 : undefined, + maxWidth: isIOS ? '80%' : undefined, }, }) diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx index b94cf54e9..135615a3b 100644 --- a/src/view/com/util/UserAvatar.tsx +++ b/src/view/com/util/UserAvatar.tsx @@ -1,5 +1,5 @@ import React, {useMemo} from 'react' -import {StyleSheet, View} from 'react-native' +import {Pressable, StyleSheet, View} from 'react-native' import Svg, {Circle, Rect, Path} from 'react-native-svg' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {IconProp} from '@fortawesome/fontawesome-svg-core' @@ -12,13 +12,31 @@ import { import {useStores} from 'state/index' import {colors} from 'lib/styles' import {DropdownButton} from './forms/DropdownButton' +import {Link} from './Link' import {usePalette} from 'lib/hooks/usePalette' import {isWeb, isAndroid} from 'platform/detection' import {Image as RNImage} from 'react-native-image-crop-picker' import {AvatarModeration} from 'lib/labeling/types' +import {isDesktopWeb} from 'platform/detection' type Type = 'user' | 'algo' | 'list' +interface BaseUserAvatarProps { + type?: Type + size: number + avatar?: string | null + moderation?: AvatarModeration +} + +interface UserAvatarProps extends BaseUserAvatarProps { + onSelectNewAvatar?: (img: RNImage | null) => void +} + +interface PreviewableUserAvatarProps extends BaseUserAvatarProps { + did: string + handle: string +} + const BLUR_AMOUNT = isWeb ? 5 : 100 function DefaultAvatar({type, size}: {type: Type; size: number}) { @@ -91,13 +109,7 @@ export function UserAvatar({ avatar, moderation, onSelectNewAvatar, -}: { - type?: Type - size: number - avatar?: string | null - moderation?: AvatarModeration - onSelectNewAvatar?: (img: RNImage | null) => void -}) { +}: UserAvatarProps) { const store = useStores() const pal = usePalette('default') const {requestCameraAccessIfNeeded} = useCameraPermission() @@ -244,6 +256,32 @@ export function UserAvatar({ ) } +export function PreviewableUserAvatar(props: PreviewableUserAvatarProps) { + const store = useStores() + + if (isDesktopWeb) { + return ( + <Link href={`/profile/${props.handle}`} title={props.handle} asAnchor> + <UserAvatar {...props} /> + </Link> + ) + } + return ( + <Pressable + onPress={() => + store.shell.openModal({ + name: 'profile-preview', + did: props.did, + }) + } + accessibilityRole="button" + accessibilityLabel={props.handle} + accessibilityHint=""> + <UserAvatar {...props} /> + </Pressable> + ) +} + const styles = StyleSheet.create({ editButtonContainer: { position: 'absolute', |