fix: harden and de-slop the merged sidebar/chat/settings batch

Post-merge follow-ups for #2740 #2735 #2734 #2690 #2676 #2738 #2684
#2689 #2733 #2739 #2462 #2687 #2736 #2618 #2697, plus three regressions
found while reviewing them:

- ctrl/cmd+digit while typing no longer switches session tabs (#2503 was
  still open in practice: the guard only covered the mod+alt surface binding)
- Shiki template-call sanitizer now covers every bundled grammar, including
  the js/ts aliases and embedding grammars; timed-out highlight requests are
  memoized and no longer cancel unrelated in-flight requests
- settings flush on suspend uses keepalive and also fires on Capacitor
  appStateChange; keeps the selected model persisted across mode switches
- remote-only branches fetch before checkout; range helpers fail clearly
- git status invalidation now fires for runtime adapters too
- settings number inputs and select triggers size in ch so they scale with
  the interface font
- recent-activity timestamps tick from one list-level ticker
- Markdown preview find goes through the shared find_in_file keybind with
  containment, no longer counts its own bar, and debounces observer runs
- #2676 reverted; #2524 fixed by fading the sticky header's own background
  instead of overlaying the content below it
- sticky group headers in the model picker and sidebar render again
  (oc-sticky-fade-scroller class restored after 9b9d7069c)
- project switcher names are left-aligned again (wrapper lost in 26dbc2f30)
- tool card quick-open icon is always visible and opens the same line as the
  expanded card's button
- tautological tests replaced or removed; new oxlint findings fixed
This commit is contained in:
Bohdan Triapitsyn
2026-08-29 01:06:43 +03:00
parent a182f4f4ff
commit 48bcac1758
53 changed files with 1125 additions and 375 deletions
+39 -4
View File
@@ -2599,6 +2599,25 @@ export async function getUntrackedDiffs(directory, filePaths = [], { concurrency
return results;
}
const refResolvesToCommit = async (git, ref) => git
.raw(['rev-parse', '--verify', '--quiet', `${ref}^{commit}`])
.then((value) => Boolean(String(value || '').trim()))
.catch(() => false);
/**
* The branch list includes remote-only branches that `ls-remote` reported but
* the repository never fetched (#2098), so a comparison can name a ref that does
* not exist locally. Say that plainly instead of letting git's "ambiguous
* argument" surface as an opaque failure.
*/
async function assertRangeRefsResolve(git, refs) {
for (const ref of refs) {
if (!(await refResolvesToCommit(git, ref))) {
throw new Error(`Ref "${ref}" is not available locally. Fetch it before comparing.`);
}
}
}
export async function getRangeDiff(directory, { base, head, path: filePath, contextLines = 3 } = {}) {
const { directoryPath, directoryGit, repoRoot, git } = await createRepositoryGitContext(directory);
const baseRef = typeof base === 'string' ? base.trim() : '';
@@ -2641,6 +2660,8 @@ export async function getRangeDiff(directory, { base, head, path: filePath, cont
}
}
await assertRangeRefsResolve(git, [resolvedBase, headRef]);
const args = ['diff', '--no-color'];
if (typeof contextLines === 'number' && !Number.isNaN(contextLines)) {
args.push(`-U${Math.max(0, contextLines)}`);
@@ -2741,6 +2762,8 @@ export async function getRangeFiles(directory, { base, head } = {}) {
// ignore
}
await assertRangeRefsResolve(git, [resolvedBase, headRef]);
// `-C` (copy detection among changed files only, so cheap) makes copies
// surface as C entries instead of plain additions; rename detection is on
// by default.
@@ -3824,10 +3847,6 @@ const resolveBranchCheckoutTarget = async (git, branchName) => {
}
const remoteRef = requested.replace(/^remotes\//, '');
if (!(await gitRefExists(git, `refs/remotes/${remoteRef}`))) {
return asRequested;
}
const remotes = await git.getRemotes();
const remote = remotes.find((entry) => entry?.name && remoteRef.startsWith(`${entry.name}/`));
if (!remote) {
@@ -3840,6 +3859,22 @@ const resolveBranchCheckoutTarget = async (git, branchName) => {
return asRequested;
}
// The branch list also carries branches that only `ls-remote` knows about
// (#2098): they exist on the remote but were never fetched, so there is no
// remote-tracking ref and a literal checkout fails with a pathspec error.
// Fetch the single branch first so the tracking ref exists, then fall through
// to the normal create-with-tracking path.
if (!(await gitRefExists(git, `refs/remotes/${remoteRef}`))) {
try {
await git.fetch(remote.name, localBranch);
} catch (error) {
throw new Error(`Failed to fetch ${localBranch} from ${remote.name}: ${error?.message || error}`);
}
if (!(await gitRefExists(git, `refs/remotes/${remoteRef}`))) {
throw new Error(`Branch ${localBranch} no longer exists on remote ${remote.name}`);
}
}
const localExists = await gitRefExists(git, `refs/heads/${localBranch}`);
return { branch: localBranch, remoteRef: localExists ? null : remoteRef };
};