diff --git a/src/state/models/navigation.ts b/src/state/models/navigation.ts index 533336a4..0ec097af 100644 --- a/src/state/models/navigation.ts +++ b/src/state/models/navigation.ts @@ -1,20 +1,23 @@ import {makeAutoObservable} from 'mobx' import {isObj, hasProp} from '../lib/type-guards' -let __tabId = 0 -function genTabId() { - return ++__tabId +let __id = 0 +function genId() { + return ++__id } interface HistoryItem { url: string ts: number title?: string + id: number } +export type HistoryPtr = [number, number] + export class NavigationTabModel { - id = genTabId() - history: HistoryItem[] = [{url: '/', ts: Date.now()}] + id = genId() + history: HistoryItem[] = [{url: '/', ts: Date.now(), id: genId()}] index = 0 isNewTab = false @@ -47,6 +50,7 @@ export class NavigationTabModel { url: item.url, title: item.title, index: start + i, + id: item.id, })) } @@ -61,6 +65,7 @@ export class NavigationTabModel { url: item.url, title: item.title, index: start + i, + id: item.id, })) } @@ -78,7 +83,7 @@ export class NavigationTabModel { if (this.index < this.history.length - 1) { this.history.length = this.index + 1 } - this.history.push({url, title, ts: Date.now()}) + this.history.push({url, title, ts: Date.now(), id: genId()}) this.index = this.history.length - 1 } } @@ -86,7 +91,12 @@ export class NavigationTabModel { refresh() { this.history = [ ...this.history.slice(0, this.index), - {url: this.current.url, title: this.current.title, ts: Date.now()}, + { + url: this.current.url, + title: this.current.title, + ts: Date.now(), + id: this.current.id, + }, ...this.history.slice(this.index + 1), ] } @@ -109,8 +119,13 @@ export class NavigationTabModel { } } - setTitle(title: string) { - this.current.title = title + setTitle(id: number, title: string) { + this.history = this.history.map(h => { + if (h.id === id) { + return {...h, title} + } + return h + }) } setIsNewTab(v: boolean) { @@ -203,8 +218,8 @@ export class NavigationModel { this.tab.refresh() } - setTitle(title: string) { - this.tab.setTitle(title) + setTitle(ptr: HistoryPtr, title: string) { + this.tabs.find(t => t.id === ptr[0])?.setTitle(ptr[1], title) } // tab management diff --git a/src/view/routes.ts b/src/view/routes.ts index c4929707..272a1b09 100644 --- a/src/view/routes.ts +++ b/src/view/routes.ts @@ -17,6 +17,7 @@ import {ProfileMembers} from './screens/ProfileMembers' import {Settings} from './screens/Settings' export type ScreenParams = { + navIdx: [number, number] params: Record visible: boolean scrollElRef?: MutableRefObject | undefined> diff --git a/src/view/screens/Contacts.tsx b/src/view/screens/Contacts.tsx index 65c933b3..c0e265ca 100644 --- a/src/view/screens/Contacts.tsx +++ b/src/view/screens/Contacts.tsx @@ -8,13 +8,13 @@ import {colors} from '../lib/styles' import {ScreenParams} from '../routes' import {useStores} from '../../state' -export const Contacts = ({visible, params}: ScreenParams) => { +export const Contacts = ({navIdx, visible, params}: ScreenParams) => { const store = useStores() const selectorInterp = useSharedValue(0) useEffect(() => { if (visible) { - store.nav.setTitle(`Contacts`) + store.nav.setTitle(navIdx, `Contacts`) } }, [store, visible]) diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index 668ec3a7..609b1ca3 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -12,6 +12,7 @@ import {ScreenParams} from '../routes' import {s, colors} from '../lib/styles' export const Home = observer(function Home({ + navIdx, visible, scrollElRef, }: ScreenParams) { @@ -51,7 +52,7 @@ export const Home = observer(function Home({ console.log('Updating home feed') defaultFeedView.update() } else { - store.nav.setTitle('Home') + store.nav.setTitle(navIdx, 'Home') console.log('Fetching home feed') defaultFeedView.setup().then(() => { if (aborted) return diff --git a/src/view/screens/Notifications.tsx b/src/view/screens/Notifications.tsx index 71eda34d..7e4de497 100644 --- a/src/view/screens/Notifications.tsx +++ b/src/view/screens/Notifications.tsx @@ -7,7 +7,7 @@ import {useStores} from '../../state' import {NotificationsViewModel} from '../../state/models/notifications-view' import {ScreenParams} from '../routes' -export const Notifications = ({visible}: ScreenParams) => { +export const Notifications = ({navIdx, visible}: ScreenParams) => { const [hasSetup, setHasSetup] = useState(false) const [notesView, setNotesView] = useState< NotificationsViewModel | undefined @@ -24,7 +24,7 @@ export const Notifications = ({visible}: ScreenParams) => { console.log('Updating notifications feed') notesView?.update() } else { - store.nav.setTitle('Notifications') + store.nav.setTitle(navIdx, 'Notifications') const newNotesView = new NotificationsViewModel(store, {}) setNotesView(newNotesView) newNotesView.setup().then(() => { diff --git a/src/view/screens/PostDownvotedBy.tsx b/src/view/screens/PostDownvotedBy.tsx index a7747683..4d975279 100644 --- a/src/view/screens/PostDownvotedBy.tsx +++ b/src/view/screens/PostDownvotedBy.tsx @@ -6,14 +6,14 @@ import {ScreenParams} from '../routes' import {useStores} from '../../state' import {makeRecordUri} from '../lib/strings' -export const PostDownvotedBy = ({visible, params}: ScreenParams) => { +export const PostDownvotedBy = ({navIdx, visible, params}: ScreenParams) => { const store = useStores() const {name, rkey} = params const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey) useEffect(() => { if (visible) { - store.nav.setTitle('Downvoted by') + store.nav.setTitle(navIdx, 'Downvoted by') } }, [store, visible]) diff --git a/src/view/screens/PostRepostedBy.tsx b/src/view/screens/PostRepostedBy.tsx index 263af195..8e834669 100644 --- a/src/view/screens/PostRepostedBy.tsx +++ b/src/view/screens/PostRepostedBy.tsx @@ -6,14 +6,14 @@ import {ScreenParams} from '../routes' import {useStores} from '../../state' import {makeRecordUri} from '../lib/strings' -export const PostRepostedBy = ({visible, params}: ScreenParams) => { +export const PostRepostedBy = ({navIdx, visible, params}: ScreenParams) => { const store = useStores() const {name, rkey} = params const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey) useEffect(() => { if (visible) { - store.nav.setTitle('Reposted by') + store.nav.setTitle(navIdx, 'Reposted by') } }, [store, visible]) diff --git a/src/view/screens/PostThread.tsx b/src/view/screens/PostThread.tsx index fc804f61..69dda742 100644 --- a/src/view/screens/PostThread.tsx +++ b/src/view/screens/PostThread.tsx @@ -6,14 +6,14 @@ import {PostThread as PostThreadComponent} from '../com/post-thread/PostThread' import {ScreenParams} from '../routes' import {useStores} from '../../state' -export const PostThread = ({visible, params}: ScreenParams) => { +export const PostThread = ({navIdx, visible, params}: ScreenParams) => { const store = useStores() const {name, rkey} = params const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey) useEffect(() => { if (visible) { - store.nav.setTitle(`Post by ${name}`) + store.nav.setTitle(navIdx, `Post by ${name}`) } }, [visible, store.nav, name]) diff --git a/src/view/screens/PostUpvotedBy.tsx b/src/view/screens/PostUpvotedBy.tsx index 0bf662de..d87fa548 100644 --- a/src/view/screens/PostUpvotedBy.tsx +++ b/src/view/screens/PostUpvotedBy.tsx @@ -6,14 +6,14 @@ import {ScreenParams} from '../routes' import {useStores} from '../../state' import {makeRecordUri} from '../lib/strings' -export const PostUpvotedBy = ({visible, params}: ScreenParams) => { +export const PostUpvotedBy = ({navIdx, visible, params}: ScreenParams) => { const store = useStores() const {name, rkey} = params const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey) useEffect(() => { if (visible) { - store.nav.setTitle('Upvoted by') + store.nav.setTitle(navIdx, 'Upvoted by') } }, [store, visible]) diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx index 0edb503d..e637c6ad 100644 --- a/src/view/screens/Profile.tsx +++ b/src/view/screens/Profile.tsx @@ -23,7 +23,7 @@ const LOADING_ITEM = {_reactKey: '__loading__'} const END_ITEM = {_reactKey: '__end__'} const EMPTY_ITEM = {_reactKey: '__empty__'} -export const Profile = observer(({visible, params}: ScreenParams) => { +export const Profile = observer(({navIdx, visible, params}: ScreenParams) => { const store = useStores() const [hasSetup, setHasSetup] = useState(false) const uiState = useMemo( @@ -41,7 +41,7 @@ export const Profile = observer(({visible, params}: ScreenParams) => { uiState.update() } else { console.log('Fetching profile for', params.name) - store.nav.setTitle(params.name) + store.nav.setTitle(navIdx, params.name) uiState.setup().then(() => { if (aborted) return setHasSetup(true) diff --git a/src/view/screens/ProfileFollowers.tsx b/src/view/screens/ProfileFollowers.tsx index ac776a05..b19a5bc3 100644 --- a/src/view/screens/ProfileFollowers.tsx +++ b/src/view/screens/ProfileFollowers.tsx @@ -5,13 +5,13 @@ import {ProfileFollowers as ProfileFollowersComponent} from '../com/profile/Prof import {ScreenParams} from '../routes' import {useStores} from '../../state' -export const ProfileFollowers = ({visible, params}: ScreenParams) => { +export const ProfileFollowers = ({navIdx, visible, params}: ScreenParams) => { const store = useStores() const {name} = params useEffect(() => { if (visible) { - store.nav.setTitle(`Followers of ${name}`) + store.nav.setTitle(navIdx, `Followers of ${name}`) } }, [store, visible, name]) diff --git a/src/view/screens/ProfileFollows.tsx b/src/view/screens/ProfileFollows.tsx index c075851c..e54b562e 100644 --- a/src/view/screens/ProfileFollows.tsx +++ b/src/view/screens/ProfileFollows.tsx @@ -5,13 +5,13 @@ import {ProfileFollows as ProfileFollowsComponent} from '../com/profile/ProfileF import {ScreenParams} from '../routes' import {useStores} from '../../state' -export const ProfileFollows = ({visible, params}: ScreenParams) => { +export const ProfileFollows = ({navIdx, visible, params}: ScreenParams) => { const store = useStores() const {name} = params useEffect(() => { if (visible) { - store.nav.setTitle(`Followed by ${name}`) + store.nav.setTitle(navIdx, `Followed by ${name}`) } }, [store, visible, name]) diff --git a/src/view/screens/ProfileMembers.tsx b/src/view/screens/ProfileMembers.tsx index dd222109..b4b6c7e5 100644 --- a/src/view/screens/ProfileMembers.tsx +++ b/src/view/screens/ProfileMembers.tsx @@ -5,13 +5,13 @@ import {ProfileMembers as ProfileMembersComponent} from '../com/profile/ProfileM import {ScreenParams} from '../routes' import {useStores} from '../../state' -export const ProfileMembers = ({visible, params}: ScreenParams) => { +export const ProfileMembers = ({navIdx, visible, params}: ScreenParams) => { const store = useStores() const {name} = params useEffect(() => { if (visible) { - store.nav.setTitle(`Members of ${name}`) + store.nav.setTitle(navIdx, `Members of ${name}`) } }, [store, visible, name]) diff --git a/src/view/screens/Search.tsx b/src/view/screens/Search.tsx index 7f3dd966..71bac4ad 100644 --- a/src/view/screens/Search.tsx +++ b/src/view/screens/Search.tsx @@ -7,13 +7,13 @@ import {ScreenParams} from '../routes' import {useStores} from '../../state' import {colors} from '../lib/styles' -export const Search = ({visible, params}: ScreenParams) => { +export const Search = ({navIdx, visible, params}: ScreenParams) => { const store = useStores() const {name} = params useEffect(() => { if (visible) { - store.nav.setTitle(`Search`) + store.nav.setTitle(navIdx, `Search`) } }, [store, visible, name]) const onComposePress = () => { diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx index a0aec89f..b7344cf0 100644 --- a/src/view/screens/Settings.tsx +++ b/src/view/screens/Settings.tsx @@ -8,14 +8,17 @@ import {ViewHeader} from '../com/util/ViewHeader' import {Link} from '../com/util/Link' import {UserAvatar} from '../com/util/UserAvatar' -export const Settings = observer(function Settings({visible}: ScreenParams) { +export const Settings = observer(function Settings({ + navIdx, + visible, +}: ScreenParams) { const store = useStores() useEffect(() => { if (!visible) { return } - store.nav.setTitle('Settings') + store.nav.setTitle(navIdx, 'Settings') }, [visible, store]) const onPressSignout = () => { diff --git a/src/view/shell/mobile/index.tsx b/src/view/shell/mobile/index.tsx index cad681bd..b4b98e35 100644 --- a/src/view/shell/mobile/index.tsx +++ b/src/view/shell/mobile/index.tsx @@ -268,7 +268,7 @@ export const MobileShell: React.FC = observer(() => { {screenRenderDesc.screens.map( - ({Com, params, key, current, previous}) => { + ({Com, navIdx, params, key, current, previous}) => { return ( { ]}> @@ -361,6 +362,7 @@ export const MobileShell: React.FC = observer(() => { */ type ScreenRenderDesc = MatchResult & { key: string + navIdx: [number, number] current: boolean previous: boolean isNewTab: boolean @@ -388,6 +390,7 @@ function constructScreenRenderDesc(nav: NavigationModel): { 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,