about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2023-02-23 17:22:03 -0600
committerPaul Frazee <pfrazee@gmail.com>2023-02-23 17:22:03 -0600
commit154c34e915231a03e289dd36294592911d9c9900 (patch)
treee024768ec8b4296ec0711b2b981de62f83195525
parentb4f2a6979afeeb6b0b29bbf668d61b23b65b47ec (diff)
downloadvoidsky-154c34e915231a03e289dd36294592911d9c9900.tar.zst
Rework modals to support multiple active
-rw-r--r--src/lib/media/picker.web.tsx11
-rw-r--r--src/state/models/shell-ui.ts117
-rw-r--r--src/view/com/lightbox/ImageViewing/index.tsx4
-rw-r--r--src/view/com/login/CreateAccount.tsx7
-rw-r--r--src/view/com/login/Signin.tsx6
-rw-r--r--src/view/com/modals/Modal.tsx51
-rw-r--r--src/view/com/modals/Modal.web.tsx73
-rw-r--r--src/view/com/profile/ProfileHeader.tsx17
-rw-r--r--src/view/com/util/UserAvatar.tsx3
-rw-r--r--src/view/com/util/UserBanner.tsx3
-rw-r--r--src/view/com/util/forms/DropdownButton.tsx30
-rw-r--r--src/view/shell/mobile/index.tsx6
-rw-r--r--src/view/shell/web/index.tsx6
13 files changed, 147 insertions, 187 deletions
diff --git a/src/lib/media/picker.web.tsx b/src/lib/media/picker.web.tsx
index aaa084634..746feaedd 100644
--- a/src/lib/media/picker.web.tsx
+++ b/src/lib/media/picker.web.tsx
@@ -1,6 +1,5 @@
 /// <reference lib="dom" />
 
-import {CropImageModal} from 'state/models/shell-ui'
 import {PickerOpts, CameraOpts, CropperOpts, PickedMedia} from './types'
 export type {PickedMedia} from './types'
 import {RootStoreModel} from 'state/index'
@@ -51,15 +50,17 @@ export async function openCropper(
 ): Promise<PickedMedia> {
   // TODO handle more opts
   return new Promise((resolve, reject) => {
-    store.shell.openModal(
-      new CropImageModal(opts.path, (img?: PickedMedia) => {
+    store.shell.openModal({
+      name: 'crop-image',
+      uri: opts.path,
+      onSelect: (img?: PickedMedia) => {
         if (img) {
           resolve(img)
         } else {
           reject(new Error('Canceled'))
         }
-      }),
-    )
+      },
+    })
   })
 }
 
diff --git a/src/state/models/shell-ui.ts b/src/state/models/shell-ui.ts
index b9f480ecd..640bed0b3 100644
--- a/src/state/models/shell-ui.ts
+++ b/src/state/models/shell-ui.ts
@@ -2,75 +2,57 @@ import {RootStoreModel} from './root-store'
 import {makeAutoObservable} from 'mobx'
 import {ProfileViewModel} from './profile-view'
 import {isObj, hasProp} from 'lib/type-guards'
-import {PickedMedia} from 'view/com/util/images/image-crop-picker/types'
+import {PickedMedia} from 'lib/media/types'
 
