Skip to content

feat: make activity panel draggable + slow snapshot poll to 3000ms - #34

Open
Liangebra wants to merge 3 commits into
NanmiCoder:mainfrom
Liangebra:feat/activity-panel-draggable
Open

feat: make activity panel draggable + slow snapshot poll to 3000ms#34
Liangebra wants to merge 3 commits into
NanmiCoder:mainfrom
Liangebra:feat/activity-panel-draggable

Conversation

@Liangebra

@Liangebra Liangebra commented Aug 16, 2026

Copy link
Copy Markdown

PR: 活动面板可拖动 + 轮询降频

Summary

  1. 活动面板可拖动:按住面板头部即可把右上角浮层拖到屏幕任意位置;
    定位从 right/bottom 切换为 left/top(拖动后 inline 覆盖),并 localStorage 持久化
    (键 dsh-agent-teams:panel-pos),刷新/重开后保持在原地;未拖动时维持默认右上角。
    折叠态 badge 也跟随同一保存位置,不跳回右上角。
  2. 轮询降频(纯轮询,无 SSE 通道):POLL_MS 1000→3000ms。面板每轮 Promise.all
    /state/state?archived=1,原 1s 一轮实为 2 请求/s;改为 3s 一轮后快照请求负载
    降约 3 倍。面板的 /state唯一刷新机制(没有 SSE),这是纯轮询降频——
    最大刷新延迟从 1s 增至 3s,对右上角状态监视面板可接受。

改动

  • src/client/ActivityPanel.tsx:新增 PANEL_POS_KEY/readPanelPos/clampPanelPos 辅助函数、
    组件内 panelPos/panelRef/dragRef 状态、onHeaderPointerDown/Move/Up 拖拽处理器、
    <aside> 加 ref/data-dragged/inline 位置、<header> 加 pointer 处理器与 title;
    CollapsedBadge 接收 panelPos 并应用同一 left/top;POLL_MS=3000
  • src/client/ActivityPanel.module.css.panelHeadcursor:grab/touch-action:none
    .panel[data-dragged=true] 关动画。

lib/ 为构建产物且被 .gitignore 忽略——本 PR 仅改源码,构建方 pnpm build 重新生成。)

验证

  • 本地改 lib/client.js(编译产物)后硬刷新 DSH 页面:
    • 确认服务端下发的 bundle 含 PANEL_POS_KEY/clampPanelPos/data-dragged/cursor:grabPOLL_MS=3e3
    • 实测 /plugins/dsh-agent-teams/state 轮询间隔 ≈3000ms(从原 1s 降为 3s),无 console 报错;
  • 用与实际处理器逻辑一致的 DOM 模拟验证拖拽:按下→移动更新 left/top(精确跟随指针位移、视口内夹紧)、
    释放结束、localStorage 写入位置;badge reflow 实测 left/top 精确跟随;关闭按钮上的 pointerdown 不触发拖拽。

备注

  • 拖拽手柄为面板 头部(header)——避免拖整张面板时与任务点击/列表滚动冲突。
  • 面板 /state纯轮询(本插件无 SSE/事件推送通道),POLL_MS 是它的唯一刷新定时器;
    由 1000ms 提至 3000ms 后最大刷新延迟为 3s(此前为 1s),对右上角状态监视可接受,快照负载降约 3 倍。

Drag the AgentTeams floater by its header to reposition it: mousedown→capture→move updates left/top (clamped to viewport) and the position persists to localStorage (dsh-agent-teams:panel-pos). Default stays the top-right corner; a saved position switches the aside to left/top anchoring.

Also raise POLL_MS 1000→3000 for the host snapshot route (two /state calls per poll) to cut request load ~3x while keeping events instant via polling-as-backstop.

Pointer-down on the close button is ignored so clicks still reach it.
Copilot AI lite review requested due to automatic review settings August 16, 2026 14:30

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR enhances the AgentTeams ActivityPanel floater UX by adding draggable positioning with persistence, and reduces backend load by slowing the snapshot polling cadence.

