about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2023-01-26 17:55:15 -0600
committerPaul Frazee <pfrazee@gmail.com>2023-01-26 17:55:15 -0600
commitd04a6d7539c53ec3510175459c1ca8c8e7e994da (patch)
treeacdc3b3e9dd59bf0fa242bac8d94be1744ac4033 /src
parent57d876a5304860bf47ff10553e55b568c0a6daba (diff)
downloadvoidsky-d04a6d7539c53ec3510175459c1ca8c8e7e994da.tar.zst
Add web layout components
Diffstat (limited to 'src')
-rw-r--r--src/view/com/post-thread/PostThread.tsx11
-rw-r--r--src/view/com/posts/Feed.tsx17
-rw-r--r--src/view/com/util/Views.tsx1
-rw-r--r--src/view/com/util/Views.web.tsx70
-rw-r--r--src/view/shell/web/index.tsx24
5 files changed, 98 insertions, 25 deletions
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