From 334611b375fe0af89555ac2d4c682f685c49137a Mon Sep 17 00:00:00 2001 From: Syed Laraib Ahmed <67756542+Laraib-1629@users.noreply.github.com> Date: Mon, 11 May 2026 14:04:43 +0530 Subject: [PATCH] feat(web): add PWA manifest and wire mobile accordion on dashboard (#1476) * feat(web): add PWA manifest and wire mobile accordion on dashboard - Add manifest.json with standalone display mode and theme colors - Link manifest in layout.tsx generateMetadata - Pass compactMobile, collapsed, onToggle to AttentionZone from Dashboard so the mobile accordion (already implemented) is now activated Closes #175 * fix(web): add missing PWA icons and split icon purposes - Add icon-192.png and icon-512.png to public/ (were 404ing on PWA install) - Split combined 'any maskable' into separate icon entries per W3C best practice to avoid safe-zone cropping in non-maskable contexts - Apply Prettier formatting to Dashboard.tsx (long SVG attribute lines) * fix(web): resolve merge conflict, fix types, use dynamic icon routes - Resolve Dashboard.tsx merge conflict with upstream refactored useSessionEvents - Type handleZoneToggle as (level: AttentionLevel) per reviewer request - Start all zones collapsed on mobile for better UX (collapsedZones init) - Add scope to manifest.json per PWA best practice - Switch manifest icons from static PNGs to dynamic /icon-192 and /icon-512 routes that use the existing renderIconElement system (branded icons) - Remove static icon-192.png and icon-512.png black square placeholders * fix(web): wire BottomSheet preview, fix mobile tests, update manifest - Add onPreview to AttentionZone, opens BottomSheet on mobile tap - Add previewSession state and bottom sheet handlers to Dashboard - Default collapsedZones to done+working only, not all zones - Fix isMergeReady to use server attentionLevels instead of client recompute - Restore isMerged guard on DoneCard restore button - Update manifest.ts with scope, orientation, maskable icon entries - Update manifest.test.ts to expect new fields - Update Dashboard.mobile.test.tsx for MobileSessionRow compact row structure - Revert inverted Dashboard.doneBar.test.tsx assertion * fix(web): add display:flex to kanban-board mobile override --- packages/web/src/app/globals.css | 3 +- packages/web/src/app/manifest.test.ts | 4 ++ packages/web/src/app/manifest.ts | 4 ++ packages/web/src/components/Dashboard.tsx | 63 ++++++++++++++++--- .../__tests__/Dashboard.doneBar.test.tsx | 4 +- .../__tests__/Dashboard.mobile.test.tsx | 29 +++++---- 6 files changed, 85 insertions(+), 22 deletions(-) diff --git a/packages/web/src/app/globals.css b/packages/web/src/app/globals.css index 38a300e88..8bb4b4016 100644 --- a/packages/web/src/app/globals.css +++ b/packages/web/src/app/globals.css @@ -5817,7 +5817,8 @@ html.light .xterm .xterm-viewport:hover::-webkit-scrollbar-thumb:active { /* -- Kanban board: stack columns vertically -- */ .kanban-board { - grid-template-columns: minmax(0, 1fr); + display: flex; + flex-direction: column; height: auto; min-height: auto; overflow-x: visible; diff --git a/packages/web/src/app/manifest.test.ts b/packages/web/src/app/manifest.test.ts index bd6e7e62f..de9f09808 100644 --- a/packages/web/src/app/manifest.test.ts +++ b/packages/web/src/app/manifest.test.ts @@ -12,13 +12,17 @@ describe("app manifest", () => { name: "ao | Agent Orchestrator", short_name: "ao", start_url: "/", + scope: "/", display: "standalone", + orientation: "portrait-primary", background_color: "#121110", theme_color: "#121110", icons: [ { src: "/apple-icon", sizes: "180x180", type: "image/png" }, { src: "/icon-192", sizes: "192x192", type: "image/png", purpose: "any" }, + { src: "/icon-192", sizes: "192x192", type: "image/png", purpose: "maskable" }, { src: "/icon-512", sizes: "512x512", type: "image/png", purpose: "any" }, + { src: "/icon-512", sizes: "512x512", type: "image/png", purpose: "maskable" }, ], }); }); diff --git a/packages/web/src/app/manifest.ts b/packages/web/src/app/manifest.ts index 6977692da..2138c2d92 100644 --- a/packages/web/src/app/manifest.ts +++ b/packages/web/src/app/manifest.ts @@ -8,13 +8,17 @@ export default function manifest(): MetadataRoute.Manifest { short_name: "ao", description: "Dashboard for managing parallel AI coding agents", start_url: "/", + scope: "/", display: "standalone", + orientation: "portrait-primary", background_color: "#121110", theme_color: "#121110", icons: [ { src: "/apple-icon", sizes: "180x180", type: "image/png" }, { src: "/icon-192", sizes: "192x192", type: "image/png", purpose: "any" }, + { src: "/icon-192", sizes: "192x192", type: "image/png", purpose: "maskable" }, { src: "/icon-512", sizes: "512x512", type: "image/png", purpose: "any" }, + { src: "/icon-512", sizes: "512x512", type: "image/png", purpose: "maskable" }, ], }; } diff --git a/packages/web/src/components/Dashboard.tsx b/packages/web/src/components/Dashboard.tsx index f9dd25245..2e5a3eade 100644 --- a/packages/web/src/components/Dashboard.tsx +++ b/packages/web/src/components/Dashboard.tsx @@ -25,6 +25,7 @@ import { ConnectionBar } from "./ConnectionBar"; import { CopyDebugBundleButton } from "./CopyDebugBundleButton"; import { SidebarContext } from "./workspace/SidebarContext"; import { projectDashboardPath, projectSessionPath } from "@/lib/routes"; +import { BottomSheet } from "./BottomSheet"; interface DashboardProps { initialSessions: DashboardSession[]; @@ -121,7 +122,7 @@ function DoneCard({ ) : null} {formatRelativeTimeCompact(session.lastActivityAt)} - {canRestore ? ( + {canRestore && !isMerged ? (