mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
Omit unsupported combined diff tabs from mobile session snapshots (#6520)
Combined diff tabs (such as branch, commit, or uncommitted changes) use display labels as relative paths and require the desktop-only combined renderer. Excluding these tabs from the mobile snapshots prevents mobile clients from incorrectly attempting to read them via files.read.
This commit is contained in:
@@ -725,6 +725,85 @@ describe('buildMobileSessionTabSnapshots', () => {
|
||||
expect(tab).not.toHaveProperty('diffSource')
|
||||
})
|
||||
|
||||
it.each([
|
||||
['combined-branch', 'wt-1::all-diffs::branch::main', 'Branch Changes (main)'],
|
||||
['combined-commit', 'wt-1::all-diffs::commit::abc123', 'Commit abc123'],
|
||||
['combined-all', 'wt-1::all-diffs::uncommitted', 'All Changes'],
|
||||
['combined-uncommitted', 'wt-1::all-diffs::uncommitted::unstaged', 'Changes']
|
||||
] as const)('omits unsupported %s diff tabs from mobile file snapshots', (source, id, label) => {
|
||||
const state = makeState({
|
||||
browserTabsByWorktree: {},
|
||||
tabBarOrderByWorktree: { 'wt-1': [id] },
|
||||
activeFileId: id,
|
||||
activeFileIdByWorktree: { 'wt-1': id },
|
||||
activeTabType: 'editor',
|
||||
activeTabTypeByWorktree: { 'wt-1': 'editor' },
|
||||
openFiles: [
|
||||
{
|
||||
id,
|
||||
filePath: '/repo',
|
||||
relativePath: label,
|
||||
worktreeId: 'wt-1',
|
||||
language: 'plaintext',
|
||||
mode: 'diff',
|
||||
diffSource: source,
|
||||
isDirty: false
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const snapshot = buildMobileSessionTabSnapshots(state)[0]
|
||||
|
||||
expect(snapshot?.tabs).toEqual([])
|
||||
expect(snapshot?.activeTabId).toBeNull()
|
||||
expect(snapshot?.activeTabType).toBeNull()
|
||||
})
|
||||
|
||||
it('does not recover unsupported combined diff tabs through split-group fallback', () => {
|
||||
const combinedId = 'wt-1::all-diffs::branch::main'
|
||||
const state = makeState({
|
||||
activeGroupIdByWorktree: { 'wt-1': 'group-right' },
|
||||
groupsByWorktree: {
|
||||
'wt-1': [
|
||||
{
|
||||
id: 'group-right',
|
||||
activeTabId: 'combined-tab-right',
|
||||
tabOrder: [],
|
||||
recentTabIds: []
|
||||
}
|
||||
]
|
||||
} as unknown as AppState['groupsByWorktree'],
|
||||
unifiedTabsByWorktree: {
|
||||
'wt-1': [
|
||||
{
|
||||
id: 'combined-tab-right',
|
||||
groupId: 'group-right',
|
||||
contentType: 'diff',
|
||||
entityId: combinedId,
|
||||
title: 'Branch Changes (main)'
|
||||
}
|
||||
]
|
||||
} as unknown as AppState['unifiedTabsByWorktree'],
|
||||
openFiles: [
|
||||
{
|
||||
id: combinedId,
|
||||
filePath: '/repo',
|
||||
relativePath: 'Branch Changes (main)',
|
||||
worktreeId: 'wt-1',
|
||||
language: 'plaintext',
|
||||
mode: 'diff',
|
||||
diffSource: 'combined-branch',
|
||||
isDirty: false
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const snapshot = buildMobileSessionTabSnapshots(state)[0]
|
||||
|
||||
expect(snapshot?.tabs).toEqual([])
|
||||
expect(snapshot?.tabGroups).toBeUndefined()
|
||||
})
|
||||
|
||||
it('publishes a missing non-markdown editor with its unified tab id and split group', () => {
|
||||
const fileId = '/repo/src/app.ts'
|
||||
const state = makeState({
|
||||
|
||||
@@ -700,7 +700,11 @@ export function buildMobileSessionTabSnapshots(
|
||||
const unifiedTabByIdForWorktree = new Map(
|
||||
(state.unifiedTabsByWorktree[worktreeId] ?? []).map((tab) => [tab.id, tab])
|
||||
)
|
||||
const editorIds = openFileIndexes.idsByWorktree.get(worktreeId) ?? []
|
||||
const openFilesForWorktree = openFileIndexes.byWorktreeAndId.get(worktreeId)
|
||||
const editorIds = (openFileIndexes.idsByWorktree.get(worktreeId) ?? []).filter((fileId) => {
|
||||
const file = openFilesForWorktree?.get(fileId)
|
||||
return file ? isMobilePublishableOpenFile(file) : false
|
||||
})
|
||||
const publishableTerminalIds = [...terminalTabByIdForWorktree.values()]
|
||||
.filter((terminal) => !isWebOnlyMirroredTerminalTab(state, terminal))
|
||||
.map((terminal) => terminal.id)
|
||||
@@ -732,8 +736,8 @@ export function buildMobileSessionTabSnapshots(
|
||||
)
|
||||
)
|
||||
} else if (item.type === 'editor') {
|
||||
const file = openFileIndexes.byWorktreeAndId.get(worktreeId)?.get(item.id)
|
||||
if (!file) {
|
||||
const file = openFilesForWorktree?.get(item.id)
|
||||
if (!file || !isMobilePublishableOpenFile(file)) {
|
||||
continue
|
||||
}
|
||||
const markdown = buildMobileMarkdownTab(
|
||||
@@ -774,7 +778,6 @@ export function buildMobileSessionTabSnapshots(
|
||||
// Why: split-group projection can miss plain editor files during hydration.
|
||||
// Publish the missing file so paired mobile/web clients still mirror it.
|
||||
const fallbackEditorTabs: FallbackEditorTabTarget[] = []
|
||||
const openFilesForWorktree = openFileIndexes.byWorktreeAndId.get(worktreeId)
|
||||
if (openFilesForWorktree) {
|
||||
const unifiedEditorTabs = getEditorUnifiedTabsForWorktree(state, worktreeId)
|
||||
const unifiedEditorFileIds = new Set(unifiedEditorTabs.map((tab) => tab.entityId))
|
||||
@@ -783,7 +786,7 @@ export function buildMobileSessionTabSnapshots(
|
||||
continue
|
||||
}
|
||||
const file = openFilesForWorktree.get(unifiedTab.entityId)
|
||||
if (!file) {
|
||||
if (!file || !isMobilePublishableOpenFile(file)) {
|
||||
continue
|
||||
}
|
||||
const markdown = buildMobileMarkdownTab(
|
||||
@@ -802,6 +805,9 @@ export function buildMobileSessionTabSnapshots(
|
||||
emittedEditorTabIds.add(unifiedTab.id)
|
||||
}
|
||||
for (const file of openFilesForWorktree.values()) {
|
||||
if (!isMobilePublishableOpenFile(file)) {
|
||||
continue
|
||||
}
|
||||
if (emittedEditorFileIds.has(file.id)) {
|
||||
continue
|
||||
}
|
||||
@@ -1435,6 +1441,23 @@ function isMobileFileDiffSource(
|
||||
return diffSource === 'staged' || diffSource === 'unstaged'
|
||||
}
|
||||
|
||||
function isMobileUnsupportedCombinedDiffSource(
|
||||
diffSource: AppState['openFiles'][number]['diffSource']
|
||||
): boolean {
|
||||
return (
|
||||
diffSource === 'combined-all' ||
|
||||
diffSource === 'combined-uncommitted' ||
|
||||
diffSource === 'combined-branch' ||
|
||||
diffSource === 'combined-commit'
|
||||
)
|
||||
}
|
||||
|
||||
function isMobilePublishableOpenFile(file: AppState['openFiles'][number]): boolean {
|
||||
// Why: combined diff tabs use display labels as relative paths and require
|
||||
// the desktop combined renderer; mobile would otherwise try files.read.
|
||||
return !isMobileUnsupportedCombinedDiffSource(file.diffSource)
|
||||
}
|
||||
|
||||
function buildMobileBrowserTab(
|
||||
state: AppState,
|
||||
workspace: NonNullable<AppState['browserTabsByWorktree'][string]>[number],
|
||||
|
||||
Reference in New Issue
Block a user