about summary refs log tree commit diff
path: root/src/view/shell/web/index.tsx
blob: fedc9c3d6b0c7f4198a7a31a99674cbed16dbb6c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import React from 'react'
import {observer} from 'mobx-react-lite'
import {View, StyleSheet} 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}>
        <Login />
      </View>
    )
  }

  return (
    <View style={[styles.outerContainer, pal.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>
      ))}
      <DesktopLeftColumn />
      <DesktopRightColumn />
    </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}
  // />
})

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