diff options
Diffstat (limited to 'src/view')
-rw-r--r-- | src/view/com/modals/EditProfile.tsx | 8 | ||||
-rw-r--r-- | src/view/com/modals/Modal.tsx | 2 | ||||
-rw-r--r-- | src/view/com/notifications/Feed.tsx | 4 | ||||
-rw-r--r-- | src/view/com/notifications/FeedItem.tsx | 51 | ||||
-rw-r--r-- | src/view/com/post-thread/PostThreadItem.tsx | 9 | ||||
-rw-r--r-- | src/view/com/post/Post.tsx | 27 | ||||
-rw-r--r-- | src/view/lib/styles.ts | 2 | ||||
-rw-r--r-- | src/view/screens/Notifications.tsx | 32 | ||||
-rw-r--r-- | src/view/shell/mobile/index.tsx | 4 |
9 files changed, 88 insertions, 51 deletions
diff --git a/src/view/com/modals/EditProfile.tsx b/src/view/com/modals/EditProfile.tsx index 50acccf67..1b5c99d97 100644 --- a/src/view/com/modals/EditProfile.tsx +++ b/src/view/com/modals/EditProfile.tsx @@ -65,8 +65,8 @@ export function Component({ return ( <View style={s.flex1}> - <Text style={[s.textCenter, s.bold, s.f16]}>Edit my profile</Text> <BottomSheetScrollView style={styles.inner}> + <Text style={styles.title}>Edit my profile</Text> {error !== '' && ( <View style={s.mb10}> <ErrorMessage message={error} /> @@ -114,6 +114,12 @@ const styles = StyleSheet.create({ inner: { padding: 14, }, + title: { + textAlign: 'center', + fontWeight: 'bold', + fontSize: 24, + marginBottom: 18, + }, group: { marginBottom: 10, }, diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx index 9d7033411..47b627435 100644 --- a/src/view/com/modals/Modal.tsx +++ b/src/view/com/modals/Modal.tsx @@ -35,7 +35,7 @@ export const Modal = observer(function Modal() { } else { bottomSheetRef.current?.close() } - }, [store.shell.isModalActive, bottomSheetRef]) + }, [store.shell.isModalActive, bottomSheetRef, store.shell.activeModal?.name]) let snapPoints: (string | number)[] = CLOSED_SNAPPOINTS let element diff --git a/src/view/com/notifications/Feed.tsx b/src/view/com/notifications/Feed.tsx index 90d16604d..d3a911f2a 100644 --- a/src/view/com/notifications/Feed.tsx +++ b/src/view/com/notifications/Feed.tsx @@ -43,7 +43,7 @@ export const Feed = observer(function Feed({ onPressTryAgain={onPressTryAgain} /> )} - {view.hasContent && ( + {view.hasLoaded && ( <FlatList data={view.notifications} keyExtractor={item => item._reactKey} @@ -53,7 +53,7 @@ export const Feed = observer(function Feed({ onEndReached={onEndReached} /> )} - {view.isEmpty && ( + {view.hasLoaded && view.isEmpty && ( <EmptyState icon="bell" message="No notifications yet!" /> )} </View> diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx index 8741e4236..166b1bf99 100644 --- a/src/view/com/notifications/FeedItem.tsx +++ b/src/view/com/notifications/FeedItem.tsx @@ -4,11 +4,12 @@ import {StyleSheet, Text, View} from 'react-native' import {AtUri} from '../../../third-party/uri' import {FontAwesomeIcon, Props} from '@fortawesome/react-native-fontawesome' import {NotificationsViewItemModel} from '../../../state/models/notifications-view' +import {PostThreadViewModel} from '../../../state/models/post-thread-view' import {s, colors} from '../../lib/styles' import {ago, pluralize} from '../../../lib/strings' import {UpIconSolid} from '../../lib/icons' import {UserAvatar} from '../util/UserAvatar' -import {PostText} from '../post/PostText' +import {ErrorMessage} from '../util/ErrorMessage' import {Post} from '../post/Post' import {Link} from '../util/Link' import {InviteAccepter} from './InviteAccepter' @@ -42,16 +43,22 @@ export const FeedItem = observer(function FeedItem({ } }, [item]) + if (item.additionalPost?.notFound) { + // don't render anything if the target post was deleted or unfindable + return <View /> + } + if (item.isReply) { return ( - <Link - style={[ - styles.outerMinimal, - item.isRead ? undefined : styles.outerUnread, - ]} - href={itemHref} - title={itemTitle}> - <Post uri={item.uri} /> + <Link href={itemHref} title={itemTitle}> + <Post + uri={item.uri} + initView={item.additionalPost} + style={[ + styles.outerMinimal, + item.isRead ? undefined : styles.outerUnread, + ]} + /> </Link> ) } @@ -170,7 +177,7 @@ export const FeedItem = observer(function FeedItem({ </Text> </View> {item.isUpvote || item.isRepost || item.isTrend ? ( - <PostText uri={item.subjectUri} style={[s.gray5]} /> + <AdditionalPostText additionalPost={item.additionalPost} /> ) : ( <></> )} @@ -181,17 +188,24 @@ export const FeedItem = observer(function FeedItem({ <InviteAccepter item={item} /> </View> )} - {item.isReply ? ( - <View style={s.pt5}> - <Post uri={item.uri} /> - </View> - ) : ( - <></> - )} </Link> ) }) +function AdditionalPostText({ + additionalPost, +}: { + additionalPost?: PostThreadViewModel +}) { + if (!additionalPost) { + return <View /> + } + if (additionalPost.error) { + return <ErrorMessage message={additionalPost.error} /> + } + return <Text style={[s.gray5]}>{additionalPost.thread?.record.text}</Text> +} + const styles = StyleSheet.create({ outer: { backgroundColor: colors.white, @@ -207,8 +221,9 @@ const styles = StyleSheet.create({ marginBottom: 0, }, outerUnread: { + backgroundColor: colors.unreadNotifBg, borderWidth: 1, - borderColor: colors.blue2, + borderColor: colors.blue1, }, layout: { flexDirection: 'row', diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx index 85c241ce4..d08ca3e4a 100644 --- a/src/view/com/post-thread/PostThreadItem.tsx +++ b/src/view/com/post-thread/PostThreadItem.tsx @@ -88,6 +88,15 @@ export const PostThreadItem = observer(function PostThreadItem({ ) } + if (deleted) { + return ( + <View style={[styles.outer, s.p20, s.flexRow]}> + <FontAwesomeIcon icon={['far', 'trash-can']} style={[s.gray4]} /> + <Text style={[s.gray5, s.ml10]}>This post has been deleted.</Text> + </View> + ) + } + if (item._isHighlightedPost) { return ( <> diff --git a/src/view/com/post/Post.tsx b/src/view/com/post/Post.tsx index 4d668cac3..736b40157 100644 --- a/src/view/com/post/Post.tsx +++ b/src/view/com/post/Post.tsx @@ -1,8 +1,15 @@ import React, {useState, useEffect} from 'react' +import { + ActivityIndicator, + StyleProp, + StyleSheet, + Text, + View, + ViewStyle, +} from 'react-native' import {observer} from 'mobx-react-lite' import {AtUri} from '../../../third-party/uri' import * as PostType from '../../../third-party/api/src/client/types/app/bsky/feed/post' -import {ActivityIndicator, StyleSheet, Text, View} from 'react-native' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {PostThreadViewModel} from '../../../state/models/post-thread-view' import {Link} from '../util/Link' @@ -15,19 +22,27 @@ import {UserAvatar} from '../util/UserAvatar' import {useStores} from '../../../state' import {s, colors} from '../../lib/styles' -export const Post = observer(function Post({uri}: {uri: string}) { +export const Post = observer(function Post({ + uri, + initView, + style, +}: { + uri: string + initView?: PostThreadViewModel + style?: StyleProp<ViewStyle> +}) { const store = useStores() - const [view, setView] = useState<PostThreadViewModel | undefined>() + const [view, setView] = useState<PostThreadViewModel | undefined>(initView) const [deleted, setDeleted] = useState(false) useEffect(() => { - if (view?.params.uri === uri) { + if (initView || view?.params.uri === uri) { return // no change needed? or trigger refresh? } const newView = new PostThreadViewModel(store, {uri, depth: 0}) setView(newView) newView.setup().catch(err => console.error('Failed to fetch post', err)) - }, [uri, view?.params.uri, store]) + }, [initView, uri, view?.params.uri, store]) // deleted // = @@ -109,7 +124,7 @@ export const Post = observer(function Post({uri}: {uri: string}) { } return ( - <Link style={styles.outer} href={itemHref} title={itemTitle}> + <Link style={[styles.outer, style]} href={itemHref} title={itemTitle}> <View style={styles.layout}> <View style={styles.layoutAvi}> <Link href={authorHref} title={authorTitle}> diff --git a/src/view/lib/styles.ts b/src/view/lib/styles.ts index 8bb26ef88..1ac6283a2 100644 --- a/src/view/lib/styles.ts +++ b/src/view/lib/styles.ts @@ -41,6 +41,8 @@ export const colors = { green3: '#20bc07', green4: '#148203', green5: '#082b03', + + unreadNotifBg: '#ebf6ff', } export const gradients = { diff --git a/src/view/screens/Notifications.tsx b/src/view/screens/Notifications.tsx index 1e7abdb90..b168ffaff 100644 --- a/src/view/screens/Notifications.tsx +++ b/src/view/screens/Notifications.tsx @@ -7,43 +7,33 @@ import {NotificationsViewModel} from '../../state/models/notifications-view' import {ScreenParams} from '../routes' export const Notifications = ({navIdx, visible}: ScreenParams) => { - const [hasSetup, setHasSetup] = useState<boolean>(false) - const [notesView, setNotesView] = useState< - NotificationsViewModel | undefined - >() const store = useStores() useEffect(() => { - let aborted = false if (!visible) { return } + console.log('Updating notifications feed') store.me.refreshMemberships() // needed for the invite notifications - if (hasSetup) { - console.log('Updating notifications feed') - notesView?.update() - } else { - store.nav.setTitle(navIdx, 'Notifications') - const newNotesView = new NotificationsViewModel(store, {}) - setNotesView(newNotesView) - newNotesView.setup().then(() => { - if (aborted) return - setHasSetup(true) + store.me.notifications + .update() + .catch(e => { + console.error('Error while updating notifications feed', e) }) - } - return () => { - aborted = true - } + .then(() => { + store.me.notifications.updateReadState() + }) + store.nav.setTitle(navIdx, 'Notifications') }, [visible, store]) const onPressTryAgain = () => { - notesView?.refresh() + store.me.notifications.refresh() } return ( <View style={{flex: 1}}> <ViewHeader title="Notifications" /> - {notesView && <Feed view={notesView} onPressTryAgain={onPressTryAgain} />} + <Feed view={store.me.notifications} onPressTryAgain={onPressTryAgain} /> </View> ) } diff --git a/src/view/shell/mobile/index.tsx b/src/view/shell/mobile/index.tsx index ccde52a2c..27524bcae 100644 --- a/src/view/shell/mobile/index.tsx +++ b/src/view/shell/mobile/index.tsx @@ -321,7 +321,7 @@ export const MobileShell: React.FC = observer(() => { <Btn icon={isAtHome ? 'home-solid' : 'home'} onPress={onPressHome} - onLongPress={doNewTab('/')} + onLongPress={TABS_ENABLED ? doNewTab('/') : undefined} /> {TABS_ENABLED ? ( <Btn @@ -333,7 +333,7 @@ export const MobileShell: React.FC = observer(() => { <Btn icon={isAtNotifications ? 'bell-solid' : 'bell'} onPress={onPressNotifications} - onLongPress={doNewTab('/notifications')} + onLongPress={TABS_ENABLED ? doNewTab('/notifications') : undefined} notificationCount={store.me.notificationCount} /> <Btn |