# dsh-qol
Quality-of-life tweaks for the DeepSeek Harness (dsh) Web GUI: a session tab bar, sidebar swipe gestures, IME/keyboard adaptation, touch feedback, a full-screen settings rewrite and more — **13 features**, each independently toggleable from **Settings → QoL**, taking effect instantly and persisted per browser. Mobile-first; some features (tab bar, status animation, etc.) apply on desktop too. ## Features | Feature | Description | Default | |---|---|---| | Active-session Tab Bar | Horizontally shows active session tabs at the top of the page; unread/running tabs pinned first, one-tap switching, no accidental keyboard pull-up; fresh sessions show as "New Session"; middle-click/× to close (closing the last tab lands on a fresh session, and the fresh session itself cannot be closed); **the + button sits right after the last tab** (Chrome-style) | On | | Sidebar swipe | Expand the sidebar by swiping right and collapse by swiping left **anywhere on screen** (64px threshold, non-following; the left 16px edge yields to the system back gesture; input fields / horizontal scrollers skipped; no response while a dialog is open; swiping over buttons is safe — it never triggers a click) | On | | Sidebar overlay | On mobile the sidebar opens as an overlay covering content instead of squeezing the main area into a reflow | On | | Collapsed-sidebar recents | When the sidebar is collapsed, circular first-letter icons of recently active sessions appear under the search box, with status badges | On | | Collapse sidebar on switch | On narrow screens, picking a session in the sidebar auto-collapses it and returns to the conversation (≤768px only) | On | | No keyboard on switch | Switching sessions never auto-focuses the input box, so the IME never pops up; covers sidebar session rows, active tabs, collapsed rail icons and archive jumps; tapping the input box directly still focuses it manually | On | | IME/keyboard adaptation | viewport meta (`viewport-fit=cover` + `interactive-widget=resizes-content`), a `100dvh` height chain, composer safe area, iOS `visualViewport` CSS-variable fallback (**never changes element sizes/fonts**) | On | | Touch feedback | `touch-action: manipulation` (kills the 300ms delay and double-tap zoom), disables the system tap highlight, `:active` press feedback, iOS `:active` fix, respects `prefers-reduced-motion` (**never changes element sizes**) | On | | Full-screen settings rewrite | The settings dialog stacks full-screen at ≤768px with horizontally scrolling tabs, a collapsed-tab-width bugfix and safe-area adaptation | On | | Settings tab memory | Reopening settings restores the last selected tab instead of resetting to General | On | | Code/table inner scroll | Long code blocks and tables scroll horizontally inside their containers; body text wraps without overflowing | On | | Hide permission dropdown | Hides the permission (Access mode) dropdown trigger inside the input box to save horizontal space; model selection and context usage are unaffected | On | | Status animation optimization | Replaces the SVG opacity chase-dot animation with a CSS transform pulse on the compositor thread, zero main-thread cost. Measured idle FPS via rAF: 35 → 55 | On | ## Install ```bash dsh plugin --profile web add dsh-qol ``` No manual configuration needed after install — the bundled `cordis.patch.yml` mounts automatically; once installed, a **QoL** section appears on the settings page after refreshing the web UI. Install straight from GitHub (source install; `lib/` is hand-written source and needs no local build, but the package declares a `prepare` syntax-check script, which pnpm ≥10 blocks the first time): ```bash dsh plugin --profile web add github:john-walks-slow/dsh-qol # Add the package name pnpm prints to allowBuilds in # ~/.dsh/profiles/web/pnpm-workspace.yaml, then re-run ``` ## Usage 1. Open the dsh Web GUI (best on mobile). 2. Settings → **QoL**: 13 toggle rows (name + one-line description). Each click takes effect **instantly**, no page refresh needed. 3. Toggles persist automatically in browser `localStorage` (key `dsh.qol.v1`) for this browser only; deleting that key restores the all-on defaults. What a saved toggle set actually looks like (`localStorage["dsh.qol.v1"]`): ```json { "active-tabbar": true, "sidebar-gesture": true, "ime-viewport": true, "tap-feedback": true } ``` The implementation is an **attribute total-gate**: every feature maps to an `html[data-qol-