diff options
author | Paul Frazee <pfrazee@gmail.com> | 2023-01-26 17:55:15 -0600 |
---|---|---|
committer | Paul Frazee <pfrazee@gmail.com> | 2023-01-26 17:55:15 -0600 |
commit | d04a6d7539c53ec3510175459c1ca8c8e7e994da (patch) | |
tree | acdc3b3e9dd59bf0fa242bac8d94be1744ac4033 | |
parent | 57d876a5304860bf47ff10553e55b568c0a6daba (diff) | |
download | voidsky-d04a6d7539c53ec3510175459c1ca8c8e7e994da.tar.zst |
Add web layout components
-rw-r--r-- | public/index.html | 2 | ||||
-rw-r--r-- | src/view/com/post-thread/PostThread.tsx | 11 | ||||
-rw-r--r-- | src/view/com/posts/Feed.tsx | 17 | ||||
-rw-r--r-- | src/view/com/util/Views.tsx | 1 | ||||
-rw-r--r-- | src/view/com/util/Views.web.tsx | 70 | ||||
-rw-r--r-- | src/view/shell/web/index.tsx | 24 |
6 files changed, 99 insertions, 26 deletions
diff --git a/public/index.html b/public/index.html index f3791c836..c01f68c30 100644 --- a/public/index.html +++ b/public/index.html @@ -10,7 +10,7 @@ /* These styles disable body scrolling if you are using <ScrollView> */ body { overflow: hidden; } /* These styles make the root element full-height */ - #root { display:flex; height:100%; } + #app-root { display:flex; height:100%; } /* These styles are for src/view/com/modals/WebModal */ div[data-modal-overlay] { diff --git a/src/view/com/post-thread/PostThread.tsx b/src/view/com/post-thread/PostThread.tsx index a52bc643c..59dbf1e16 100644 --- a/src/view/com/post-thread/PostThread.tsx +++ b/src/view/com/post-thread/PostThread.tsx @@ -1,6 +1,7 @@ import React, {useRef} from 'react' import {observer} from 'mobx-react-lite' -import {ActivityIndicator, FlatList, View} from 'react-native' +import {ActivityIndicator, View} from 'react-native' +import {CenteredView, FlatList} from '../util/Views' import { PostThreadViewModel, PostThreadViewPostModel, @@ -50,9 +51,9 @@ export const PostThread = observer(function PostThread({ // = if ((view.isLoading && !view.isRefreshing) || view.params.uri !== uri) { return ( - <View> + <CenteredView> <ActivityIndicator /> - </View> + </CenteredView> ) } @@ -60,9 +61,9 @@ export const PostThread = observer(function PostThread({ // = if (view.hasError) { return ( - <View> + <CenteredView> <ErrorMessage message={view.error} onPressTryAgain={onRefresh} /> - </View> + </CenteredView> ) } diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx index db6877660..db05caa3c 100644 --- a/src/view/com/posts/Feed.tsx +++ b/src/view/com/posts/Feed.tsx @@ -3,11 +3,11 @@ import {observer} from 'mobx-react-lite' import { ActivityIndicator, View, - FlatList, StyleProp, StyleSheet, ViewStyle, } from 'react-native' +import {CenteredView, FlatList} from '../util/Views' import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' import {EmptyState} from '../util/EmptyState' import {ErrorMessage} from '../util/error/ErrorMessage' @@ -86,11 +86,16 @@ export const Feed = observer(function Feed({ ) return ( <View testID={testID} style={style}> - {!data && <PromptButtons onPressCompose={onPressCompose} />} - {feed.isLoading && !data && <PostFeedLoadingPlaceholder />} - {feed.hasError && ( - <ErrorMessage message={feed.error} onPressTryAgain={onPressTryAgain} /> - )} + <CenteredView> + {!data && <PromptButtons onPressCompose={onPressCompose} />} + {feed.isLoading && !data && <PostFeedLoadingPlaceholder />} + {feed.hasError && ( + <ErrorMessage + message={feed.error} + onPressTryAgain={onPressTryAgain} + /> + )} + </CenteredView> {feed.hasLoaded && data && ( <FlatList ref={scrollElRef} diff --git a/src/view/com/util/Views.tsx b/src/view/com/util/Views.tsx new file mode 100644 index 000000000..07dcc4deb --- /dev/null +++ b/src/view/com/util/Views.tsx @@ -0,0 +1 @@ +export {View as CenteredView, FlatList, ScrollView} from 'react-native' diff --git a/src/view/com/util/Views.web.tsx b/src/view/com/util/Views.web.tsx new file mode 100644 index 000000000..fdb0fd1bf --- /dev/null +++ b/src/view/com/util/Views.web.tsx @@ -0,0 +1,70 @@ +/** + * In the Web build, we center all content so that it mirrors the + * mobile experience (a single narrow column). We then place a UI + * shell around the content if you're in desktop. + * + * Because scrolling is handled by components deep in the hierarchy, + * we can't just wrap the top-level element with a max width. The + * centering has to be done at the ScrollView. + * + * These components wrap the RN ScrollView-based components to provide + * consistent layout. It also provides <CenteredView> for views that + * need to match layout but which aren't scrolled. + */ + +import React from 'react' +import { + FlatList as RNFlatList, + FlatListProps, + ScrollView as RNScrollView, + ScrollViewProps, + StyleSheet, + StyleProp, + View, + ViewProps, +} from 'react-native' + +export function CenteredView({ + style, + ...props +}: React.PropsWithChildren<ViewProps>) { + style = addStyle(style, styles.container) + return <View style={style} {...props} /> +} + +export function FlatList<ItemT>({ + contentContainerStyle, + ...props +}: React.PropsWithChildren<FlatListProps<ItemT>>) { + contentContainerStyle = addStyle(contentContainerStyle, styles.container) + return <RNFlatList contentContainerStyle={contentContainerStyle} {...props} /> +} + +export function ScrollView({ + contentContainerStyle, + ...props +}: React.PropsWithChildren<ScrollViewProps>) { + contentContainerStyle = addStyle(contentContainerStyle, styles.container) + return ( + <RNScrollView contentContainerStyle={contentContainerStyle} {...props} /> + ) +} + +function addStyle<T>( + base: StyleProp<T>, + addedStyle: StyleProp<T>, +): StyleProp<T> { + if (Array.isArray(base)) { + return base.concat([addedStyle]) + } + return [base, addedStyle] +} + +const styles = StyleSheet.create({ + container: { + width: '100%', + maxWidth: 600, + marginLeft: 'auto', + marginRight: 'auto', + }, +}) diff --git a/src/view/shell/web/index.tsx b/src/view/shell/web/index.tsx index 9032eb884..c7bfeff19 100644 --- a/src/view/shell/web/index.tsx +++ b/src/view/shell/web/index.tsx @@ -18,26 +18,22 @@ export const WebShell: React.FC = observer(() => { if (!store.session.hasSession) { return ( <View style={styles.outerContainer}> - <View style={styles.innerContainer}> - <Login /> - </View> + <Login /> </View> ) } return ( <View style={[styles.outerContainer, pal.view]}> - <View style={styles.innerContainer}> - {screenRenderDesc.screens.map(({Com, navIdx, params, key, current}) => ( - <View - key={key} - style={[s.h100pct, current ? styles.visible : styles.hidden]}> - <ErrorBoundary> - <Com params={params} navIdx={navIdx} visible={current} /> - </ErrorBoundary> - </View> - ))} - </View> + {screenRenderDesc.screens.map(({Com, navIdx, params, key, current}) => ( + <View + key={key} + style={[s.h100pct, current ? styles.visible : styles.hidden]}> + <ErrorBoundary> + <Com params={params} navIdx={navIdx} visible={current} /> + </ErrorBoundary> + </View> + ))} </View> ) // TODO |