Repository navigation
fix(desktop): local-first project icons - #5845
Merged
Merged
Conversation
Kitenite
marked this pull request as ready for review
July 22, 2026 05:28
Contributor
Author
🚀 Preview Deployment🔗 Preview Links
Preview updates automatically with new commits |
|
Ready to review this PR? Stage has broken it down into 9 individual chapters for you: Chapters generated by Stage for commit d03dfe4 on Jul 28, 2026 10:28am UTC. |
Kitenite
force-pushed
the
triage/issue-5843-29860767946
branch
2 times, most recently
from
July 28, 2026 03:12
720f486 to
14f790a
Compare
Kitenite
force-pushed
the
triage/issue-5843-29860767946
branch
from
July 28, 2026 03:17
14f790a to
ca12aa8
Compare
Project icons were a cloud-only feature (v2Project.uploadIcon/resetIconToGitHub/ removeIcon keyed by v2Projects.id), but v2 projects are host-local — their id has no cloud row except for legacy cloud-created projects. So setting an icon failed with "Project not found" on every local-first project (#5843), and the uploaded icon was never displayed (the UI derived icons from repoOwner). Move project icons fully into the host-service local model and remove the dead cloud machinery. Host-service (local storage): - Add an `icon` column to the host `projects` table (migration 0012) and a `project.setIcon` mutation that writes via updateLocalProject (bumps updatedAt + broadcasts project:changed). Thread `icon` through project.list/get, ProjectSnapshot, and the useHostProjects merge layer. Desktop renderer: - Single resolveProjectIconUrl helper (custom icon -> GitHub avatar -> none), used by every project-icon surface: settings, dashboard sidebar, project list, task filter, recent projects, new-workspace picker, and the v2-workspaces list/header (V2WorkspaceProjectIcon now takes a resolved iconUrl). No site derives the URL from repoOwner anymore. - IconUploadField calls the host client, downscales the chosen image to a 128x128 PNG data-URI client-side (no cloud blob), and offers Upload / Reset. Mobile: - useHostProjects honors the host `icon` field for parity. Removals (cloud icon model is now unused): - Delete v2Project.uploadIcon/resetIconToGitHub/removeIcon and the dead GitHub-avatar icon hydration in create/linkRepoCloneUrl. - Delete the orphaned fetchAndStoreGitHubAvatar helper. - Drop the dead projectGithubOwner/githubOwner plumbing that only fed the icon. The cloud v2Projects.iconUrl column is left in place; dropping it needs the broader Electric/mobile teardown (see plans/remove-cloud-project-model.md). Verified end-to-end via CDP: setting an icon in settings updates the sidebar and workspace list live; reset reverts to the GitHub avatar; no "Project not found". Closes #5843
Kitenite
force-pushed
the
triage/issue-5843-29860767946
branch
from
July 28, 2026 10:27
ca12aa8 to
d03dfe4
Compare
Merged
7 tasks
Kitenite
added a commit
that referenced
this pull request
Aug 7, 2026
… v1 import carry-over (#6249) * feat(desktop,host-service): v2 project colors — icon+color picker, v1 import carry-over - host-service: add projects.color column (migration 0015), thread it through ProjectSnapshot / project.list / project.get, and add a project.setColor mutation mirroring setIcon - v1→v2 import: carry the v1 accent color onto the imported v2 project (best-effort, both the auto-migrator and the wizard path via importV1Project); 'default' sentinel stays unset - v2 settings: extend IconUploadField into a simple icon+color picker — color swatches (ColorSelector) plus a lucide glyph grid baked into the existing setIcon data-URI path, alongside upload/reset - render the accent color on the v2 ProjectThumbnail (tinted border and letter fallback, matching v1) in project settings, the settings project list, and the dashboard sidebar The 'Remove icon' tRPC error (v2/project/removeIcon) was already fixed on main by #5845; no call sites remain and reset goes through project.setIcon(null). * feat(desktop,host-service): allow removing the project icon with a v1-style letter fallback - setIcon accepts a 'none' sentinel: explicitly no icon, suppressing the GitHub avatar fallback so every surface renders the first-letter tile (tinted by the project color) via resolveProjectIconUrl — v1's hide_image equivalent - picker gains 'Remove icon' (when any icon shows) alongside 'Reset to default'; the trigger thumbnail now renders ProjectThumbnail, so an icon-less project shows its letter tile instead of a placeholder - v1→v2 import carries hide_image as the 'none' icon * fix(desktop): gate glyph re-bake on persisted color and disable swatches while pending Review follow-ups (Greptile/CodeRabbit/cubic): - setIcon/setColor return success; a rejected color no longer re-bakes the session glyph into a color the project never stored, and a failed setIcon no longer marks the glyph as session-active - ColorSelector gains a disabled prop; the picker disables swatches during mutations so rapid clicks can't land out of order - ProjectThumbnail accepts only exact #rrggbb before tinting (hexToRgba slices fixed offsets; malformed values now render as unset)
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The v2 project icon picker (
IconUploadField) called the cloudv2Project.uploadIcon/resetIconToGitHub/removeIconmutations, which are keyed byv2Projects.id. But v2 projects are host-local (useHostProjectsfan-out overclient.project.list) — their id has no cloudv2Projectsrow except for legacy cloud-created projects. So setting an icon failed with "Project not found" on every local-first project (the common case), and even on the projects where it "worked" the uploaded icon was never displayed (the v2 UI derived the icon fromrepoOwner). That's the #5843 regression.CDP-confirmed before the fix: upload →
Project not foundon a local-first project; success only on a legacy cloud-linked project.Fix — move icons to the local-first model
Project icons now work the same way name, branch prefix, and worktree location already do: host-service local storage.
Host-service
iconcolumn to the localprojectstable (migration0012_dear_morph.sql, generated via drizzle-kit).project.setIconmutation (mirrorssetBranchPrefix), writing throughupdateLocalProjectso it bumpsupdatedAtand broadcastsproject:changed. Input validated as an image data-URI, capped at 256KB.iconthreaded throughproject.list/get,toProjectSnapshot, and theProjectSnapshotevent type.Renderer
useHostProjectsmerge layer carriesicon(local-host-wins).V2ProjectSettingsresolves the icon as custom → GitHub avatar → placeholder, so an uploaded icon shows immediately in both the header and the picker.IconUploadFieldrewritten to call the host clientproject.setIcon, downscale the chosen image to a 128×128 PNG data-URI client-side (no cloud blob), and offer Upload image… / Reset to default.Cloud teardown
uploadIcon/resetIconToGitHub/removeIconprocs + their tests. The renderer now has zerov2Project.*calls. (Thev2Projects.iconUrlcolumn is left in place; dropping it belongs to the broader teardown — seeplans/remove-cloud-project-model.md.)Verification
typecheckclean (host-service, trpc, desktop);biomeclean.setIcontests, mutation-verified to fail without the fix); trpcv2-project18 pass;V2ProjectSettings1 pass.supersetproject that returned "Project not found" before: upload → icon persists asdata:image/pngand displays; Reset to default → reverts to the GitHub avatar. No more "Project not found".Context
This supersedes the original cloud-based wiring on this branch. It's Phase A of a broader effort to stop the local-first desktop app from querying the cloud for app data (chat, tasks, automations, secrets) — scoped in
plans/remove-cloud-project-model.md.Closes #5843