dsh-remote-mobile 1.5.0 → 1.7.0
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/CHANGELOG.md +45 -0
- package/README.md +32 -2
- package/README_EN.md +32 -2
- package/lib/bridge/compat.d.ts +8 -2
- package/lib/bridge/compat.js +44 -13
- package/lib/client.js +349 -281
- package/lib/index.js +55 -35
- package/lib/styles/style-snippets.js +136 -58
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -143,45 +143,65 @@ export function apply(ctx, config = {}) {
|
|
|
143
143
|
}
|
|
144
144
|
// 6. 服务就绪时输出提示横幅与接入地址
|
|
145
145
|
let printed = false;
|
|
146
|
+
let disposed = false;
|
|
147
|
+
let timer1 = null;
|
|
148
|
+
let timer2 = null;
|
|
149
|
+
try {
|
|
150
|
+
ctx.on?.('dispose', () => {
|
|
151
|
+
disposed = true;
|
|
152
|
+
if (timer1)
|
|
153
|
+
clearTimeout(timer1);
|
|
154
|
+
if (timer2)
|
|
155
|
+
clearTimeout(timer2);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
catch { }
|
|
146
159
|
const printReadyBanner = () => {
|
|
147
|
-
|
|
160
|
+
// 生命周期守卫:若上下文已废弃/进入 dispose,放弃回调
|
|
161
|
+
if (disposed || printed)
|
|
148
162
|
return;
|
|
149
163
|
printed = true;
|
|
150
|
-
if (ctx.webServer && ctx.webServer.server) {
|
|
151
|
-
patchHttpServerWithVirtualizer(ctx.webServer.server, gateMiddleware, store, styleStore);
|
|
152
|
-
}
|
|
153
164
|
try {
|
|
154
|
-
const
|
|
155
|
-
if (
|
|
156
|
-
|
|
165
|
+
const webServer = (typeof ctx.get === 'function' ? ctx.get('webServer') : undefined) || ctx.webServer;
|
|
166
|
+
if (webServer?.server) {
|
|
167
|
+
patchHttpServerWithVirtualizer(webServer.server, gateMiddleware, store, styleStore);
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
const conn = typeof ctx.get === 'function' ? ctx.get('connection') : undefined;
|
|
171
|
+
if (conn)
|
|
172
|
+
attachConnectionAuth(conn);
|
|
173
|
+
}
|
|
174
|
+
catch (e) {
|
|
175
|
+
ctx.logger?.debug?.('[dsh-remote-mobile] 就绪回调获取 connection 失败:', e);
|
|
176
|
+
}
|
|
177
|
+
const tsIp = getLocalTailscaleIp();
|
|
178
|
+
const lanIp = getLocalLanIp();
|
|
179
|
+
const port = webServer?.port ?? 3080;
|
|
180
|
+
const opts = store.getOptions();
|
|
181
|
+
const divider = '─'.repeat(72);
|
|
182
|
+
console.log(`\n┌${divider}`);
|
|
183
|
+
console.log(`│ [dsh-remote-mobile] 官方临时 Token 鉴权已接管,PC/移动端访问无需携带官方token`);
|
|
184
|
+
console.log(`│ 远程安全网关已就绪,支持手机浏览器访问:`);
|
|
185
|
+
console.log(`│ • 本机回环: http://127.0.0.1:${port}`);
|
|
186
|
+
if (lanIp && lanIp !== '127.0.0.1') {
|
|
187
|
+
console.log(`│ • 局域网: http://${lanIp}:${port} (同 Wi-Fi 局域网直连)`);
|
|
188
|
+
}
|
|
189
|
+
if (tsIp) {
|
|
190
|
+
console.log(`│ • 虚拟私网: http://${tsIp}:${port} (Tailscale 私网异地直连)`);
|
|
191
|
+
}
|
|
192
|
+
console.log(`│ 访问与配置说明:`);
|
|
193
|
+
console.log(`│ - 手机/远程设备打开对应地址即可直接访问`);
|
|
194
|
+
console.log(`│ - 在本机打开 Web 界面 ->「设置」->「远程与移动端」进行安全管理:`);
|
|
195
|
+
console.log(`│ 可开启免密直连(局域网/Tailscale)、查看 6 位临时配对码或设置长期密码`);
|
|
196
|
+
console.log(`│ - 项目文档: https://github.com/IceApriler/dsh-remote-mobile`);
|
|
197
|
+
console.log(`└${divider}\n`);
|
|
198
|
+
ctx.logger?.info?.(`[dsh-remote-mobile] 移动端远程控制与安全门禁已激活 (上下文虚拟化桥接就绪,样式片段: ${styleStore.list().length} 个)`);
|
|
199
|
+
if (tsIp) {
|
|
200
|
+
ctx.logger?.info?.(`[dsh-remote-mobile] Tailscale 地址: http://${tsIp}:${port} (免密直连: ${opts.allowTailscale ? '已开启' : '已关闭'})`);
|
|
201
|
+
}
|
|
157
202
|
}
|
|
158
203
|
catch (e) {
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
const tsIp = getLocalTailscaleIp();
|
|
162
|
-
const lanIp = getLocalLanIp();
|
|
163
|
-
const port = ctx.webServer?.port ?? 3080;
|
|
164
|
-
const opts = store.getOptions();
|
|
165
|
-
const divider = '─'.repeat(72);
|
|
166
|
-
console.log(`\n┌${divider}`);
|
|
167
|
-
console.log(`│ [dsh-remote-mobile] 官方临时 Token 鉴权已接管,PC/移动端访问无需携带官方token`);
|
|
168
|
-
console.log(`│ 远程安全网关已就绪,支持手机浏览器访问:`);
|
|
169
|
-
console.log(`│ • 本机回环: http://127.0.0.1:${port}`);
|
|
170
|
-
if (lanIp && lanIp !== '127.0.0.1') {
|
|
171
|
-
console.log(`│ • 局域网: http://${lanIp}:${port} (同 Wi-Fi 局域网直连)`);
|
|
172
|
-
}
|
|
173
|
-
if (tsIp) {
|
|
174
|
-
console.log(`│ • 虚拟私网: http://${tsIp}:${port} (Tailscale 私网异地直连)`);
|
|
175
|
-
}
|
|
176
|
-
console.log(`│ 访问与配置说明:`);
|
|
177
|
-
console.log(`│ - 手机/远程设备打开对应地址即可直接访问`);
|
|
178
|
-
console.log(`│ - 在本机打开 Web 界面 ->「设置」->「远程与移动端」进行安全管理:`);
|
|
179
|
-
console.log(`│ 可开启免密直连(局域网/Tailscale)、查看 6 位临时配对码或设置长期密码`);
|
|
180
|
-
console.log(`│ - 项目文档: https://github.com/IceApriler/dsh-remote-mobile`);
|
|
181
|
-
console.log(`└${divider}\n`);
|
|
182
|
-
ctx.logger?.info?.(`[dsh-remote-mobile] 移动端远程控制与安全门禁已激活 (上下文虚拟化桥接就绪,样式片段: ${styleStore.list().length} 个)`);
|
|
183
|
-
if (tsIp) {
|
|
184
|
-
ctx.logger?.info?.(`[dsh-remote-mobile] Tailscale 地址: http://${tsIp}:${port} (免密直连: ${opts.allowTailscale ? '已开启' : '已关闭'})`);
|
|
204
|
+
// 上下文若在并发或极端时序下重载,静默退出,防止未捕获异常导致主进程崩溃
|
|
185
205
|
}
|
|
186
206
|
};
|
|
187
207
|
// 1) 优先在 loader 插件树就绪后紧跟官方提示打印
|
|
@@ -190,7 +210,7 @@ export function apply(ctx, config = {}) {
|
|
|
190
210
|
const settled = loader?.await?.();
|
|
191
211
|
if (settled && typeof settled.then === 'function') {
|
|
192
212
|
settled.then(() => {
|
|
193
|
-
setTimeout(printReadyBanner, 120);
|
|
213
|
+
timer1 = setTimeout(printReadyBanner, 120);
|
|
194
214
|
}).catch((e) => {
|
|
195
215
|
ctx.logger?.debug?.('[dsh-remote-mobile] loader await 异常:', e);
|
|
196
216
|
});
|
|
@@ -200,7 +220,7 @@ export function apply(ctx, config = {}) {
|
|
|
200
220
|
ctx.logger?.debug?.('[dsh-remote-mobile] 获取 loader 失败:', e);
|
|
201
221
|
}
|
|
202
222
|
// 2) 兜底定时器(避免无 loader 环境时不输出)
|
|
203
|
-
setTimeout(printReadyBanner, 1500);
|
|
223
|
+
timer2 = setTimeout(printReadyBanner, 1500);
|
|
204
224
|
}
|
|
205
225
|
// 导出所有子模块类型与核心工具
|
|
206
226
|
export * from './auth/tailscale.js';
|
|
@@ -62,11 +62,39 @@ const PRESET_SIDEBAR_CSS = `
|
|
|
62
62
|
position: relative !important;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
/* 核心修复:显式将三列锁定到各自的 Grid 轨道!
|
|
66
|
+
官方 AppFrame 为三栏 CSS Grid 布局(sidebarCol + centerCol + rightbarCol)。
|
|
67
|
+
当 sidebarCol 设为 position: fixed 后脱离 Grid 自动流,会导致后续两列前移:
|
|
68
|
+
centerCol 移入第 1 列(0px),rightbarCol 移入第 2 列(1fr 全宽) 并全屏覆盖在
|
|
69
|
+
对话区上方,其透明容器拦截全部点击与触摸手势(Issue #6)。
|
|
70
|
+
通过显式指定 grid-column,确保每列始终位于设计轨道,杜绝错位覆盖。 */
|
|
71
|
+
[class*="_frame"]:has([class*="_sidebarCol"]) > [class*="_sidebarCol"] {
|
|
72
|
+
grid-column: 1 !important;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
[class*="_frame"]:has([class*="_sidebarCol"]) [class*="_centerCol"],
|
|
76
|
+
[class*="_frame"]:has([class*="_sidebarCol"]) > [class*="_centerCol"] {
|
|
77
|
+
grid-column: 2 !important;
|
|
66
78
|
width: 100vw !important;
|
|
67
79
|
max-width: 100vw !important;
|
|
68
80
|
}
|
|
69
81
|
|
|
82
|
+
[class*="_frame"]:has([class*="_sidebarCol"]) > [class*="_rightbarCol"] {
|
|
83
|
+
grid-column: 3 !important;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* 右侧栏折叠态穿透防御:折叠时宽度清零并禁用指针事件,杜绝透明层与边缘手柄拦截触摸 */
|
|
87
|
+
[class*="_frame"][data-rightbar-collapsed] [class*="_rightbarCol"],
|
|
88
|
+
[class*="_rightbarCol"]:not(:has([data-sidebar-right-open])) {
|
|
89
|
+
width: 0px !important;
|
|
90
|
+
min-width: 0px !important;
|
|
91
|
+
pointer-events: none !important;
|
|
92
|
+
}
|
|
93
|
+
[class*="_rightbarCol"]:has([data-sidebar-right-open]),
|
|
94
|
+
[class*="_frame"]:not([data-rightbar-collapsed]) [class*="_rightbarCol"] {
|
|
95
|
+
pointer-events: auto !important;
|
|
96
|
+
}
|
|
97
|
+
|
|
70
98
|
/* 2. 侧边栏最外层容器:作为整体抽屉浮层(阴影仅加在最外层,严禁污染内部列表) */
|
|
71
99
|
[class*="_sidebarCol"] {
|
|
72
100
|
position: fixed !important;
|
|
@@ -116,6 +144,48 @@ const PRESET_SIDEBAR_CSS = `
|
|
|
116
144
|
background: rgb(0 0 0 / 24%);
|
|
117
145
|
}
|
|
118
146
|
|
|
147
|
+
/* 兜底防御:当左侧栏实际处于折叠状态(内部含 _collapsed 类,如官方仅收起内部但 frame
|
|
148
|
+
未及时打上 data-sidebar-collapsed)时,严禁渲染遮罩,彻底杜绝黑纱常驻与点击拦截 */
|
|
149
|
+
[class*="_frame"]:has([class*="_sidebarCol"]:has([class*="_collapsed"]))::after,
|
|
150
|
+
[class*="_frame"][data-sidebar-collapsed]::after {
|
|
151
|
+
content: none !important;
|
|
152
|
+
display: none !important;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* 展开态自适应宽度:支持 360px 窄屏与大屏手机灵活伸缩,覆盖官方内联 280px */
|
|
156
|
+
[class*="_sidebarCol"]:not(:has([class*="_collapsed"])) {
|
|
157
|
+
width: min(85vw, 320px) !important;
|
|
158
|
+
max-width: 85vw !important;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* 条目触控热区友好化:行高 44px + 次级操作按钮 36px,防误触相邻会话并易于点击更多操作 */
|
|
162
|
+
[class*="_sidebarCol"] [role="treeitem"],
|
|
163
|
+
[class*="_sidebarCol"] [data-dsh-part="sidebar-entry"] {
|
|
164
|
+
min-height: 44px !important;
|
|
165
|
+
}
|
|
166
|
+
[class*="_sidebarCol"] [role="treeitem"] button,
|
|
167
|
+
[class*="_sidebarCol"] [role="treeitem"] [role="button"] {
|
|
168
|
+
min-width: 36px !important;
|
|
169
|
+
min-height: 36px !important;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/* 触屏设备没有 hover:工作区/会话右侧操作按钮(更多操作 ⋯、新建会话 + 等)
|
|
173
|
+
在 PC 依赖鼠标悬停显现,移动端必须常显,保证触屏用户可随时直接交互 */
|
|
174
|
+
[class*="_sidebarCol"] [class*="_rowActions"] {
|
|
175
|
+
opacity: 1 !important;
|
|
176
|
+
visibility: visible !important;
|
|
177
|
+
display: flex !important;
|
|
178
|
+
align-items: center !important;
|
|
179
|
+
flex-shrink: 0 !important;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* 标题容器弹性自适应并防文字挤出视野,超长文本自然截断不破坏按钮布局 */
|
|
183
|
+
[class*="_sidebarCol"] [class*="_projectText"],
|
|
184
|
+
[class*="_sidebarCol"] [class*="_sessionText"] {
|
|
185
|
+
min-width: 0 !important;
|
|
186
|
+
flex: 1 1 auto !important;
|
|
187
|
+
}
|
|
188
|
+
|
|
119
189
|
/* 内层根节点铺满抽屉:覆盖官方响应式脚本写入的内联 width,
|
|
120
190
|
消除「外层 ~320 / 内层内联 280」的宽度差与右缘空白条 */
|
|
121
191
|
[class*="_sidebarCol"] > [data-slot="sidebar"] > div {
|
|
@@ -144,15 +214,16 @@ const PRESET_SIDEBAR_CSS = `
|
|
|
144
214
|
display: none !important;
|
|
145
215
|
}
|
|
146
216
|
|
|
147
|
-
/* 折叠状态下,Logo 按钮悬浮在屏幕左上角作为展开把手(与 dsh-draggable-nav 拖拽脚本联动)
|
|
217
|
+
/* 折叠状态下,Logo 按钮悬浮在屏幕左上角作为展开把手(与 dsh-draggable-nav 拖拽脚本联动)
|
|
218
|
+
放大到 44px 触控尺寸,并避让刘海屏/灵动岛顶部安全区 */
|
|
148
219
|
[class*="_sidebarCol"] [class*="_collapsed"] [class*="_logoRow"],
|
|
149
220
|
[class*="_frame"][data-sidebar-collapsed] [class*="_sidebarCol"] [class*="_logoRow"] {
|
|
150
221
|
position: fixed !important;
|
|
151
|
-
top:
|
|
152
|
-
left:
|
|
153
|
-
width:
|
|
154
|
-
height:
|
|
155
|
-
border-radius:
|
|
222
|
+
top: max(12px, env(safe-area-inset-top)) !important;
|
|
223
|
+
left: 12px !important;
|
|
224
|
+
width: 44px !important;
|
|
225
|
+
height: 44px !important;
|
|
226
|
+
border-radius: 12px !important;
|
|
156
227
|
background: var(--dsw-alias-bg-layer-1, rgba(255, 255, 255, 0.95)) !important;
|
|
157
228
|
backdrop-filter: blur(12px) !important;
|
|
158
229
|
-webkit-backdrop-filter: blur(12px) !important;
|
|
@@ -197,8 +268,17 @@ const PRESET_SIDEBAR_CSS = `
|
|
|
197
268
|
min-height: 0 !important;
|
|
198
269
|
}
|
|
199
270
|
}
|
|
271
|
+
|
|
272
|
+
/* 8. 兼容处理:隐藏生态插件中重复挂载的小鲸鱼悬浮按钮 (#dshRemoteWhale) 避免入口与手势冲突 */
|
|
273
|
+
#dshRemoteWhale,
|
|
274
|
+
button[id="dshRemoteWhale"],
|
|
275
|
+
[data-dsh-plugin="remote-web-ui"] {
|
|
276
|
+
display: none !important;
|
|
277
|
+
pointer-events: none !important;
|
|
278
|
+
visibility: hidden !important;
|
|
279
|
+
}
|
|
200
280
|
`;
|
|
201
|
-
/**
|
|
281
|
+
/** 设置面板预设:官方设置弹窗上下堆叠 + 顶部导航横滑 + 内容纵向自然滚览 */
|
|
202
282
|
const PRESET_SETTINGS_CSS = `
|
|
203
283
|
/* ===== dsh-remote-mobile · 设置面板适配 ===== */
|
|
204
284
|
/* 注:窄屏媒体查询由注入层按端包裹 */
|
|
@@ -217,38 +297,9 @@ const PRESET_SETTINGS_CSS = `
|
|
|
217
297
|
overscroll-behavior: contain !important;
|
|
218
298
|
}
|
|
219
299
|
|
|
220
|
-
/* 移动端设置弹窗顶部固定提示:内容较宽(530px 等比微缩)需左右滑动浏览。
|
|
221
|
-
挂在 overlay 容器 ::before 上(absolute 定位相对 fixed overlay),
|
|
222
|
-
不随弹窗内容滚动,也不参与 flex 居中布局。内测声明等通用 Modal
|
|
223
|
-
(_root 容器,不在本选择器集合内)不会出现此提示。 */
|
|
224
|
-
[data-slot*="overlay"]:has([role="dialog"])::before,
|
|
225
|
-
[class*="_overlay"]:has([role="dialog"])::before,
|
|
226
|
-
[class*="_modalWrapper"]:has([role="dialog"])::before {
|
|
227
|
-
content: "↔ 左右滑动浏览设置";
|
|
228
|
-
position: absolute;
|
|
229
|
-
top: 16px;
|
|
230
|
-
left: 50%;
|
|
231
|
-
transform: translateX(-50%);
|
|
232
|
-
z-index: 100006 !important;
|
|
233
|
-
box-sizing: border-box;
|
|
234
|
-
white-space: nowrap;
|
|
235
|
-
max-width: calc(100vw - 32px);
|
|
236
|
-
overflow: hidden;
|
|
237
|
-
text-overflow: ellipsis;
|
|
238
|
-
background: rgba(0, 0, 0, 0.62);
|
|
239
|
-
color: #ffffff;
|
|
240
|
-
font-size: 12px;
|
|
241
|
-
line-height: 18px;
|
|
242
|
-
border-radius: 999px;
|
|
243
|
-
padding: 4px 14px;
|
|
244
|
-
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
|
|
245
|
-
pointer-events: none;
|
|
246
|
-
text-align: center;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
300
|
/* 弹窗卡片:仅命中设置弹窗——外层 overlay 容器内含 role=dialog(设置弹窗由
|
|
250
301
|
data-slot overlay / overlay 类包裹)。内测声明等通用 Modal 直接挂在 body、
|
|
251
|
-
无 data-slot overlay
|
|
302
|
+
无 data-slot overlay,天然排除。卡片设为纵向滚动,取消横向滑动。 */
|
|
252
303
|
[data-slot*="overlay"]:has([role="dialog"]) [role="dialog"],
|
|
253
304
|
[data-slot*="overlay"]:has([role="dialog"]) [class*="_dialog"],
|
|
254
305
|
[data-slot*="overlay"]:has([role="dialog"]) [class*="_modalContent"],
|
|
@@ -260,25 +311,22 @@ const PRESET_SETTINGS_CSS = `
|
|
|
260
311
|
[class*="_modalWrapper"]:has([role="dialog"]) [class*="_modalContent"],
|
|
261
312
|
[class*="_settingsModal"] {
|
|
262
313
|
position: relative !important;
|
|
263
|
-
width:
|
|
264
|
-
max-width:
|
|
265
|
-
height: 86vh !important;
|
|
314
|
+
width: 96vw !important;
|
|
315
|
+
max-width: 96vw !important;
|
|
266
316
|
height: 86dvh !important;
|
|
267
|
-
max-height:
|
|
268
|
-
max-height: 88dvh !important;
|
|
317
|
+
max-height: 86dvh !important;
|
|
269
318
|
margin: auto !important;
|
|
270
319
|
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4) !important;
|
|
271
|
-
border-radius:
|
|
320
|
+
border-radius: 14px !important;
|
|
272
321
|
background: var(--dsw-alias-bg-layer-1, #ffffff) !important;
|
|
273
|
-
overflow-x:
|
|
274
|
-
overflow-y:
|
|
322
|
+
overflow-x: hidden !important;
|
|
323
|
+
overflow-y: auto !important;
|
|
275
324
|
-webkit-overflow-scrolling: touch !important;
|
|
276
325
|
overscroll-behavior: contain !important;
|
|
277
|
-
font-size:
|
|
326
|
+
font-size: 14px !important;
|
|
278
327
|
}
|
|
279
328
|
|
|
280
|
-
/*
|
|
281
|
-
content 右侧内容)统一 zoom 0.88,保证整窗一致缩放。 */
|
|
329
|
+
/* 取消 zoom 微缩,恢复正常比例 */
|
|
282
330
|
[data-slot*="overlay"]:has([role="dialog"]) [role="dialog"] > *,
|
|
283
331
|
[data-slot*="overlay"]:has([role="dialog"]) [class*="_dialog"] > *,
|
|
284
332
|
[data-slot*="overlay"]:has([role="dialog"]) [class*="_modalContent"] > *,
|
|
@@ -289,12 +337,10 @@ const PRESET_SETTINGS_CSS = `
|
|
|
289
337
|
[class*="_modalWrapper"]:has([role="dialog"]) [class*="_dialog"] > *,
|
|
290
338
|
[class*="_modalWrapper"]:has([role="dialog"]) [class*="_modalContent"] > *,
|
|
291
339
|
[class*="_settingsModal"] > * {
|
|
292
|
-
zoom:
|
|
340
|
+
zoom: 1 !important;
|
|
293
341
|
}
|
|
294
342
|
|
|
295
|
-
/*
|
|
296
|
-
内容且字号更精致。左侧导航列表不强制宽度,保持官方窄宽。
|
|
297
|
-
同样限定在设置弹窗上下文内,避免波及通用 Modal。 */
|
|
343
|
+
/* 取消 530px 定宽:主体内容 div 铺满宽度,高度自然自适应 */
|
|
298
344
|
[data-slot*="overlay"]:has([role="dialog"]) [role="dialog"] > div,
|
|
299
345
|
[data-slot*="overlay"]:has([role="dialog"]) [class*="_dialog"] > div,
|
|
300
346
|
[data-slot*="overlay"]:has([role="dialog"]) [class*="_modalContent"] > div,
|
|
@@ -305,9 +351,41 @@ const PRESET_SETTINGS_CSS = `
|
|
|
305
351
|
[class*="_modalWrapper"]:has([role="dialog"]) [class*="_dialog"] > div,
|
|
306
352
|
[class*="_modalWrapper"]:has([role="dialog"]) [class*="_modalContent"] > div,
|
|
307
353
|
[class*="_settingsModal"] > div {
|
|
308
|
-
min-width:
|
|
309
|
-
width:
|
|
310
|
-
height:
|
|
354
|
+
min-width: 0 !important;
|
|
355
|
+
width: 100% !important;
|
|
356
|
+
height: auto !important;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/* 上下堆叠:只命中带 nav 的设置类弹窗,通用 Modal 不受影响 */
|
|
360
|
+
[role="dialog"]:has(nav) {
|
|
361
|
+
flex-direction: column !important;
|
|
362
|
+
}
|
|
363
|
+
[role="dialog"]:has(nav) > nav {
|
|
364
|
+
width: 100% !important;
|
|
365
|
+
flex: none !important;
|
|
366
|
+
}
|
|
367
|
+
[role="dialog"] [class*="_navTitle"] {
|
|
368
|
+
display: none !important;
|
|
369
|
+
}
|
|
370
|
+
[role="dialog"] [class*="_navList"] {
|
|
371
|
+
display: flex !important;
|
|
372
|
+
flex-direction: row !important;
|
|
373
|
+
overflow-x: auto !important;
|
|
374
|
+
overflow-y: hidden !important;
|
|
375
|
+
gap: 4px !important;
|
|
376
|
+
padding: 4px 2px !important;
|
|
377
|
+
-webkit-overflow-scrolling: touch !important;
|
|
378
|
+
}
|
|
379
|
+
[role="dialog"] [class*="_navList"] > * {
|
|
380
|
+
flex: none !important;
|
|
381
|
+
white-space: nowrap !important;
|
|
382
|
+
}
|
|
383
|
+
/* 移动端收紧官方内容区的厚 padding(原 24px/32px),释放横向显示空间 */
|
|
384
|
+
[role="dialog"] [class*="_content"] {
|
|
385
|
+
width: 100% !important;
|
|
386
|
+
min-width: 0 !important;
|
|
387
|
+
flex: 1 1 auto !important;
|
|
388
|
+
padding: 10px 4px !important;
|
|
311
389
|
}
|
|
312
390
|
|
|
313
391
|
/* 重置插件市场等弹窗在窄屏隐藏左侧 nav 的行为:保持导航列表可见。
|
|
@@ -616,8 +694,8 @@ export const BUILTIN_PRESETS = [
|
|
|
616
694
|
id: 'preset-settings',
|
|
617
695
|
name: { zh: '设置面板适配', en: 'Settings Panel' },
|
|
618
696
|
description: {
|
|
619
|
-
zh: '
|
|
620
|
-
en: '
|
|
697
|
+
zh: '官方设置弹窗上下堆叠自适应浏览:顶部导航横滑切换,内容纵向自然滚览,告别横向截断。',
|
|
698
|
+
en: 'Stacks settings dialog vertically: horizontal scrollable nav tabs at top, vertical flowing content.',
|
|
621
699
|
},
|
|
622
700
|
defaultPcEnabled: false,
|
|
623
701
|
defaultMobileEnabled: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-remote-mobile",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "DeepSeek Harness 远程与移动端安全网关插件:零修改 DSH 底层代码安全开放局域网与 Tailscale 连接 | DeepSeek Harness (DSH) Remote & Mobile Security Guard: safely opens Tailscale/LAN with zero core modifications, QR scan auth, RSA encryption & brute-force defense.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|