dsh-focus-overlay 0.7.2 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -10,7 +10,8 @@
10
10
  </p>
11
11
 
12
12
  <p align="center">
13
- <img src="https://badgen.net/npm/v/dsh-focus-overlay" alt="npm version">
13
+ <img src="https://img.shields.io/npm/v/dsh-focus-overlay" alt="npm version">
14
+ <img src="https://img.shields.io/npm/dm/dsh-focus-overlay" alt="npm downloads (monthly)">
14
15
  <img src="https://badgen.net/badge/license/MIT/green" alt="license">
15
16
  <img src="https://badgen.net/badge/dsh/%3E%3D0.1.0-rc.5/blue" alt="dsh version">
16
17
  </p>
@@ -22,6 +23,7 @@
22
23
  - **Fold tool calls** — an assistant turn collapses into a one-line summary
23
24
  - **Quick navigation** — a right-side node navbar with hover preview and click-to-jump
24
25
  - **Auto-focus & reminders** — after a reply completes, optionally auto-enter focus at your question; while in focus, get a toast for a new reply or when the AI is waiting on you
26
+ - **Hotkey F** — press `F` anywhere to enter focus mode instantly (toggleable in settings); typing in an input never triggers it
25
27
 
26
28
  These features are designed to give **small screens** more content space: tucking away the persistent header/composer and tool steps lets the conversation use as much of the screen as possible.
27
29
 
@@ -59,6 +61,7 @@ Once in focus mode, an assistant turn no longer shows every step — it folds in
59
61
  | i18n | Chinese / English copy, follows the UI language |
60
62
  | Plugin configuration card | A collapsible card under "Settings → Plugins → Plugin configuration": navbar toggle, open-position strategy, text-area width — persisted to `localStorage` |
61
63
  | Auto-enter focus | After a reply **completes normally**, auto-open focus at your question; abnormal endings (stop / error / max-tokens / interrupt) never fire |
64
+ | F hotkey | Press `F` anywhere to enter focus mode instantly (default on, toggleable in settings); never fires while typing in an input, auto-repeat ignored |
62
65
  | Reply / waiting reminders | In focus, a "New reply ready + View" toast on completion; an "AI is waiting for your reply + Reply" toast on a question/approval, auto-cleared once answered |
63
66
  | DSH-better-sidebar compatibility | While in focus, auto-hide its top-right panel toggle buttons and any open right/bottom panels (and release the squeezed layout); restored on exit |
64
67
 
@@ -103,7 +106,7 @@ Restart `dsh web` after install.
103
106
 
104
107
  ## Usage
105
108
 
106
- 1. Open a session and click the **"Focus"** button in the session header action row.
109
+ 1. Open a session and click the **"Focus"** button in the session header action row (or press `F` — toggleable in settings).
107
110
  2. You enter the full-screen focus view: a thin top bar (session title + exit) and the conversation only, with tool steps folded into summary lines.
108
111
  3. Hover the right-side dots to preview, click to jump; a centered "↓ back to latest" button appears when you're not at the bottom.
109
112
  4. Press `Esc` or click "Exit focus" to return — the original UI is untouched.
@@ -117,6 +120,7 @@ In the sidebar "Settings → Plugins → Plugin configuration", expand the "Focu
117
120
  | Option | Description |
118
121
  | --- | --- |
119
122
  | Auto-enter focus mode when the AI finishes a reply | On a normal completion: auto-open at your question when closed, or a "New reply ready" toast when open (default off) |
123
+ | Press F to enter focus mode | Press `F` anywhere to enter focus mode instantly; never fires while typing in an input (default on) |
120
124
  | Sync the current reading position when entering focus mode | Open at the message you're reading; off opens at your most recent question (default on) |
121
125
  | Show right-side turn navbar | One navigation dot per user message (turn) — hover to preview, click to jump (default on) |
122
126
  | Text width | 480–1200px slider for the reading column (default 760px) |
package/README.md CHANGED
@@ -8,7 +8,8 @@
8
8
  </p>
9
9
 
10
10
  <p align="center">
