dsh-bridge-gateway 0.1.6 → 0.1.7
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 +11 -0
- package/client/client.js +202 -43
- package/client/index.js +218 -43
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
本项目 `dsh-bridge-gateway` 是基于 [dsh-bridge](https://github.com/wenbin-wb/dsh-bridge) 的移植增强分支,在保留原版能力之外,重点新增「公网直连网关」。
|
|
4
4
|
|
|
5
|
+
## [0.1.7] - 2026-09-12
|
|
6
|
+
|
|
7
|
+
### 变更(移动端第三批:标题行密度)
|
|
8
|
+
- 对话/轨迹/上下文 改为标题行内的「对话 ▾」下拉按钮(弃用胶囊方案):插在标准模式与访达图标之间,原生样式观感,点开下拉切换视图,文案动态读取、语言无关。
|
|
9
|
+
- 修复 tabs 胶囊与标题行折成两行的问题:删除级联中残留的 titleRow wrap 规则,标题行强制单行。
|
|
10
|
+
- 原生 corner 按钮(打开右侧边栏)负边距归零,单行布局下不再被裁切。
|
|
11
|
+
|
|
12
|
+
### 修复
|
|
13
|
+
- workbuddy-connect 的 Reasoning levels 按钮:移动端删除文字节点只留图标(此前裁切露字),悬停宽度锁定不再引起工具栏抖动。
|
|
14
|
+
- 修复标签文案同步无条件写入 textContent 触发 MutationObserver 死循环导致页面卡死的问题。
|
|
15
|
+
|
|
5
16
|
## [0.1.6] - 2026-09-12
|
|
6
17
|
|
|
7
18
|
### 修复(移动端第二批:布局密度与面板)
|
package/client/client.js
CHANGED
|
@@ -3829,62 +3829,97 @@ function injectMobileStyles() {
|
|
|
3829
3829
|
display: none !important;
|
|
3830
3830
|
}
|
|
3831
3831
|
|
|
3832
|
-
/* ---- \u5BF9\u8BDD/\u8F68\u8FF9/\u4E0A\u4E0B\u6587 \u6807\u7B7E\
|
|
3833
|
-
\u539F\
|
|
3834
|
-
\
|
|
3835
|
-
\
|
|
3836
|
-
header[class*="wSkVaW_header"] {
|
|
3837
|
-
position: relative !important;
|
|
3838
|
-
}
|
|
3832
|
+
/* ---- \u5BF9\u8BDD/\u8F68\u8FF9/\u4E0A\u4E0B\u6587 \u6807\u7B7E\u6298\u53E0\u8FDB\u6807\u9898\u884C\uFF08\u540C\u4E00\u884C\uFF09 ----
|
|
3833
|
+
\u539F\u751F tablist \u6574\u884C\u9690\u85CF\uFF1B\u7531 setupMobileExperience \u6CE8\u5165\u4E00\u4E2A\u539F\u751F\u6837\u5F0F\u7684
|
|
3834
|
+
\u300C\u5BF9\u8BDD\u300D\u6309\u94AE\uFF08\u63D2\u5728\u6807\u51C6\u6A21\u5F0F\u4E0E\u8BBF\u8FBE\u56FE\u6807\u4E4B\u95F4\uFF09\uFF0C\u70B9\u51FB\u5F39\u4E0B\u62C9\u5207\u6362\u4E09\u4E2A\u89C6\u56FE\u3002
|
|
3835
|
+
\u6309\u94AE\u6587\u6848\u4E0E\u9009\u9879\u6587\u6848\u90FD\u4ECE\u539F\u751F tab \u52A8\u6001\u8BFB\u53D6\uFF0C\u8BED\u8A00\u65E0\u5173\u3002 */
|
|
3839
3836
|
div[class*="wSkVaW_tabs"] {
|
|
3840
|
-
position: absolute !important;
|
|
3841
|
-
top: 38px !important;
|
|
3842
|
-
right: 6px !important;
|
|
3843
|
-
left: auto !important;
|
|
3844
|
-
width: auto !important;
|
|
3845
|
-
max-width: 62vw !important;
|
|
3846
|
-
height: 30px !important;
|
|
3847
|
-
display: inline-flex !important;
|
|
3848
|
-
align-items: center !important;
|
|
3849
|
-
gap: 2px !important;
|
|
3850
|
-
padding: 2px !important;
|
|
3851
|
-
border-radius: 999px !important;
|
|
3852
|
-
background: var(--dsw-alias-tooltip-bg, #43454a) !important;
|
|
3853
|
-
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3) !important;
|
|
3854
|
-
overflow-x: auto !important;
|
|
3855
|
-
scrollbar-width: none !important;
|
|
3856
|
-
z-index: 30 !important;
|
|
3857
|
-
}
|
|
3858
|
-
div[class*="wSkVaW_tabs"]::-webkit-scrollbar {
|
|
3859
3837
|
display: none !important;
|
|
3860
3838
|
}
|
|
3861
|
-
|
|
3862
|
-
|
|
3839
|
+
.dsh-mobile-tab-btn {
|
|
3840
|
+
display: inline-flex !important;
|
|
3841
|
+
align-items: center !important;
|
|
3842
|
+
gap: 5px !important;
|
|
3843
|
+
position: relative !important;
|
|
3844
|
+
height: 28px !important;
|
|
3845
|
+
min-height: 28px !important;
|
|
3863
3846
|
padding: 0 10px !important;
|
|
3864
3847
|
border-radius: 999px !important;
|
|
3865
|
-
|
|
3848
|
+
background: var(--dsw-alias-bg-layer-2, rgba(127, 127, 127, 0.12)) !important;
|
|
3849
|
+
color: var(--dsw-alias-label-primary, inherit) !important;
|
|
3850
|
+
font-size: 12.5px !important;
|
|
3851
|
+
line-height: 28px !important;
|
|
3866
3852
|
white-space: nowrap !important;
|
|
3853
|
+
cursor: pointer !important;
|
|
3854
|
+
}
|
|
3855
|
+
.dsh-mobile-tab-btn svg {
|
|
3867
3856
|
flex: 0 0 auto !important;
|
|
3868
3857
|
}
|
|
3858
|
+
.dsh-mobile-tab-dropdown {
|
|
3859
|
+
position: absolute !important;
|
|
3860
|
+
top: calc(100% + 6px) !important;
|
|
3861
|
+
left: 0 !important;
|
|
3862
|
+
min-width: 132px !important;
|
|
3863
|
+
z-index: 60 !important;
|
|
3864
|
+
padding: 4px !important;
|
|
3865
|
+
border-radius: 12px !important;
|
|
3866
|
+
background: var(--dsw-alias-bg-layer-2, #2c2c2e) !important;
|
|
3867
|
+
border: 1px solid var(--dsw-alias-border-l2, transparent) !important;
|
|
3868
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35) !important;
|
|
3869
|
+
}
|
|
3870
|
+
.dsh-mobile-tab-dropdown .dsh-mobile-tab-option {
|
|
3871
|
+
display: flex !important;
|
|
3872
|
+
align-items: center !important;
|
|
3873
|
+
justify-content: space-between !important;
|
|
3874
|
+
gap: 8px !important;
|
|
3875
|
+
width: 100% !important;
|
|
3876
|
+
padding: 7px 10px !important;
|
|
3877
|
+
border: 0 !important;
|
|
3878
|
+
border-radius: 8px !important;
|
|
3879
|
+
background: transparent !important;
|
|
3880
|
+
color: var(--dsw-alias-label-primary, inherit) !important;
|
|
3881
|
+
font-size: 13px !important;
|
|
3882
|
+
line-height: 18px !important;
|
|
3883
|
+
cursor: pointer !important;
|
|
3884
|
+
text-align: left !important;
|
|
3885
|
+
}
|
|
3886
|
+
.dsh-mobile-tab-dropdown .dsh-mobile-tab-option:hover {
|
|
3887
|
+
background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.15)) !important;
|
|
3888
|
+
}
|
|
3889
|
+
.dsh-mobile-tab-dropdown .dsh-mobile-tab-option[data-active='true'] {
|
|
3890
|
+
color: var(--dsw-alias-brand-text, var(--dsw-alias-label-primary, inherit)) !important;
|
|
3891
|
+
font-weight: 600 !important;
|
|
3892
|
+
}
|
|
3869
3893
|
|
|
3870
3894
|
/* ---- \u9876\u680F\u300C\u6807\u51C6\u6A21\u5F0F\u300D\u4E0E\u300C\u5BF9\u8BDD\u7BA1\u7406\u300D\u91CD\u53E0\u4FEE\u590D ----
|
|
3871
3895
|
\u5B9E\u6D4B\uFF08390px\uFF09\uFF1A\u6807\u51C6\u6A21\u5F0F(\u5728 titleCluster \u5185) \u53F3\u8FB9\u754C 102\uFF0C
|
|
3872
3896
|
\u5BF9\u8BDD\u7BA1\u7406(\u5728 headerUtilities \u5185) \u5DE6\u8FB9\u754C 91 \u2192 \u6C34\u5E73\u91CD\u53E0 11px\u3002
|
|
3873
|
-
\
|
|
3874
|
-
\
|
|
3875
|
-
\u4FEE\u590D\uFF1A\u5141\u8BB8 titleRow \u6362\u884C + \u8BA9\u4E24\u4FA7\u5404\u81EA\u53EF\u6536\u7F29\u5E76\u9650\u5BBD\u3002 */
|
|
3897
|
+
\u4FEE\u590D\uFF1AtitleRow \u5F3A\u5236\u5355\u884C\uFF08tabs \u5DF2\u5E76\u5165\u540C\u4E00\u884C\uFF09\uFF0C\u8D85\u5BBD\u65F6 titleCluster
|
|
3898
|
+
\u5185\u90E8\u622A\u65AD\u800C\u4E0D\u662F\u6362\u884C\u2014\u2014\u6362\u884C\u4F1A\u8BA9 header \u53D8\u4E24\u884C\u3001\u6324\u538B\u4E2D\u95F4\u7A7A\u95F4\u3002 */
|
|
3876
3899
|
div[class*="wSkVaW_titleRow"],
|
|
3877
3900
|
div[class*="_titleRow"] {
|
|
3878
|
-
|
|
3879
|
-
|
|
3901
|
+
display: flex !important;
|
|
3902
|
+
flex-direction: row !important;
|
|
3903
|
+
flex-wrap: nowrap !important;
|
|
3904
|
+
align-items: center !important;
|
|
3905
|
+
flex: 1 1 auto !important;
|
|
3906
|
+
min-width: 0 !important;
|
|
3880
3907
|
column-gap: 8px !important;
|
|
3881
|
-
overflow:
|
|
3908
|
+
overflow: hidden !important;
|
|
3882
3909
|
}
|
|
3883
3910
|
div[class*="wSkVaW_titleCluster"],
|
|
3884
3911
|
div[class*="_titleCluster"] {
|
|
3885
|
-
flex:
|
|
3912
|
+
flex: 0 1 auto !important;
|
|
3886
3913
|
min-width: 0 !important;
|
|
3887
3914
|
max-width: 100% !important;
|
|
3915
|
+
overflow: hidden !important;
|
|
3916
|
+
}
|
|
3917
|
+
/* \u539F\u751F corner \u6309\u94AE\u5E26 margin-right:-16px \u60AC\u6302\u8BBE\u8BA1\uFF0C\u5728\u5355\u884C + overflow:hidden \u4E0B
|
|
3918
|
+
\u4F1A\u88AB\u88C1\u6389 16px\u2014\u2014\u5F52\u96F6\u540E\u6574\u884C\u521A\u597D\u653E\u4E0B\uFF1Acluster69 + utilities123 + corner28 */
|
|
3919
|
+
div[class*="wSkVaW_headerCorner"] {
|
|
3920
|
+
margin-right: 0 !important;
|
|
3921
|
+
margin-left: 0 !important;
|
|
3922
|
+
flex: 0 0 auto !important;
|
|
3888
3923
|
}
|
|
3889
3924
|
div[class*="wSkVaW_headerActions"],
|
|
3890
3925
|
div[class*="_headerActions"] {
|
|
@@ -4055,13 +4090,9 @@ function injectMobileStyles() {
|
|
|
4055
4090
|
box-sizing: border-box !important;
|
|
4056
4091
|
}
|
|
4057
4092
|
|
|
4058
|
-
/* ---- \u9876\u90E8\u63A7\u4EF6\u9632\u6EA2\u51FA\u88C1\u5207\uFF08320px \u4E0B main \u5206\u652F chip \u6EA2\u51FA 39px \u88AB\u88C1\uFF09 ----
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
flex-wrap: wrap !important;
|
|
4062
|
-
row-gap: 6px !important;
|
|
4063
|
-
overflow: visible !important;
|
|
4064
|
-
}
|
|
4093
|
+
/* ---- \u9876\u90E8\u63A7\u4EF6\u9632\u6EA2\u51FA\u88C1\u5207\uFF08320px \u4E0B main \u5206\u652F chip \u6EA2\u51FA 39px \u88AB\u88C1\uFF09 ----
|
|
4094
|
+
\u6CE8\u610F\uFF1AtitleRow \u7684 wrap \u89C4\u5219\u5DF2\u5220\u9664\u2014\u2014tabs \u6298\u53E0\u8FDB\u6807\u9898\u884C\u540E\u5FC5\u987B\u5355\u884C\uFF0C
|
|
4095
|
+
\u8FD9\u91CC\u7684 wrap \u4F1A\u5728\u7EA7\u8054\u4E2D\u8D62\u8FC7\u524D\u9762\u7684 nowrap\uFF0C\u5BFC\u81F4\u6807\u9898\u884C\u91CD\u65B0\u6298\u6210\u4E24\u884C\u3002 */
|
|
4065
4096
|
button[class*="_7rgC5q_chip"],
|
|
4066
4097
|
button[class*="cubgiG_seat"],
|
|
4067
4098
|
div[class*="_7rgC5q_chipWrap"] {
|
|
@@ -4211,6 +4242,15 @@ function injectMobileStyles() {
|
|
|
4211
4242
|
justify-content: center !important;
|
|
4212
4243
|
gap: 0 !important;
|
|
4213
4244
|
font-size: 0 !important;
|
|
4245
|
+
/* \u60AC\u505C\u9501\u5B9A\uFF1A\u5BBD\u5EA6\u4E0E\u4F4D\u79FB\u90FD\u4E0D\u53D8\uFF0C\u675C\u7EDD\u5DE5\u5177\u680F/\u5BF9\u8BDD\u6846\u6296\u52A8 */
|
|
4246
|
+
transition: none !important;
|
|
4247
|
+
border-radius: 8px !important;
|
|
4248
|
+
}
|
|
4249
|
+
div[class*="uV2eYG_trailing"] span > button:not([class]):hover {
|
|
4250
|
+
width: 26px !important;
|
|
4251
|
+
min-width: 26px !important;
|
|
4252
|
+
padding: 0 2px !important;
|
|
4253
|
+
background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.15)) !important;
|
|
4214
4254
|
}
|
|
4215
4255
|
div[class*="uV2eYG_trailing"] span > button:not([class]) svg {
|
|
4216
4256
|
flex: 0 0 auto !important;
|
|
@@ -4775,6 +4815,125 @@ function setupMobileExperience(rpcCall, ctx) {
|
|
|
4775
4815
|
const panelObserver = new MutationObserver(ensurePanelCloseButton);
|
|
4776
4816
|
panelObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["class"] });
|
|
4777
4817
|
window.addEventListener("resize", ensurePanelCloseButton);
|
|
4818
|
+
const mobileTabState = { btn: null, dropdown: null };
|
|
4819
|
+
const nativeTabs = () => [...document.querySelectorAll('[role="tablist"] [role="tab"]')];
|
|
4820
|
+
const closeTabDropdown = () => {
|
|
4821
|
+
if (mobileTabState.dropdown) {
|
|
4822
|
+
mobileTabState.dropdown.remove();
|
|
4823
|
+
mobileTabState.dropdown = null;
|
|
4824
|
+
}
|
|
4825
|
+
};
|
|
4826
|
+
const renderTabDropdown = () => {
|
|
4827
|
+
closeTabDropdown();
|
|
4828
|
+
if (!mobileTabState.btn) return;
|
|
4829
|
+
const dropdown = document.createElement("div");
|
|
4830
|
+
dropdown.className = "dsh-mobile-tab-dropdown";
|
|
4831
|
+
const tabs = nativeTabs();
|
|
4832
|
+
tabs.forEach((tabEl) => {
|
|
4833
|
+
const isActive = tabEl.getAttribute("aria-selected") === "true";
|
|
4834
|
+
const option = document.createElement("button");
|
|
4835
|
+
option.type = "button";
|
|
4836
|
+
option.className = "dsh-mobile-tab-option";
|
|
4837
|
+
option.setAttribute("data-active", isActive ? "true" : "false");
|
|
4838
|
+
const name2 = document.createElement("span");
|
|
4839
|
+
name2.textContent = tabEl.textContent.replace(/\s+/g, " ").trim();
|
|
4840
|
+
option.appendChild(name2);
|
|
4841
|
+
if (isActive) {
|
|
4842
|
+
const check = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
4843
|
+
check.setAttribute("width", "14");
|
|
4844
|
+
check.setAttribute("height", "14");
|
|
4845
|
+
check.setAttribute("viewBox", "0 0 24 24");
|
|
4846
|
+
check.setAttribute("fill", "none");
|
|
4847
|
+
check.setAttribute("stroke", "currentColor");
|
|
4848
|
+
check.setAttribute("stroke-width", "2.5");
|
|
4849
|
+
check.setAttribute("stroke-linecap", "round");
|
|
4850
|
+
check.setAttribute("stroke-linejoin", "round");
|
|
4851
|
+
check.innerHTML = '<polyline points="20 6 9 17 4 12"></polyline>';
|
|
4852
|
+
option.appendChild(check);
|
|
4853
|
+
}
|
|
4854
|
+
option.onclick = (e) => {
|
|
4855
|
+
e.stopPropagation();
|
|
4856
|
+
tabEl.click();
|
|
4857
|
+
closeTabDropdown();
|
|
4858
|
+
syncTabButtonLabel();
|
|
4859
|
+
};
|
|
4860
|
+
dropdown.appendChild(option);
|
|
4861
|
+
});
|
|
4862
|
+
mobileTabState.btn.appendChild(dropdown);
|
|
4863
|
+
mobileTabState.dropdown = dropdown;
|
|
4864
|
+
};
|
|
4865
|
+
const syncTabButtonLabel = () => {
|
|
4866
|
+
if (!mobileTabState.btn || !mobileTabState.btn.isConnected) return;
|
|
4867
|
+
const active = nativeTabs().find((t) => t.getAttribute("aria-selected") === "true");
|
|
4868
|
+
const labelEl = mobileTabState.btn.querySelector(".dsh-mobile-tab-btn-label");
|
|
4869
|
+
if (!labelEl || !active) return;
|
|
4870
|
+
const name2 = active.textContent.replace(/\s+/g, " ").trim();
|
|
4871
|
+
if (labelEl.textContent !== name2) labelEl.textContent = name2;
|
|
4872
|
+
};
|
|
4873
|
+
const ensureTabButton = () => {
|
|
4874
|
+
if (typeof window === "undefined" || window.innerWidth > 768) return;
|
|
4875
|
+
const titleRow = document.querySelector('div[class*="wSkVaW_titleRow"]');
|
|
4876
|
+
const cluster = titleRow ? titleRow.querySelector('div[class*="wSkVaW_titleCluster"]') : null;
|
|
4877
|
+
if (!titleRow || !cluster) {
|
|
4878
|
+
closeTabDropdown();
|
|
4879
|
+
if (mobileTabState.btn) {
|
|
4880
|
+
mobileTabState.btn.remove();
|
|
4881
|
+
mobileTabState.btn = null;
|
|
4882
|
+
}
|
|
4883
|
+
return;
|
|
4884
|
+
}
|
|
4885
|
+
if (mobileTabState.btn && mobileTabState.btn.isConnected && titleRow.contains(mobileTabState.btn)) {
|
|
4886
|
+
syncTabButtonLabel();
|
|
4887
|
+
return;
|
|
4888
|
+
}
|
|
4889
|
+
document.querySelectorAll(".dsh-mobile-tab-btn").forEach((el) => el.remove());
|
|
4890
|
+
const tabBtn = document.createElement("button");
|
|
4891
|
+
tabBtn.type = "button";
|
|
4892
|
+
const pillBtn = titleRow.querySelector('div[class*="wSkVaW_titleCluster"] button');
|
|
4893
|
+
const utilBtn = titleRow.querySelector('div[class*="wSkVaW_headerUtilities"] button');
|
|
4894
|
+
const mimic = pillBtn && pillBtn.className || utilBtn && utilBtn.className || "";
|
|
4895
|
+
tabBtn.className = (mimic ? mimic + " " : "") + "dsh-mobile-tab-btn";
|
|
4896
|
+
tabBtn.innerHTML = `<span class="dsh-mobile-tab-btn-label">\u5BF9\u8BDD</span><svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>`;
|
|
4897
|
+
tabBtn.onclick = (e) => {
|
|
4898
|
+
e.stopPropagation();
|
|
4899
|
+
if (mobileTabState.dropdown) closeTabDropdown();
|
|
4900
|
+
else renderTabDropdown();
|
|
4901
|
+
};
|
|
4902
|
+
titleRow.insertBefore(tabBtn, cluster.nextSibling);
|
|
4903
|
+
mobileTabState.btn = tabBtn;
|
|
4904
|
+
syncTabButtonLabel();
|
|
4905
|
+
};
|
|
4906
|
+
const cleanReasoningButtons = () => {
|
|
4907
|
+
if (typeof window === "undefined" || window.innerWidth > 768) return;
|
|
4908
|
+
document.querySelectorAll('div[class*="uV2eYG_trailing"] span > button:not([class])').forEach((btn) => {
|
|
4909
|
+
if (btn.dataset.dshTextCleaned === "1") return;
|
|
4910
|
+
[...btn.childNodes].forEach((node) => {
|
|
4911
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
4912
|
+
if (node.tagName.toLowerCase() === "svg" || typeof node.querySelector === "function" && node.querySelector("svg")) return;
|
|
4913
|
+
}
|
|
4914
|
+
node.remove();
|
|
4915
|
+
});
|
|
4916
|
+
btn.dataset.dshTextCleaned = "1";
|
|
4917
|
+
});
|
|
4918
|
+
};
|
|
4919
|
+
const titleExtrasObserver = new MutationObserver(() => {
|
|
4920
|
+
ensureTabButton();
|
|
4921
|
+
cleanReasoningButtons();
|
|
4922
|
+
});
|
|
4923
|
+
titleExtrasObserver.observe(document.body, { childList: true, subtree: true });
|
|
4924
|
+
window.addEventListener("resize", () => {
|
|
4925
|
+
if (window.innerWidth > 768) closeTabDropdown();
|
|
4926
|
+
});
|
|
4927
|
+
document.addEventListener(
|
|
4928
|
+
"click",
|
|
4929
|
+
(e) => {
|
|
4930
|
+
if (!mobileTabState.dropdown) return;
|
|
4931
|
+
if (!mobileTabState.dropdown.contains(e.target) && !e.target.closest(".dsh-mobile-tab-btn")) closeTabDropdown();
|
|
4932
|
+
},
|
|
4933
|
+
true
|
|
4934
|
+
);
|
|
4935
|
+
ensureTabButton();
|
|
4936
|
+
cleanReasoningButtons();
|
|
4778
4937
|
document.addEventListener("click", (e) => {
|
|
4779
4938
|
if (typeof window === "undefined" || window.innerWidth > 768) return;
|
|
4780
4939
|
const trigger = e.target.closest('button[aria-label*="\u9762\u677F"], button[aria-label*="\u5DE5\u4F5C\u533A"], div[class*="toggleCluster"] button, button[class*="subagent"], div[class*="headerActions"] button, div[class*="titleRow"] button');
|
package/client/index.js
CHANGED
|
@@ -3426,62 +3426,97 @@ function injectMobileStyles() {
|
|
|
3426
3426
|
display: none !important;
|
|
3427
3427
|
}
|
|
3428
3428
|
|
|
3429
|
-
/* ---- 对话/轨迹/上下文
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
header[class*="wSkVaW_header"] {
|
|
3434
|
-
position: relative !important;
|
|
3435
|
-
}
|
|
3429
|
+
/* ---- 对话/轨迹/上下文 标签折叠进标题行(同一行) ----
|
|
3430
|
+
原生 tablist 整行隐藏;由 setupMobileExperience 注入一个原生样式的
|
|
3431
|
+
「对话」按钮(插在标准模式与访达图标之间),点击弹下拉切换三个视图。
|
|
3432
|
+
按钮文案与选项文案都从原生 tab 动态读取,语言无关。 */
|
|
3436
3433
|
div[class*="wSkVaW_tabs"] {
|
|
3437
|
-
position: absolute !important;
|
|
3438
|
-
top: 38px !important;
|
|
3439
|
-
right: 6px !important;
|
|
3440
|
-
left: auto !important;
|
|
3441
|
-
width: auto !important;
|
|
3442
|
-
max-width: 62vw !important;
|
|
3443
|
-
height: 30px !important;
|
|
3444
|
-
display: inline-flex !important;
|
|
3445
|
-
align-items: center !important;
|
|
3446
|
-
gap: 2px !important;
|
|
3447
|
-
padding: 2px !important;
|
|
3448
|
-
border-radius: 999px !important;
|
|
3449
|
-
background: var(--dsw-alias-tooltip-bg, #43454a) !important;
|
|
3450
|
-
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3) !important;
|
|
3451
|
-
overflow-x: auto !important;
|
|
3452
|
-
scrollbar-width: none !important;
|
|
3453
|
-
z-index: 30 !important;
|
|
3454
|
-
}
|
|
3455
|
-
div[class*="wSkVaW_tabs"]::-webkit-scrollbar {
|
|
3456
3434
|
display: none !important;
|
|
3457
3435
|
}
|
|
3458
|
-
|
|
3459
|
-
|
|
3436
|
+
.dsh-mobile-tab-btn {
|
|
3437
|
+
display: inline-flex !important;
|
|
3438
|
+
align-items: center !important;
|
|
3439
|
+
gap: 5px !important;
|
|
3440
|
+
position: relative !important;
|
|
3441
|
+
height: 28px !important;
|
|
3442
|
+
min-height: 28px !important;
|
|
3460
3443
|
padding: 0 10px !important;
|
|
3461
3444
|
border-radius: 999px !important;
|
|
3462
|
-
|
|
3445
|
+
background: var(--dsw-alias-bg-layer-2, rgba(127, 127, 127, 0.12)) !important;
|
|
3446
|
+
color: var(--dsw-alias-label-primary, inherit) !important;
|
|
3447
|
+
font-size: 12.5px !important;
|
|
3448
|
+
line-height: 28px !important;
|
|
3463
3449
|
white-space: nowrap !important;
|
|
3450
|
+
cursor: pointer !important;
|
|
3451
|
+
}
|
|
3452
|
+
.dsh-mobile-tab-btn svg {
|
|
3464
3453
|
flex: 0 0 auto !important;
|
|
3465
3454
|
}
|
|
3455
|
+
.dsh-mobile-tab-dropdown {
|
|
3456
|
+
position: absolute !important;
|
|
3457
|
+
top: calc(100% + 6px) !important;
|
|
3458
|
+
left: 0 !important;
|
|
3459
|
+
min-width: 132px !important;
|
|
3460
|
+
z-index: 60 !important;
|
|
3461
|
+
padding: 4px !important;
|
|
3462
|
+
border-radius: 12px !important;
|
|
3463
|
+
background: var(--dsw-alias-bg-layer-2, #2c2c2e) !important;
|
|
3464
|
+
border: 1px solid var(--dsw-alias-border-l2, transparent) !important;
|
|
3465
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35) !important;
|
|
3466
|
+
}
|
|
3467
|
+
.dsh-mobile-tab-dropdown .dsh-mobile-tab-option {
|
|
3468
|
+
display: flex !important;
|
|
3469
|
+
align-items: center !important;
|
|
3470
|
+
justify-content: space-between !important;
|
|
3471
|
+
gap: 8px !important;
|
|
3472
|
+
width: 100% !important;
|
|
3473
|
+
padding: 7px 10px !important;
|
|
3474
|
+
border: 0 !important;
|
|
3475
|
+
border-radius: 8px !important;
|
|
3476
|
+
background: transparent !important;
|
|
3477
|
+
color: var(--dsw-alias-label-primary, inherit) !important;
|
|
3478
|
+
font-size: 13px !important;
|
|
3479
|
+
line-height: 18px !important;
|
|
3480
|
+
cursor: pointer !important;
|
|
3481
|
+
text-align: left !important;
|
|
3482
|
+
}
|
|
3483
|
+
.dsh-mobile-tab-dropdown .dsh-mobile-tab-option:hover {
|
|
3484
|
+
background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.15)) !important;
|
|
3485
|
+
}
|
|
3486
|
+
.dsh-mobile-tab-dropdown .dsh-mobile-tab-option[data-active='true'] {
|
|
3487
|
+
color: var(--dsw-alias-brand-text, var(--dsw-alias-label-primary, inherit)) !important;
|
|
3488
|
+
font-weight: 600 !important;
|
|
3489
|
+
}
|
|
3466
3490
|
|
|
3467
3491
|
/* ---- 顶栏「标准模式」与「对话管理」重叠修复 ----
|
|
3468
3492
|
实测(390px):标准模式(在 titleCluster 内) 右边界 102,
|
|
3469
3493
|
对话管理(在 headerUtilities 内) 左边界 91 → 水平重叠 11px。
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
修复:允许 titleRow 换行 + 让两侧各自可收缩并限宽。 */
|
|
3494
|
+
修复:titleRow 强制单行(tabs 已并入同一行),超宽时 titleCluster
|
|
3495
|
+
内部截断而不是换行——换行会让 header 变两行、挤压中间空间。 */
|
|
3473
3496
|
div[class*="wSkVaW_titleRow"],
|
|
3474
3497
|
div[class*="_titleRow"] {
|
|
3475
|
-
|
|
3476
|
-
|
|
3498
|
+
display: flex !important;
|
|
3499
|
+
flex-direction: row !important;
|
|
3500
|
+
flex-wrap: nowrap !important;
|
|
3501
|
+
align-items: center !important;
|
|
3502
|
+
flex: 1 1 auto !important;
|
|
3503
|
+
min-width: 0 !important;
|
|
3477
3504
|
column-gap: 8px !important;
|
|
3478
|
-
overflow:
|
|
3505
|
+
overflow: hidden !important;
|
|
3479
3506
|
}
|
|
3480
3507
|
div[class*="wSkVaW_titleCluster"],
|
|
3481
3508
|
div[class*="_titleCluster"] {
|
|
3482
|
-
flex:
|
|
3509
|
+
flex: 0 1 auto !important;
|
|
3483
3510
|
min-width: 0 !important;
|
|
3484
3511
|
max-width: 100% !important;
|
|
3512
|
+
overflow: hidden !important;
|
|
3513
|
+
}
|
|
3514
|
+
/* 原生 corner 按钮带 margin-right:-16px 悬挂设计,在单行 + overflow:hidden 下
|
|
3515
|
+
会被裁掉 16px——归零后整行刚好放下:cluster69 + utilities123 + corner28 */
|
|
3516
|
+
div[class*="wSkVaW_headerCorner"] {
|
|
3517
|
+
margin-right: 0 !important;
|
|
3518
|
+
margin-left: 0 !important;
|
|
3519
|
+
flex: 0 0 auto !important;
|
|
3485
3520
|
}
|
|
3486
3521
|
div[class*="wSkVaW_headerActions"],
|
|
3487
3522
|
div[class*="_headerActions"] {
|
|
@@ -3652,13 +3687,9 @@ function injectMobileStyles() {
|
|
|
3652
3687
|
box-sizing: border-box !important;
|
|
3653
3688
|
}
|
|
3654
3689
|
|
|
3655
|
-
/* ---- 顶部控件防溢出裁切(320px 下 main 分支 chip 溢出 39px 被裁) ----
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
flex-wrap: wrap !important;
|
|
3659
|
-
row-gap: 6px !important;
|
|
3660
|
-
overflow: visible !important;
|
|
3661
|
-
}
|
|
3690
|
+
/* ---- 顶部控件防溢出裁切(320px 下 main 分支 chip 溢出 39px 被裁) ----
|
|
3691
|
+
注意:titleRow 的 wrap 规则已删除——tabs 折叠进标题行后必须单行,
|
|
3692
|
+
这里的 wrap 会在级联中赢过前面的 nowrap,导致标题行重新折成两行。 */
|
|
3662
3693
|
button[class*="_7rgC5q_chip"],
|
|
3663
3694
|
button[class*="cubgiG_seat"],
|
|
3664
3695
|
div[class*="_7rgC5q_chipWrap"] {
|
|
@@ -3808,6 +3839,15 @@ function injectMobileStyles() {
|
|
|
3808
3839
|
justify-content: center !important;
|
|
3809
3840
|
gap: 0 !important;
|
|
3810
3841
|
font-size: 0 !important;
|
|
3842
|
+
/* 悬停锁定:宽度与位移都不变,杜绝工具栏/对话框抖动 */
|
|
3843
|
+
transition: none !important;
|
|
3844
|
+
border-radius: 8px !important;
|
|
3845
|
+
}
|
|
3846
|
+
div[class*="uV2eYG_trailing"] span > button:not([class]):hover {
|
|
3847
|
+
width: 26px !important;
|
|
3848
|
+
min-width: 26px !important;
|
|
3849
|
+
padding: 0 2px !important;
|
|
3850
|
+
background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.15)) !important;
|
|
3811
3851
|
}
|
|
3812
3852
|
div[class*="uV2eYG_trailing"] span > button:not([class]) svg {
|
|
3813
3853
|
flex: 0 0 auto !important;
|
|
@@ -4390,6 +4430,141 @@ function setupMobileExperience(rpcCall, ctx) {
|
|
|
4390
4430
|
panelObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] });
|
|
4391
4431
|
window.addEventListener('resize', ensurePanelCloseButton);
|
|
4392
4432
|
|
|
4433
|
+
// 1.5 移动端标题行「对话」下拉:隐藏原生 tablist,在标准模式右边注入一个
|
|
4434
|
+
// 原生样式的「对话 ▾」按钮,点开下拉选择 对话/轨迹/上下文 切换视图。
|
|
4435
|
+
// 文案从原生 tab 动态读取(语言无关);按钮类名复刻原生标题行按钮。
|
|
4436
|
+
const mobileTabState = { btn: null, dropdown: null };
|
|
4437
|
+
|
|
4438
|
+
const nativeTabs = () => [...document.querySelectorAll('[role="tablist"] [role="tab"]')];
|
|
4439
|
+
|
|
4440
|
+
const closeTabDropdown = () => {
|
|
4441
|
+
if (mobileTabState.dropdown) {
|
|
4442
|
+
mobileTabState.dropdown.remove();
|
|
4443
|
+
mobileTabState.dropdown = null;
|
|
4444
|
+
}
|
|
4445
|
+
};
|
|
4446
|
+
|
|
4447
|
+
const renderTabDropdown = () => {
|
|
4448
|
+
closeTabDropdown();
|
|
4449
|
+
if (!mobileTabState.btn) return;
|
|
4450
|
+
const dropdown = document.createElement('div');
|
|
4451
|
+
dropdown.className = 'dsh-mobile-tab-dropdown';
|
|
4452
|
+
const tabs = nativeTabs();
|
|
4453
|
+
tabs.forEach((tabEl) => {
|
|
4454
|
+
const isActive = tabEl.getAttribute('aria-selected') === 'true';
|
|
4455
|
+
const option = document.createElement('button');
|
|
4456
|
+
option.type = 'button';
|
|
4457
|
+
option.className = 'dsh-mobile-tab-option';
|
|
4458
|
+
option.setAttribute('data-active', isActive ? 'true' : 'false');
|
|
4459
|
+
const name = document.createElement('span');
|
|
4460
|
+
name.textContent = tabEl.textContent.replace(/\s+/g, ' ').trim();
|
|
4461
|
+
option.appendChild(name);
|
|
4462
|
+
if (isActive) {
|
|
4463
|
+
const check = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
4464
|
+
check.setAttribute('width', '14');
|
|
4465
|
+
check.setAttribute('height', '14');
|
|
4466
|
+
check.setAttribute('viewBox', '0 0 24 24');
|
|
4467
|
+
check.setAttribute('fill', 'none');
|
|
4468
|
+
check.setAttribute('stroke', 'currentColor');
|
|
4469
|
+
check.setAttribute('stroke-width', '2.5');
|
|
4470
|
+
check.setAttribute('stroke-linecap', 'round');
|
|
4471
|
+
check.setAttribute('stroke-linejoin', 'round');
|
|
4472
|
+
check.innerHTML = '<polyline points="20 6 9 17 4 12"></polyline>';
|
|
4473
|
+
option.appendChild(check);
|
|
4474
|
+
}
|
|
4475
|
+
option.onclick = (e) => {
|
|
4476
|
+
e.stopPropagation();
|
|
4477
|
+
tabEl.click();
|
|
4478
|
+
closeTabDropdown();
|
|
4479
|
+
syncTabButtonLabel();
|
|
4480
|
+
};
|
|
4481
|
+
dropdown.appendChild(option);
|
|
4482
|
+
});
|
|
4483
|
+
mobileTabState.btn.appendChild(dropdown);
|
|
4484
|
+
mobileTabState.dropdown = dropdown;
|
|
4485
|
+
};
|
|
4486
|
+
|
|
4487
|
+
const syncTabButtonLabel = () => {
|
|
4488
|
+
if (!mobileTabState.btn || !mobileTabState.btn.isConnected) return;
|
|
4489
|
+
const active = nativeTabs().find((t) => t.getAttribute('aria-selected') === 'true');
|
|
4490
|
+
const labelEl = mobileTabState.btn.querySelector('.dsh-mobile-tab-btn-label');
|
|
4491
|
+
if (!labelEl || !active) return;
|
|
4492
|
+
// 只有文案真的变化才写入:textContent 无条件赋值会移除并重建文本节点,
|
|
4493
|
+
// 触发 MutationObserver → 无限循环,页面卡死。
|
|
4494
|
+
const name = active.textContent.replace(/\s+/g, ' ').trim();
|
|
4495
|
+
if (labelEl.textContent !== name) labelEl.textContent = name;
|
|
4496
|
+
};
|
|
4497
|
+
|
|
4498
|
+
const ensureTabButton = () => {
|
|
4499
|
+
if (typeof window === 'undefined' || window.innerWidth > 768) return;
|
|
4500
|
+
const titleRow = document.querySelector('div[class*="wSkVaW_titleRow"]');
|
|
4501
|
+
const cluster = titleRow ? titleRow.querySelector('div[class*="wSkVaW_titleCluster"]') : null;
|
|
4502
|
+
if (!titleRow || !cluster) {
|
|
4503
|
+
closeTabDropdown();
|
|
4504
|
+
if (mobileTabState.btn) {
|
|
4505
|
+
mobileTabState.btn.remove();
|
|
4506
|
+
mobileTabState.btn = null;
|
|
4507
|
+
}
|
|
4508
|
+
return;
|
|
4509
|
+
}
|
|
4510
|
+
if (mobileTabState.btn && mobileTabState.btn.isConnected && titleRow.contains(mobileTabState.btn)) {
|
|
4511
|
+
syncTabButtonLabel();
|
|
4512
|
+
return;
|
|
4513
|
+
}
|
|
4514
|
+
document.querySelectorAll('.dsh-mobile-tab-btn').forEach((el) => el.remove());
|
|
4515
|
+
const tabBtn = document.createElement('button');
|
|
4516
|
+
tabBtn.type = 'button';
|
|
4517
|
+
// 观感对齐:优先复刻标准模式胶囊的类,其次访达图标按钮,最后自有样式兜底
|
|
4518
|
+
const pillBtn = titleRow.querySelector('div[class*="wSkVaW_titleCluster"] button');
|
|
4519
|
+
const utilBtn = titleRow.querySelector('div[class*="wSkVaW_headerUtilities"] button');
|
|
4520
|
+
const mimic = (pillBtn && pillBtn.className) || (utilBtn && utilBtn.className) || '';
|
|
4521
|
+
tabBtn.className = (mimic ? mimic + ' ' : '') + 'dsh-mobile-tab-btn';
|
|
4522
|
+
tabBtn.innerHTML = `<span class="dsh-mobile-tab-btn-label">对话</span><svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>`;
|
|
4523
|
+
tabBtn.onclick = (e) => {
|
|
4524
|
+
e.stopPropagation();
|
|
4525
|
+
if (mobileTabState.dropdown) closeTabDropdown();
|
|
4526
|
+
else renderTabDropdown();
|
|
4527
|
+
};
|
|
4528
|
+
titleRow.insertBefore(tabBtn, cluster.nextSibling);
|
|
4529
|
+
mobileTabState.btn = tabBtn;
|
|
4530
|
+
syncTabButtonLabel();
|
|
4531
|
+
};
|
|
4532
|
+
|
|
4533
|
+
// workbuddy-connect 的 Reasoning 按钮:移动端删掉文字节点只留图标(svg 保留),
|
|
4534
|
+
// 插件重渲染后新按钮由观察器重新清理
|
|
4535
|
+
const cleanReasoningButtons = () => {
|
|
4536
|
+
if (typeof window === 'undefined' || window.innerWidth > 768) return;
|
|
4537
|
+
document.querySelectorAll('div[class*="uV2eYG_trailing"] span > button:not([class])').forEach((btn) => {
|
|
4538
|
+
if (btn.dataset.dshTextCleaned === '1') return;
|
|
4539
|
+
[...btn.childNodes].forEach((node) => {
|
|
4540
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
4541
|
+
if (node.tagName.toLowerCase() === 'svg' || (typeof node.querySelector === 'function' && node.querySelector('svg'))) return;
|
|
4542
|
+
}
|
|
4543
|
+
node.remove();
|
|
4544
|
+
});
|
|
4545
|
+
btn.dataset.dshTextCleaned = '1';
|
|
4546
|
+
});
|
|
4547
|
+
};
|
|
4548
|
+
|
|
4549
|
+
const titleExtrasObserver = new MutationObserver(() => {
|
|
4550
|
+
ensureTabButton();
|
|
4551
|
+
cleanReasoningButtons();
|
|
4552
|
+
});
|
|
4553
|
+
titleExtrasObserver.observe(document.body, { childList: true, subtree: true });
|
|
4554
|
+
window.addEventListener('resize', () => {
|
|
4555
|
+
if (window.innerWidth > 768) closeTabDropdown();
|
|
4556
|
+
});
|
|
4557
|
+
document.addEventListener(
|
|
4558
|
+
'click',
|
|
4559
|
+
(e) => {
|
|
4560
|
+
if (!mobileTabState.dropdown) return;
|
|
4561
|
+
if (!mobileTabState.dropdown.contains(e.target) && !e.target.closest('.dsh-mobile-tab-btn')) closeTabDropdown();
|
|
4562
|
+
},
|
|
4563
|
+
true,
|
|
4564
|
+
);
|
|
4565
|
+
ensureTabButton();
|
|
4566
|
+
cleanReasoningButtons();
|
|
4567
|
+
|
|
4393
4568
|
// 移动端点击面板/工作区触发按钮时,自动激活 dsh-workbench-open
|
|
4394
4569
|
document.addEventListener('click', (e) => {
|
|
4395
4570
|
if (typeof window === 'undefined' || window.innerWidth > 768) return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-bridge-gateway",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "以 dsh-bridge 为根基、融合 remote-gateway 能力的 DSH 远程访问网关:局域网 / Cloudflare 隧道 / 自建隧道之外,新增「公网直连网关」(0.0.0.0 监听 + 自带 HTTPS 自签证书 + 强制登录门禁),解决移动端外网直连操控电脑。",
|
|
5
5
|
"releaseNotes": "【dsh-bridge-gateway 0.1.5】\n• 🔧 适配 DSH 0.1.5:RPC 通道迁移到 webServer 直注册 + requestRejection 鉴权\n• 📱 移动端深度适配:顶栏防重叠、分支 chip 不再裁切、输入框宽度对齐并 sticky 固定、44px 点击热区、侧边栏焦点陷阱消除\n• 默认不启用,安装后原有局域网/隧道/IM 行为完全不变",
|
|
6
6
|
"type": "module",
|