Files
spark-store/docs/superpowers/plans/2026-05-20-client-ui-polish.md

12 KiB

Client UI Polish Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Fix the client-side account, favorites, reviews, sync, restore, and shell UI issues reported in QA.

Architecture: Preserve existing Vue component boundaries. Add thin wrappers/helpers for modal account management, custom titlebar, review star controls, and sync restore candidate resolution. Backend-dependent review actions are client-side affordances only until backend endpoints exist.

Tech Stack: Vue 3 Composition API, TypeScript strict mode, Electron IPC, Tailwind CSS, Vitest, Testing Library Vue.


File Structure

  • Create src/components/UserManagementModal.vue to present UserManagementView as a global overlay.
  • Create src/components/WindowTitleBar.vue for frameless titlebar UI and window controls.
  • Modify src/App.vue to mount the new account modal, pass sync feedback to installed apps modal, pass favorite status to detail modal, and use restore candidate helper.
  • Modify src/components/AppSidebar.vue and src/components/AccountQuickMenu.vue for overflow-safe labels and menu closing coverage.
  • Modify src/components/UserManagementView.vue for cover-image rendering and modal-friendly layout.
  • Modify src/components/InstalledAppsModal.vue to show sync feedback locally.
  • Modify src/components/FavoriteFolderSelector.vue for normalized default-folder de-dupe and favorited-state text/actions.
  • Modify src/components/FavoriteFolderManager.vue so the entire row content opens detail while checkbox stays isolated.
  • Modify src/components/AppDetailModal.vue and src/components/AppDetailPage.vue to show 已收藏 state.
  • Modify src/components/ReviewsPanel.vue for star rating, filters, user detail affordance, and disabled backend-dependent actions.
  • Modify src/modules/appListSync.ts for resolveCloudInstallCandidate().
  • Modify electron/main/index.ts, electron/preload/index.ts, and src/vite-env.d.ts for frameless window controls.
  • Add/update unit tests under src/__tests__/unit/.

Task 1: Account Menu And User Management Modal

Files:

  • Create: src/components/UserManagementModal.vue

  • Modify: src/App.vue

  • Modify: src/components/AppSidebar.vue

  • Modify: src/components/AccountQuickMenu.vue

  • Modify: src/components/UserManagementView.vue

  • Modify: src/global/typedefinition.ts

  • Modify: src/modules/backendApi.ts

  • Modify: src/global/authState.ts

  • Test: src/__tests__/unit/AppSidebar.account.test.ts

  • Test: src/__tests__/unit/UserManagementView.test.ts

  • Test: src/__tests__/unit/App.account-placeholders.test.ts

  • Test: src/__tests__/unit/accountTypes.test.ts

  • Test: src/__tests__/unit/authState.test.ts

  • Step 1: Write failing sidebar tests

Add tests to src/__tests__/unit/AppSidebar.account.test.ts that verify each quick-menu action closes the menu, and that a user with empty displayName and long username still gets truncate/min-width classes.

  • Step 2: Run sidebar tests red

Run: npm run test -- --run src/__tests__/unit/AppSidebar.account.test.ts

Expected: FAIL for missing fallback username coverage or quick-menu item truncation coverage.

  • Step 3: Implement sidebar overflow and close safety

Update account label wrappers and quick-menu item labels with min-w-0, truncate, and explicit close-before-emit behavior already used by the parent.

  • Step 4: Write failing user management modal tests

Update src/__tests__/unit/App.account-placeholders.test.ts so opening “用户管理” asserts a role="dialog" overlay exists and the main app grid/favorites frame is not replaced by currentView === 'account'.

  • Step 5: Write failing cover field tests

Update src/__tests__/unit/accountTypes.test.ts, authState.test.ts, and UserManagementView.test.ts for optional coverUrl on SparkUser and visible cover rendering.

  • Step 6: Implement modal and cover rendering

