Switch to temporary 'fixed tabs' model for default and notifications

zio/stable
Paul Frazee 2022-12-08 14:21:28 -06:00
parent 539bf5d350
commit 53b8f0d040
3 changed files with 91 additions and 17 deletions

View File

@ -6,6 +6,20 @@ function genId() {
return ++__id return ++__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 "Notifications" tab
// These tabs always retain the first 2 items in their history.
// The default tab is used for basically everything except notifications.
// -prf
export enum TabPurpose {
Default = 0,
Notifs = 1,
}
interface HistoryItem { interface HistoryItem {
url: string url: string
ts: number ts: number
@ -17,14 +31,22 @@ export type HistoryPtr = [number, number]
export class NavigationTabModel { export class NavigationTabModel {
id = genId() id = genId()
history: HistoryItem[] = [ history: HistoryItem[]
{url: '/menu', ts: Date.now(), id: genId()},
{url: '/', ts: Date.now(), id: genId()},
]
index = 1 index = 1
isNewTab = false isNewTab = false
constructor() { constructor(public fixedTabPurpose: TabPurpose) {
if (fixedTabPurpose === TabPurpose.Notifs) {
this.history = [
{url: '/menu', ts: Date.now(), id: genId()},
{url: '/notifications', ts: Date.now(), id: genId()},
]
} else {
this.history = [
{url: '/menu', ts: Date.now(), id: genId()},
{url: '/', ts: Date.now(), id: genId()},
]
}
makeAutoObservable(this, { makeAutoObservable(this, {
serialize: false, serialize: false,
hydrate: false, hydrate: false,
@ -86,6 +108,12 @@ export class NavigationTabModel {
if (this.index < this.history.length - 1) { if (this.index < this.history.length - 1) {
this.history.length = this.index + 1 this.history.length = this.index + 1
} }
// TEMP ensure the tab has its purpose's main view -prf
if (this.history.length < 2) {
const fixedUrl =
this.fixedTabPurpose === TabPurpose.Notifs ? '/notifications' : '/'
this.history.push({url: fixedUrl, ts: Date.now(), id: genId()})
}
this.history.push({url, title, ts: Date.now(), id: genId()}) this.history.push({url, title, ts: Date.now(), id: genId()})
this.index = this.history.length - 1 this.index = this.history.length - 1
} }
@ -110,14 +138,19 @@ export class NavigationTabModel {
} }
} }
resetTo(path: string) { // TEMP
if (this.index >= 1 && this.history[1]?.url === path) { // a helper to bring the tab back to its base state
// fall back in history to target // -prf
fixedTabReset() {
if (this.index >= 1) {
// fall back in history to "main" view
if (this.index > 1) { if (this.index > 1) {
this.index = 1 this.index = 1
} }
} else { } else {
this.history = [this.history[0], {url: path, ts: Date.now(), id: genId()}] const url =
this.fixedTabPurpose === TabPurpose.Notifs ? '/notifications' : '/'
this.history = [this.history[0], {url, ts: Date.now(), id: genId()}]
this.index = 1 this.index = 1
} }
} }
@ -192,7 +225,10 @@ export class NavigationTabModel {
} }
export class NavigationModel { export class NavigationModel {
tabs: NavigationTabModel[] = [new NavigationTabModel()] tabs: NavigationTabModel[] = [
new NavigationTabModel(TabPurpose.Default),
new NavigationTabModel(TabPurpose.Notifs),
]
tabIndex = 0 tabIndex = 0
constructor() { constructor() {
@ -203,7 +239,10 @@ export class NavigationModel {
} }
clear() { clear() {
this.tabs = [new NavigationTabModel()] this.tabs = [
new NavigationTabModel(TabPurpose.Default),
new NavigationTabModel(TabPurpose.Notifs),
]
this.tabIndex = 0 this.tabIndex = 0
} }
@ -258,11 +297,25 @@ export class NavigationModel {
// tab management // tab management
// = // =
// TEMP
// fixed tab helper function
// -prf
switchTo(purpose: TabPurpose, reset: boolean) {
if (purpose === TabPurpose.Notifs) {
this.tabIndex = 1
} else {
this.tabIndex = 0
}
if (reset) {
this.tab.fixedTabReset()
}
}
newTab(url: string, title?: string) { newTab(url: string, title?: string) {
if (!TABS_ENABLED) { if (!TABS_ENABLED) {
return this.navigate(url) return this.navigate(url)
} }
const tab = new NavigationTabModel() const tab = new NavigationTabModel(TabPurpose.Default)
tab.navigate(url, title) tab.navigate(url, title)
tab.isNewTab = true tab.isNewTab = true
this.tabs.push(tab) this.tabs.push(tab)

View File

@ -37,7 +37,12 @@ export const Menu = ({navIdx, visible}: ScreenParams) => {
// = // =
const onNavigate = (url: string) => { const onNavigate = (url: string) => {
store.nav.navigate(url) if (url === '/notifications') {
store.nav.switchTo(1, true)
} else {
store.nav.switchTo(0, true)
store.nav.navigate(url)
}
} }
const onPressCreateScene = () => { const onPressCreateScene = () => {
store.shell.openModal(new CreateSceneModel()) store.shell.openModal(new CreateSceneModel())

View File

@ -121,13 +121,29 @@ export const MobileShell: React.FC = observer(() => {
const screenRenderDesc = constructScreenRenderDesc(store.nav) const screenRenderDesc = constructScreenRenderDesc(store.nav)
const onPressHome = () => { const onPressHome = () => {
if (store.nav.tab.current.url === '/') { if (store.nav.tab.fixedTabPurpose === 0) {
scrollElRef.current?.scrollToOffset({offset: 0}) if (store.nav.tab.current.url === '/') {
scrollElRef.current?.scrollToOffset({offset: 0})
} else {
store.nav.tab.fixedTabReset()
}
} else { } else {
store.nav.tab.resetTo('/') store.nav.switchTo(0, false)
if (store.nav.tab.index === 0) {
store.nav.tab.fixedTabReset()
}
}
}
const onPressNotifications = () => {
if (store.nav.tab.fixedTabPurpose === 1) {
store.nav.tab.fixedTabReset()
} else {
store.nav.switchTo(1, false)
if (store.nav.tab.index === 0) {
store.nav.tab.fixedTabReset()
}
} }
} }
const onPressNotifications = () => store.nav.tab.resetTo('/notifications')
const onPressTabs = () => toggleTabsMenu(!isTabsSelectorActive) const onPressTabs = () => toggleTabsMenu(!isTabsSelectorActive)
const doNewTab = (url: string) => () => store.nav.newTab(url) const doNewTab = (url: string) => () => store.nav.newTab(url)