Skip to content

feat(web-studio): PWA, mobile UI polish, OAuth-setup tab, request-logs touch-ups#2178

Merged
t0saki merged 2 commits into
mainfrom
feat/web-studio-pwa-mobile-and-root-redirect
May 21, 2026
Merged

feat(web-studio): PWA, mobile UI polish, OAuth-setup tab, request-logs touch-ups#2178
t0saki merged 2 commits into
mainfrom
feat/web-studio-pwa-mobile-and-root-redirect

Conversation

@ZaynJarvis
Copy link
Copy Markdown
Collaborator

Summary

A single PR rolling up this round of web-studio work. Three themes plus a
handful of small polish items.

PWA & install

  • web-studio/public/manifest.json + 192/512 + maskable icons + a thin
    service-worker.js. Registered in web-studio/src/main.tsx.
  • web-studio/index.html: viewport-fit=cover, apple-mobile-web-app-*,
    application-name = OpenViking Studio.
  • openviking/server/app.py: / -> /studio/ redirect so the PWA
    start_url resolves correctly when the app is opened from the bare host.

OAuth setup as its own tab

  • New /studio/oauth/setup route + OAuthSetupDialog. Sidebar footer
    entry routes to the dialog on >=md and to the dedicated page on phone
    (full-screen dialogs are hard to dismiss on mobile).
  • OTP form extracted from the connection dialog into a reusable component
    (connection-dialog.tsx shrinks by ~200 lines).

Mobile / phone-view polish

  • Home
    • Metric chips: grid minmax(92px,...) -> minmax(140px,...), removed
      truncate so chips wrap instead of clipping.
    • Context-commits tooltip clamps into the viewport on narrow screens.
    • Context-commits heatmap auto-scrolls to the rightmost (latest) cell on
      mount so phone view opens on the current week.
  • Dialog: max-h-[calc(100dvh-2rem)] + overflow-y-auto overscroll-contain so long dialogs do not overflow on phone.
  • FS / resources route
    • Full-height container uses h-[calc(100svh-6rem)] + symmetric
      -my-6 so the outer SidebarInset ScrollArea no longer overflows by
      the parent's py-6 (was 100vh - 3.5rem + -mt-6 -mb-4).
    • Inner panes use overlay-style scrollbars on phone (matches iOS / the
      Atlas reference); PWA standalone mode also hides the outer page
      scrollbar on this route via
      @media (display-mode: standalone) + :has(.web-studio-resource-fs).
    • Tighter row density on phone (text-xs md:text-sm, py-1 md:py-1.5)
      in file-tree and file-list; removed the old 1rem upscale media
      query that was making everything large.
    • FolderIcon size-5 -> size-4 so folder and file rows share the
      same text x-offset.
    • Folder highlight only when no file is selected (clean single-select
      semantics); the parent stops passing selectedFileUri when the
      selectedFile is actually a directory.
    • Toolbar refresh button: size="icon-sm" + pl-4 so its icon center
      aligns with the header sidebar trigger on phone.
  • Find-palette: centered + max-h-[calc(100svh-2rem)] on phone (was
    top-anchored pt-[12vh] + 84vh).
  • Inputs: search inputs in the retrieval bar and find-palette get
    text-base md:text-sm so iOS does not auto-zoom on focus (already true
    for the shared <Input> component).

Request logs

  • Time column now formats as YYYY.MM.DD HH:MM:SSam/pm (locale-stable,
    same density as the rest of the app).
  • Total calls clamps display at 999+ so the metric does not look
    pegged when the API caps at 1000.
  • Pagination row centers on phone (justify-center), preserves
    justify-between on >= sm.

i18n

  • Retrieval placeholder -> Search context / 输入检索内容.
  • Find-palette placeholder -> Search / 搜索.
  • Context-commits title drops in the last year (the date range chip
    next to it still shows the window).
  • find() / search() -> find / search in mode toggle + today
    retrievals stats.
  • Sidebar workspace header -> OpenViking Studio.

Test plan

  • pnpm build clean.
  • Chromium phone emulation: verified FS layout, find-palette,
    pagination, context-commits scroll, dialog overflow, folder/file
    highlight round-trip.
  • @ZaynJarvis to validate on iOS PWA standalone mode.

…s touch-ups

PWA & install
- manifest 192/512 + maskable icons, service-worker registration in main.tsx,
  apple-mobile-web-app meta + viewport-fit=cover in index.html.
- openviking/server/app.py: redirect "/" -> "/studio/" so the PWA install
  start_url resolves correctly when accessed from the bare host.

OAuth setup as its own tab
- New /studio/oauth/setup route + OAuthSetupDialog; sidebar footer entry
  routes to the dialog on >=md and to the dedicated page on phone (mobile
  fullscreen dialogs are hard to dismiss). OTP form extracted from the
  connection dialog into a reusable component.

