about summary refs log tree commit diff
path: root/src/state/models/navigation.ts
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2023-03-13 16:01:43 -0500
committerGitHub <noreply@github.com>2023-03-13 16:01:43 -0500
commit56cf890debeb9872f791ccb992a5587f2c05fd9e (patch)
tree929453b41274a712d8b2fce441e98a0cd030d305 /src/state/models/navigation.ts
parent503e03d91e1de4bfeabec1eb2d97dcdceb13fcc5 (diff)
downloadvoidsky-56cf890debeb9872f791ccb992a5587f2c05fd9e.tar.zst
Move to expo and react-navigation (#288)
* WIP - adding expo

* WIP - adding expo 2

* Fix tsc

* Finish adding expo

* Disable the 'require cycle' warning

* Tweak plist

* Modify some dependency versions to make expo happy

* Fix icon fill

* Get Web compiling for expo

* 1.7

* Switch to react-navigation in expo2 (#287)

* WIP Switch to react-navigation

* WIP Switch to react-navigation 2

* WIP Switch to react-navigation 3

* Convert all screens to react navigation

* Update BottomBar for react navigation

* Update mobile menu to be react-native drawer

* Fixes to drawer and bottombar

* Factor out some helpers

* Replace the navigation model with react-navigation

* Restructure the shell folder and fix the header positioning

* Restore the error boundary

* Fix tsc

* Implement not-found page

* Remove react-native-gesture-handler (no longer used)

* Handle notifee card presses

* Handle all navigations from the state layer

* Fix drawer behaviors

* Fix two linking issues

* Switch to our react-native-progress fork to fix an svg rendering issue

* Get Web working with react-navigation

* Refactor routes and navigation for a bit more clarity

* Remove dead code

* Rework Web shell to left/right nav to make this easier

* Fix ViewHeader for desktop web

* Hide profileheader back btn on desktop web

* Move the compose button to the left nav

* Implement reply prompt in threads for desktop web

* Composer refactors

* Factor out all platform-specific text input behaviors from the composer

* Small fix

* Update the web build to use tiptap for the composer

* Tune up the mention autocomplete dropdown

* Simplify the default avatar and banner

* Fixes to link cards in web composer

* Fix dropdowns on web

* Tweak load latest on desktop

* Add web beta message and feedback link

* Fix up links in desktop web
Diffstat (limited to 'src/state/models/navigation.ts')
-rw-r--r--src/state/models/navigation.ts434
1 files changed, 0 insertions, 434 deletions
diff --git a/src/state/models/navigation.ts b/src/state/models/navigation.ts
deleted file mode 100644
index 11af65912..000000000
--- a/src/state/models/navigation.ts
+++ /dev/null
@@ -1,434 +0,0 @@
-import {RootStoreModel} from './root-store'
-import {makeAutoObservable} from 'mobx'
-import {TABS_ENABLED} from 'lib/build-flags'
-import * as analytics from 'lib/analytics'
-import {isNative} from 'platform/detection'
-
-let __id = 0
-function genId() {
-  return String(++__id)
-}
-
-// NOTE
-// this model was originally built for a freeform "tabs" concept like a browser
-// we've since decided to pause that idea and do something more traditional
-// until we're fully sure what that is, the tabs are being repurposed into a fixed topology
-// - Tab 0: The "Default" tab
-// - Tab 1: The "Search" tab
-// - Tab 2: The "Notifications" tab
-// These tabs always retain the first item in their history.
-// -prf
-export enum TabPurpose {
-  Default = 0,
-  Search = 1,
-  Notifs = 2,
-}
-
-export const TabPurposeMainPath: Record<TabPurpose, string> = {
-  [TabPurpose.Default]: '/',
-  [TabPurpose.Search]: '/search',
-  [TabPurpose.Notifs]: '/notifications',
-}
-
-interface HistoryItem {
-  url: string
-  ts: number
-  title?: string
-  id: string
-}
-
-export type HistoryPtr = string // `{tabId}-{historyId}`
-
-export class NavigationTabModel {
-  id = genId()
-  history: HistoryItem[]
-  index = 0
-  isNewTab = false
-
-  constructor(public fixedTabPurpose: TabPurpose) {
-    this.history = [
-      {url: TabPurposeMainPath[fixedTabPurpose], ts: Date.now(), id: genId()},
-    ]
-    makeAutoObservable(this, {
-      serialize: false,
-      hydrate: false,
-    })
-  }
-  // accessors
-  // =
-
-  get current() {
-    return this.history[this.index]
-  }
-
-  get canGoBack() {
-    return this.index > 0
-  }
-
-  get canGoForward() {
-    return this.index < this.history.length - 1
-  }
-
-  getBackList(n: number) {
-    const start = Math.max(this.index - n, 0)
-    const end = this.index
-    return this.history.slice(start, end).map((item, i) => ({
-      url: item.url,
-      title: item.title,
-      index: start + i,
-      id: item.id,
-    }))
-  }
-
-  get backTen() {
-    return this.getBackList(10)
-  }
-
-  getForwardList(n: number) {
-    const start = Math.min(this.index + 1, this.history.length)
-    const end = Math.min(this.index + n + 1, this.history.length)
-    return this.history.slice(start, end).map((item, i) => ({
-      url: item.url,
-      title: item.title,
-      index: start + i,
-      id: item.id,
-    }))
-  }
-
-  get forwardTen() {
-    return this.getForwardList(10)
-  }
-
-  // navigation
-  // =
-
-  navigate(url: string, title?: string) {
-    try {
-      const path = url.split('/')[1]
-      analytics.track('Navigation', {
-        path,
-      })
-    } catch (error) {}
-
-    if (this.current?.url === url) {
-      this.refresh()
-    } else {
-      if (this.index < this.history.length - 1) {
-        this.history.length = this.index + 1
-      }
-      // TEMP ensure the tab has its purpose's main view -prf
-      if (this.history.length < 1) {
-        const fixedUrl = TabPurposeMainPath[this.fixedTabPurpose]
-        this.history.push({url: fixedUrl, ts: Date.now(), id: genId()})
-      }
-      this.history.push({url, title, ts: Date.now(), id: genId()})
-      this.index = this.history.length - 1
-      if (!isNative) {
-        window.history.pushState({hindex: this.index, hurl: url}, '', url)
-      }
-    }
-  }
-
-  refresh() {
-    this.history = [
-      ...this.history.slice(0, this.index),
-      {
-        url: this.current.url,
-        title: this.current.title,
-        ts: Date.now(),
-        id: this.current.id,
-      },
-      ...this.history.slice(this.index + 1),
-    ]
-  }
-
-  goBack() {
-    if (this.canGoBack) {
-      this.index--
-      if (!isNative) {
-        window.history.back()
-      }
-    }
-  }
-
-  // TEMP
-  // a helper to bring the tab back to its base state
-  // -prf
-  fixedTabReset() {
-    this.index = 0
-  }
-
-  goForward() {
-    if (this.canGoForward) {
-      this.index++
-      if (!isNative) {
-        window.history.forward()
-      }
-    }
-  }
-
-  goToIndex(index: number) {
-    if (index >= 0 && index <= this.history.length - 1) {
-      const delta = index - this.index
-      this.index = index
-      if (!isNative) {
-        window.history.go(delta)
-      }
-    }
-  }
-
-  setTitle(id: string, title: string) {
-    this.history = this.history.map(h => {
-      if (h.id === id) {
-        return {...h, title}
-      }
-      return h
-    })
-  }
-
-  setIsNewTab(v: boolean) {
-    this.isNewTab = v
-  }
-
-  // browser only
-  // =
-
-  resetTo(url: string) {
-    this.index = 0
-    this.history.push({url, title: '', ts: Date.now(), id: genId()})
-    this.index = this.history.length - 1
-  }
-
-  // persistence
-  // =
-
-  serialize(): unknown {
-    return {
-      history: this.history,
-      index: this.index,
-    }
-  }
-
-  hydrate(_v: unknown) {
-    // TODO fixme
-    // if (isObj(v)) {
-    //   if (hasProp(v, 'history') && Array.isArray(v.history)) {
-    //     for (const item of v.history) {
-    //       if (
-    //         isObj(item) &&
-    //         hasProp(item, 'url') &&
-    //         typeof item.url === 'string'
-    //       ) {
-    //         let copy: HistoryItem = {
-    //           url: item.url,
-    //           ts:
-    //             hasProp(item, 'ts') && typeof item.ts === 'number'
-    //               ? item.ts
-    //               : Date.now(),
-    //         }
-    //         if (hasProp(item, 'title') && typeof item.title === 'string') {
-    //           copy.title = item.title
-    //         }
-    //         this.history.push(copy)
-    //       }
-    //     }
-    //   }
-    //   if (hasProp(v, 'index') && typeof v.index === 'number') {
-    //     this.index = v.index
-    //   }
-    //   if (this.index >= this.history.length - 1) {
-    //     this.index = this.history.length - 1
-    //   }
-    // }
-  }
-}
-
-export class NavigationModel {
-  tabs: NavigationTabModel[] = isNative
-    ? [
-        new NavigationTabModel(TabPurpose.Default),
-        new NavigationTabModel(TabPurpose.Search),
-        new NavigationTabModel(TabPurpose.Notifs),
-      ]
-    : [new NavigationTabModel(TabPurpose.Default)]
-  tabIndex = 0
-
-  constructor(public rootStore: RootStoreModel) {
-    makeAutoObservable(this, {
-      rootStore: false,
-      serialize: false,
-      hydrate: false,
-    })
-  }
-
-  /**
-   * Used only in the web build to sync with browser history state
-   */
-  bindWebNavigation() {
-    if (!isNative) {
-      window.addEventListener('popstate', e => {
-        const {hindex, hurl} = e.state
-        if (hindex >= 0 && hindex <= this.tab.history.length - 1) {
-          this.tab.index = hindex
-        }
-        if (this.tab.current.url !== hurl) {
-          // desynced because they went back to an old tab session-
-          // do a reset to match that
-          this.tab.resetTo(hurl)
-        }
-
-        // sanity check
-        if (this.tab.current.url !== window.location.pathname) {
-          // state has completely desynced, reload
-          window.location.reload()
-        }
-      })
-    }
-  }
-
-  clear() {
-    this.tabs = isNative
-      ? [
-          new NavigationTabModel(TabPurpose.Default),
-          new NavigationTabModel(TabPurpose.Search),
-          new NavigationTabModel(TabPurpose.Notifs),
-        ]
-      : [new NavigationTabModel(TabPurpose.Default)]
-    this.tabIndex = 0
-  }
-
-  // accessors
-  // =
-
-  get tab() {
-    return this.tabs[this.tabIndex]
-  }
-
-  get tabCount() {
-    return this.tabs.length
-  }
-
-  isCurrentScreen(tabId: string, index: number) {
-    return this.tab.id === tabId && this.tab.index === index
-  }
-
-  // navigation
-  // =
-
-  navigate(url: string, title?: string) {
-    this.rootStore.emitNavigation()
-    this.tab.navigate(url, title)
-  }
-
-  refresh() {
-    this.tab.refresh()
-  }
-
-  setTitle(ptr: HistoryPtr, title: string) {
-    const [tid, hid] = ptr.split('-')
-    this.tabs.find(t => t.id === tid)?.setTitle(hid, title)
-  }
-
-  handleLink(url: string) {
-    let path
-    if (url.startsWith('/')) {
-      path = url
-    } else if (url.startsWith('http')) {
-      try {
-        path = new URL(url).pathname
-      } catch (e) {
-        console.error('Invalid url', url, e)
-        return
-      }
-    } else {
-      console.error('Invalid url', url)
-      return
-    }
-    this.navigate(path)
-  }
-
-  // tab management
-  // =
-
-  // TEMP
-  // fixed tab helper function
-  // -prf
-  switchTo(purpose: TabPurpose, reset: boolean) {
-    this.rootStore.emitNavigation()
-    switch (purpose) {
-      case TabPurpose.Notifs:
-        this.tabIndex = 2
-        break
-      case TabPurpose.Search:
-        this.tabIndex = 1
-        break
-      default:
-        this.tabIndex = 0
-    }
-    if (reset) {
-      this.tab.fixedTabReset()
-    }
-  }
-
-  newTab(url: string, title?: string) {
-    if (!TABS_ENABLED) {
-      return this.navigate(url)
-    }
-    const tab = new NavigationTabModel(TabPurpose.Default)
-    tab.navigate(url, title)
-    tab.isNewTab = true
-    this.tabs.push(tab)
-    this.tabIndex = this.tabs.length - 1
-  }
-
-  setActiveTab(tabIndex: number) {
-    if (!TABS_ENABLED) {
-      return
-    }
-    this.tabIndex = Math.max(Math.min(tabIndex, this.tabs.length - 1), 0)
-  }
-
-  closeTab(tabIndex: number) {
-    if (!TABS_ENABLED) {
-      return
-    }
-    this.tabs = [
-      ...this.tabs.slice(0, tabIndex),
-      ...this.tabs.slice(tabIndex + 1),
-    ]
-    if (this.tabs.length === 0) {
-      this.newTab('/')
-    } else if (this.tabIndex >= this.tabs.length) {
-      this.tabIndex = this.tabs.length - 1
-    }
-  }
-
-  // persistence
-  // =
-
-  serialize(): unknown {
-    return {
-      tabs: this.tabs.map(t => t.serialize()),
-      tabIndex: this.tabIndex,
-    }
-  }
-
-  hydrate(_v: unknown) {
-    // TODO fixme
-    this.clear()
-    /*if (isObj(v)) {
-      if (hasProp(v, 'tabs') && Array.isArray(v.tabs)) {
-        for (const tab of v.tabs) {
-          const copy = new NavigationTabModel()
-          copy.hydrate(tab)
-          if (copy.history.length) {
-            this.tabs.push(copy)
-          }
-        }
-      }
-      if (hasProp(v, 'tabIndex') && typeof v.tabIndex === 'number') {
-        this.tabIndex = v.tabIndex
-      }
-    }*/
-  }
-}