Skip to content

feat(app): replace Dashboard with profile dropdown popover - #234

Merged
jeonghun-jj-lee merged 17 commits into
local/amicodefrom
profile-dropdown-popover
Aug 23, 2026
Merged

feat(app): replace Dashboard with profile dropdown popover#234
jeonghun-jj-lee merged 17 commits into
local/amicodefrom
profile-dropdown-popover

Conversation

@jeonghun-jj-lee

@jeonghun-jj-lee jeonghun-jj-lee commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Closes #231

Summary by CodeRabbit

  • New Features
    • Added a profile popover for viewing and editing role, bio, affiliation, avatar, and external links.
    • Added avatar upload and removal support.
    • New sessions now resume existing sessions or drafts when available, or start a fresh draft.
    • Added session navigation to the new-session screen and improved active-session indication.
  • Improvements
    • Added a profile shortcut to the title bar.
    • Removed the legacy home-toggle control.
    • Added clearer handling when no server or project is available.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5bf97e96-e810-4dcd-8a0b-5d039796d4ce

📥 Commits

Reviewing files that changed from the base of the PR and between 77bb1c8 and 50b990e.

📒 Files selected for processing (15)
  • packages/app/src/app.tsx
  • packages/app/src/components/profile-popover.tsx
  • packages/app/src/components/session/session-header.tsx
  • packages/app/src/components/titlebar.tsx
  • packages/app/src/i18n/en.ts
  • packages/app/src/pages/new-session/new-session-view.tsx
  • packages/core/src/database/schema.gen.ts
  • packages/opencode/src/server/amicode/profile.ts
  • packages/opencode/src/server/routes/instance/httpapi/server.ts
  • packages/opencode/test/preload.ts
  • packages/opencode/test/server/amicode-connections-routes.test.ts
  • packages/opencode/test/server/amicode-profile.test.ts
  • packages/opencode/test/server/amicode-widgets-src.test.ts
  • packages/opencode/test/server/httpapi-compression.test.ts
  • packages/ui/src/v2/components/icon.tsx

📝 Walkthrough

Walkthrough

The app replaces the new-layout home route with session landing logic and adds a titlebar profile popover. Session dropdown state is passed explicitly. The profile API accepts expanded identity fields, and related tests improve environment and runtime isolation.

Changes

App experience

Layer / File(s) Summary
Session landing and status controls
packages/app/src/app.tsx, packages/app/src/pages/new-session/new-session-view.tsx
The root route navigates to an existing session or draft tab, or creates a draft when a server and project are available. The new-session view displays session and status controls.
Profile popover and titlebar integration
packages/app/src/components/profile-popover.tsx, packages/app/src/components/titlebar.tsx, packages/app/src/i18n/en.ts, packages/ui/src/v2/components/icon.tsx
The titlebar adds profile access and removes home controls. The popover supports profile display, editing, links, avatar handling, and empty-profile states.
Session dropdown state wiring
packages/app/src/components/session/session-header.tsx, packages/core/src/database/schema.gen.ts
The session dropdown receives the current session ID explicitly. The session schema adds a nullable directories column.

Profile API

Layer / File(s) Summary
Profile persistence and HTTP input
packages/opencode/src/server/amicode/profile.ts, packages/opencode/src/server/routes/instance/httpapi/server.ts
Profile saving and responses now include role, description, GitHub, avatar, and custom-link fields. The POST route accepts query and JSON inputs.

Test maintenance

Layer / File(s) Summary
Expanded profile endpoint validation
packages/opencode/test/server/amicode-profile.test.ts
Tests cover expanded profile persistence, response serialization, custom links, cleanup, and empty-value clearing.
Test runtime and network assertions
packages/opencode/test/preload.ts, packages/opencode/test/server/amicode-connections-routes.test.ts, packages/opencode/test/server/amicode-widgets-src.test.ts, packages/opencode/test/server/httpapi-compression.test.ts
Tests isolate configuration, account for macOS environment variables, simulate bind changes directly, load widget modules through blob URLs, and measure compression thresholds from raw responses.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested reviewers: brendonovich, aarontrowbridge

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ProfilePopoverTrigger
  participant ProfileAPI
  participant saveProfile
  User->>ProfilePopoverTrigger: open profile popover
  ProfilePopoverTrigger->>ProfileAPI: fetch profile
  ProfilePopoverTrigger->>ProfileAPI: submit edited fields
  ProfileAPI->>saveProfile: persist profile
  saveProfile-->>ProfileAPI: return normalized profile
  ProfileAPI-->>ProfilePopoverTrigger: display updated profile
Loading
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch profile-dropdown-popover

Comment @coderabbitai help to get the list of available commands.

…b, custom_link fields

Add role, description, github, and custom_link (url + label) to the profile
data model. saveProfile accepts the new fields via query params, profileBody
includes them in the GET response, and the HTTP route passes them through.