Mobile UI fixes
- Home metric chips: grid minmax 92px -> 140px, removed truncate so chips
  wrap instead of clipping.
- Context-commits tooltip: clamps into viewport on narrow screens.
- Context-commits heatmap: auto-scrolls to rightmost (latest) on items
  change so phone view opens on the current week.
- Dialog: max-h-[calc(100dvh-2rem)] + overflow-y-auto for phone overflow.
- FS page (resources):
  * full-height container uses calc(100svh-6rem) + symmetric -my-6 so the
    outer ScrollArea no longer overflows by parent's py-6.
  * inner overlay-style scrollbars on phone (matches iOS / Atlas).
  * PWA standalone mode hides the outer page scrollbar on this route.
  * Tighter row density on phone (text-xs / py-1) to match Atlas.
  * FolderIcon size-5 -> size-4 so folder and file text columns align.
  * Folder highlight only when no file is selected (clean single-select).
  * Toolbar refresh button: size-icon-sm + pl-4 to align with the header
    sidebar trigger on phone.
- Find-palette: phone-center + max-h-[calc(100svh-2rem)] (was top-anchored
  + 84vh). Search input min font-size 16px to dodge iOS auto-zoom; same
  treatment in the retrieval search bar.

Request logs
- Time column: dot-separated YYYY.MM.DD HH:MM:SSam/pm (compact, no locale
  variance).
- Total calls clamps display at "999+".
- Pagination row: justify-center on phone (sm:justify-between preserved).

i18n
- Retrieval placeholder: "Search context" / "输入检索内容".
- Find-palette placeholder: "Search" / "搜索".
- Context-commits title: drop "in the last year" (range chip still shows).
- find / search labels: drop the parentheses.
- Workspace sidebar header: "OpenViking Studio".

Build verified after each change. Phone view validated via Chromium
emulation; iOS PWA-mode scrollbar fix scoped behind
@media (display-mode: standalone).
@github-actions
Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🏅 Score: 90
🧪 No relevant tests
🔒 No security concerns identified
✅ No TODO sections
🔀 Multiple PR themes

Sub-PR theme: PWA support for web studio

Relevant files:

  • web-studio/src/main.tsx
  • web-studio/public/service-worker.js
  • web-studio/public/manifest.json
  • web-studio/index.html
  • web-studio/src/styles.css

Sub-PR theme: OAuth setup tab and reusable OTP form

Relevant files:

  • web-studio/src/components/oauth-setup-dialog.tsx
  • web-studio/src/routes/oauth/setup.tsx
  • web-studio/src/components/app-shell.tsx
  • web-studio/src/routeTree.gen.ts
  • web-studio/src/i18n/locales/en.ts
  • web-studio/src/i18n/locales/zh-CN.ts

Sub-PR theme: Mobile UI polish across web studio

Relevant files:

  • web-studio/src/routes/home/-components/context-commits-panel.tsx
  • web-studio/src/routes/home/-components/metric-panels.tsx
  • web-studio/src/routes/home/-components/panel.tsx
  • web-studio/src/components/ui/dialog.tsx
  • web-studio/src/routes/request-logs/-components/pagination.tsx
  • web-studio/src/routes/request-logs/-lib/format.ts
  • web-studio/src/routes/request-logs/route.tsx
  • web-studio/src/routes/resources/-components/file-list.tsx
  • web-studio/src/routes/resources/-components/file-tree.tsx
  • web-studio/src/routes/resources/-components/find-palette.tsx
  • web-studio/src/routes/resources/-components/viking-file-manager.tsx
  • web-studio/src/routes/retrieval/-components/search-bar.tsx
  • web-studio/src/styles.css

⚡ No major issues detected

@github-actions
Copy link
Copy Markdown

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Api resilience
Add timeout to OTP API call using AbortController

Add timeout and abort controller to the OTP generation API call for better
resilience. This prevents hanging requests if the server is unresponsive.

web-studio/src/components/oauth-setup-dialog.tsx [133-141]

