Add web layout components

zio/stable
Paul Frazee 2023-01-26 17:55:15 -06:00
parent 57d876a530
commit d04a6d7539
6 changed files with 99 additions and 26 deletions

View File

@ -10,7 +10,7 @@
/* These styles disable body scrolling if you are using <ScrollView> */ /* These styles disable body scrolling if you are using <ScrollView> */
body { overflow: hidden; } body { overflow: hidden; }
/* These styles make the root element full-height */ /* 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 */ /* These styles are for src/view/com/modals/WebModal */
div[data-modal-overlay] { div[data-modal-overlay] {

View File

@ -1,6 +1,7 @@
import React, {useRef} from 'react' import React, {useRef} from 'react'
import {observer} from 'mobx-react-lite' 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 { import {
PostThreadViewModel, PostThreadViewModel,
PostThreadViewPostModel, PostThreadViewPostModel,
@ -50,9 +51,9 @@ export const PostThread = observer(function PostThread({
// = // =
if ((view.isLoading && !view.isRefreshing) || view.params.uri !== uri) { if ((view.isLoading && !view.isRefreshing) || view.params.uri !== uri) {
return ( return (
<View> <CenteredView>
<ActivityIndicator /> <ActivityIndicator />
</View> </CenteredView>
) )
} }
@ -60,9 +61,9 @@ export const PostThread = observer(function PostThread({
// = // =
if (view.hasError) { if (view.hasError) {
return ( return (
<View> <CenteredView>
<ErrorMessage message={view.error} onPressTryAgain={onRefresh} /> <ErrorMessage message={view.error} onPressTryAgain={onRefresh} />
</View> </CenteredView>
) )
} }

View File

@ -3,11 +3,11 @@ import {observer} from 'mobx-react-lite'
import { import {
ActivityIndicator, ActivityIndicator,
View, View,
FlatList,
StyleProp, StyleProp,
StyleSheet, StyleSheet,
ViewStyle, ViewStyle,
} from 'react-native' } from 'react-native'
import {CenteredView, FlatList} from '../util/Views'
import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
import {EmptyState} from '../util/EmptyState' import {EmptyState} from '../util/EmptyState'
import {ErrorMessage} from '../util/error/ErrorMessage' import {ErrorMessage} from '../util/error/ErrorMessage'
@ -86,11 +86,16 @@ export const Feed = observer(function Feed({
) )
return ( return (
<View testID={testID} style={style}> <View testID={testID} style={style}>
<CenteredView>
{!data && <PromptButtons onPressCompose={onPressCompose} />} {!data && <PromptButtons onPressCompose={onPressCompose} />}
{feed.isLoading && !data && <PostFeedLoadingPlaceholder />} {feed.isLoading && !data && <PostFeedLoadingPlaceholder />}
{feed.hasError && ( {feed.hasError && (
<ErrorMessage message={feed.error} onPressTryAgain={onPressTryAgain} /> <ErrorMessage
message={feed.error}
onPressTryAgain={onPressTryAgain}
/>
)} )}
</CenteredView>
{feed.hasLoaded && data && ( {feed.hasLoaded && data && (
<FlatList <FlatList
ref={scrollElRef} ref={scrollElRef}

View File

@ -0,0 +1 @@
export {View as CenteredView, FlatList, ScrollView} from 'react-native'

View File

@ -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',
},
})

View File

@ -18,16 +18,13 @@ export const WebShell: React.FC = observer(() => {
if (!store.session.hasSession) { if (!store.session.hasSession) {
return ( return (
<View style={styles.outerContainer}> <View style={styles.outerContainer}>
<View style={styles.innerContainer}>
<Login /> <Login />
</View> </View>
</View>
) )
} }
return ( return (
<View style={[styles.outerContainer, pal.view]}> <View style={[styles.outerContainer, pal.view]}>
<View style={styles.innerContainer}>
{screenRenderDesc.screens.map(({Com, navIdx, params, key, current}) => ( {screenRenderDesc.screens.map(({Com, navIdx, params, key, current}) => (
<View <View
key={key} key={key}
@ -38,7 +35,6 @@ export const WebShell: React.FC = observer(() => {
</View> </View>
))} ))}
</View> </View>
</View>
) )
// TODO // TODO
// <Modal /> // <Modal />