11
- <img src="https://badgen.net/npm/v/dsh-focus-overlay" alt="npm version">
11
+ <img src="https://img.shields.io/npm/v/dsh-focus-overlay" alt="npm version">
12
+ <img src="https://img.shields.io/npm/dm/dsh-focus-overlay" alt="npm downloads (monthly)">
12
13
  <img src="https://badgen.net/badge/license/MIT/green" alt="license">
13
14
  <img src="https://badgen.net/badge/dsh/%3E%3D0.1.0-rc.5/blue" alt="dsh version">
14
15
  </p>
@@ -20,6 +21,7 @@
20
21
  - **折叠工具调用** —— 一轮 AI 回复折叠成一句话摘要
21
22
  - **快速导航** —— 右侧节点导航条,悬停预览、点击跳转
22
23
  - **自动专注与提醒** —— 回复完成后可自动进入专注并定位到你的提问;专注中收到新回复、或被 AI 提问等待时弹出提醒
24
+ - **快捷键 F** —— 任意界面按 `F` 一键进入专注模式,可在设置中关闭;在输入框内打字不会误触发
23
25
 
24
26
  这些功能专为**小屏幕**提供更多内容呈现空间:收起常驻的标题/输入区与工具步骤,让有限的屏幕尽可能多地展示对话。
25
27
 
@@ -57,6 +59,7 @@
57
59
  | i18n | 中 / 英文案,跟随界面语言 |
58
60
  | 插件配置卡片 | 在「设置 → 插件 → 插件配置」中的可折叠卡片,含导航条开关、打开定位策略、文字区宽度,持久化到 `localStorage` |
59
61
  | 自动进入专注 | 回复**正常完成**后自动打开专注并定位到本轮你的提问;异常结束(停止 / 报错 / 超 token / 打断)不触发 |
62
+ | F 键快捷键 | 任意界面按 `F` 立即进入专注(默认开,可在设置中关闭);输入框内打字不触发,长按自动忽略 |
60
63
  | 回复 / 等待提醒 | 专注中回复完成弹「新回复已生成 + 查看」;AI 提问 / 审批等待时弹「AI 正在等待你的回复 + 去回复」,回答完自动消失 |
61
64
  | 兼容 DSH-better-sidebar | 进入专注时自动隐藏其右上角的收放面板按钮与已开启的右侧/底部面板,并释放被挤压的布局;退出专注后按原状态还原 |
62
65
 
@@ -101,7 +104,7 @@ dsh web
101
104
 
102
105
  ## 使用
103
106
 
104
- 1. 打开任意会话,点击标题栏操作区的 **「专注」** 按钮。
107
+ 1. 打开任意会话,点击标题栏操作区的 **「专注」** 按钮(或直接按 `F` 键,可在设置中关闭该快捷键)。
105
108
  2. 进入全屏专注视图:顶部只有一条极窄栏(会话标题 + 退出),正文只显示你与 AI 的对话,工具步骤折叠为摘要行。
106
109
  3. 右侧导航圆点可悬停预览、点击跳转;离开底部时右下出现居中的「↓ 回到最新」。
107
110
  4. 按 `Esc` 或点「退出专注」返回原界面,原位置/状态保持不变。
@@ -115,6 +118,7 @@ dsh web
115
118
  | 选项 | 说明 |
116
119
  | --- | --- |
117
120
  | AI完成回复后,自动进入专注模式 | AI 正常完成回复后自动进入并定位到你的提问;已打开时弹「新回复已生成」(默认关) |
121
+ | 按 F 键进入专注模式 | 任意界面按 `F` 立即进入专注模式;输入框内打字不触发(默认开) |
118
122
  | 进入专注模式时,同步当前阅读位置 | 进入时定位到你正在阅读的消息;关闭则定位到你最近一次提问(默认开) |
119
123
  | 显示右侧轮次导航条 | 在右侧显示导航圆点,每个用户消息(一轮)对应一个,悬停预览、点击跳转(默认开) |
120
124
  | 文字区宽度 | 480–1200px 滑块,调整正文阅读列宽(默认 760px) |
