Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 11 additions & 28 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ file is the human-readable summary of what changed and why.

### Desktop / Web UI

- **Session rows have a ⋮ menu** — every session in the sidebar's Recents and on
the **View all** list now carries a vertical three-dot button at its right
edge, appearing on hover. It opens the same menu the ⋯ button beside a session
title opens: **Rename**, **Share…** (only where sharing is enabled),
**Archive**, **Delete…**. Renaming edits the row's label in place — Enter
saves, Esc cancels — instead of taking you into the session first; deleting
still asks for confirmation and takes the session's children with it. Sharing
from a row opens the session and its share popover, because the share state
is not carried by the list. Previously the only way to rename, archive or
delete was to open the session and use the menu next to its title.

- **The sidebar collapses, and Search opens the recents list** — two buttons join
the titlebar. The leftmost one hides and restores the sidebar, so a session can
have the full window width; it remembers the choice for next launch, and it
Expand All @@ -20,8 +31,6 @@ file is the human-readable summary of what changed and why.
app menu now works too — it had no effect on this layout, since the command it
dispatches was only ever registered by the old one.

### Desktop / Web UI

- **The sidebar is always on screen, and it carries your recent sessions** —
the Projects list plus Settings and Help used to be a column belonging to the
home screen, so opening a session left you with no navigation but the tab bar.
Expand All @@ -34,32 +43,6 @@ file is the human-readable summary of what changed and why.
screen, unchanged from today, now framed by the sidebar. Below a narrow window
width the sidebar hides and the home screen keeps its previous stacked layout.

- **The desktop app opens on a new session** — launching used to drop you on a
list of past work. It now opens a fresh composer, reusing an existing empty
draft rather than accumulating one per launch. This replaces reopening the
screen the window was last on; that session is one click away in Recents, and
the tab bar still restores it. The browser UI is unaffected — there, `/` is a
URL you asked for, so it keeps showing the recents screen.

- **The channel badge moved to the bottom of the sidebar** — the blue **DEV**
(or **BETA**) tag used to sit at the far left of the titlebar, pushing the
Home button along with it. It now sits under Help at the foot of the sidebar,
and Home leads the titlebar. On a dev build the badge still toggles the debug
bar. Release builds show no badge, as before, and the sidebar closes the gap
rather than leaving a hole where it would have been.

- **The new-session screen sits on a card, like every other screen** — it was
painted in the same tone as the window chrome, so next to the sidebar it read
as empty space rather than as the screen you are on, while sessions and the
recents list floated on a raised white card. It now uses that same card.

- **The Home button goes to a new session** — it used to toggle between the
recent-sessions list and whichever tab you came from, which no longer matches
what the home screen is. It (and `mod+b`) now takes you to a new session,
selecting an already-open empty draft rather than opening another, and it
lights up while you are on one. The full list is still a click away under
**View all**.

## 1.18.4-8