Add UserManagementModal.vue, add showUserManagementModal state in App.vue, keep currentView unchanged when opening user management, and pass through close, open-forum, edit-profile, toggle-sync, sync-now, and refresh-downloads events.

  • Step 7: Run account tests green

Run: npm run test -- --run src/__tests__/unit/AppSidebar.account.test.ts src/__tests__/unit/UserManagementView.test.ts src/__tests__/unit/App.account-placeholders.test.ts src/__tests__/unit/accountTypes.test.ts src/__tests__/unit/authState.test.ts

Expected: PASS.


Task 2: Favorites State And Interaction Polish

Files:

  • Modify: src/App.vue

  • Modify: src/components/FavoriteFolderSelector.vue

  • Modify: src/components/FavoriteFolderManager.vue

  • Modify: src/components/AppDetailModal.vue

  • Modify: src/components/AppDetailPage.vue

  • Modify: src/modules/backendApi.ts

  • Test: src/__tests__/unit/FavoriteFolderSelector.test.ts

  • Test: src/__tests__/unit/FavoriteFolderManager.test.ts

  • Test: src/__tests__/unit/AppDetailModal.test.ts

  • Test: src/__tests__/unit/App.account-placeholders.test.ts

  • Step 1: Write failing selector de-dupe tests

Add a test where backend returns folder name 默认收藏夹 and assert only one default folder button appears.

  • Step 2: Run selector test red

Run: npm run test -- --run src/__tests__/unit/FavoriteFolderSelector.test.ts

Expected: FAIL because current de-dupe compares exact name only.

  • Step 3: Normalize default folder names

Trim folder names before default-folder comparison.

  • Step 4: Write failing detail favorite-state tests

Add tests asserting a favorited app renders 已收藏 in AppDetailModal and emits the favorite action when clicked.

  • Step 5: Implement favorite state props

Add favorited/favoriteFolderName props to detail components and compute current favorite metadata in App.vue from loaded folders/items.

  • Step 6: Write failing row click test

Add a test that clicking the favorite row text/image area opens detail while clicking the checkbox only selects.

  • Step 7: Implement row-click behavior

Make the favorite row content area larger/clickable and keep checkbox event isolated.

  • Step 8: Run favorites tests green

Run: npm run test -- --run src/__tests__/unit/FavoriteFolderSelector.test.ts src/__tests__/unit/FavoriteFolderManager.test.ts src/__tests__/unit/AppDetailModal.test.ts src/__tests__/unit/App.account-placeholders.test.ts

Expected: PASS.


Task 3: Review Panel Client UX

Files:

  • Modify: src/components/ReviewsPanel.vue

  • Modify: src/global/typedefinition.ts

  • Modify: src/modules/backendApi.ts

  • Test: src/__tests__/unit/ReviewsPanel.test.ts

  • Step 1: Write failing star rating test

Add a test that clicks the “3 星” star button and verifies submitReview receives rating: 3.

  • Step 2: Write failing filter test

Add reviews with different packageArch and distro; assert selecting an architecture or OS filter hides non-matching reviews.

  • Step 3: Write failing review action/user tests

Add a test that reviewer avatar/name are buttons emitting/showing user detail affordance, and that like/reply/delete controls render with delete disabled unless local permission allows it.

  • Step 4: Run review tests red

Run: npm run test -- --run src/__tests__/unit/ReviewsPanel.test.ts

Expected: FAIL because current UI uses select rating and lacks filters/actions.

  • Step 5: Implement star rating and filters

Replace the native rating select with five star buttons and add local filter controls for package architecture and distro.

  • Step 6: Implement client-only review actions

Render like/reply/delete buttons. Like/reply show a local “后端接口接入后可用” message. Delete is visible only for author/admin-compatible client data; otherwise omit or disable it.

  • Step 7: Run review tests green

Run: npm run test -- --run src/__tests__/unit/ReviewsPanel.test.ts

