mirror of
https://github.com/stablyai/orca.git
synced 2026-10-02 16:02:15 +00:00
* fix(mobile): keep phone tab selection across host snapshots Preserve device-owned tab focus across ordinary host republications while explicit follow navigation remains authoritative. Retire closed selections across clients so stale snapshots cannot resurrect tabs. * fix(mobile): acknowledge session tab closes * fix(mobile): avoid tombstones for uncommitted closes * fix(web): implement session close IPC stubs * refactor: simplify mobile tab close flow * fix: bound session tab close confirmation
69 lines
2.2 KiB
TypeScript
69 lines
2.2 KiB
TypeScript
type SessionTabLike = {
|
|
id: string
|
|
isActive: boolean
|
|
}
|
|
|
|
export type ActiveSessionTabSelectionSource =
|
|
| 'snapshot'
|
|
| 'pending-tab'
|
|
| 'selected-tab'
|
|
| 'navigation-intent'
|
|
|
|
export type ResolveActiveSessionTabResult<T extends SessionTabLike> = {
|
|
activeTab: T | null
|
|
selectionSource: ActiveSessionTabSelectionSource
|
|
clearPendingActiveSessionTabId: boolean
|
|
retainSelectedSessionTabId: boolean
|
|
}
|
|
|
|
export function resolveActiveSessionTab<T extends SessionTabLike>(
|
|
tabs: readonly T[],
|
|
opts: {
|
|
pendingActiveSessionTabId: string | null
|
|
selectedSessionTabId: string | null
|
|
navigationIntent?: 'follow'
|
|
}
|
|
): ResolveActiveSessionTabResult<T> {
|
|
const snapshotActive = tabs.find((tab) => tab.isActive) ?? tabs[0] ?? null
|
|
const pendingActiveSessionTabId = opts.pendingActiveSessionTabId
|
|
// Why: targeted follow is the only host action allowed to supersede phone-local intent.
|
|
if (opts.navigationIntent === 'follow') {
|
|
return {
|
|
activeTab: snapshotActive,
|
|
selectionSource: 'navigation-intent',
|
|
clearPendingActiveSessionTabId: pendingActiveSessionTabId !== null,
|
|
retainSelectedSessionTabId: false
|
|
}
|
|
}
|
|
if (pendingActiveSessionTabId) {
|
|
if (snapshotActive?.id === pendingActiveSessionTabId) {
|
|
return {
|
|
activeTab: snapshotActive,
|
|
selectionSource: 'snapshot',
|
|
clearPendingActiveSessionTabId: true,
|
|
retainSelectedSessionTabId: false
|
|
}
|
|
}
|
|
const pendingTab = tabs.find((tab) => tab.id === pendingActiveSessionTabId) ?? null
|
|
if (pendingTab) {
|
|
return {
|
|
activeTab: pendingTab,
|
|
selectionSource: 'pending-tab',
|
|
clearPendingActiveSessionTabId: false,
|
|
retainSelectedSessionTabId: false
|
|
}
|
|
}
|
|
}
|
|
const clearPendingActiveSessionTabId = pendingActiveSessionTabId !== null
|
|
const selectedTab = opts.selectedSessionTabId
|
|
? (tabs.find((tab) => tab.id === opts.selectedSessionTabId) ?? null)
|
|
: null
|
|
return {
|
|
activeTab: selectedTab ?? snapshotActive,
|
|
selectionSource: selectedTab ? 'selected-tab' : 'snapshot',
|
|
clearPendingActiveSessionTabId,
|
|
// Why: transient browser guest swaps must not erase the device's explicit pick.
|
|
retainSelectedSessionTabId: Boolean(opts.selectedSessionTabId) && !selectedTab
|
|
}
|
|
}
|