### Agent
Expand Down
2 changes: 2 additions & 0 deletions DIVERGENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ from the squash message first, or use a plain merge.
| `packages/app/src/components/titlebar.tsx` | Two changes, both to the **v2 titlebar branch only** (`useV2Titlebar()`); the legacy branch below it is untouched. (1) The Home button (and its `home.toggle` command, `mod+b`) opens a new session instead of toggling between `/` and the last active tab: `tabs.toggleHome(...)` becomes a `goHome` that selects an already-open draft if there is one and otherwise falls through to the existing `openNewTab()` project-resolution chain. Its pressed / `aria-pressed` state keys on `layout.route().type === "draft"` rather than `"home"`. The icon, label (`home.title`) and keybind are unchanged, as is `tabs.toggleHome` itself, which is simply no longer called. (2) `<ChannelIndicator>` is dropped from that row and the component gains an `export`, so the sidebar can render the DEV/BETA badge at its bottom instead; `Titlebar` keeps its `debugTools` prop because the legacy branch still renders the badge inline. (3) Two buttons added to the row: a sidebar collapse toggle (`sidebar-right` icon, `data-action="titlebar-sidebar-toggle"`, `pressed` while open) as its **first** child, ahead of the `windows() || linux()` `WindowsAppMenu`; and a Search button (`magnifying-glass`, `data-action="titlebar-search"`) immediately after Home, navigating to `/?focus=search`. The toggle reads the fork-only `useAppSidebar()` and is wrapped in `<Show when={appSidebar}>`, which is what keeps it out of the legacy shell. Labels reuse the existing `command.sidebar.toggle` and `home.sessions.search.placeholder` keys — no new i18n. | The home screen is a new session in this fork, so Home has to go there; toggling into the recent-sessions list contradicted that. Reuse-before-create keeps repeated presses from stacking up draft tabs — unlike the New session button, which is expected to always make a new one. Moving the badge lets Home lead the titlebar (measured: x 137 → 92 on macOS, the traffic-light inset). | Keep our `goHome` and the removed indicator. If upstream reworks the titlebar, re-apply both rather than restoring `toggleHome` or the inline badge. If upstream deletes `tabs.toggleHome`, nothing here breaks. Do not remove `Titlebar`'s `debugTools` prop — the legacy titlebar still needs it. Keep `useAppSidebar()` optional-by-design: `useV2Titlebar()` is just `newLayoutDesigns()`, so this titlebar also renders inside the legacy shell, which has no provider — swapping it for `createSimpleContext` would throw there (verified: with the new layout off, the legacy shell renders its own rail, no toggle, and no exception). |
| `packages/app/src/pages/layout-new.tsx` (again) | Mounts the fork-only `<LaunchNewSession />`, which on desktop redirects one time per boot to a new-session draft (reusing an existing empty draft rather than stacking one up per launch). It pins its decision to the pathname the window came up on and disarms as soon as anything navigates, so it can never hijack a later visit to `/` — the sidebar's "View all" links there. Desktop-only: in the browser there is no "launch" distinct from "navigate to /", so redirecting would make the recents screen unreachable by URL and would break two `packages/app/e2e` specs that `goto("/")`. | Launching should put you in front of a prompt, the way Claude Desktop does, rather than on a list. This supersedes the desktop's restore-last-screen behaviour (`getLastActiveUrl`, `packages/desktop/src/renderer/index.tsx`); the previous session stays one click away in Recents and its tab is still restored. | Keep the mount. If upstream restructures this layout, re-add it. Do not "simplify" the boot-window guard into a plain `location.pathname === "/"` check — that is the bug it exists to prevent. |
| `packages/app/src/pages/layout-new.tsx`, `packages/app/src/pages/home.tsx`, `packages/app/src/i18n/{en,es}.ts` | **Persistent app sidebar.** Upstream's project column is an `<aside>` owned by `NewHome`, so it exists only on `/`. It becomes app chrome: `layout-new.tsx` wraps its `<main>` in a row flex and renders the fork-only `<AppSidebar class="hidden lg:flex">` beside it, so the sidebar survives every navigation. **The row components stay in `home.tsx`** — `HomeUtilityNav`, `HomeServerRow`, `HomeProjectList`, `HomeProjectEmpty`, `HomeRecentlyClosedRow` and the classes `HOME_PROJECT_NAV_ROW` / `HOME_PROJECT_NAV_LABEL` / `HOME_SECTION_LABEL` gain an `export` and nothing else, so upstream edits to them still apply cleanly; the fork-only `src/components/app-sidebar.tsx` imports and composes them, adding only the column shell and the Recents section. `home.tsx` otherwise loses just `HomeProjectColumn` (dead once the sidebar owns that composition) and the `NewHome` selection/action block, and its grid collapses from `lg:grid-cols-[280px_minmax(0,720px)]` to one `max-w-[760px]` column. The sub-`lg` `HomeUtilityNav` mount is untouched, so the stacked mobile layout is upstream's. The state both screens need (`focusedServer`, `projects`, `selectedProject`, `newSessionProject`, `projectDirectories`, the session-index query, `openNewSession`, `openProjectNewSession`, `openSession`, `selectProject`, `addProjects`, `editProject`, `closeProject`, `unseenCount`, `clearNotifications`, `chooseProject`, `isBackgroundOpen`, `buildHomeSessionRecords`, `HomeSessionRecord`) moves to fork-only `src/pages/home-model.tsx`, which both callers instantiate — safe because the selection lives in `useLayout().home`, the index is one TanStack query deduped by key, and the server-normalizing effect is idempotent. New i18n keys `sidebar.recents`, `sidebar.recents.new`, `sidebar.recents.viewAll` in `en` + `es`. `layout-new.tsx` additionally wraps its shell in the fork-only `<AppSidebarProvider>` (so the titlebar toggle and the sidebar share one collapse state), `AppSidebar` renders nothing while collapsed, and `NewHome` consumes a `?focus=search` param — clearing it after use, the way `pages/new-session.tsx` handles `?prompt` — to focus the search field for the titlebar's Search button. That focus ref changed from a `let` to a signal because `HomeSessionSearch` binds it from `onMount`, which runs after `NewHome`'s effects, so a plain ref is still undefined when the param arrives. `AppSidebarProvider` also registers the `sidebar.toggle` command (no keybind — `mod+b` is Home's here, unlike in the legacy layout), which is what the app menu's View → Toggle Sidebar dispatches; only `LegacyLayout` registered it before, so that item did nothing on this layout. It lives on the provider, not on `AppSidebar`, so collapsing does not unregister the command that undoes it. Both shells can be mounted at once on `/:dir` routes, so the id may be registered twice there; the command registry keeps the first entry, which is the outer (new-layout) one. Every `data-component`/`data-action` hook is untouched (`home-project-row`, `home-add-project`, `home-session-row`, `home-session-search`, …) because `packages/app/e2e` selects on them. | The desktop app should navigate like Claude Desktop — one always-visible sidebar with Projects, Recents and pinned Settings/Help — instead of losing all navigation the moment a session opens. Exporting the row components in place rather than relocating them keeps `home.tsx` down to ~36 added lines: upstream changes to those components merge without a conflict, which relocating them would have forfeited. | Keep our structure. On conflict take upstream's `home.tsx` wholesale and re-apply the four edits: the `export` keywords, the `HomeProjectColumn` deletion, the `createHomeModel()` swap in `NewHome`, and the single-column grid. If upstream edits an exported row component, just take it. Never let a `data-component`/`data-action` hook drift — the e2e suite has no other handle on these rows. |
| `packages/app/src/pages/session/timeline/message-timeline.tsx` | **Session actions menu extracted.** The ⋯ menu beside the session title — both renderings, the legacy `DropdownMenu` and the v2 `MenuV2`, ~145 lines — and the `DialogDeleteSession` closure move verbatim to the fork-only `packages/app/src/components/session-actions-menu.tsx`, and this file renders `<SessionActionsMenu>` instead, passing its existing `openTitleEditor` / share / `archiveSession` / `deleteSession` as callbacks and its trigger element out through `triggerRef` (the share popover still anchors to it). The extracted dialog takes a resolved `title` and an `onConfirm` rather than a `sessionID`, so the caller supplies `sessionTitle(sync().session.get(id)?.title)`. The `title` store loses `pendingRename`/`pendingShare`: deferring Rename and Share until the menu's `onCloseAutoFocus` is now the component's job, since every caller needs it (a list row's inline editor is blurred by the returning focus exactly as the header's was). Also gains one fork-only `createEffect` that consumes `consumeSessionShareRequest(sessionID())` and opens the share popover — the session rows' Share routes through it. | The sidebar's Recents rows and the home session list open the same menu; three copies of four items would drift. Only this file rendered the menu, so extraction is the smallest way to share it. | Keep the extraction. On conflict, take upstream's `message-timeline.tsx` wholesale and re-apply: delete both inline menu blocks and the local `DialogDeleteSession`, mount `<SessionActionsMenu>` with the same callbacks, drop the two `pending*` store fields, and re-add the share-request effect. If upstream adds a menu item, add it to `session-actions-menu.tsx` (both variants) rather than back here. Do not "simplify" the component's deferred rename/share into a plain `onSelect` — focus return is what it exists to survive. |
| `packages/app/src/pages/home.tsx` | `HomeSessionRow` gains the same `<SessionActionsMenu>` (hover/focus/menu-open revealed, vertical dots) and inline rename: while renaming, the row renders a `div` with `InlineEditor` instead of the `button`, because an input inside a button is invalid markup and swallows keystrokes into the open-session handler. `NewHome` holds one `createInlineEditorController()` for the list and passes it plus the model down. Its local `archiveSession` is deleted — `createHomeModel()` owns `archiveSession`/`renameSession`/`deleteSession` now, so the sidebar and this screen run one implementation (extends the "state both screens need moves to home-model.tsx" split in the persistent-sidebar row above); the call site becomes `model.archiveSession`. Upstream's `SHOW_HOME_SESSION_ARCHIVE` block is left exactly as-is — the flag is `false`, so it renders nothing, and touching it would widen the diff for no gain. `data-component="home-session-row"` and every other selector are untouched (`packages/app/e2e` binds to them); the menu adds `data-action="session-menu"`. | The Recents rows and "View all" are the same list at two sizes; a menu on one and not the other makes "View all" a dead end. | Keep our row structure. On conflict take upstream's row and re-apply the menu, the editing branch, and the `model.*` action wiring. Never let a `data-component`/`data-action` hook drift. If upstream re-enables `SHOW_HOME_SESSION_ARCHIVE`, drop that block instead — its absolutely-positioned archive button would sit on top of the menu. |
| `packages/desktop/icons/{dev,beta,prod}/` (all PNGs, `icon.icns`, `icon.ico`, `dock.png`), `packages/desktop/icons/README.md` | Regenerated from the fork-only `packages/desktop/icons/icon.svg` by the fork-only `packages/desktop/scripts/generate-icons.ts`: the brand-red `#ee0033` CoDev "C" — the `--mini` splash badge glyph, at the VS Code extension icon's proportions (unit = 120/1024, mark 480x600 centered) — on a white tile, replacing upstream's black/blueprint "o" mark. All three channels are byte-identical for now (chosen deliberately over upstream's per-channel treatments); the generator still writes them separately so a channel can diverge later. `icon.icns` members and `dock.png` use the macOS Big Sur grid (824/1024 inset + drop shadow); Windows, Linux and Store assets stay full-bleed. README rewritten from the Tauri-CLI + Image2Icon recipe to the generator. The stale Tauri-era `android/` and `ios/` subfolders are left untouched — nothing in the Electron build reads them. | Closes the "desktop app icons need design assets" rebrand gap: the Dock/taskbar icon was still upstream's mark. | Keep our assets and README (binary: take ours wholesale). Regenerate via the script rather than hand-editing; if upstream adds an icon size, add it to `FLAT_PNGS`/`ICONSET` and rerun. |
| `packages/tui/src/theme/assets/codev.json` (new file), `packages/tui/src/theme/index.ts`, `packages/tui/src/context/theme.tsx` | Added the `codev` theme — upstream's `opencode.json` palette with `darkSecondary` → `#0891b2` (brand teal) — registered it in the theme index, and made it the default/fallback theme (`"opencode"` → `"codev"` in the store default, kv fallback, and load-failure fallbacks). `theme/assets/opencode.json` itself matches upstream again. | Brand accent lives in a fork-owned theme instead of edits to upstream's palette; the default theme carries the brand. | Keep our theme file, its index registration, and the fallback strings; when upstream changes the opencode palette, mirror it into `codev.json` (keeping our `darkSecondary`). |
| `packages/opencode/src/cli/ui.ts` | `wordmark`/`logo()` render the lowercase codev wordmark via `ansiWordmark` (bold, no shadow, "dev" in brand red on TTY) | Help banner matches the TUI home banner. | Keep our wordmark + logo(); take upstream's surrounding changes. |
Expand Down
Loading
Loading