Expected: PASS.


Task 4: Sync Feedback And Cross-Origin Restore

Files:

  • Modify: src/App.vue

  • Modify: src/components/InstalledAppsModal.vue

  • Modify: src/modules/appListSync.ts

  • Test: src/__tests__/unit/appListSync.test.ts

  • Test: src/__tests__/unit/App.account-placeholders.test.ts

  • Step 1: Write failing restore helper tests

Add resolveCloudInstallCandidate() tests for exact origin/category match, same package fallback across origin, and no candidate.

  • Step 2: Run sync helper tests red

Run: npm run test -- --run src/__tests__/unit/appListSync.test.ts

Expected: FAIL because helper is missing.

  • Step 3: Implement restore helper

Export resolveCloudInstallCandidate(item, apps) from appListSync.ts and use it in App.vue installCloudItems().

  • Step 4: Write failing sync feedback test

Update App.account-placeholders.test.ts or InstalledAppsModal.test.ts to assert clicking sync in the installed-apps modal shows 同步完成 or an error message in that modal.

  • Step 5: Implement modal sync feedback prop

Add syncMessage prop to InstalledAppsModal.vue and pass syncStatusMessage from App.vue.

  • Step 6: Run sync tests green

Run: npm run test -- --run src/__tests__/unit/appListSync.test.ts src/__tests__/unit/App.account-placeholders.test.ts src/__tests__/unit/InstalledAppsModal.test.ts

Expected: PASS.


Task 5: Frameless Window And Shell Polish

Files:

  • Create: src/components/WindowTitleBar.vue

  • Modify: src/App.vue

  • Modify: electron/main/index.ts

  • Modify: electron/preload/index.ts

  • Modify: src/vite-env.d.ts

  • Test: add or update appropriate unit tests for titlebar component and source config.

  • Step 1: Write failing titlebar component test

Create a unit test that renders WindowTitleBar.vue, clicks minimize/maximize/close, and verifies IPC messages are sent.

  • Step 2: Write failing Electron config test or static check

Add a lightweight test/static assertion that BrowserWindow is created with frame: false.

  • Step 3: Implement IPC handlers and titlebar

Set frame: false in BrowserWindow; add IPC listeners for window minimize, toggle maximize, and close using existing close guard; add WindowTitleBar.vue with drag/no-drag regions.

  • Step 4: Mount titlebar in App.vue

Place the titlebar at the top of the root layout and adjust sticky header offsets as needed.

  • Step 5: Verify category capsule color

Run existing CategoryBar.test.ts; no code change needed if it already asserts #2b7fff.

Run: npm run test -- --run src/__tests__/unit/CategoryBar.test.ts

Expected: PASS.


Task 6: Final Verification

Files:

  • All files touched by previous tasks.

  • Step 1: Run targeted unit tests

Run the union of tests touched by this plan:

npm run test -- --run src/__tests__/unit/AppSidebar.account.test.ts src/__tests__/unit/UserManagementView.test.ts src/__tests__/unit/App.account-placeholders.test.ts src/__tests__/unit/accountTypes.test.ts src/__tests__/unit/authState.test.ts src/__tests__/unit/FavoriteFolderSelector.test.ts src/__tests__/unit/FavoriteFolderManager.test.ts src/__tests__/unit/AppDetailModal.test.ts src/__tests__/unit/ReviewsPanel.test.ts src/__tests__/unit/appListSync.test.ts src/__tests__/unit/InstalledAppsModal.test.ts src/__tests__/unit/CategoryBar.test.ts

Expected: PASS.

  • Step 2: Run production build

Run: npm run build:vite

Expected: PASS.

  • Step 3: Check diff whitespace

Run: git diff --check

Expected: no output.

  • Step 4: Commit client changes

Commit message: fix(ui): polish account favorites reviews and shell

  • Step 5: Push feature branch

Push fix/client-ui-account-favorites for review or merge.