dsh-in-hand 1.7.7 → 1.7.8
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.md +15 -0
- package/lib/page.html +58 -5
- package/lib/sw.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -266,6 +266,21 @@ PDF / ZIP / MP4)。这是**按内容识别**,不是"按内容放行" ——
|
|
|
266
266
|
|
|
267
267
|

|
|
268
268
|
|
|
269
|
+
### v1.7.8:长会话不再整屏闪、附件信封不再露标签
|
|
270
|
+
|
|
271
|
+
图片的骨架流光用 `inset:0` 绝对定位,却忘了给 `.md-imgwrap` 定位,包含块一路退到**视口**。
|
|
272
|
+
长会话里总有还没进入视口的懒加载图,它们永远带着 `.loading`,于是整屏多出一条 1.35s
|
|
273
|
+
无限循环的亮带(用户原话「反复闪屏」),`translateX(55%)` 还把页面从 390 撑到 601。现在
|
|
274
|
+
流光被关进图片盒、不吃点击,离屏图也不再挂任何动画:
|
|
275
|
+
|
|
276
|
+
| 改前(整屏亮带,可横向滚到 601) | 改后(390,静止) |
|
|
277
|
+
| --- | --- |
|
|
278
|
+
|  |  |
|
|
279
|
+
|
|
280
|
+
同一轮的第二个修复:DSH 给模型看的 `<path>…</path><type>image</type><content>…</content>`
|
|
281
|
+
信封,以前在手机上原样显示成 XML(某会话第一条消息整条都是它),现在渲染成图片卡,
|
|
282
|
+
拿不到图时仍是那条 36px 提示条。
|
|
283
|
+
|
|
269
284
|
### 页面为什么不做整页重建
|
|
270
285
|
|
|
271
286
|
页面每 3 秒轮询一次,但**数据没变就完全不碰 DOM**,只刷新右上角时间戳。首版是
|
package/lib/page.html
CHANGED
|
@@ -1083,7 +1083,7 @@ html,body{overflow-x:clip}
|
|
|
1083
1083
|
② min-height:0:没拿到 intrinsic size 之前**不占位撑高**,加载完再长出来,
|
|
1084
1084
|
避免"先铺一块 44px 空气、再跳一下"的布局抖动;
|
|
1085
1085
|
③ 圆角与边框在图片盒子上,加载失败换成提示条时形状/位置不变。 */
|
|
1086
|
-
.md-imgwrap{display:block;width:100%;max-width:100%;min-height:0;padding:0;margin:var(--sp-2) 0;border:0;
|
|
1086
|
+
.md-imgwrap{display:block;position:relative;width:100%;max-width:100%;min-height:0;padding:0;margin:var(--sp-2) 0;border:0;
|
|
1087
1087
|
background:none;text-align:left;border-radius:var(--dsw-radius-md);overflow:hidden}
|
|
1088
1088
|
.md-img{display:block;width:100%;max-width:100%;height:auto;min-height:0;border:1px solid var(--line);
|
|
1089
1089
|
border-radius:var(--dsw-radius-md);background:var(--panel2)}
|
|
@@ -1240,12 +1240,17 @@ html,body{overflow-x:clip}
|
|
|
1240
1240
|
@keyframes nudge{0%,100%{transform:translateX(0)}30%{transform:translateX(-2px)}70%{transform:translateX(2px)}}
|
|
1241
1241
|
|
|
1242
1242
|
/* 图片:先落一块纸纹,显影时轻轻放大一点。注意 .loading 是 JS **之后**才加的 ——
|
|
1243
|
-
JS 不跑时 .md-img 完全可见,绝不留隐形图。
|
|
1243
|
+
JS 不跑时 .md-img 完全可见,绝不留隐形图。
|
|
1244
|
+
2026-10-22(v1.7.8):.md-imgwrap 必须 position:relative —— 否则下面这条
|
|
1245
|
+
`inset:0` 的绝对定位流光会以**视口**为包含块:长会话里只要有一张懒加载图片
|
|
1246
|
+
还没进入视口,它就一直带着 .loading,于是整屏出现一条 1.35s 无限循环的亮带
|
|
1247
|
+
(用户报的"反复闪屏"),还把它自己的 translateX(55%) 算进文档宽度,
|
|
1248
|
+
把 390 的页面撑到 601(横向可滚)。同时流光绝不能吃点击。 */
|
|
1244
1249
|
.md-img{transition:opacity var(--mo-slow) var(--mo-ease),transform var(--mo-slow) var(--mo-ease)}
|
|
1245
1250
|
.md-imgwrap.loading .md-img{opacity:0;transform:scale(1.012)}
|
|
1246
1251
|
.md-imgwrap.done .md-img{opacity:1;transform:none}
|
|
1247
1252
|
.md-imgwrap.loading::after{
|
|
1248
|
-
content:'';position:absolute;inset:0;
|
|
1253
|
+
content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
|
|
1249
1254
|
background:linear-gradient(100deg,transparent 18%,var(--mo-ink) 42%,transparent 62%);
|
|
1250
1255
|
animation:sheen 1.35s var(--mo-ease) infinite;
|
|
1251
1256
|
}
|
|
@@ -2436,12 +2441,54 @@ function blocksInto(el, text){
|
|
|
2436
2441
|
return el
|
|
2437
2442
|
}
|
|
2438
2443
|
|
|
2444
|
+
/* DSH 把「用户贴了一个附件」序列化成一段**信封文本**给模型看:
|
|
2445
|
+
<path>C:\…\a.png</path><type>image</type><content>image/png image, 1398x1542 px, 437517 bytes</content>
|
|
2446
|
+
这段协议在手机上也原样显示过 —— 用户看到的是 XML 标签(2026-10-22 的
|
|
2447
|
+
「Token Router 说明书与印刷 PDF」会话,第一条消息整条都是它)。v1.7.8 解析成
|
|
2448
|
+
真正的图片 / 文件卡(同样走 imgNode 的失败兜底),文本里不再留标签。 */
|
|
2449
|
+
var ENVELOPE_RE = /<path>([\s\S]*?)<\/path>\s*<type>\s*(image|file)\s*<\/type>\s*<content>([\s\S]*?)<\/content>/g
|
|
2450
|
+
function splitAttachmentEnvelopes(text){
|
|
2451
|
+
var images = [], files = []
|
|
2452
|
+
var clean = String(text == null ? '' : text).replace(ENVELOPE_RE, function(all, p, kind, meta){
|
|
2453
|
+
var path = String(p || '').trim()
|
|
2454
|
+
if (!path) return ''
|
|
2455
|
+
var info = { path:path, meta:String(meta || '').replace(/\s+/g, ' ').trim() }
|
|
2456
|
+
if (kind === 'image') images.push(info)
|
|
2457
|
+
else files.push(info)
|
|
2458
|
+
return ''
|
|
2459
|
+
})
|
|
2460
|
+
return {
|
|
2461
|
+
text: clean.replace(/\n{3,}/g, '\n\n').replace(/^\s+|\s+$/g, ''),
|
|
2462
|
+
images: images,
|
|
2463
|
+
files: files
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
function envelopeAttachmentsNode(env){
|
|
2467
|
+
var wrap = document.createElement('div'); wrap.className = 'message-attachments'
|
|
2468
|
+
var i
|
|
2469
|
+
for (i = 0; i < env.images.length; i++) {
|
|
2470
|
+
var a = env.images[i]
|
|
2471
|
+
var node = imgNode(fileUrlFor(a.path), baseName(a.path))
|
|
2472
|
+
if (a.meta) node.title = (node.title ? node.title + ' · ' : '') + a.meta
|
|
2473
|
+
wrap.appendChild(node)
|
|
2474
|
+
}
|
|
2475
|
+
for (i = 0; i < env.files.length; i++) {
|
|
2476
|
+
var f = env.files[i]
|
|
2477
|
+
wrap.appendChild(fileCard(fileUrlFor(f.path), baseName(f.path), '文件'))
|
|
2478
|
+
}
|
|
2479
|
+
return wrap.children.length ? wrap : null
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2439
2482
|
function bubNode(text, opts){
|
|
2440
2483
|
var o = opts || {}
|
|
2441
2484
|
var wrap = document.createElement('div'); wrap.className = 'bubwrap'
|
|
2442
2485
|
var b = document.createElement('div')
|
|
2443
2486
|
b.className = 'bub'
|
|
2444
2487
|
var s = String(text == null ? '' : text)
|
|
2488
|
+
var env = splitAttachmentEnvelopes(s)
|
|
2489
|
+
if (env.images.length || env.files.length) s = env.text
|
|
2490
|
+
var attach = envelopeAttachmentsNode(env)
|
|
2491
|
+
if (attach) b.appendChild(attach)
|
|
2445
2492
|
var parts = s.split('```')
|
|
2446
2493
|
if (parts.length > 1) {
|
|
2447
2494
|
for (var i = 0; i < parts.length; i++) {
|
|
@@ -5280,8 +5327,11 @@ window.fetch = function (u, o) {
|
|
|
5280
5327
|
}
|
|
5281
5328
|
|
|
5282
5329
|
/* 4c. 图片:没加载完的才标 .loading(骨架流光),加载完 .done 显影。
|
|
5283
|
-
注意 .loading 是这里**加上**的 —— JS 不跑时图片本来就直接可见。
|
|
5330
|
+
注意 .loading 是这里**加上**的 —— JS 不跑时图片本来就直接可见。
|
|
5331
|
+
2026-10-22(v1.7.8):只给**贴着视口**的图挂流光。长会话里几十张懒加载图
|
|
5332
|
+
永远在视口外,以前它们会一直挂着 .loading,流光动画也就永远在跑(闪屏)。 */
|
|
5284
5333
|
var wraps = doc.querySelectorAll('.md-imgwrap')
|
|
5334
|
+
var vh = window.innerHeight || 800
|
|
5285
5335
|
for (var j = 0; j < wraps.length; j++) {
|
|
5286
5336
|
var w = wraps[j]
|
|
5287
5337
|
if (w.classList.contains('done')) continue
|
|
@@ -5291,7 +5341,10 @@ window.fetch = function (u, o) {
|
|
|
5291
5341
|
w.classList.remove('loading')
|
|
5292
5342
|
w.classList.add('done')
|
|
5293
5343
|
} else {
|
|
5294
|
-
w.
|
|
5344
|
+
var wr = w.getBoundingClientRect()
|
|
5345
|
+
var near = wr.bottom > -vh && wr.top < vh * 2
|
|
5346
|
+
if (near) w.classList.add('loading')
|
|
5347
|
+
else w.classList.remove('loading')
|
|
5295
5348
|
}
|
|
5296
5349
|
}
|
|
5297
5350
|
|
package/lib/sw.js
CHANGED
|
@@ -46,7 +46,8 @@ const SHELL = ['/taskwatch', '/taskwatch/icon-192.png', '/taskwatch/icon-512.png
|
|
|
46
46
|
// 又足以把整站打死。别再加回来。
|
|
47
47
|
// v17(v1.7.7):页面换了正文图片的兜底渲染(坏图 → 44px 以内提示条)与抽屉图标
|
|
48
48
|
// (字符字形 → 内联 SVG)。外壳里的 icon-192 也是预缓存的,一起升号清掉旧壳。
|
|
49
|
-
|
|
49
|
+
// v18(v1.7.8):图片流光的包含块修好(长会话不再整屏闪)+ 附件信封改成图片卡。
|
|
50
|
+
const CACHE = 'taskwatch-v18'
|
|
50
51
|
|
|
51
52
|
const JSON_HEADERS = { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }
|
|
52
53
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-in-hand",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.8",
|
|
4
4
|
"description": "掌上 DSH:DeepSeek Harness 的手机端,不用装 App——会话、实时对话、交付文件、后台任务与待批准。 / DSH in hand: the phone client for DeepSeek Harness with no app to install.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|