-export class ConfirmModal {
-  name = 'confirm'
-
-  constructor(
-    public title: string,
-    public message: string | (() => JSX.Element),
-    public onPressConfirm: () => void | Promise<void>,
-  ) {
-    makeAutoObservable(this)
-  }
+export interface ConfirmModal {
+  name: 'confirm'
+  title: string
+  message: string | (() => JSX.Element)
+  onPressConfirm: () => void | Promise<void>
 }
 
-export class EditProfileModal {
-  name = 'edit-profile'
-
-  constructor(
-    public profileView: ProfileViewModel,
-    public onUpdate?: () => void,
-  ) {
-    makeAutoObservable(this)
-  }
+export interface EditProfileModal {
+  name: 'edit-profile'
+  profileView: ProfileViewModel
+  onUpdate?: () => void
 }
 
-export class ServerInputModal {
-  name = 'server-input'
-
-  constructor(
-    public initialService: string,
-    public onSelect: (url: string) => void,
-  ) {
-    makeAutoObservable(this)
-  }
+export interface ServerInputModal {
+  name: 'server-input'
+  initialService: string
+  onSelect: (url: string) => void
 }
 
-export class ReportPostModal {
-  name = 'report-post'
-
-  constructor(public postUri: string, public postCid: string) {
-    makeAutoObservable(this)
-  }
+export interface ReportPostModal {
+  name: 'report-post'
+  postUri: string
+  postCid: string
 }
 
-export class ReportAccountModal {
-  name = 'report-account'
-
-  constructor(public did: string) {
-    makeAutoObservable(this)
-  }
+export interface ReportAccountModal {
+  name: 'report-account'
+  did: string
 }
 
-export class CropImageModal {
-  name = 'crop-image'
-
-  constructor(
-    public uri: string,
-    public onSelect: (img?: PickedMedia) => void,
-  ) {}
+export interface CropImageModal {
+  name: 'crop-image'
+  uri: string
+  onSelect: (img?: PickedMedia) => void
 }
 
-export class DeleteAccountModal {
-  name = 'delete-account'
-
-  constructor() {
-    makeAutoObservable(this)
-  }
+export interface DeleteAccountModal {
+  name: 'delete-account'
 }
 
+export type Modal =
+  | ConfirmModal
+  | EditProfileModal
+  | ServerInputModal
+  | ReportPostModal
+  | ReportAccountModal
+  | CropImageModal
+  | DeleteAccountModal
+
 interface LightboxModel {}
 
 export class ProfileImageLightbox implements LightboxModel {
@@ -111,15 +93,7 @@ export class ShellUiModel {
   minimalShellMode = false
   isMainMenuOpen = false
   isModalActive = false
-  activeModal:
-    | ConfirmModal
-    | EditProfileModal
-    | ServerInputModal
-    | ReportPostModal
-    | ReportAccountModal
-    | CropImageModal
-    | DeleteAccountModal
-    | undefined
+  activeModals: Modal[] = []
   isLightboxActive = false
   activeLightbox: ProfileImageLightbox | ImagesLightbox | undefined
   isComposerActive = false
@@ -159,24 +133,15 @@ export class ShellUiModel {
     this.isMainMenuOpen = v
   }
 
-  openModal(
-    modal:
-      | ConfirmModal
-      | EditProfileModal
-      | ServerInputModal
-      | ReportPostModal
-      | ReportAccountModal
-      | CropImageModal
-      | DeleteAccountModal,
-  ) {
+  openModal(modal: Modal) {
     this.rootStore.emitNavigation()
     this.isModalActive = true
-    this.activeModal = modal
+    this.activeModals.push(modal)
   }
 
   closeModal() {
-    this.isModalActive = false
-    this.activeModal = undefined
+    this.activeModals.pop()
+    this.isModalActive = this.activeModals.length > 0
   }
 
   openLightbox(lightbox: ProfileImageLightbox | ImagesLightbox) {
diff --git a/src/view/com/lightbox/ImageViewing/index.tsx b/src/view/com/lightbox/ImageViewing/index.tsx
index 83259330f..722540a58 100644
--- a/src/view/com/lightbox/ImageViewing/index.tsx
+++ b/src/view/com/lightbox/ImageViewing/index.tsx
@@ -17,7 +17,7 @@ import {
   VirtualizedList,
   ModalProps,
 } from 'react-native'
-import {Modal} from '../../modals/Modal'
+import {ModalsContainer} from '../../modals/Modal'
 
 import ImageItem from './components/ImageItem/ImageItem'
 import ImageDefaultHeader from './components/ImageDefaultHeader'
@@ -98,7 +98,7 @@ function ImageViewing({
 
   return (
     <View style={styles.screen} onLayout={onLayout}>
-      <Modal />
+      <ModalsContainer />
       <View style={[styles.container, {opacity, backgroundColor}]}>
         <Animated.View style={[styles.header, {transform: headerTransform}]}>
           {typeof HeaderComponent !== 'undefined' ? (
diff --git a/src/view/com/login/CreateAccount.tsx b/src/view/com/login/CreateAccount.tsx
index 6dc93f5e3..870013f3b 100644
--- a/src/view/com/login/CreateAccount.tsx
+++ b/src/view/com/login/CreateAccount.tsx
@@ -25,7 +25,6 @@ import {makeValidHandle, createFullHandle} from 'lib/strings/handles'
 import {toNiceDomain} from 'lib/strings/url-helpers'
 import {useStores, DEFAULT_SERVICE} from 'state/index'
 import {ServiceDescription} from 'state/models/session'
-import {ServerInputModal} from 'state/models/shell-ui'
 import {usePalette} from 'lib/hooks/usePalette'
 import {cleanError} from 'lib/strings/errors'
 
@@ -84,7 +83,11 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => {
   const onPressRetryConnect = () => setRetryDescribeTrigger({})
 
   const onPressSelectService = () => {
-    store.shell.openModal(new ServerInputModal(serviceUrl, setServiceUrl))
+    store.shell.openModal({
+      name: 'server-input',
+      initialService: serviceUrl,
+      onSelect: setServiceUrl,
+    })
     Keyboard.dismiss()
   }
 
diff --git a/src/view/com/login/Signin.tsx b/src/view/com/login/Signin.tsx
index eed173119..a311e2999 100644
--- a/src/view/com/login/Signin.tsx
+++ b/src/view/com/login/Signin.tsx
@@ -279,7 +279,11 @@ const LoginForm = ({
   const [password, setPassword] = useState<string>('')
 
   const onPressSelectService = () => {
-    store.shell.openModal(new ServerInputModal(serviceUrl, setServiceUrl))
+    store.shell.openModal({
+      name: 'server-input',
+      initialService: serviceUrl,
+      onSelect: setServiceUrl,
+    })
     Keyboard.dismiss()
     track('Signin:PressedSelectService')
   }
diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx
index 2529d0d5b..d4c8ada69 100644
--- a/src/view/com/modals/Modal.tsx
+++ b/src/view/com/modals/Modal.tsx
@@ -5,8 +5,6 @@ import BottomSheet from '@gorhom/bottom-sheet'
 import {useStores} from 'state/index'
 import {createCustomBackdrop} from '../util/BottomSheetCustomBackdrop'
 
-import * as models from 'state/models/shell-ui'
-
 import * as ConfirmModal from './Confirm'
 import * as EditProfileModal from './EditProfile'
 import * as ServerInputModal from './ServerInput'
@@ -32,52 +30,37 @@ export const Modal = observer(function Modal() {
     store.shell.closeModal()
   }
 
+  const activeModal = React.useMemo(
+    () => store.shell.activeModals.at(-1),
+    [store.shell.activeModals],
+  )
+
   useEffect(() => {
     if (store.shell.isModalActive) {
       bottomSheetRef.current?.expand()
     } else {
       bottomSheetRef.current?.close()
     }
-  }, [store.shell.isModalActive, bottomSheetRef, store.shell.activeModal?.name])
+  }, [store.shell.isModalActive, bottomSheetRef, activeModal?.name])
 
   let snapPoints: (string | number)[] = CLOSED_SNAPPOINTS
   let element
-  if (store.shell.activeModal?.name === 'confirm') {
+  if (activeModal?.name === 'confirm') {
     snapPoints = ConfirmModal.snapPoints
-    element = (
-      <ConfirmModal.Component
-        {...(store.shell.activeModal as models.ConfirmModal)}
-      />
-    )
-  } else if (store.shell.activeModal?.name === 'edit-profile') {
+    element = <ConfirmModal.Component {...activeModal} />
+  } else if (activeModal?.name === 'edit-profile') {
     snapPoints = EditProfileModal.snapPoints
-    element = (
-      <EditProfileModal.Component
-        {...(store.shell.activeModal as models.EditProfileModal)}
-      />
-    )
-  } else if (store.shell.activeModal?.name === 'server-input') {
+    element = <EditProfileModal.Component {...activeModal} />
+  } else if (activeModal?.name === 'server-input') {
     snapPoints = ServerInputModal.snapPoints
-    element = (
-      <ServerInputModal.Component
-        {...(store.shell.activeModal as models.ServerInputModal)}
-      />
-    )
-  } else if (store.shell.activeModal?.name === 'report-post') {
+    element = <ServerInputModal.Component {...activeModal} />
+  } else if (activeModal?.name === 'report-post') {
     snapPoints = ReportPostModal.snapPoints
-    element = (
-      <ReportPostModal.Component
-        {...(store.shell.activeModal as models.ReportPostModal)}
-      />
-    )
-  } else if (store.shell.activeModal?.name === 'report-account') {
+    element = <ReportPostModal.Component {...activeModal} />
+  } else if (activeModal?.name === 'report-account') {
     snapPoints = ReportAccountModal.snapPoints
-    element = (
-      <ReportAccountModal.Component
-        {...(store.shell.activeModal as models.ReportAccountModal)}
-      />
-    )
-  } else if (store.shell.activeModal?.name === 'delete-account') {
+    element = <ReportAccountModal.Component {...activeModal} />
+  } else if (activeModal?.name === 'delete-account') {
     snapPoints = DeleteAccountModal.snapPoints
     element = <DeleteAccountModal.Component />
   } else {
diff --git a/src/view/com/modals/Modal.web.tsx b/src/view/com/modals/Modal.web.tsx
index 2af02695a..38b526d29 100644
--- a/src/view/com/modals/Modal.web.tsx
+++ b/src/view/com/modals/Modal.web.tsx
@@ -3,8 +3,7 @@ import {TouchableWithoutFeedback, StyleSheet, View} from 'react-native'
 import {observer} from 'mobx-react-lite'
 import {useStores} from 'state/index'
 import {usePalette} from 'lib/hooks/usePalette'
-
-import * as models from 'state/models/shell-ui'
+import type {Modal as ModalIface} from 'state/models/shell-ui'
 
 import * as ConfirmModal from './Confirm'
 import * as EditProfileModal from './EditProfile'
@@ -13,7 +12,23 @@ import * as ReportPostModal from './ReportPost'
 import * as ReportAccountModal from './ReportAccount'
 import * as CropImageModal from './crop-image/CropImage.web'
 
-export const Modal = observer(function Modal() {
+export const ModalsContainer = observer(function ModalsContainer() {
+  const store = useStores()
+
+  if (!store.shell.isModalActive) {
+    return null
+  }
+
+  return (
+    <>
+      {store.shell.activeModals.map((modal, i) => (
+        <Modal key={`modal-${i}`} modal={modal} />
+      ))}
+    </>
+  )
+})
+
+function Modal({modal}: {modal: ModalIface}) {
   const store = useStores()
   const pal = usePalette('default')
 
@@ -22,7 +37,7 @@ export const Modal = observer(function Modal() {
   }
 
   const onPressMask = () => {
-    if (store.shell.activeModal?.name === 'crop-image') {
+    if (modal.name === 'crop-image') {
       return // dont close on mask presses during crop
     }
     store.shell.closeModal()
@@ -32,42 +47,18 @@ export const Modal = observer(function Modal() {
   }
 
   let element
-  if (store.shell.activeModal?.name === 'confirm') {
-    element = (
-      <ConfirmModal.Component
-        {...(store.shell.activeModal as models.ConfirmModal)}
-      />
-    )
-  } else if (store.shell.activeModal?.name === 'edit-profile') {
-    element = (
-      <EditProfileModal.Component
-        {...(store.shell.activeModal as models.EditProfileModal)}
-      />
-    )
-  } else if (store.shell.activeModal?.name === 'server-input') {
-    element = (
-      <ServerInputModal.Component
-        {...(store.shell.activeModal as models.ServerInputModal)}
-      />
-    )
-  } else if (store.shell.activeModal?.name === 'report-post') {
-    element = (
-      <ReportPostModal.Component
-        {...(store.shell.activeModal as models.ReportPostModal)}
-      />
-    )
-  } else if (store.shell.activeModal?.name === 'report-account') {
-    element = (
-      <ReportAccountModal.Component
-        {...(store.shell.activeModal as models.ReportAccountModal)}
-      />
-    )
-  } else if (store.shell.activeModal?.name === 'crop-image') {
-    element = (
-      <CropImageModal.Component
-        {...(store.shell.activeModal as models.CropImageModal)}
-      />
-    )
+  if (modal.name === 'confirm') {
+    element = <ConfirmModal.Component {...modal} />
+  } else if (modal.name === 'edit-profile') {
+    element = <EditProfileModal.Component {...modal} />
+  } else if (modal.name === 'server-input') {
+    element = <ServerInputModal.Component {...modal} />
+  } else if (modal.name === 'report-post') {
+    element = <ReportPostModal.Component {...modal} />
+  } else if (modal.name === 'report-account') {
+    element = <ReportAccountModal.Component {...modal} />
+  } else if (modal.name === 'crop-image') {
+    element = <CropImageModal.Component {...modal} />
   } else {
     return null
   }
@@ -81,7 +72,7 @@ export const Modal = observer(function Modal() {
       </View>
     </TouchableWithoutFeedback>
   )
-})
+}
 
 const styles = StyleSheet.create({
   mask: {
diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx
index 0ca6e1e74..087b1f39b 100644
--- a/src/view/com/profile/ProfileHeader.tsx
+++ b/src/view/com/profile/ProfileHeader.tsx
@@ -15,11 +15,7 @@ import {
 import {BlurView} from '../util/BlurView'
 import {ProfileViewModel} from 'state/models/profile-view'
 import {useStores} from 'state/index'
-import {
-  EditProfileModal,
-  ReportAccountModal,
-  ProfileImageLightbox,
-} from 'state/models/shell-ui'
+import {ProfileImageLightbox} from 'state/models/shell-ui'
 import {pluralize} from 'lib/strings/helpers'
 import {toShareUrl} from 'lib/strings/url-helpers'
 import {s, gradients} from 'lib/styles'
@@ -65,7 +61,11 @@ export const ProfileHeader = observer(function ProfileHeader({
   }
   const onPressEditProfile = () => {
     track('ProfileHeader:EditProfileButtonClicked')
-    store.shell.openModal(new EditProfileModal(view, onRefreshAll))
+    store.shell.openModal({
+      name: 'edit-profile',
+      profileView: view,
+      onUpdate: onRefreshAll,
+    })
   }
   const onPressFollowers = () => {
     track('ProfileHeader:FollowersButtonClicked')
@@ -101,7 +101,10 @@ export const ProfileHeader = observer(function ProfileHeader({
   }
   const onPressReportAccount = () => {
     track('ProfileHeader:ReportAccountButtonClicked')
-    store.shell.openModal(new ReportAccountModal(view.did))
+    store.shell.openModal({
+      name: 'report-account',
+      did: view.did,
+    })
   }
 
   // loading
diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx
index 0c5c9d254..5a7a4801d 100644
--- a/src/view/com/util/UserAvatar.tsx
+++ b/src/view/com/util/UserAvatar.tsx
@@ -18,6 +18,7 @@ import {useStores} from 'state/index'
 import {colors, gradients} from 'lib/styles'
 import {DropdownButton} from './forms/DropdownButton'
 import {usePalette} from 'lib/hooks/usePalette'
+import {isWeb} from 'platform/detection'
 
 export function UserAvatar({
   size,
@@ -58,7 +59,7 @@ export function UserAvatar({
   )
 
   const dropdownItems = [
-    {
+    !isWeb && {
       label: 'Camera',
       icon: 'camera' as IconProp,
       onPress: async () => {
diff --git a/src/view/com/util/UserBanner.tsx b/src/view/com/util/UserBanner.tsx
index c17294f3d..06a80d45b 100644
--- a/src/view/com/util/UserBanner.tsx
+++ b/src/view/com/util/UserBanner.tsx
@@ -18,6 +18,7 @@ import {
 } from 'lib/permissions'
 import {DropdownButton} from './forms/DropdownButton'
 import {usePalette} from 'lib/hooks/usePalette'
+import {isWeb} from 'platform/detection'
 
 export function UserBanner({
   banner,
@@ -29,7 +30,7 @@ export function UserBanner({
   const store = useStores()
   const pal = usePalette('default')
   const dropdownItems = [
-    {
+    !isWeb && {
       label: 'Camera',
       icon: 'camera' as IconProp,
       onPress: async () => {
diff --git a/src/view/com/util/forms/DropdownButton.tsx b/src/view/com/util/forms/DropdownButton.tsx
index 8fddd5941..2946c5ca0 100644
--- a/src/view/com/util/forms/DropdownButton.tsx
+++ b/src/view/com/util/forms/DropdownButton.tsx
@@ -16,7 +16,6 @@ import {Button, ButtonType} from './Button'
 import {colors} from 'lib/styles'
 import {toShareUrl} from 'lib/strings/url-helpers'
 import {useStores} from 'state/index'
-import {ReportPostModal, ConfirmModal} from 'state/models/shell-ui'
 import {TABS_ENABLED} from 'lib/build-flags'
 import {usePalette} from 'lib/hooks/usePalette'
 import {useTheme} from 'lib/ThemeContext'
@@ -28,6 +27,7 @@ export interface DropdownItem {
   label: string
   onPress: () => void
 }
+type MaybeDropdownItem = DropdownItem | false | undefined
 
 export type DropdownButtonType = ButtonType | 'bare'
 
@@ -44,7 +44,7 @@ export function DropdownButton({
 }: {
   type?: DropdownButtonType
   style?: StyleProp<ViewStyle>
-  items: DropdownItem[]
+  items: MaybeDropdownItem[]
   label?: string
   menuWidth?: number
   children?: React.ReactNode
@@ -71,7 +71,12 @@ export function DropdownButton({
           ? pageX + width + rightOffset
           : pageX + width - menuWidth
         const newY = pageY + height + bottomOffset
-        createDropdownMenu(newX, newY, menuWidth, items)
+        createDropdownMenu(
+          newX,
+          newY,
+          menuWidth,
+          items.filter(v => !!v) as DropdownItem[],
+        )
       },
     )
   }
@@ -151,7 +156,11 @@ export function PostDropdownBtn({
       icon: 'circle-exclamation',
       label: 'Report post',
       onPress() {
-        store.shell.openModal(new ReportPostModal(itemUri, itemCid))
+        store.shell.openModal({
+          name: 'report-post',
+          postUri: itemUri,
+          postCid: itemCid,
+        })
       },
     },
     isAuthor
@@ -159,13 +168,12 @@ export function PostDropdownBtn({
           icon: ['far', 'trash-can'],
           label: 'Delete post',
           onPress() {
-            store.shell.openModal(
-              new ConfirmModal(
-                'Delete this post?',
-                'Are you sure? This can not be undone.',
-                onDeletePost,
-              ),
-            )
+            store.shell.openModal({
+              name: 'confirm',
+              title: 'Delete this post?',
+              message: 'Are you sure? This can not be undone.',
+              onPressConfirm: onDeletePost,
+            })
           },
         }
       : undefined,
diff --git a/src/view/shell/mobile/index.tsx b/src/view/shell/mobile/index.tsx
index 0b3921b7e..da8e73a60 100644
--- a/src/view/shell/mobile/index.tsx
+++ b/src/view/shell/mobile/index.tsx
@@ -28,7 +28,7 @@ import {Login} from '../../screens/Login'
 import {Menu} from './Menu'
 import {Onboard} from '../../screens/Onboard'
 import {HorzSwipe} from '../../com/util/gestures/HorzSwipe'
-import {Modal} from '../../com/modals/Modal'
+import {ModalsContainer} from '../../com/modals/Modal'
 import {Lightbox} from '../../com/lightbox/Lightbox'
 import {Text} from '../../com/util/text/Text'
 import {ErrorBoundary} from '../../com/util/ErrorBoundary'
@@ -366,7 +366,7 @@ export const MobileShell: React.FC = observer(() => {
     return (
       <View style={styles.outerContainer}>
         <Login />
-        <Modal />
+        <ModalsContainer />
       </View>
     )
   }
@@ -515,7 +515,7 @@ export const MobileShell: React.FC = observer(() => {
           notificationCount={store.me.notifications.unreadCount}
         />
       </Animated.View>
-      <Modal />
+      <ModalsContainer />
       <Lightbox />
       <Composer
         active={store.shell.isComposerActive}
diff --git a/src/view/shell/web/index.tsx b/src/view/shell/web/index.tsx
index be0460f00..b9ae32f27 100644
--- a/src/view/shell/web/index.tsx
+++ b/src/view/shell/web/index.tsx
@@ -11,7 +11,7 @@ import {Onboard} from '../../screens/Onboard'
 import {Login} from '../../screens/Login'
 import {ErrorBoundary} from '../../com/util/ErrorBoundary'
 import {Lightbox} from '../../com/lightbox/Lightbox'
-import {Modal} from '../../com/modals/Modal'
+import {ModalsContainer} from '../../com/modals/Modal'
 import {Text} from 'view/com/util/text/Text'
 import {Composer} from './Composer'
 import {usePalette} from 'lib/hooks/usePalette'
@@ -32,7 +32,7 @@ export const WebShell: React.FC = observer(() => {
     return (
       <View style={styles.outerContainer}>
         <Login />
-        <Modal />
+        <ModalsContainer />
       </View>
     )
   }
@@ -67,7 +67,7 @@ export const WebShell: React.FC = observer(() => {
         imagesOpen={store.shell.composerOpts?.imagesOpen}
         onPost={store.shell.composerOpts?.onPost}
       />
-      <Modal />
+      <ModalsContainer />
       <Lightbox />
     </View>
   )