DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Freeze Content On Window Resize — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
F

freeze-content-on-window-resize

Freeze Content On Window Resize

DSH Web GUI 插件:固定对话阅读栏,并在窗口调整大小时保持阅读位置不变。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:nnnanann/Deepseek-harness-freeze-content-on-window-resize#0c3209a77106d68b207a1a783a7890ad68b11f14
README兼容性版本

兼容性与来源证明

Freeze Content On Window Resize 以 freeze-content-on-window-resize 发布,当前版本为 1.0.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/10/7

版本

1.0.0stable
2026/10/7

相关插件

正在加载相关插件…

最新版
1.0.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 0
周下载
0
最近提交
2026/10/7
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 ui-customization 分类下经过校验的插件。

Client Ui Skill Explorer@linxin666/dsh-client-ui-skill-explorerDSH 技能中心:按来源(bundled / project / user / custom / runtime)浏览已加载的技能,在 Web GUI 面板中启用或禁用、创建和删除技能。Remote Web Ui@linxin666/dsh-remote-web-ui通过扫码配对访问 dsh Web GUI,共享一个官方界面:设置按钮旁的二维码可将手机和 PC 配对到同一个 Web GUI(手机采用竖屏触控适配层,PC 使用完整桌面界面),通过一次性令牌和 rClient Ui Task Board@linxin666/dsh-client-ui-task-board面向 DSH Web GUI 的主机权威任务面板,支持实际会话执行、主机 cron 调度以及可选的跨平台空闲睡眠保护;以挂载方式提供,无需修改 DSH 源代码。Client Ui Git Graph@linxin666/dsh-client-ui-git-graph外部 dsh Web GUI 插件:空会话 Git 分支选择器和 Git 图,包含实际的主机端 Git 操作与防护,作为 dsh 配置文件包

README

Freeze content on window resize

A plugin for the DeepSeek Harness (DSH) Web GUI that stops the conversation you are reading from moving when the window is resized.

English | 中文


Requirements

  • DSH with its Web GUI — the desktop app's window, or dsh web.
  • Developed and verified against DSH desktop 0.2.0-rc.2 (win32). It keys off DSH's own data attributes rather than hashed class names, so newer builds should keep working.
  • Nothing to install or build: no dependencies, no bundler, no compiler.

The problem

Resize the window while reading a long answer and the text under your eyes changes: the paragraph you were on is gone and you have to find your place again.

It is not an illusion, and it is not your scroll wheel. The transcript column is:

/* the column's shipped class name in DSH 0.2.0-rc.2 — an internal name, not an API */
.xz4KEq_column {
  width: 100%;
  max-width: var(--dsh-chat-content-width);
  margin: 0 auto;
}

…inside a scrollport, while DSH derives that content width from the pane and republishes it from a ResizeObserver on every resize:

Stored width preferenceContent width
none (a fresh install, or never dragged a width handle)clamp(680px, 0.64 × pane, 920px)
a width you dragged before (localStorage["dsh.conversation.contentWidth"])min(max(preference, 640px), max(640px, pane − 176px))

So with no stored preference the reading column tracks the window across the whole pane range where that clamp is not saturated (roughly 1063–1438px): there is no threshold to stay above, and every resize step re-wraps the text. With a stored preference the width is fixed until the pane can no longer fit it, and only from there does it shrink with the window.

Meanwhile the browser keeps scrollTop in pixels — a number that no longer points at the same text. The Chat view's own resize handler only re-follows the tail or re-probes the active turn; it never restores the reader's anchor.

Measured: forcing the re-wrap a narrower window produces — a 140px narrower column — moved the reading line 2417px away from where it was, and the anchor compensation put it back to a 0px offset. How that is measured — you can run it yourself.

What it does

MechanismEffect
Lock the content widthEvery mounted reading column is pinned to one pixel width (width, min-width, max-width, all !important), so how text wraps never depends on the window. A narrower window scrolls horizontally instead of re-flowing.
Keep the reading positionEach column keeps a live anchor — the row on the reading line (data-chat-anchor-key) plus its offset from the viewport top. After a resize or zoom, the anchor is re-aligned across two animation frames plus one delayed pass.

While the view is pinned to the newest content ([data-chat-following-tail], the "follow the tail" state) the anchor compensation stands down and DSH's own auto-follow does its job; the width lock still applies.

The column you are reading takes the width you configure. A transcript embedded in a side panel keeps its own panel-derived width — that width never depended on the window in the first place.

One consequence is worth knowing before you install: once locked, widening the window no longer widens the reading column. Stock DSH does widen it whenever the clamp is not saturated. That is the point of the lock — pick your width once and it stays — and the Width setting or DSH's own drag handles are how you change it.

Install

The profile name is the directory under ~/.dsh/profiles/; this plugin was developed against one called desktop. Substitute your own in the commands below.

Recommended — no manual clone:

dsh plugin --profile desktop add github:nnnanann/freeze-content-on-window-resize

dsh plugin add forwards its argument to pnpm, so any spec pnpm accepts works. From a local checkout instead:

git clone https://github.com/nnnanann/freeze-content-on-window-resize
dsh plugin --profile desktop add link:<the cloned folder>

