From 288ec5a597658383f7c4d52abb6c19a4c1a18803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20Gro=C3=9F?= Date: Wed, 22 Jul 2026 13:02:18 +0200 Subject: [PATCH] Add descriptive Codiff window titles --- electron/__tests__/window-title.test.ts | 54 +++++++++++++++++++++++++ electron/main.cjs | 13 ++++-- electron/window-title.cjs | 27 +++++++++++++ 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 electron/__tests__/window-title.test.ts create mode 100644 electron/window-title.cjs diff --git a/electron/__tests__/window-title.test.ts b/electron/__tests__/window-title.test.ts new file mode 100644 index 00000000..79a395c9 --- /dev/null +++ b/electron/__tests__/window-title.test.ts @@ -0,0 +1,54 @@ +import { createRequire } from 'node:module'; +import { expect, test } from 'vite-plus/test'; + +const require = createRequire(import.meta.url); +const { getRepositoryWindowTitle } = require('../window-title.cjs') as { + getRepositoryWindowTitle: (state: { + root: string; + source: + | { type: 'working-tree' } + | { ref: string; type: 'branch-working-tree' } + | { ref: string; type: 'commit' } + | { number?: number; type: 'pull-request'; url: string } + | { base: string; head: string; symmetric: boolean; type: 'range' }; + }) => string; +}; + +const root = '/Users/reviewer/Documents/GitHub/MyCoolRepo'; + +test('titles windows with the repository and selected source', () => { + expect(getRepositoryWindowTitle({ root, source: { type: 'working-tree' } })).toBe( + 'Codiff – MyCoolRepo', + ); + expect( + getRepositoryWindowTitle({ + root, + source: { + number: 1337, + type: 'pull-request', + url: 'https://github.com/framer/MyCoolRepo/pull/1337', + }, + }), + ).toBe('Codiff – MyCoolRepo/1337'); + expect( + getRepositoryWindowTitle({ + root, + source: { type: 'pull-request', url: 'https://github.com/framer/MyCoolRepo/pull/1338' }, + }), + ).toBe('Codiff – MyCoolRepo/1338'); + expect( + getRepositoryWindowTitle({ + root, + source: { ref: 'feature/new-title', type: 'branch-working-tree' }, + }), + ).toBe('Codiff – MyCoolRepo/feature/new-title'); + expect(getRepositoryWindowTitle({ root, source: { ref: 'a1b2c3d4', type: 'commit' } })).toBe( + 'Codiff – MyCoolRepo/a1b2c3d', + ); + expect( + getRepositoryWindowTitle({ + root, + source: { base: 'main', head: 'feature', symmetric: true, type: 'range' }, + }), + ).toBe('Codiff – MyCoolRepo/main...feature'); +}); diff --git a/electron/main.cjs b/electron/main.cjs index 1c09e4ae..801f202e 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -54,6 +54,7 @@ const { writeConfig, } = require('./config.cjs'); const { readReviewAssistantReply } = require('./review-assist.cjs'); +const { getRepositoryWindowTitle } = require('./window-title.cjs'); const { findMatchingWindowIdentity, getWindowIdentity, @@ -228,6 +229,12 @@ const getMarkdownDocumentContext = (webContentsId) => ({ /** @param {number} webContentsId @param {RepositoryState} state */ const storeResolvedRepositoryState = (webContentsId, state) => { windowRepositories.set(webContentsId, state.root); + const browserWindow = BrowserWindow.getAllWindows().find( + (window) => window.webContents.id === webContentsId, + ); + if (browserWindow && !browserWindow.isDestroyed()) { + browserWindow.setTitle(getRepositoryWindowTitle(state)); + } const launchOptions = windowLaunchOptions.get(webContentsId); if (launchOptions) { windowLaunchOptions.set(webContentsId, { @@ -839,9 +846,6 @@ const createWindow = ( minHeight: 520, minWidth: 880, show: false, - title: launchOptions.planFile - ? `Codiff Plan - ${basename(launchOptions.planFile)}` - : `Codiff - ${repositoryPath}`, titleBarStyle: useMacVibrancy ? 'hiddenInset' : 'default', ...(useMacVibrancy ? { @@ -993,6 +997,9 @@ const createWindow = ( if (!currentLaunchOptions?.planFile) { return; } + // The renderer's static HTML title replaces constructor titles during navigation. + // Set this after every plan load so native window lists keep the plan filename. + window.setTitle(`Codiff Plan – ${basename(currentLaunchOptions.planFile)}`); void readMarkdownDocument( { kind: 'plan', path: currentLaunchOptions.planFile }, getMarkdownDocumentContext(webContentsId), diff --git a/electron/window-title.cjs b/electron/window-title.cjs new file mode 100644 index 00000000..ef643907 --- /dev/null +++ b/electron/window-title.cjs @@ -0,0 +1,27 @@ +// @ts-check + +const { basename } = require('node:path'); +const { parseReviewUrl } = require('./review-source.cjs'); + +/** @param {import('../core/types.ts').ReviewSource} source */ +const getWindowSourceTitle = (source) => + source.type === 'working-tree' + ? null + : source.type === 'pull-request' + ? String(source.number ?? parseReviewUrl(source.url)?.number ?? 'PR') + : source.type === 'commit' + ? source.ref.slice(0, 7) + : source.type === 'range' + ? `${source.base}${source.symmetric ? '...' : '..'}${source.head}` + : source.ref; + +/** + * @param {import('../core/types.ts').RepositoryState} state + */ +const getRepositoryWindowTitle = (state) => { + // Use the resolved source so aliases such as HEAD and a PR URL become the view the user opened. + const sourceTitle = getWindowSourceTitle(state.source); + return `Codiff – ${basename(state.root)}${sourceTitle ? `/${sourceTitle}` : ''}`; +}; + +module.exports = { getRepositoryWindowTitle };