diff options
author | Paul Frazee <pfrazee@gmail.com> | 2022-11-16 13:05:36 -0600 |
---|---|---|
committer | Paul Frazee <pfrazee@gmail.com> | 2022-11-16 13:05:36 -0600 |
commit | 17825cd611c3bbc47fe55b5e7dfe1a39fdca2274 (patch) | |
tree | d60bfbc55eee788316b991728683557303a9b8f8 /src | |
parent | e003f2e3cbbdfe2f8b709c1a7f1dbbcfb5e7e5f0 (diff) | |
download | voidsky-17825cd611c3bbc47fe55b5e7dfe1a39fdca2274.tar.zst |
Add placeholder loading states
Diffstat (limited to 'src')
-rw-r--r-- | src/view/com/notifications/Feed.tsx | 5 | ||||
-rw-r--r-- | src/view/com/posts/Feed.tsx | 5 | ||||
-rw-r--r-- | src/view/com/util/LoadingPlaceholder.tsx | 122 | ||||
-rw-r--r-- | src/view/com/util/PostCtrls.tsx | 2 | ||||
-rw-r--r-- | src/view/screens/Profile.tsx | 3 |
5 files changed, 128 insertions, 9 deletions
diff --git a/src/view/com/notifications/Feed.tsx b/src/view/com/notifications/Feed.tsx index ac56823f6..90d16604d 100644 --- a/src/view/com/notifications/Feed.tsx +++ b/src/view/com/notifications/Feed.tsx @@ -1,11 +1,12 @@ import React from 'react' import {observer} from 'mobx-react-lite' -import {Text, View, FlatList} from 'react-native' +import {View, FlatList} from 'react-native' import { NotificationsViewModel, NotificationsViewItemModel, } from '../../../state/models/notifications-view' import {FeedItem} from './FeedItem' +import {NotificationFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' import {ErrorMessage} from '../util/ErrorMessage' import {EmptyState} from '../util/EmptyState' @@ -32,7 +33,7 @@ export const Feed = observer(function Feed({ return ( <View style={{flex: 1}}> {view.isLoading && !view.isRefreshing && !view.hasContent && ( - <Text>Loading...</Text> + <NotificationFeedLoadingPlaceholder /> )} {view.hasError && ( <ErrorMessage diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx index c2aabd7b7..7d8c1b4c3 100644 --- a/src/view/com/posts/Feed.tsx +++ b/src/view/com/posts/Feed.tsx @@ -1,6 +1,7 @@ import React, {MutableRefObject} from 'react' import {observer} from 'mobx-react-lite' -import {Text, View, FlatList, StyleProp, ViewStyle} from 'react-native' +import {View, FlatList, StyleProp, ViewStyle} from 'react-native' +import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' import {EmptyState} from '../util/EmptyState' import {ErrorMessage} from '../util/ErrorMessage' import {FeedModel, FeedItemModel} from '../../../state/models/feed-view' @@ -31,7 +32,7 @@ export const Feed = observer(function Feed({ return ( <View style={style}> {feed.isLoading && !feed.isRefreshing && !feed.hasContent && ( - <Text>Loading...</Text> + <PostFeedLoadingPlaceholder /> )} {feed.hasError && ( <ErrorMessage diff --git a/src/view/com/util/LoadingPlaceholder.tsx b/src/view/com/util/LoadingPlaceholder.tsx index 55b6ad1b3..c198407de 100644 --- a/src/view/com/util/LoadingPlaceholder.tsx +++ b/src/view/com/util/LoadingPlaceholder.tsx @@ -1,13 +1,16 @@ import React, {useEffect, useMemo} from 'react' import { Animated, + StyleSheet, StyleProp, useWindowDimensions, View, ViewStyle, } from 'react-native' import LinearGradient from 'react-native-linear-gradient' -import {colors} from '../../lib/styles' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' +import {UpIcon, DownIcon} from '../../lib/icons' +import {s, colors} from '../../lib/styles' export function LoadingPlaceholder({ width, @@ -49,7 +52,7 @@ export function LoadingPlaceholder({ { width, height, - backgroundColor: colors.gray2, + backgroundColor: '#e7e9ea', borderRadius: 6, overflow: 'hidden', }, @@ -62,7 +65,7 @@ export function LoadingPlaceholder({ transform: [{translateX: offset}], }}> <LinearGradient - colors={[colors.gray2, '#d4d2d2', colors.gray2]} + colors={['#e7e9ea', '#e2e2e2', '#e7e9ea']} start={{x: 0, y: 0}} end={{x: 1, y: 0}} style={{width: '100%', height: '100%'}} @@ -71,3 +74,116 @@ export function LoadingPlaceholder({ </View> ) } + +export function PostLoadingPlaceholder({ + style, +}: { + style?: StyleProp<ViewStyle> +}) { + return ( + <View style={[styles.post, style]}> + <LoadingPlaceholder width={50} height={50} style={styles.avatar} /> + <View style={[s.flex1]}> + <LoadingPlaceholder width={100} height={8} style={[s.mb10]} /> + <LoadingPlaceholder width={200} height={8} style={[s.mb5]} /> + <LoadingPlaceholder width={200} height={8} style={[s.mb5]} /> + <LoadingPlaceholder width={120} height={8} style={[s.mb10]} /> + <View style={s.flexRow}> + <View style={s.flex1}> + <FontAwesomeIcon + style={s.gray3} + icon={['far', 'comment']} + size={14} + /> + </View> + <View style={s.flex1}> + <FontAwesomeIcon style={s.gray3} icon="retweet" size={18} /> + </View> + <View style={s.flex1}> + <UpIcon style={s.gray3} size={18} /> + </View> + <View style={s.flex1}> + <DownIcon style={s.gray3} size={18} /> + </View> + </View> + </View> + </View> + ) +} + +export function PostFeedLoadingPlaceholder() { + return ( + <> + <PostLoadingPlaceholder /> + <PostLoadingPlaceholder /> + <PostLoadingPlaceholder /> + <PostLoadingPlaceholder /> + <PostLoadingPlaceholder /> + <PostLoadingPlaceholder /> + <PostLoadingPlaceholder /> + <PostLoadingPlaceholder /> + <PostLoadingPlaceholder /> + <PostLoadingPlaceholder /> + <PostLoadingPlaceholder /> + </> + ) +} + +export function NotificationLoadingPlaceholder({ + style, +}: { + style?: StyleProp<ViewStyle> +}) { + return ( + <View style={[styles.notification, style]}> + <View style={[s.flexRow, s.mb10]}> + <LoadingPlaceholder width={30} height={30} style={styles.smallAvatar} /> + </View> + <LoadingPlaceholder width={200} height={8} style={[s.mb5]} /> + <LoadingPlaceholder width={120} height={8} style={[s.mb5]} /> + </View> + ) +} + +export function NotificationFeedLoadingPlaceholder() { + return ( + <> + <NotificationLoadingPlaceholder /> + <NotificationLoadingPlaceholder /> + <NotificationLoadingPlaceholder /> + <NotificationLoadingPlaceholder /> + <NotificationLoadingPlaceholder /> + <NotificationLoadingPlaceholder /> + <NotificationLoadingPlaceholder /> + <NotificationLoadingPlaceholder /> + <NotificationLoadingPlaceholder /> + <NotificationLoadingPlaceholder /> + <NotificationLoadingPlaceholder /> + </> + ) +} + +const styles = StyleSheet.create({ + post: { + flexDirection: 'row', + backgroundColor: colors.white, + borderRadius: 6, + padding: 10, + margin: 1, + }, + avatar: { + borderRadius: 25, + marginRight: 10, + }, + notification: { + backgroundColor: colors.white, + borderRadius: 6, + padding: 10, + paddingLeft: 46, + margin: 1, + }, + smallAvatar: { + borderRadius: 15, + marginRight: 10, + }, +}) diff --git a/src/view/com/util/PostCtrls.tsx b/src/view/com/util/PostCtrls.tsx index ab9e261cf..5362228a9 100644 --- a/src/view/com/util/PostCtrls.tsx +++ b/src/view/com/util/PostCtrls.tsx @@ -77,7 +77,7 @@ export function PostCtrls(opts: PostCtrlsOpts) { icon={['far', 'comment']} size={14} /> - <Text style={s.f13}>{opts.replyCount}</Text> + <Text style={[s.ml5, s.f13]}>{opts.replyCount}</Text> </TouchableOpacity> </View> <View style={s.flex1}> diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx index aed482bfb..0edb503da 100644 --- a/src/view/screens/Profile.tsx +++ b/src/view/screens/Profile.tsx @@ -12,6 +12,7 @@ import {ConfirmModel} from '../../state/models/shell-ui' import {ProfileHeader} from '../com/profile/ProfileHeader' import {FeedItem} from '../com/posts/FeedItem' import {ProfileCard} from '../com/profile/ProfileCard' +import {PostFeedLoadingPlaceholder} from '../com/util/LoadingPlaceholder' import {ErrorScreen} from '../com/util/ErrorScreen' import {ErrorMessage} from '../com/util/ErrorMessage' import {EmptyState} from '../com/util/EmptyState' @@ -106,7 +107,7 @@ export const Profile = observer(({visible, params}: ScreenParams) => { if (uiState) { if (uiState.isInitialLoading) { items.push(LOADING_ITEM) - renderItem = () => <Text style={styles.loading}>Loading...</Text> + renderItem = () => <PostFeedLoadingPlaceholder /> } else if (uiState.currentView.hasError) { items.push({ _reactKey: '__error__', |