Either form adds a dependency to the profile's package.json, appends freeze-content-on-window-resize to dsh.profile.bundles, and installs. The profile loads the plugin live — an open GUI page picks it up without a restart. If a github: spec is rejected by your DSH build, use the clone-and-link: form above.

There is no build step: client/client.js is committed as a hand-written DSH client bundle (window.__ModuleLoader__.load({ id, factory })). Nothing needs compiling after a clone, and editing that file hot-reloads it in an open page.

Uninstall:

dsh plugin --profile desktop remove freeze-content-on-window-resize

Use

A 26px, mostly transparent lock button sits in the window's bottom-right corner (fixed to the window, so it can sit over the right sidebar when that is open — hide it from the panel if you would rather). Its tooltip repeats the two shortcuts below. Click it for the settings panel:

Panel item中文Meaning
Lock content width锁定内容宽度The master switch. Off returns stock DSH behavior.
Width宽度A number box, or the presets 620 / 680 / 748 / 820 / 920. On first run it adopts DSH's current content width, so nothing jumps when you install it.
Keep reading position保持阅读位置The anchor compensation switch.
Show this control显示此控件Hides the button itself.
Reset恢复默认Back to the defaults.

The panel follows DSH's own UI language. It ships a Chinese and an English dictionary and falls back to Chinese when DSH is in any other language. A grey line under the switches restates the tradeoff: "Locking stops the text from re-wrapping; a narrower window scrolls horizontally instead."

Keyboard shortcuts (ignored while a text field has focus):

ShortcutAction
Alt+Shift+LToggle the width lock
Alt+Shift+WCycle the preset widths

DSH's own width drag handles keep working: pressing one (cursor: col-resize) releases the lock, and releasing the pointer adopts the width you dragged to as the new locked width.

Settings live in the page's localStorage under freeze-content-on-window-resize:config (width: 0 means "adopt DSH's own width" — it is resolved and stored on first run):

{ "lockWidth": true, "width": 748, "keepPosition": true, "showControl": true }

Diagnostics

In the page's DevTools console:

__fcwr.status()
// { lockWidth, width, keepPosition, showControl,
//   columns: [ { primary, width, anchor }, ... ] }
// columns[].width is the width that column is locked to; 0 means it is not locked.

__fcwr.realign()   // re-align to the current anchor right now
__fcwr.dispose()   // tear down this run without unloading the plugin
  • freeze-content-on-window-resize:boot — a stamp rewritten on every start: revision, at, href, locale, copy, copyState, lockWidth, and every column's locked width and anchor.
  • copyState explains the panel language: bound (the host locale service supplies the copy), pending (no answer yet), no-service (no locale service), no-dictionary (that language has none here), or an error: / inject-failed: message.
  • On boot the console logs one line, in the active UI language: [freeze-content-on-window-resize] 1.0.0 locked reading columns: 884px (primary) / … — or … width lock off when the lock is disabled.

How it works

  • No hashed class names. Only DSH's stable data attributes are used: [data-chat-flow] (the column), [data-conversation-scroll] (the outer scrollport), [data-composer-seat] (the composer), [data-chat-anchor-key] (an anchor row), [data-chat-following-tail] (the pin-to-newest state).
  • The width variable is republished only to the element that holds both a column and its own composer — the nearest common ancestor. That keeps wide markdown tables, the composer card and the width handles consistent with the locked column, without leaking one panel's width into another panel's subtree.
  • Per-column state. Anchor, width, and scrollport overflow are tracked per column, and a MutationObserver plus a ResizeObserver re-adopt a column that React remounted.
  • Scroll handling is a capture-phase listener on document, so one binding survives React remounts; only scrolls belonging to a transcript count as "the reader is scrolling".
  • Idempotent. Nothing is written when the width, the lock state and the target elements are unchanged, so resizing never causes its own jitter.
  • No dependencies and no build tooling. Plain DOM — no React, no bundle step. Its host touchpoints are all optional and guarded: an invisible shell.overlay seat that renders null (so the shell and cordis_inspect can see the bundle is mounted), a freezeContentOnWindowResize service face on ctx.provide, and the DSH locale service for the panel copy. Without any of them the plugin still works.

Known limitations

  • Browser zoom (Ctrl+wheel) changes the font size, so text still re-flows; the reading-position anchor is what pulls the reading line back in that case.
  • A window narrower than the locked width shows a horizontal scrollbar in the transcript. That is the price of never re-wrapping, and it is the behavior the lock is for — lower the width or turn the lock off if you would rather re-flow.
  • Only the primary reading column follows the Width setting; embedded transcripts stay at their own panel-derived width.
  • DSH's internal names and the width formula above are implementation details of 0.2.0-rc.2, not a stable API; a future build can change them.

Repository layout

client/client.js      the browser half — everything this plugin actually does
lib/index.js          the host half — an empty Loader entry, on purpose
cordis.patch.yml      the bundle patch that inserts the Loader entry
package.json          declares dsh.bundle.patch and dsh.client
docs/self-test.md     the measurement behind this README, runnable from DevTools

License

MIT