about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/App.web.tsx7
-rw-r--r--src/view/com/login/CreateAccount.tsx6
-rw-r--r--src/view/com/login/Signin.tsx10
-rw-r--r--src/view/com/util/forms/DropdownButton.tsx6
-rw-r--r--src/view/shell/desktop-web/index.tsx35
-rw-r--r--src/view/shell/web/index.tsx140
-rw-r--r--src/view/shell/web/left-column.tsx (renamed from src/view/shell/desktop-web/left-column.tsx)0
-rw-r--r--src/view/shell/web/right-column.tsx (renamed from src/view/shell/desktop-web/right-column.tsx)0
8 files changed, 158 insertions, 46 deletions
diff --git a/src/App.web.tsx b/src/App.web.tsx
index 0be05486c..67ef680a5 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -1,7 +1,8 @@
 import React, {useState, useEffect} from 'react'
+import {SafeAreaProvider} from 'react-native-safe-area-context'
 import * as view from './view/index'
 import {RootStoreModel, setupState, RootStoreProvider} from './state'
-import {DesktopWebShell} from './view/shell/desktop-web'
+import {WebShell} from './view/shell/web'
 // import Toast from 'react-native-root-toast' TODO
 
 function App() {
@@ -22,7 +23,9 @@ function App() {
 
   return (
     <RootStoreProvider value={rootStore}>
-      <DesktopWebShell />
+      <SafeAreaProvider>
+        <WebShell />
+      </SafeAreaProvider>
     </RootStoreProvider>
   )
   // <Toast.ToastContainer /> TODO
diff --git a/src/view/com/login/CreateAccount.tsx b/src/view/com/login/CreateAccount.tsx
index be5074eee..dbb3ab52f 100644
--- a/src/view/com/login/CreateAccount.tsx
+++ b/src/view/com/login/CreateAccount.tsx
@@ -15,7 +15,7 @@ import {
 } from '@fortawesome/react-native-fontawesome'
 import {ComAtprotoAccountCreate} from '@atproto/api'
 import * as EmailValidator from 'email-validator'
-import {useAnalytics} from '@segment/analytics-react-native'
+// import {useAnalytics} from '@segment/analytics-react-native' TODO
 import {LogoTextHero} from './Logo'
 import {Picker} from '../util/Picker'
 import {TextLink} from '../util/Link'
@@ -32,7 +32,7 @@ import {ServerInputModal} from '../../../state/models/shell-ui'
 import {usePalette} from '../../lib/hooks/usePalette'
 
 export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => {
-  const {track} = useAnalytics()
+  // const {track} = useAnalytics() TODO
   const pal = usePalette('default')
   const store = useStores()
   const [isProcessing, setIsProcessing] = useState<boolean>(false)
@@ -109,7 +109,7 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => {
         password,
         inviteCode,
       })
-      track('Create Account')
+      // track('Create Account') TODO
     } catch (e: any) {
       let errMsg = e.toString()
       if (e instanceof ComAtprotoAccountCreate.InvalidInviteCodeError) {
diff --git a/src/view/com/login/Signin.tsx b/src/view/com/login/Signin.tsx
index 1c8a54ad8..8a260a9ba 100644
--- a/src/view/com/login/Signin.tsx
+++ b/src/view/com/login/Signin.tsx
@@ -14,7 +14,7 @@ import {
 } from '@fortawesome/react-native-fontawesome'
 import * as EmailValidator from 'email-validator'
 import {sessionClient as AtpApi, SessionServiceClient} from '@atproto/api'
-import {useAnalytics} from '@segment/analytics-react-native'
+// import {useAnalytics} from '@segment/analytics-react-native' TODO
 import {LogoTextHero} from './Logo'
 import {Text} from '../util/text/Text'
 import {UserAvatar} from '../util/UserAvatar'
@@ -153,7 +153,7 @@ const ChooseAccountForm = ({
   onSelectAccount: (account?: AccountData) => void
   onPressBack: () => void
 }) => {
-  const {track} = useAnalytics()
+  // const {track} = useAnalytics() TODO
   const pal = usePalette('default')
   const [isProcessing, setIsProcessing] = React.useState(false)
 
@@ -161,7 +161,7 @@ const ChooseAccountForm = ({
     if (account.accessJwt && account.refreshJwt) {
       setIsProcessing(true)
       if (await store.session.resumeSession(account)) {
-        track('Sign In', {resumedSession: true})
+        // track('Sign In', {resumedSession: true}) TODO
         setIsProcessing(false)
         return
       }
@@ -261,7 +261,7 @@ const LoginForm = ({
   onPressBack: () => void
   onPressForgotPassword: () => void
 }) => {
-  const {track} = useAnalytics()
+  // const {track} = useAnalytics() TODO
   const pal = usePalette('default')
   const [isProcessing, setIsProcessing] = useState<boolean>(false)
   const [handle, setHandle] = useState<string>(initialHandle)
@@ -302,7 +302,7 @@ const LoginForm = ({
         handle: fullHandle,
         password,
       })
-      track('Sign In', {resumedSession: false})
+      // track('Sign In', {resumedSession: false}) TODO
     } catch (e: any) {
       const errMsg = e.toString()
       store.log.warn('Failed to login', e)
diff --git a/src/view/com/util/forms/DropdownButton.tsx b/src/view/com/util/forms/DropdownButton.tsx
index 1fa03f4c7..f911529d2 100644
--- a/src/view/com/util/forms/DropdownButton.tsx
+++ b/src/view/com/util/forms/DropdownButton.tsx
@@ -76,7 +76,11 @@ export function DropdownButton({
         onPress={onPress}
         hitSlop={HITSLOP}
         // Fix an issue where specific references cause runtime error in jest environment
-        ref={process.env.JEST_WORKER_ID != null ? null : ref}>
+        ref={
+          typeof process !== 'undefined' && process.env.JEST_WORKER_ID != null
+            ? null
+            : ref
+        }>
         {children}
       </TouchableOpacity>
     )
diff --git a/src/view/shell/desktop-web/index.tsx b/src/view/shell/desktop-web/index.tsx
deleted file mode 100644
index 194954349..000000000
--- a/src/view/shell/desktop-web/index.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from 'react'
-import {observer} from 'mobx-react-lite'
-import {View, StyleSheet} from 'react-native'
-import {DesktopLeftColumn} from './left-column'
-import {DesktopRightColumn} from './right-column'
-import {useStores} from '../../../state'
-
-export const DesktopWebShell: React.FC = observer(({children}) => {
-  const store = useStores()
-  return (
-    <View style={styles.outerContainer}>
-      {store.session.hasSession ? (
-        <>
-          <DesktopLeftColumn />
-          <View style={styles.innerContainer}>{children}</View>
-          <DesktopRightColumn />
-        </>
-      ) : (
-        <View style={styles.innerContainer}>{children}</View>
-      )}
-    </View>
-  )
-})
-
-const styles = StyleSheet.create({
-  outerContainer: {
-    height: '100%',
-  },
-  innerContainer: {
-    marginLeft: 'auto',
-    marginRight: 'auto',
-    width: '600px',
-    height: '100%',
-  },
-})
diff --git a/src/view/shell/web/index.tsx b/src/view/shell/web/index.tsx
new file mode 100644
index 000000000..9032eb884
--- /dev/null
+++ b/src/view/shell/web/index.tsx
@@ -0,0 +1,140 @@
+import React from 'react'
+import {observer} from 'mobx-react-lite'
+import {View, StyleSheet, Text} from 'react-native'
+import {useStores} from '../../../state'
+import {match, MatchResult} from '../../routes'
+// import {DesktopLeftColumn} from './left-column'
+// import {DesktopRightColumn} from './right-column'
+import {Login} from '../../screens/Login'
+import {ErrorBoundary} from '../../com/util/ErrorBoundary'
+import {usePalette} from '../../lib/hooks/usePalette'
+import {s} from '../../lib/styles'
+
+export const WebShell: React.FC = observer(() => {
+  const pal = usePalette('default')
+  const store = useStores()
+  const screenRenderDesc = constructScreenRenderDesc(store.nav)
+
+  if (!store.session.hasSession) {
+    return (
+      <View style={styles.outerContainer}>
+        <View style={styles.innerContainer}>
+          <Login />
+        </View>
+      </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>
+    </View>
+  )
+  // TODO
+  // <Modal />
+  // <Lightbox />
+  // <Composer
+  //   active={store.shell.isComposerActive}
+  //   onClose={() => store.shell.closeComposer()}
+  //   winHeight={winDim.height}
+  //   replyTo={store.shell.composerOpts?.replyTo}
+  //   imagesOpen={store.shell.composerOpts?.imagesOpen}
+  //   onPost={store.shell.composerOpts?.onPost}
+  // />
+  // return (
+  //   <View style={styles.outerContainer}>
+  //     {store.session.hasSession ? (
+  //       <>
+  //         <DesktopLeftColumn />
+  //         <View style={styles.innerContainer}>
+  //           <Text>Hello, world! (Logged in)</Text>
+  //           {children}
+  //         </View>
+  //         <DesktopRightColumn />
+  //       </>
+  //     ) : (
+  //       <View style={styles.innerContainer}>
+  //         <Text>Hello, world! (Logged out)</Text>
+  //         {children}
+  //       </View>
+  //     )}
+  //   </View>
+  // )
+})
+
+/**
+ * This method produces the information needed by the shell to
+ * render the current screens with screen-caching behaviors.
+ */
+type ScreenRenderDesc = MatchResult & {
+  key: string
+  navIdx: string
+  current: boolean
+  previous: boolean
+  isNewTab: boolean
+}
+function constructScreenRenderDesc(nav: NavigationModel): {
+  icon: IconProp
+  hasNewTab: boolean
+  screens: ScreenRenderDesc[]
+} {
+  let hasNewTab = false
+  let icon: IconProp = 'magnifying-glass'
+  let screens: ScreenRenderDesc[] = []
+  for (const tab of nav.tabs) {
+    const tabScreens = [
+      ...tab.getBackList(5),
+      Object.assign({}, tab.current, {index: tab.index}),
+    ]
+    const parsedTabScreens = tabScreens.map(screen => {
+      const isCurrent = nav.isCurrentScreen(tab.id, screen.index)
+      const isPrevious = nav.isCurrentScreen(tab.id, screen.index + 1)
+      const matchRes = match(screen.url)
+      if (isCurrent) {
+        icon = matchRes.icon
+      }
+      hasNewTab = hasNewTab || tab.isNewTab
+      return Object.assign(matchRes, {
+        key: `t${tab.id}-s${screen.index}`,
+        navIdx: `${tab.id}-${screen.id}`,
+        current: isCurrent,
+        previous: isPrevious,
+        isNewTab: tab.isNewTab,
+      }) as ScreenRenderDesc
+    })
+    screens = screens.concat(parsedTabScreens)
+  }
+  return {
+    icon,
+    hasNewTab,
+    screens,
+  }
+}
+
+const styles = StyleSheet.create({
+  outerContainer: {
+    height: '100%',
+  },
+  innerContainer: {
+    marginLeft: 'auto',
+    marginRight: 'auto',
+    width: '600px',
+    height: '100%',
+  },
+  visible: {
+    display: 'flex',
+  },
+  hidden: {
+    display: 'none',
+  },
+})
diff --git a/src/view/shell/desktop-web/left-column.tsx b/src/view/shell/web/left-column.tsx
index 3ce6c2eca..3ce6c2eca 100644
--- a/src/view/shell/desktop-web/left-column.tsx
+++ b/src/view/shell/web/left-column.tsx
diff --git a/src/view/shell/desktop-web/right-column.tsx b/src/view/shell/web/right-column.tsx
index 5fe65cac8..5fe65cac8 100644
--- a/src/view/shell/desktop-web/right-column.tsx
+++ b/src/view/shell/web/right-column.tsx