Changes:

  • Make the activity panel draggable via its header, persisting the panel position in localStorage.
  • Clamp dragged positions to keep the panel reachable on-screen.
  • Reduce snapshot polling cadence from 1000ms to 3000ms to lower request volume.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/client/ActivityPanel.tsx Adds draggable position state/persistence + pointer handlers; increases POLL_MS to 3000ms.
src/client/ActivityPanel.module.css Updates header cursor/touch behavior and disables entry animation after dragging.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +527 to +534
useEffect(() => {
try {
if (panelPos === null) localStorage.removeItem(PANEL_POS_KEY)
else localStorage.setItem(PANEL_POS_KEY, JSON.stringify(panelPos))
} catch {
// Privacy mode / quota: non-fatal.
}
}, [panelPos])

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

已修复:localStorage 持久化改用防抖(250ms settle)——拖动过程中的高频 setPanelPos 只会在手势停稳后写一次,不再每次 pointer move 同步写 localStorage 造成 jank;panelPos 为 null 时立即移除键,卸载时 flush 未写定时的待写。见 commit 128b4a6

Comment on lines +75 to +84
function clampPanelPos(pos: { x: number; y: number }, panelWidth: number, panelHeight: number): { x: number; y: number } {
const minX = -(panelWidth * 0.6)
const maxX = window.innerWidth - 24
const minY = 8
const maxY = window.innerHeight - 24
return {
x: Math.max(minX, Math.min(maxX, pos.x)),
y: Math.max(minY, Math.min(maxY, pos.y)),
}
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

已修复:clampPanelPos 现同时使用 panelWidth 与 panelHeight——至少保留 MIN_VISIBLE(48px) 在屏内,maxX/maxY 不再只留 ~24px,避免整块几乎拖出屏幕;不再有未用参数。见 commit 128b4a6

Comment on lines +538 to +546
const onHeaderPointerDown = (event: ReactPointerEvent<HTMLElement>): void => {
const target = event.target as HTMLElement
if (target.closest('button') !== null) return
const el = panelRef.current
if (el === null) return
// Capture on the header so move/up keep flowing to it even when the pointer
// leaves the panel mid-drag.
const handle = event.currentTarget as HTMLElement
handle.setPointerCapture(event.pointerId)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

已修复:onHeaderPointerDown 先判 event.button === 0(仅主键),并调用 preventDefault() 抑制拖动过程中的文本选择;右键/中键不再误触拖拽,close 按钮守卫保持不变。见 commit 128b4a6

When the panel has been dragged, the collapsed badge now uses the same saved left/top (right:auto) so collapsing/expanding keeps the floater where the user left it, instead of snapping back to the top-right corner.
@Liangebra

Copy link
Copy Markdown
Author

更正说明 (accuracy fix):

本 PR 对轮询的表述有一处需要更正——此前 PR 描述 / 首次提交信息里 "SSE 保持即时性 / polling-as-backstop" 的写法有误:AgentTeams 活动面板没有 SSE / 事件推送通道/state 轮询是它唯一的刷新机制。

实际情况:

  • 这是纯轮询降频:POLL_MS 1000 → 3000ms(每轮拉 /state 与 /state?archived=1 两个接口)。
  • 面板最大刷新延迟从 1s 增至 3s;对右上角状态监视面板可接受。
  • 快照请求负载降约 3 倍。

PR 描述已同步更正(见 Summary 与 备注)。此评论用于澄清首次提交信息里 "polling-as-backstop" 的措辞。

- debounce the localStorage panel-pos persistence (~250ms) so a drag does not do a synchronous write on every pointer move (removes jank)
- clampPanelPos now uses both panel dimensions: at least a MIN_VISIBLE chunk stays on-screen (was ~24px), matching the comment
- drag starts only on the primary button and calls preventDefault() so right/middle clicks are ignored and text selection is suppressed
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.

2 participants