package/lib/client.js CHANGED
@@ -272,6 +272,20 @@ window.__ModuleLoader__.load({
272
272
  function onboardingSeen(stored, version) {
273
273
  return stored === version;
274
274
  }
275
+ /** Whether a keydown should enter focus mode via the F hotkey. Pure decision so
276
+ * the guard rails are unit-testable: the pref must be enabled, focus must not
277
+ * already be open, the press must not land in an editable element (composer /
278
+ * inputs — typing "f" must never yank the user into focus mode), no modifier
279
+ * may be held, auto-repeat is ignored, and the key must be F (either case). */
280
+ function hotkeyShouldEnter(e, opts) {
281
+ if (!opts.enabled) return false;
282
+ if (opts.focusOn) return false;
283
+ if (opts.typing) return false;
284
+ if (e.repeat) return false;
285
+ if (e.ctrlKey || e.metaKey || e.altKey) return false;
286
+ const k = typeof e.key === "string" ? e.key : "";
287
+ return k === "f" || k === "F";
288
+ }
275
289
  //#endregion
276
290
  //#region src/client/settings.ts
277
291
  const KEY = "dsh-focus-overlay:prefs";
@@ -279,7 +293,8 @@ window.__ModuleLoader__.load({
279
293
  navbar: true,
280
294
  scroll: "preserve",
281
295
  width: 760,
282
- autoFocus: false
296
+ autoFocus: false,
297
+ hotkey: true
283
298
  };
284
299
  function load() {
285
300
  try {
@@ -815,6 +830,23 @@ window.__ModuleLoader__.load({
815
830
  children: t("settings.autoFocus.hint")
816
831
  })]
817
832
  }),
833
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
834
+ className: "fm-plugin-field",
835
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
836
+ className: "fm-plugin-check",
837
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
838
+ type: "checkbox",
839
+ checked: prefs.hotkey,
840
+ onChange: (e) => prefsStore.update({ hotkey: e.target.checked })
841
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
842
+ className: "fm-plugin-check-label",
843
+ children: t("settings.hotkey")
844
+ })]
845
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
846
+ className: "fm-plugin-field-hint",
847
+ children: t("settings.hotkey.hint")
848
+ })]
849
+ }),
818
850
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
819
851
  className: "fm-plugin-field",
820
852
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
@@ -966,7 +998,8 @@ window.__ModuleLoader__.load({
966
998
  "fullscreen",
967
999
  "fold",
968
1000
  "navbar",
969
- "autoFocus"
1001
+ "autoFocus",
1002
+ "hotkey"
970
1003
  ].map((f) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: t("onboarding.feature." + f) }, f))
971
1004
  }),
972
1005
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
@@ -1090,6 +1123,8 @@ body[data-fm-focus] #root :has(> [data-slot="conversation"]){margin-bottom:0!imp
1090
1123
  "settings.scrollPreserve.hint": "进入时定位到你正在阅读的消息;关闭则定位到你最近一次提问",
1091
1124
  "settings.autoFocus": "AI完成回复后,自动进入专注模式",
1092
1125
  "settings.autoFocus.hint": "AI 正常完成回复后自动进入并定位到你的提问",
1126
+ "settings.hotkey": "按 F 键进入专注模式",
1127
+ "settings.hotkey.hint": "在任意界面按下 F 立即进入专注模式;在输入框内打字不会触发",
1093
1128
  "settings.width": "文字区宽度",
1094
1129
  "settings.width.hint": "专注模式正文的阅读列宽(480–1200px)",
1095
1130
  "empty": "暂无打开的会话",
@@ -1121,6 +1156,7 @@ body[data-fm-focus] #root :has(> [data-slot="conversation"]){margin-bottom:0!imp
1121
1156
  "onboarding.feature.fold": "折叠工具调用 —— 把 AI 的命令、编辑、搜索等步骤折叠成一行摘要",
1122
1157
  "onboarding.feature.navbar": "右侧导航条 —— 按用户消息快速跳转,悬停预览",
1123
1158
  "onboarding.feature.autoFocus": "自动专注与提醒 —— 回复完成自动进入专注,AI 提问 / 等待时提醒",
