about summary refs log tree commit diff
path: root/src/state/models/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/models/ui')
-rw-r--r--src/state/models/ui/shell.ts207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/state/models/ui/shell.ts b/src/state/models/ui/shell.ts
new file mode 100644
index 000000000..db6ae2eac
--- /dev/null
+++ b/src/state/models/ui/shell.ts
@@ -0,0 +1,207 @@
+import {RootStoreModel} from '../root-store'
+import {makeAutoObservable} from 'mobx'
+import {ProfileViewModel} from '../profile-view'
+import {isObj, hasProp} from 'lib/type-guards'
+import {PickedMedia} from 'lib/media/types'
+
+export interface ConfirmModal {
+  name: 'confirm'
+  title: string
+  message: string | (() => JSX.Element)
+  onPressConfirm: () => void | Promise<void>
+}
+
+export interface EditProfileModal {
+  name: 'edit-profile'
+  profileView: ProfileViewModel
+  onUpdate?: () => void
+}
+
+export interface ServerInputModal {
+  name: 'server-input'
+  initialService: string
+  onSelect: (url: string) => void
+}
+
+export interface ReportPostModal {
+  name: 'report-post'
+  postUri: string
+  postCid: string
+}
+
+export interface ReportAccountModal {
+  name: 'report-account'
+  did: string
+}
+
+export interface CropImageModal {
+  name: 'crop-image'
+  uri: string
+  onSelect: (img?: PickedMedia) => void
+}
+
+export interface DeleteAccountModal {
+  name: 'delete-account'
+}
+
+export interface RepostModal {
+  name: 'repost'
+  onRepost: () => void
+  onQuote: () => void
+  isReposted: boolean
+}
+
+export interface ChangeHandleModal {
+  name: 'change-handle'
+  onChanged: () => void
+}
+
+export type Modal =
+  | ConfirmModal
+  | EditProfileModal
+  | ServerInputModal
+  | ReportPostModal
+  | ReportAccountModal
+  | CropImageModal
+  | DeleteAccountModal
+  | RepostModal
+  | ChangeHandleModal
+
+interface LightboxModel {}
+
+export class ProfileImageLightbox implements LightboxModel {
+  name = 'profile-image'
+  constructor(public profileView: ProfileViewModel) {
+    makeAutoObservable(this)
+  }
+}
+
+export class ImagesLightbox implements LightboxModel {
+  name = 'images'
+  constructor(public uris: string[], public index: number) {
+    makeAutoObservable(this)
+  }
+  setIndex(index: number) {
+    this.index = index
+  }
+}
+
+export interface ComposerOptsPostRef {
+  uri: string
+  cid: string
+  text: string
+  author: {
+    handle: string
+    displayName?: string
+    avatar?: string
+  }
+}
+export interface ComposerOptsQuote {
+  uri: string
+  cid: string
+  text: string
+  indexedAt: string
+  author: {
+    handle: string
+    displayName?: string
+    avatar?: string
+  }
+}
+export interface ComposerOpts {
+  replyTo?: ComposerOptsPostRef
+  onPost?: () => void
+  quote?: ComposerOptsQuote
+}
+
+export class ShellUiModel {
+  darkMode = false
+  minimalShellMode = false
+  isDrawerOpen = false
+  isModalActive = false
+  activeModals: Modal[] = []
+  isLightboxActive = false
+  activeLightbox: ProfileImageLightbox | ImagesLightbox | undefined
+  isComposerActive = false
+  composerOpts: ComposerOpts | undefined
+  isOnboarding = false
+
+  constructor(public rootStore: RootStoreModel) {
+    makeAutoObservable(this, {
+      serialize: false,
+      rootStore: false,
+      hydrate: false,
+    })
+  }
+
+  serialize(): unknown {
+    return {
+      darkMode: this.darkMode,
+    }
+  }
+
+  hydrate(v: unknown) {
+    if (isObj(v)) {
+      if (hasProp(v, 'darkMode') && typeof v.darkMode === 'boolean') {
+        this.darkMode = v.darkMode
+      }
+    }
+  }
+
+  setDarkMode(v: boolean) {
+    this.darkMode = v
+  }
+
+  setMinimalShellMode(v: boolean) {
+    this.minimalShellMode = v
+  }
+
+  openDrawer() {
+    this.isDrawerOpen = true
+  }
+
+  closeDrawer() {
+    this.isDrawerOpen = false
+  }
+
+  openModal(modal: Modal) {
+    this.rootStore.emitNavigation()
+    this.isModalActive = true
+    this.activeModals.push(modal)
+  }
+
+  closeModal() {
+    this.activeModals.pop()
+    this.isModalActive = this.activeModals.length > 0
+  }
+
+  openLightbox(lightbox: ProfileImageLightbox | ImagesLightbox) {
+    this.rootStore.emitNavigation()
+    this.isLightboxActive = true
+    this.activeLightbox = lightbox
+  }
+
+  closeLightbox() {
+    this.isLightboxActive = false
+    this.activeLightbox = undefined
+  }
+
+  openComposer(opts: ComposerOpts) {
+    this.rootStore.emitNavigation()
+    this.isComposerActive = true
+    this.composerOpts = opts
+  }
+
+  closeComposer() {
+    this.isComposerActive = false
+    this.composerOpts = undefined
+  }
+
+  setOnboarding(v: boolean) {
+    this.isOnboarding = v
+    if (this.isOnboarding) {
+      this.rootStore.me.mainFeed.switchFeedType('suggested')
+    } else {
+      this.rootStore.me.mainFeed.switchFeedType('home')
+    }
+  }
+}