Add web layout components
parent
57d876a530
commit
d04a6d7539
|
@ -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] {
|
||||||
|
|
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export {View as CenteredView, FlatList, ScrollView} from 'react-native'
|
|
@ -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',
|
||||||
|
},
|
||||||
|
})
|
|
@ -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 />
|
||||||
|
|
Loading…
Reference in New Issue