-      const resp = await fetch('/api/v1/auth/otp', {
-        method: 'POST',
-        cache: 'no-store',
-        headers: {
-          'Content-Type': 'application/json',
-          Authorization: `Bearer ${effectiveKey}`,
-        },
-        body: '{}',
-      })
+      const controller = new AbortController()
+      const timeoutId = setTimeout(() => controller.abort(), 10000) // 10s timeout
+      try {
+        const resp = await fetch('/api/v1/auth/otp', {
+          method: 'POST',
+          cache: 'no-store',
+          headers: {
+            'Content-Type': 'application/json',
+            Authorization: `Bearer ${effectiveKey}`,
+          },
+          body: '{}',
+          signal: controller.signal,
+        })
+        clearTimeout(timeoutId)
Suggestion importance[1-10]: 5

__

Why: Adds a timeout to the OTP generation API call using AbortController, improving resilience against unresponsive servers. The change is valid but not critical.

Low

…ommit heatmap

PR #2178 follow-ups based on phone PWA testing:

Context commits heatmap (Home)
- Re-bucket UTC (date, hour_bucket) 4h rows into viewer-local (date,
  hour) before daily aggregation, so a UTC+8 viewer's "today" cell holds
  the right local-day count instead of UTC's. Pure client-side relabel —
  each bucket's count is preserved, just attributed to the correct local
  date. Daily / "today_tokens" aggregates can't be rebucketed this way
  and still need the backend tz work (separate follow-up).
- Auto-scroll: align viewport's right edge with the rightmost rendered
  rect's right edge (not the SVG's hardcoded width=820 right edge), so
  the ~50px of trailing SVG padding stays off-screen on phone.
- Wrap the scroll write in requestAnimationFrame so HeatMap has a tick
  to lay out its SVG; otherwise scrollWidth equals clientWidth and the
  scroll snaps to the left (oldest) edge.

FS / resources route polish
- File tree: clicking a folder row now toggles expand/collapse in
  addition to opening the folder (chevron icon still works alone via
  stopPropagation, no double-toggle).
- File tree: parent passes selectedFileUri only when the selected entry
  is actually a file; opening a folder no longer leaves it competing
  with the parent's directory highlight.
- File tree: session subtree (any URI under viking://session/) sorts
  children by modTimestamp DESC instead of name, so the most recent
  session shows first.
- FolderIcon size-5 -> size-4 to match File icon and chevron, so folder
  and file rows share the same text x-offset at every depth.
- Toolbar: refresh Button now uses size="icon-sm" + pl-4 on the toolbar
  so its icon center aligns vertically with the header's sidebar
  trigger on phone.
- Breadcrumb nav: overflow-hidden -> overflow-x-auto + whitespace-nowrap
  + flex-1 so long paths scroll horizontally on phone instead of being
  cut off invisibly.

formatModTime
- Parse time-only mod_time strings ("HH:MM:SS", "12:34am" etc) against
  UTC today + Z marker — backend's format_simplified uses UTC's "today"
  reference, not the viewer's local today, so the prior local-today
  prefix mis-attributed days for non-UTC viewers.
- Date-only mod_time ("YYYY-MM-DD") renders as-is; we don't fake an
  "00:00" time component that doesn't exist.

JSONL dialog
- Cards: drop ml-auto / mx-auto / mr-auto chat-bubble alignment;
  switch w-fit max-w-[min(820px,88%)] to w-full min-w-0 max-w-full so
  long expanded messages, tool-call JSON, and markdown tables can use
  the full pane width and trigger their own internal overflow-auto
  instead of pushing the article wider than the viewport.
- List container picks up min-w-0 so the flex column can shrink.
- Kind distinction now color-only (bg / border).

Request-logs pagination
- justify-center on phone for both the summary row and the pagination
  control row; sm:justify-between / sm:justify-end preserved on tablet+.
Copy link
Copy Markdown
Collaborator

@t0saki t0saki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@t0saki t0saki merged commit 4e94734 into main May 21, 2026
5 checks passed
@t0saki t0saki deleted the feat/web-studio-pwa-mobile-and-root-redirect branch May 21, 2026 18:43
@github-project-automation github-project-automation Bot moved this from Backlog to Done in OpenViking project May 21, 2026
ZaynJarvis pushed a commit that referenced this pull request May 22, 2026
…2178 (#2192)

* docs(oauth): point OAuth client OTP to sidebar OAuth setup entry

* docs(oauth, zh): point OAuth client OTP to sidebar OAuth setup entry
t0saki pushed a commit that referenced this pull request May 22, 2026
…er-side (#2194)

PR #2178 (4e94734) shipped a `shiftBucketToLocal` helper that re-bucketed
the commit heatmap from UTC to viewer-local. PR #2190 (0d63f0e) landed
right after and added the equivalent shift server-side: backend now
accepts ?timezone= and returns rows already bucketed in the requested tz.
Keeping the client-side shift double-shifts every row by the viewer's tz
offset (e.g. UTC+8 ends up at UTC+16), so today's bucket displays under
the wrong local date.

This was supposed to be reverted on the #2178 branch before merge but the
revert commit (37e0450) was pushed after the PR had already been merged,
so it never reached main. Apply the same revert directly here.

normalizeCommitHeatmapData now keys the aggregation map by item.date as
the server returns it (already in viewer tz post-#2190).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants