diff --git a/DIVERGENCES.md b/DIVERGENCES.md index 9594066b33..1bbc1c3e7a 100644 --- a/DIVERGENCES.md +++ b/DIVERGENCES.md @@ -158,7 +158,7 @@ from the squash message first, or use a plain merge. | `packages/desktop/src/main/index.ts`, `packages/desktop/src/main/windows.ts` | APP_NAMES + window title → "CoDev Code" (Dev/Beta variants too) | Desktop app display name. | Keep our names. | | `packages/desktop/electron-builder.config.ts` | `productName` ×3 → "CoDev Code…"; artifactName → `codev-code-desktop-…`; protocol display name. Auto-update `publish` targets repointed to the fork: beta `anomalyco/opencode-beta` and prod `anomalyco/opencode` both → `quickbeard/codev-code` (upstream has no fork-side beta repo, so the two channels share one). | Installer/product branding, and a packaged build must not offer upstream OpenCode releases as CoDev updates. appId (`ai.opencode.desktop`) and the `opencode://` deep-link scheme stay upstream — identity plumbing wired into main/index.ts and app deep-links; do not rename casually. `rpm.packageName` (`opencode`/`opencode-beta`/`opencode-dev`) also stays — it names the installed Linux package, not a publish target. | Keep our names and publish targets; take upstream's other config. Two known follow-ups, both moot while the fork ships no desktop build: beta and prod now write the same `latest.yml` in one repo (splitting them needs `publish.channel` plus the hardcoded `autoUpdater.channel = "latest"` in `src/main/updater.ts`), and `codev-code` is private, which electron-updater cannot read without a token. | | `packages/desktop/src/renderer/index.tsx` | Desktop notification icon `https://opencode.ai/favicon-96x96-v3.png` → the relative `./favicon-96x96-v3.png`. The renderer's `publicDir` is `packages/app/public`, whose `favicon-96x96-v3.png` symlinks to the rebranded `packages/ui/src/assets/favicon/` mark, so the file is emitted next to `index.html` and resolves against the renderer origin (`oc://renderer/` packaged, the vite dev server otherwise) — the same asset and the same relative form `src/renderer/index.html` already uses for ``. | A desktop app should not reach out to a remote host to draw its own notification icon (it fails offline and leaks a request per notification), and the remote file is upstream-branded while the bundled one is the codev mark. | Keep our relative path. If upstream changes the URL, re-point it at the bundled asset rather than taking a new remote host. `packages/app/src/entry.tsx` and `pages/layout/helpers.ts` keep their remote `opencode.ai/favicon*` sources — same bug class, not yet fixed. | -| `packages/ui/src/assets/favicon/` (favicon-v3.svg, site.webmanifest, favicon-96x96-v3.png, apple-touch-icon-v3.png, web-app-manifest-192/512.png) | New codev mark: blocky "C" in #00cdcd on dark; manifest name "CoDev Code"/"codev" | Web/desktop favicon + PWA branding (served via packages/app/public symlinks). | Keep our assets (binary: take ours wholesale). | +| `packages/ui/src/assets/favicon/` (favicon-v3.svg, favicon-v3.ico, site.webmanifest, favicon-96x96-v3.png, apple-touch-icon-v3.png, web-app-manifest-192/512.png) | New codev mark: the blocky "C" in brand red `#ee0033` on a white tile, generated from the same geometry as the app icon by `packages/desktop/scripts/generate-icons.ts` (4x5 grid, one-unit stroke, unit = 120/1024, corner radius 229/1024); `favicon-v3.svg` is the hand-written 512-unit source of that geometry. The tab and `.ico` icons keep the rounded tile so they read as an app icon; `apple-touch-icon-v3.png` and the two maskable `web-app-manifest-*` icons are square and full-bleed, because iOS and PWA launchers apply their own mask and a pre-rounded icon leaves transparent corners that render black. Manifest name "CoDev Code"/"codev"; its `theme_color`/`background_color` stay `#080808` — those describe the PWA's chrome and splash, not the icon. **Was `#00cdcd` on a dark tile** until this row was rewritten: PR #10 pinned the favicon to the then-cyan TUI banner accent, that banner later moved to the navy/red wordmark, and the favicon was left behind as the only cyan in the tree — visibly so on desktop, where the dock icon was red while the window and notification icons were cyan. | Every surface that draws the mark should draw the same mark: the dock icon, the tab, notifications, the `codev --mini` badge and the landing page icon are now one geometry in one red. Cyan on `#131010` was the higher-contrast tile at 16px (~9.4:1 versus red's ~4.2:1) — a real cost, accepted so the brand reads consistently. | Keep our assets (binary: take ours wholesale). Regenerate with the script rather than hand-editing, and edit `icons/icon.svg` + `favicon-v3.svg` together if the geometry ever changes. | | `AGENTS.md` | Default-branch note: `dev` → `main` (single merged line; upstream has two lines saying local `main` may not exist); added fork bullets requiring every upstream-file change to get a `DIVERGENCES.md` row (and matching en + es doc updates) in the same PR, and pointing agents at this file's Divergence policy (prefer config/plugins, then `packages/codev-*`, upstream edits last) and Syncing with upstream sections | The fork's default branch is `main` (see the workflow-triggers row); agents kept basing diffs on a nonexistent `dev`. Agents edit upstream files without recording the divergence — and don't apply the placement policy or sync runbook — unless the instructions file says to. | Keep our lines; take upstream's other guidance. | | `README.md` | Replaced with fork README | Fork identity, sync + divergence policy. | Keep ours entirely. | | `CONTRIBUTING.md`, `SECURITY.md` | Product-brand prose "OpenCode" → "CoDev Code"; built-CLI command examples `opencode …` → `codev …` | Docs people actually read should name the fork's product. Upstream issue/advisory links, `packages/opencode` paths, and build-output paths stay upstream; env-var mentions follow the env-var rename row. | Keep our strings; take upstream's structural changes. | diff --git a/packages/desktop/icons/README.md b/packages/desktop/icons/README.md index a11c05fe3b..69f09e4aee 100644 --- a/packages/desktop/icons/README.md +++ b/packages/desktop/icons/README.md @@ -12,9 +12,18 @@ The three channels are currently identical — the same red C on white ships as dev, beta and prod icon. `generate-icons.ts` still writes each channel separately, so giving a channel its own treatment later is a change to that script alone. +The same run also regenerates the web and PWA favicon set in +`packages/ui/src/assets/favicon/`, whose `favicon-v3.svg` is the hand-written 512-unit +copy of this geometry. One generator for both sets is deliberate: the dock icon and the +favicon drew different marks in different colors for a while, which is the drift a +shared source prevents. The tab and `.ico` icons keep the rounded tile; the +apple-touch and maskable manifest icons are square, because those platforms apply +their own mask and a pre-rounded icon leaves transparent corners that render black. + The generator rasterizes, encodes the PNGs and builds the `.ico` itself, so the only -external tool it needs is `iconutil` for `.icns` — which means it has to run on macOS. -This replaces the old Tauri-CLI + [Image2Icon](https://img2icnsapp.com/) workflow; +external tool it needs is `iconutil` for `.icns`. That one is macOS-only, so off macOS +the script skips `.icns` (leaving the committed file alone) and regenerates everything +else. This replaces the old Tauri-CLI + [Image2Icon](https://img2icnsapp.com/) workflow; the Big Sur inset and drop shadow that step used to add are now applied directly to the `.icns` members and to `dock.png` (824/1024 rounded square), while the Windows, Linux and Store assets stay full-bleed. diff --git a/packages/desktop/scripts/generate-icons.ts b/packages/desktop/scripts/generate-icons.ts index ba4183b7a8..0752c3ba8c 100644 --- a/packages/desktop/scripts/generate-icons.ts +++ b/packages/desktop/scripts/generate-icons.ts @@ -1,5 +1,10 @@ -// Fork: regenerates every app icon in icons/{dev,beta,prod}/ from the geometry -// in icons/icon.svg — the brand-red CoDev "C" on a white tile. +// Fork: regenerates every app icon in icons/{dev,beta,prod}/ — and the web/PWA +// favicon set in packages/ui/src/assets/favicon/ — from the geometry in +// icons/icon.svg: the brand-red CoDev "C" on a white tile. +// +// Both sets come from this one script on purpose. They drew different marks in +// different colors for a while (dock icon red, favicon cyan), which is exactly +// the drift a shared generator prevents. // // Replaces the manual Tauri-CLI + Image2Icon workflow the old icons/README.md // described. Everything here is self-contained (raw rasterizer, PNG encoder, ICO @@ -21,14 +26,17 @@ const CORNER = 229 / 1024 // shadow; anything full-bleed reads as oversized next to native icons. const MACOS_TILE = 824 / 1024 -type Style = "flat" | "macos" +// "square" is full-bleed with no corner radius: iOS rounds apple-touch-icon +// itself and a pre-rounded one leaves transparent corners that render black, +// and maskable PWA icons are cropped by the launcher for the same reason. +type Style = "flat" | "macos" | "square" // Coverage of the rounded rect and of the "C" for one pixel, supersampled. function coverage(size: number, style: Style) { const samples = size <= 256 ? 8 : 4 const tile = size * (style === "macos" ? MACOS_TILE : 1) const origin = (size - tile) / 2 - const radius = tile * CORNER + const radius = style === "square" ? 0 : tile * CORNER const unit = tile * UNIT const mark = { x: origin + (tile - unit * 4) / 2, @@ -227,6 +235,19 @@ const FLAT_PNGS = [ const ICO_SIZES = [16, 24, 32, 48, 64, 128, 256] +// The web + PWA favicon set, served out of packages/app/public through symlinks. +// favicon-v3.svg next to these is the hand-written source of the same geometry. +// The tab/`.ico` icons keep the rounded tile so they read as an app icon; the +// apple-touch and maskable manifest icons are square, since their platforms +// apply their own mask. +const FAVICON_DIR = "../ui/src/assets/favicon" +const FAVICON_PNGS: ReadonlyArray = [ + ["favicon-96x96-v3.png", 96, "flat"], + ["apple-touch-icon-v3.png", 180, "square"], + ["web-app-manifest-192x192.png", 192, "square"], + ["web-app-manifest-512x512.png", 512, "square"], +] + // Apple's required iconset members: {logical size, @2x?}. const ICONSET = [16, 32, 128, 256, 512].flatMap((n) => [ { name: `icon_${n}x${n}.png`, size: n }, @@ -250,12 +271,24 @@ for (const channel of ["dev", "beta", "prod"]) { await Bun.write(`${dir}/icon.ico`, ico(ICO_SIZES.map((size) => ({ size, data: flat.get(size)! })))) await Bun.write(`${dir}/dock.png`, macos.get(256)!) - const iconset = `${dir}/icon.iconset` - await rm(iconset, { recursive: true, force: true }) - await mkdir(iconset, { recursive: true }) - await Promise.all(ICONSET.map((entry) => Bun.write(`${iconset}/${entry.name}`, macos.get(entry.size)!))) - await $`iconutil -c icns -o ${dir}/icon.icns ${iconset}` - await rm(iconset, { recursive: true, force: true }) + // iconutil ships with macOS only, so everything else regenerates on any + // platform and the committed .icns is left as is. + if (process.platform === "darwin") { + const iconset = `${dir}/icon.iconset` + await rm(iconset, { recursive: true, force: true }) + await mkdir(iconset, { recursive: true }) + await Promise.all(ICONSET.map((entry) => Bun.write(`${iconset}/${entry.name}`, macos.get(entry.size)!))) + await $`iconutil -c icns -o ${dir}/icon.icns ${iconset}` + await rm(iconset, { recursive: true, force: true }) + } - console.log(`Generated ${channel} icons in ${dir}`) + console.log( + `Generated ${channel} icons in ${dir}${process.platform === "darwin" ? "" : " (icon.icns skipped, needs macOS)"}`, + ) } + +await Promise.all( + FAVICON_PNGS.map(([name, size, style]) => Bun.write(`${FAVICON_DIR}/${name}`, png(render(size, style), size))), +) +await Bun.write(`${FAVICON_DIR}/favicon-v3.ico`, ico(ICO_SIZES.map((size) => ({ size, data: flat.get(size)! })))) +console.log(`Generated favicons in ${FAVICON_DIR}`) diff --git a/packages/ui/src/assets/favicon/apple-touch-icon-v3.png b/packages/ui/src/assets/favicon/apple-touch-icon-v3.png index 0d398245ac..107c4126c6 100644 Binary files a/packages/ui/src/assets/favicon/apple-touch-icon-v3.png and b/packages/ui/src/assets/favicon/apple-touch-icon-v3.png differ diff --git a/packages/ui/src/assets/favicon/favicon-96x96-v3.png b/packages/ui/src/assets/favicon/favicon-96x96-v3.png index 2af0e7f87f..ca3a5d76fd 100644 Binary files a/packages/ui/src/assets/favicon/favicon-96x96-v3.png and b/packages/ui/src/assets/favicon/favicon-96x96-v3.png differ diff --git a/packages/ui/src/assets/favicon/favicon-v3.ico b/packages/ui/src/assets/favicon/favicon-v3.ico index 34ca0b9c01..07e53246bc 100644 Binary files a/packages/ui/src/assets/favicon/favicon-v3.ico and b/packages/ui/src/assets/favicon/favicon-v3.ico differ diff --git a/packages/ui/src/assets/favicon/favicon-v3.svg b/packages/ui/src/assets/favicon/favicon-v3.svg index aba6d7787e..e2f166f66a 100644 --- a/packages/ui/src/assets/favicon/favicon-v3.svg +++ b/packages/ui/src/assets/favicon/favicon-v3.svg @@ -1,6 +1,18 @@ - - - - - + + + + + + + + + diff --git a/packages/ui/src/assets/favicon/web-app-manifest-192x192.png b/packages/ui/src/assets/favicon/web-app-manifest-192x192.png index d88c83f86f..0b19a6c5fe 100644 Binary files a/packages/ui/src/assets/favicon/web-app-manifest-192x192.png and b/packages/ui/src/assets/favicon/web-app-manifest-192x192.png differ diff --git a/packages/ui/src/assets/favicon/web-app-manifest-512x512.png b/packages/ui/src/assets/favicon/web-app-manifest-512x512.png index 20559c8604..c174dfb8c4 100644 Binary files a/packages/ui/src/assets/favicon/web-app-manifest-512x512.png and b/packages/ui/src/assets/favicon/web-app-manifest-512x512.png differ