1159
+ "onboarding.feature.hotkey": "快捷键 F —— 任意界面按 F 一键进入专注,可在设置中关闭",
1124
1160
  "onboarding.configure.title": "快速配置",
1125
1161
  "onboarding.laterNote": "这些设置随时可在「设置 → 插件 → 插件配置」中更改。",
1126
1162
  "onboarding.openSettings": "打开设置",
@@ -1141,6 +1177,8 @@ body[data-fm-focus] #root :has(> [data-slot="conversation"]){margin-bottom:0!imp
1141
1177
  "settings.scrollPreserve.hint": "Open at the message you're reading; off opens at your most recent question",
1142
1178
  "settings.autoFocus": "Auto-enter focus mode when the AI finishes a reply",
1143
1179
  "settings.autoFocus.hint": "Auto-open at your question after a normal reply",
1180
+ "settings.hotkey": "Press F to enter focus mode",
1181
+ "settings.hotkey.hint": "Press F anywhere to enter focus mode instantly; typing in an input never triggers it",
1144
1182
  "settings.width": "Text width",
1145
1183
  "settings.width.hint": "Reading column width (480–1200px)",
1146
1184
  "empty": "No open session",
@@ -1172,6 +1210,7 @@ body[data-fm-focus] #root :has(> [data-slot="conversation"]){margin-bottom:0!imp
1172
1210
  "onboarding.feature.fold": "Folded tool calls — collapses commands, edits and searches into one summary line",
1173
1211
  "onboarding.feature.navbar": "Right-side navbar — jump between user messages with hover previews",
1174
1212
  "onboarding.feature.autoFocus": "Auto-focus & reminders — auto-enter after a reply, notify while the AI waits",
1213
+ "onboarding.feature.hotkey": "Hotkey F — press F anywhere to enter focus mode (toggleable in settings)",
1175
1214
  "onboarding.configure.title": "Quick setup",
1176
1215
  "onboarding.laterNote": "You can change these anytime in Settings → Plugins → Plugin configuration.",
1177
1216
  "onboarding.openSettings": "Open settings",
@@ -1281,6 +1320,23 @@ body[data-fm-focus] #root :has(> [data-slot="conversation"]){margin-bottom:0!imp
1281
1320
  if (unsubSession) unsubSession();
1282
1321
  };
1283
1322
  });
1323
+ ctx.effect(() => {
1324
+ const onKey = (e) => {
1325
+ const el = e.target;
1326
+ const tag = el ? el.tagName : "";
1327
+ const typing = !!el && (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || el.isContentEditable);
1328
+ if (!hotkeyShouldEnter(e, {
1329
+ enabled: prefsStore.get().hotkey,
1330
+ typing,
1331
+ focusOn: focusStore.get()
1332
+ })) return;
1333
+ e.preventDefault();
1334
+ focusStore.captureChatAnchor();
1335
+ focusStore.set(true);
1336
+ };
1337
+ window.addEventListener("keydown", onKey, true);
1338
+ return () => window.removeEventListener("keydown", onKey, true);
1339
+ });
1284
1340
  ctx.slots.inject("shell.overlay", () => ctx.slots.register({
1285
1341
  name: "shell.overlay",
1286
1342
  id: "focus-mode-overlay",
package/lib/index.mjs CHANGED
@@ -7,7 +7,8 @@ const FocusSettingsSchema = z.object({
7
7
  navbar: z.boolean().default(true),
8
8
  scroll: z.union(["preserve", "bottom"]).default("preserve"),
9
9
  width: z.number().default(760),
10
- autoFocus: z.boolean().default(false)
10
+ autoFocus: z.boolean().default(false),
11
+ hotkey: z.boolean().default(true)
11
12
  });
12
13
  function apply(ctx) {
13
14
  ctx.inject(["settings"], (settingsCtx) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-focus-overlay",
3
- "version": "0.7.2",
3
+ "version": "0.8.1",
4
4
  "description": "Focus Mode for the dsh web GUI: a full-screen reading overlay that hides chrome and folds the AI tool-call flow into summaries, reusing the official Markdown / image primitives.",
5
5
  "type": "module",
6
6
  "main": "lib/index.mjs",