Part of #231
Remove the Home/Dashboard page route (redirect / to /new-session instead).
Replace the titlebar Home button (grid-plus icon, mod+b) with a profile
popover button (person icon, Kobalte Popover, chrome-dropdown coordination).

The popover shows a compact identity card (avatar initials, name, role,
affiliation, research area, bio) with link pills (Scholar, GitHub, Custom)
and inline editing. Empty state auto-enters edit mode.

Widget UI files are kept (used by in-chat preview in message-timeline).
Server-side widget infrastructure is unchanged.

Part of #231
- schema.gen.ts: add missing `directories` column to session table
  (the migration added it but the base schema used for fresh :memory:
  DBs didn't include it, causing 60 test failures)
- widget-src tests: use blob: URL imports instead of temp .mjs files
  (bun test runner's solid transform plugin intercepted the temp files)
- preload: clear OPENCODE_CONFIG_CONTENT so tests don't load the local
  VS Code extension's amicode plugin (which depends on smol-toml)
- connections-routes: filter __CF_USER_TEXT_ENCODING from env assertion
  (macOS injects this unconditionally)
- compression test: handle case where config response grew past 1024B
  threshold (schema additions made the response bigger)
The Navigate to /new-session caused a loop: DraftRoute falls back to /
when no draft exists, which redirects to /new-session again.

Replace with NewSessionLanding — a component that checks for existing
tabs (navigates to the most recent one) or creates a new draft tab via
tabs.newDraft(). No redirect chain, no loop.
- Use amicodeGet/amicodePost with the server connection (auth headers)
  instead of bare fetch() which fails without credentials
- Fix isEmpty() to only show edit form when profile is truly blank
  (was treating any profile with name='Practitioner' as empty)
- Remove circular beginEdit() call from EditForm body

Part of #231
Use data-component='icon-button-v2' with data-variant='ghost-muted' and
data-size='large' on the Popover trigger button so it matches the settings
gear button. The Kobalte Popover automatically adds data-expanded when
open, which the CSS handles for the pressed state.

Part of #231
Refactor SessionChatsDropdown to accept an optional currentSessionID prop
instead of depending on useSessionLayout() context. Export it so the
new-session page can render it alongside the status popover.

The titlebar right-side buttons (sessions dropdown + status) are now
always visible regardless of whether you're in an active session or a
new draft.

Part of #231
…tions test

- Add review toggle button to new-session page (same as active sessions:
  desktop-only, toggles layout.sidebar, with keybind tooltip)
- Fix connections-routes loopback test: use in-process setBindHostname
  instead of relying on real 0.0.0.0 listener (module instance isolation
  in bun test made the real-listener approach unreliable on macOS)

Part of #231
…ggle

- Status popover: remove the settings.visibility.status gate (the setting
  defaults to false, hiding the button). Match session header behavior
  where the status button always renders.
- Review toggle: removed from new-session page. The ReviewPanelV2 is
  session-specific (renders diffs/files from an active session) and has
  no mount point on the draft page — the button toggled state that
  nothing observed, making it non-functional.

New-session titlebar-right now shows: Sessions dropdown + Status popover.
The review toggle appears once you enter an active session (where the
panel actually renders).

Part of #231
…links

- Avatar: click the initials tile to pick a photo; image is center-cropped
  and resized to 96x96 PNG before saving as a data URL in profile.json.
  The avatar field is added to saveProfile and the HTTP route.

- Subtitle: role and affiliation now render on one line as
  'Role @ Affiliation' (was two separate lines).

- Links: replaced window.open (broken in webview) with
  platform.openExternal. Also replaced emoji/text icons with proper SVGs
  (GitHub mark, scholar mortarboard, chain-link).
… bio

- Avatar upload moved from read-view click to the edit form: a dashed-border
  tile at the top of the form, click to pick a photo. Read-view avatar is
  now display-only.

- Bio/description: clicking the truncated text toggles between 2-line clamp
  and full expansion.
The data URL for a 96x96 PNG is ~5-15KB which exceeds URL length limits
on many HTTP stacks. The profile route now reads fields from both query
params (for simple text fields) and a JSON body (for large fields like
avatar). The client sends avatar via amicodePost's jsonBody parameter.
@jeonghun-jj-lee
jeonghun-jj-lee force-pushed the profile-dropdown-popover branch from 705b4e4 to 1676864 Compare August 23, 2026 12:22
Profile icon now comes first (leftmost), settings gear second.
@jeonghun-jj-lee
jeonghun-jj-lee marked this pull request as ready for review August 23, 2026 13:50
@jeonghun-jj-lee
jeonghun-jj-lee merged commit 7527d32 into local/amicode Aug 23, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(app): replace Dashboard with profile dropdown popover

1 participant