diff options
Diffstat (limited to 'src/view/com')
-rw-r--r-- | src/view/com/modals/ComposePost.tsx | 9 | ||||
-rw-r--r-- | src/view/com/post-thread/PostThreadItem.tsx | 2 | ||||
-rw-r--r-- | src/view/com/post/Post.tsx | 2 | ||||
-rw-r--r-- | src/view/com/posts/Feed.tsx (renamed from src/view/com/feed/Feed.tsx) | 8 | ||||
-rw-r--r-- | src/view/com/posts/FeedItem.tsx (renamed from src/view/com/feed/FeedItem.tsx) | 9 | ||||
-rw-r--r-- | src/view/com/profile/ProfileHeader.tsx | 52 | ||||
-rw-r--r-- | src/view/com/util/ErrorMessage.tsx | 66 | ||||
-rw-r--r-- | src/view/com/util/ErrorScreen.tsx | 111 | ||||
-rw-r--r-- | src/view/com/util/Selector.tsx | 8 |
9 files changed, 204 insertions, 63 deletions
diff --git a/src/view/com/modals/ComposePost.tsx b/src/view/com/modals/ComposePost.tsx index 253db3771..22b6b14bb 100644 --- a/src/view/com/modals/ComposePost.tsx +++ b/src/view/com/modals/ComposePost.tsx @@ -1,12 +1,5 @@ import React, {useState} from 'react' -import { - KeyboardAvoidingView, - StyleSheet, - Text, - TextInput, - TouchableOpacity, - View, -} from 'react-native' +import {StyleSheet, Text, TouchableOpacity, View} from 'react-native' import {BottomSheetTextInput} from '@gorhom/bottom-sheet' import LinearGradient from 'react-native-linear-gradient' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx index d500514ef..8752ee7f9 100644 --- a/src/view/com/post-thread/PostThreadItem.tsx +++ b/src/view/com/post-thread/PostThreadItem.tsx @@ -238,7 +238,7 @@ export const PostThreadItem = observer(function PostThreadItem({ const styles = StyleSheet.create({ outer: { backgroundColor: colors.white, - borderRadius: 10, + borderRadius: 6, margin: 2, marginBottom: 0, }, diff --git a/src/view/com/post/Post.tsx b/src/view/com/post/Post.tsx index a6580fa5a..3dd5c0047 100644 --- a/src/view/com/post/Post.tsx +++ b/src/view/com/post/Post.tsx @@ -154,7 +154,7 @@ export const Post = observer(function Post({uri}: {uri: string}) { const styles = StyleSheet.create({ outer: { marginTop: 1, - borderRadius: 4, + borderRadius: 6, backgroundColor: colors.white, padding: 10, }, diff --git a/src/view/com/feed/Feed.tsx b/src/view/com/posts/Feed.tsx index 4a2ecb612..370a72e69 100644 --- a/src/view/com/feed/Feed.tsx +++ b/src/view/com/posts/Feed.tsx @@ -3,21 +3,17 @@ import {observer} from 'mobx-react-lite' import {Text, View, FlatList} from 'react-native' import {FeedViewModel, FeedViewItemModel} from '../../../state/models/feed-view' import {FeedItem} from './FeedItem' -import {SharePostModel} from '../../../state/models/shell' import {useStores} from '../../../state' export const Feed = observer(function Feed({feed}: {feed: FeedViewModel}) { const store = useStores() - const onPressShare = (uri: string) => { - store.shell.openModal(new SharePostModel(uri)) - } // TODO optimize renderItem or FeedItem, we're getting this notice from RN: -prf // VirtualizedList: You have a large list that is slow to update - make sure your // renderItem function renders components that follow React performance best practices // like PureComponent, shouldComponentUpdate, etc const renderItem = ({item}: {item: FeedViewItemModel}) => ( - <FeedItem item={item} onPressShare={onPressShare} /> + <FeedItem item={item} /> ) const onRefresh = () => { feed.refresh().catch(err => console.error('Failed to refresh', err)) @@ -33,7 +29,7 @@ export const Feed = observer(function Feed({feed}: {feed: FeedViewModel}) { {feed.hasError && <Text>{feed.error}</Text>} {feed.hasContent && ( <FlatList - data={feed.feed} + data={feed.feed.slice()} keyExtractor={item => item._reactKey} renderItem={renderItem} refreshing={feed.isRefreshing} diff --git a/src/view/com/feed/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx index e9cf83346..2376686df 100644 --- a/src/view/com/feed/FeedItem.tsx +++ b/src/view/com/posts/FeedItem.tsx @@ -4,7 +4,7 @@ import {Image, StyleSheet, Text, TouchableOpacity, View} from 'react-native' import {bsky, AdxUri} from '@adxp/mock-api' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FeedViewItemModel} from '../../../state/models/feed-view' -import {ComposePostModel} from '../../../state/models/shell' +import {ComposePostModel, SharePostModel} from '../../../state/models/shell' import {Link} from '../util/Link' import {PostDropdownBtn} from '../util/DropdownBtn' import {s, colors} from '../../lib/styles' @@ -14,10 +14,8 @@ import {useStores} from '../../../state' export const FeedItem = observer(function FeedItem({ item, - onPressShare, }: { item: FeedViewItemModel - onPressShare: (_uri: string) => void }) { const store = useStores() const record = item.record as unknown as bsky.Post.Record @@ -41,6 +39,9 @@ export const FeedItem = observer(function FeedItem({ .toggleLike() .catch(e => console.error('Failed to toggle like', record, e)) } + const onPressShare = (uri: string) => { + store.shell.openModal(new SharePostModel(uri)) + } return ( <Link style={styles.outer} href={itemHref} title={itemTitle}> @@ -151,7 +152,7 @@ export const FeedItem = observer(function FeedItem({ const styles = StyleSheet.create({ outer: { - borderRadius: 10, + borderRadius: 6, margin: 2, marginBottom: 0, backgroundColor: colors.white, diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx index 08d895554..59af6b200 100644 --- a/src/view/com/profile/ProfileHeader.tsx +++ b/src/view/com/profile/ProfileHeader.tsx @@ -17,31 +17,13 @@ import {s, gradients, colors} from '../../lib/styles' import {AVIS, BANNER} from '../../lib/assets' import Toast from '../util/Toast' import {Link} from '../util/Link' -import {Selector, SelectorItem} from '../util/Selector' export const ProfileHeader = observer(function ProfileHeader({ - user, + view, }: { - user: string + view: ProfileViewModel }) { const store = useStores() - const [view, setView] = useState<ProfileViewModel | undefined>() - - useEffect(() => { - if (view?.params.user === user) { - console.log('Profile header doing nothing') - return // no change needed? or trigger refresh? - } - console.log('Fetching profile', user) - const newView = new ProfileViewModel(store, {user: user}) - setView(newView) - newView.setup().catch(err => console.error('Failed to fetch profile', err)) - }, [user, view?.params.user, store]) - - const selectorItems: SelectorItem[] = [ - {label: 'Posts', onSelect() {}}, - {label: 'Badges', onSelect() {}}, - ] const onPressToggleFollow = () => { view?.toggleFollowing().then( @@ -66,19 +48,15 @@ export const ProfileHeader = observer(function ProfileHeader({ // TODO } const onPressFollowers = () => { - store.nav.navigate(`/profile/${user}/followers`) + store.nav.navigate(`/profile/${view.name}/followers`) } const onPressFollows = () => { - store.nav.navigate(`/profile/${user}/follows`) + store.nav.navigate(`/profile/${view.name}/follows`) } // loading // = - if ( - !view || - (view.isLoading && !view.isRefreshing) || - view.params.user !== user - ) { + if (!view || (view.isLoading && !view.isRefreshing)) { return ( <View> <ActivityIndicator /> @@ -120,13 +98,13 @@ export const ProfileHeader = observer(function ProfileHeader({ <TouchableOpacity onPress={onPressEditProfile} style={[styles.mainBtn, styles.btn]}> - <Text style={[s.fw600, s.f16]}>Edit Profile</Text> + <Text style={[s.fw400, s.f14]}>Edit Profile</Text> </TouchableOpacity> ) : view.myState.hasFollowed ? ( <TouchableOpacity onPress={onPressToggleFollow} style={[styles.mainBtn, styles.btn]}> - <Text style={[s.fw600, s.f16]}>Following</Text> + <Text style={[s.fw400, s.f14]}>Following</Text> </TouchableOpacity> ) : ( <TouchableOpacity onPress={onPressToggleFollow}> @@ -146,7 +124,7 @@ export const ProfileHeader = observer(function ProfileHeader({ <FontAwesomeIcon icon="ellipsis" style={[s.gray5]} /> </TouchableOpacity> </View> - <View style={[s.flexRow, s.mb10]}> + <View style={[s.flexRow]}> <TouchableOpacity style={[s.flexRow, s.mr10]} onPress={onPressFollowers}> @@ -167,10 +145,9 @@ export const ProfileHeader = observer(function ProfileHeader({ </View> </View> {view.description && ( - <Text style={[s.mb10, s.f15, s['lh15-1.3']]}>{view.description}</Text> + <Text style={[s.mt10, s.f15, s['lh15-1.3']]}>{view.description}</Text> )} </View> - <Selector items={selectorItems} /> </View> ) }) @@ -178,8 +155,6 @@ export const ProfileHeader = observer(function ProfileHeader({ const styles = StyleSheet.create({ outer: { backgroundColor: colors.white, - borderBottomWidth: 1, - borderColor: colors.gray2, }, banner: { width: '100%', @@ -222,14 +197,17 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', justifyContent: 'center', - paddingVertical: 8, - paddingHorizontal: 60, + paddingVertical: 6, + paddingLeft: 55, + paddingRight: 60, borderRadius: 30, + borderWidth: 1, + borderColor: 'transparent', }, btn: { alignItems: 'center', justifyContent: 'center', - paddingVertical: 8, + paddingVertical: 7, borderRadius: 30, borderWidth: 1, borderColor: colors.gray2, diff --git a/src/view/com/util/ErrorMessage.tsx b/src/view/com/util/ErrorMessage.tsx new file mode 100644 index 000000000..7c8670da3 --- /dev/null +++ b/src/view/com/util/ErrorMessage.tsx @@ -0,0 +1,66 @@ +import React from 'react' +import {StyleSheet, Text, TouchableOpacity, View} from 'react-native' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' +import {colors} from '../../lib/styles' + +export function ErrorMessage({ + message, + onPressTryAgain, +}: { + message: string + onPressTryAgain?: () => void +}) { + return ( + <View style={styles.outer}> + <View style={styles.errorIcon}> + <FontAwesomeIcon + icon="exclamation" + style={{color: colors.white}} + size={16} + /> + </View> + <Text style={styles.message}>{message}</Text> + {onPressTryAgain && ( + <TouchableOpacity style={styles.btn} onPress={onPressTryAgain}> + <FontAwesomeIcon + icon="arrows-rotate" + style={{color: colors.red4}} + size={16} + /> + </TouchableOpacity> + )} + </View> + ) +} + +const styles = StyleSheet.create({ + outer: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + backgroundColor: colors.red1, + borderWidth: 1, + borderColor: colors.red3, + borderRadius: 6, + paddingVertical: 8, + paddingHorizontal: 8, + }, + errorIcon: { + backgroundColor: colors.red4, + borderRadius: 12, + width: 24, + height: 24, + alignItems: 'center', + justifyContent: 'center', + marginRight: 8, + }, + message: { + flex: 1, + color: colors.red4, + paddingRight: 10, + }, + btn: { + paddingHorizontal: 4, + paddingVertical: 4, + }, +}) diff --git a/src/view/com/util/ErrorScreen.tsx b/src/view/com/util/ErrorScreen.tsx new file mode 100644 index 000000000..4a3e41dc9 --- /dev/null +++ b/src/view/com/util/ErrorScreen.tsx @@ -0,0 +1,111 @@ +import React from 'react' +import {StyleSheet, Text, TouchableOpacity, View} from 'react-native' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' +import {colors} from '../../lib/styles' + +export function ErrorScreen({ + title, + message, + details, + onPressTryAgain, +}: { + title: string + message: string + details?: string + onPressTryAgain?: () => void +}) { + return ( + <View style={styles.outer}> + <View style={styles.errorIconContainer}> + <View style={styles.errorIcon}> + <FontAwesomeIcon + icon="exclamation" + style={{color: colors.white}} + size={24} + /> + </View> + </View> + <Text style={styles.title}>{title}</Text> + <Text style={styles.message}>{message}</Text> + {details && <Text style={styles.details}>{details}</Text>} + {onPressTryAgain && ( + <View style={styles.btnContainer}> + <TouchableOpacity style={styles.btn} onPress={onPressTryAgain}> + <FontAwesomeIcon + icon="arrows-rotate" + style={{color: colors.white}} + size={16} + /> + <Text style={styles.btnText}>Try again</Text> + </TouchableOpacity> + </View> + )} + </View> + ) +} + +const styles = StyleSheet.create({ + outer: { + flex: 1, + backgroundColor: colors.red1, + borderWidth: 1, + borderColor: colors.red3, + borderRadius: 6, + paddingVertical: 30, + paddingHorizontal: 14, + margin: 10, + }, + title: { + textAlign: 'center', + color: colors.red4, + fontSize: 24, + marginBottom: 10, + }, + message: { + textAlign: 'center', + color: colors.red4, + marginBottom: 20, + }, + details: { + textAlign: 'center', + color: colors.black, + backgroundColor: colors.white, + borderWidth: 1, + borderColor: colors.gray5, + borderRadius: 6, + paddingVertical: 10, + paddingHorizontal: 14, + overflow: 'hidden', + marginBottom: 20, + }, + btnContainer: { + alignItems: 'center', + }, + btn: { + flexDirection: 'row', + alignItems: 'center', + backgroundColor: colors.red4, + borderRadius: 6, + paddingHorizontal: 16, + paddingVertical: 10, + }, + btnText: { + marginLeft: 5, + color: colors.white, + fontSize: 16, + fontWeight: 'bold', + }, + errorIconContainer: { + alignItems: 'center', + marginBottom: 10, + }, + errorIcon: { + backgroundColor: colors.red4, + borderRadius: 30, + width: 50, + height: 50, + alignItems: 'center', + justifyContent: 'center', + marginRight: 5, + }, +}) diff --git a/src/view/com/util/Selector.tsx b/src/view/com/util/Selector.tsx index ef7c65d59..adc393d89 100644 --- a/src/view/com/util/Selector.tsx +++ b/src/view/com/util/Selector.tsx @@ -9,17 +9,13 @@ import { } from 'react-native' import {colors} from '../../lib/styles' -export interface SelectorItem { - label: string -} - export function Selector({ style, items, onSelect, }: { style?: StyleProp<ViewStyle> - items: SelectorItem[] + items: string[] onSelect?: (index: number) => void }) { const [selectedIndex, setSelectedIndex] = useState<number>(0) @@ -36,7 +32,7 @@ export function Selector({ <TouchableWithoutFeedback key={i} onPress={() => onPressItem(i)}> <View style={selected ? styles.itemSelected : styles.item}> <Text style={selected ? styles.labelSelected : styles.label}> - {item.label} + {item} </Text> </View> </TouchableWithoutFeedback> |