dsh-claude-style 0.2.4 → 0.2.5
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 +18 -0
- package/README.en.md +1 -0
- package/README.md +3 -2
- package/docs/REFACTOR.md +294 -0
- package/docs/STYLE.md +42 -14
- package/lib/client.js +1554 -503
- package/lib/index.js +313 -2
- package/lib/model-descriptions.json +586 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -1,16 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Claude Style — Claude Code Desktop theme for the DeepSeek Harness web GUI.
|
|
3
3
|
*
|
|
4
|
-
* GENERATED FILE — do not edit. Source lives in src/
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* GENERATED FILE — do not edit. Source lives in src/ as feature fragments;
|
|
5
|
+
* `node scripts/build.mjs` assembles this bundle.
|
|
6
|
+
*
|
|
7
|
+
* JS fragments (in assembly order):
|
|
7
8
|
* - src/assets/*.svg Brand marks (inlined as CSS url() data URIs at build time)
|
|
8
|
-
* - src/
|
|
9
|
-
*
|
|
10
|
-
* - src/context.js
|
|
11
|
-
* - src/
|
|
12
|
-
* - src/
|
|
13
|
-
* - src/
|
|
9
|
+
* * - src/constants.js
|
|
10
|
+
* - src/context/host.js
|
|
11
|
+
* - src/context/prefs.js
|
|
12
|
+
* - src/context/model-copy.js
|
|
13
|
+
* - src/context/i18n.js
|
|
14
|
+
* - src/overrides/popover-utils.js
|
|
15
|
+
* - src/overrides/copy.js
|
|
16
|
+
* - src/overrides/permissions.js
|
|
17
|
+
* - src/overrides/model-picker.js
|
|
18
|
+
* - src/overrides/account-footer.js
|
|
19
|
+
* - src/overrides/scheduler.js
|
|
20
|
+
* - src/settings.js
|
|
21
|
+
* - src/entry.js
|
|
22
|
+
*
|
|
23
|
+
* Stylesheets (in assembly order):
|
|
24
|
+
* * - src/styles/tokens.css
|
|
25
|
+
* - src/styles/typography.css
|
|
26
|
+
* - src/styles/chrome.css
|
|
27
|
+
* - src/styles/composer/hero.css
|
|
28
|
+
* - src/styles/composer/card.css
|
|
29
|
+
* - src/styles/composer/inline.css
|
|
30
|
+
* - src/styles/sidebar.css
|
|
31
|
+
* - src/styles/components/permissions.css
|
|
32
|
+
* - src/styles/components/account-footer.css
|
|
33
|
+
* - src/styles/components/model-picker.css
|
|
34
|
+
* - src/styles/components/footer-takeover.css
|
|
35
|
+
* - src/styles/components/third-party.css
|
|
36
|
+
* - src/styles/components/settings.css
|
|
14
37
|
*/
|
|
15
38
|
window.__ModuleLoader__.load({
|
|
16
39
|
id: 'dsh-claude-style',
|
|
@@ -23,30 +46,39 @@ window.__ModuleLoader__.load({
|
|
|
23
46
|
// section can be a real component without a host half.
|
|
24
47
|
var React = require('react')
|
|
25
48
|
|
|
49
|
+
|
|
26
50
|
// ============================================================================
|
|
27
|
-
//
|
|
51
|
+
// 常量与配置定义 (Constants & Tokens)
|
|
28
52
|
// ============================================================================
|
|
29
53
|
var STYLE_ID = 'dsh-claude-style-style'
|
|
30
54
|
|
|
31
55
|
var COMPOSER_HINT = 'How can I help you today?'
|
|
32
56
|
|
|
33
57
|
/**
|
|
34
|
-
* Model
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
58
|
+
* Model picker copy.
|
|
59
|
+
*
|
|
60
|
+
* The copy itself is NOT here. It ships as `model-descriptions.json` beside
|
|
61
|
+
* the bundle, and the browser half fetches it at runtime (the host half
|
|
62
|
+
* serves it under MODEL_COPY_ROUTE), so the model table grows without a
|
|
63
|
+
* rebuild and no copy enters the bundle. The language comes from the shell's
|
|
64
|
+
* own `locale` service — one line per row, in the language the rest of the
|
|
65
|
+
* UI is in — never two languages stacked.
|
|
66
|
+
*
|
|
67
|
+
* The constants below are the neutral fallbacks painted before that document
|
|
68
|
+
* arrives, and kept if it never does. They are English because a failed
|
|
69
|
+
* fetch has no locale to honour.
|
|
38
70
|
*/
|
|
39
71
|
var MODEL_OFFICIAL_GROUP = 'deepseek-official'
|
|
40
|
-
var
|
|
41
|
-
var
|
|
42
|
-
var
|
|
43
|
-
var
|
|
72
|
+
var MODEL_COPY_ROUTE = '/dsh-claude-style/model-descriptions.json'
|
|
73
|
+
var MODEL_COPY_FALLBACK_LOCALE = 'en'
|
|
74
|
+
var MODEL_FALLBACK_LABEL = 'Select model'
|
|
75
|
+
var MODEL_LOADING_LABEL = 'Loading models…'
|
|
76
|
+
var MODEL_EMPTY_LABEL = 'No models available.'
|
|
77
|
+
var MODEL_EFFORT_LABEL = 'Reasoning effort'
|
|
44
78
|
var MODEL_EFFORT_DEFAULT = 'Default'
|
|
45
79
|
var MODEL_MORE_LABEL = 'More models'
|
|
46
|
-
var
|
|
47
|
-
|
|
48
|
-
'deepseek-official/deepseek-v4-pro': '更强的自主编码、知识与复杂推理能力;适合复杂或质量优先的任务,但成本更高。',
|
|
49
|
-
}
|
|
80
|
+
var MODEL_TRIGGER_LABEL = 'Select model, currently {model}'
|
|
81
|
+
var MODEL_NO_EFFORT_LABEL = 'This model offers no reasoning levels.'
|
|
50
82
|
|
|
51
83
|
/** English weekday names, indexed by Date#getDay() (0 = Sunday). */
|
|
52
84
|
var WEEKDAY_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
|
|
@@ -154,24 +186,47 @@ window.__ModuleLoader__.load({
|
|
|
154
186
|
var SEGMENTS_CLASS = 'dsh-claude-segments'
|
|
155
187
|
var SEGMENT_CLASS = 'dsh-claude-segment'
|
|
156
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Preferences, persisted in the host settings namespace `claude-style`
|
|
191
|
+
* (lib/index.js owns it; src/context/prefs.js reads and writes it). Each value is
|
|
192
|
+
* mirrored onto the document as an attribute so the stylesheet decides what
|
|
193
|
+
* a preference means, and the defaults here are the shipped behaviour.
|
|
194
|
+
*/
|
|
195
|
+
|
|
157
196
|
/** Brand marks selectable from the settings page. `claude` is the default. */
|
|
158
197
|
var BRAND_CLAUDE = 'claude'
|
|
159
198
|
var BRAND_ANTHROPIC = 'anthropic'
|
|
199
|
+
/** Leave the brand area entirely to the host: neither brand variant matches. */
|
|
200
|
+
var BRAND_OFF = 'off'
|
|
160
201
|
var DEFAULT_BRAND = BRAND_CLAUDE
|
|
161
|
-
/** localStorage key holding the chosen brand. */
|
|
162
|
-
var BRAND_STORAGE_KEY = 'dsh-claude-style:brand'
|
|
163
202
|
/** The document attribute the stylesheet switches on. */
|
|
164
203
|
var BRAND_ATTR = 'data-dsh-claude-brand'
|
|
165
204
|
|
|
205
|
+
/** Present while the skin takes over the sidebar footer (settings area + account row). */
|
|
206
|
+
var FOOTER_ATTR = 'data-dsh-claude-footer-takeover'
|
|
207
|
+
/** Present while the composer restyle applies to the page currently shown. */
|
|
208
|
+
var COMPOSER_ATTR = 'data-dsh-claude-composer-active'
|
|
209
|
+
/** Composer surfaces the restyle may cover, in settings order. */
|
|
210
|
+
var COMPOSER_SCOPES = ['off', 'hero', 'conversation', 'all']
|
|
211
|
+
/** Route the browser half reads and writes preferences through (lib/index.js). */
|
|
212
|
+
var PREFS_ROUTE = '/dsh-claude-style/prefs'
|
|
213
|
+
|
|
166
214
|
/** Wordmark aspect ratio; scripts/build.mjs sizes the sidebar word height from it (geometry lives in src/assets/claude-word.svg). */
|
|
167
215
|
var CLAUDE_WORD_ASPECT = 512.22 / 121.54
|
|
168
216
|
|
|
169
217
|
var SANS = "'Anthropic Sans Web Text','Noto Sans SC','Source Han Sans SC',-apple-system,BlinkMacSystemFont,'Segoe UI','PingFang SC','Hiragino Sans GB','Microsoft YaHei','Helvetica Neue',Helvetica,Arial,sans-serif"
|
|
170
218
|
var SERIF = "'Anthropic Serif Web Text',Georgia,'Times New Roman','Noto Serif SC','Source Han Serif SC','Songti SC','SimSun',serif"
|
|
219
|
+
/**
|
|
220
|
+
* Conversation prose: Claude sets Latin text in the serif face and lets
|
|
221
|
+
* Chinese fall through to a sans CJK — the serif Latin faces carry no CJK
|
|
222
|
+
* glyphs, so the stack leads with serif and names the sans CJK families
|
|
223
|
+
* after it. UI chrome keeps SANS; only markdown prose uses this.
|
|
224
|
+
*/
|
|
225
|
+
var PROSE = "'Anthropic Serif Web Text',Georgia,'Times New Roman','Noto Sans SC','Source Han Sans SC','PingFang SC','Hiragino Sans GB','Microsoft YaHei',sans-serif"
|
|
171
226
|
var MONO = "'Anthropic Mono Variable',ui-monospace,'SF Mono','JetBrains Mono','Fira Code',Consolas,'Liberation Mono',Menlo,Courier,monospace"
|
|
172
227
|
|
|
173
228
|
// ============================================================================
|
|
174
|
-
//
|
|
229
|
+
// 样式表(由 src/styles/*.css 内联生成,勿手改) (CSS Stylesheet)
|
|
175
230
|
// ============================================================================
|
|
176
231
|
var CSS = [
|
|
177
232
|
"/* --- 2.1 Design Tokens (Dark Base & Light Overrides) --- */",
|
|
@@ -179,19 +234,16 @@ window.__ModuleLoader__.load({
|
|
|
179
234
|
"body[data-dsh-claude-style] {",
|
|
180
235
|
" --dsw-font-family: 'Anthropic Sans Web Text','Noto Sans SC','Source Han Sans SC',-apple-system,BlinkMacSystemFont,'Segoe UI','PingFang SC','Hiragino Sans GB','Microsoft YaHei','Helvetica Neue',Helvetica,Arial,sans-serif;",
|
|
181
236
|
" --dsw-font-serif: 'Anthropic Serif Web Text',Georgia,'Times New Roman','Noto Serif SC','Source Han Serif SC','Songti SC','SimSun',serif;",
|
|
237
|
+
" --dsw-font-prose: 'Anthropic Serif Web Text',Georgia,'Times New Roman','Noto Sans SC','Source Han Sans SC','PingFang SC','Hiragino Sans GB','Microsoft YaHei',sans-serif;",
|
|
182
238
|
" --dsw-font-code: 'Anthropic Mono Variable',ui-monospace,'SF Mono','JetBrains Mono','Fira Code',Consolas,'Liberation Mono',Menlo,Courier,monospace;",
|
|
183
|
-
" /* Markdown document headings keep the
|
|
184
|
-
"
|
|
185
|
-
" `font:` shorthand
|
|
186
|
-
" directly, so overriding the
|
|
187
|
-
" the page
|
|
188
|
-
"
|
|
189
|
-
"
|
|
190
|
-
" --dsw-font-markdown-
|
|
191
|
-
" --dsw-font-markdown-h3: 700 calc(16px + var(--dsh-content-font-delta)) / calc(24px + var(--dsh-content-font-delta)) var(--dsw-font-family);",
|
|
192
|
-
" --dsw-font-markdown-base-font-family: var(--dsw-font-family);",
|
|
193
|
-
" --dsw-font-markdown-small-font-family: var(--dsw-font-family);",
|
|
194
|
-
" --dsw-font-markdown-table-font-family: var(--dsw-font-family);",
|
|
239
|
+
" /* Markdown document headings keep the host's own ladder, steepened from",
|
|
240
|
+
" 21/19/18 toward Claude's measured ≈21/17/15; h1 and h4 keep the host's",
|
|
241
|
+
" values. The host reads these through a `font:` shorthand that names",
|
|
242
|
+
" --dsw-font-family directly, so overriding the `-font-family` sub-tokens",
|
|
243
|
+
" never reached the page — the shorthand itself is what has to be",
|
|
244
|
+
" re-declared. */",
|
|
245
|
+
" --dsw-font-markdown-h2: 700 calc(18px + var(--dsh-content-font-delta)) / calc(26px + var(--dsh-content-font-delta)) var(--dsw-font-prose);",
|
|
246
|
+
" --dsw-font-markdown-h3: 700 calc(16px + var(--dsh-content-font-delta)) / calc(24px + var(--dsh-content-font-delta)) var(--dsw-font-prose);",
|
|
195
247
|
"}",
|
|
196
248
|
"",
|
|
197
249
|
"/* ---------- design tokens: warm-black (dark) palette ---------- */",
|
|
@@ -221,6 +273,13 @@ window.__ModuleLoader__.load({
|
|
|
221
273
|
" --dsw-alias-button-info-hover: #e08a6d;",
|
|
222
274
|
" --dsw-alias-interactive-bg-active: rgba(217, 119, 87, 0.30);",
|
|
223
275
|
" --dsh-claude-hover-bg: rgba(255, 255, 255, 0.08);",
|
|
276
|
+
" --dsh-claude-inline-code-fg: #e8a08a;",
|
|
277
|
+
" --dsh-claude-link: #8ab4f8;",
|
|
278
|
+
" /* The host pins the code-block surface on `pre.shiki` with !important, so it",
|
|
279
|
+
" is only reachable through its own token; #1c1b1a is the value the skin's",
|
|
280
|
+
" (inert) `pre { background }` rule always meant. */",
|
|
281
|
+
" --dsw-alias-markdown-code-block: #1c1b1a;",
|
|
282
|
+
" --dsw-alias-markdown-code-block-banner: #242320;",
|
|
224
283
|
" --dsw-alias-interactive-bg-hover: var(--dsh-claude-hover-bg);",
|
|
225
284
|
" --dsw-alias-interactive-bg-hover-solid: #2e2c29;",
|
|
226
285
|
" --dsw-alias-label-primary: #faf9f5;",
|
|
@@ -280,6 +339,13 @@ window.__ModuleLoader__.load({
|
|
|
280
339
|
" /* User message bubbles: the host's light bubble token is deepseek-50 (blue);",
|
|
281
340
|
" use the skin's button-hover gray instead. */",
|
|
282
341
|
" --dsw-specific-bubble: var(--dsh-claude-hover-bg);",
|
|
342
|
+
" /* Markdown surfaces, measured off Claude: a white code block, a neutral-gray",
|
|
343
|
+
" inline-code chip, and blue links. The chip colour is the same gray the",
|
|
344
|
+
" components hover with, so the two read as one material. */",
|
|
345
|
+
" --dsw-alias-markdown-code-block: #ffffff;",
|
|
346
|
+
" --dsw-alias-markdown-code-block-banner: #ffffff;",
|
|
347
|
+
" --dsh-claude-inline-code-fg: #943333;",
|
|
348
|
+
" --dsh-claude-link: #184f95;",
|
|
283
349
|
"}",
|
|
284
350
|
"",
|
|
285
351
|
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) {",
|
|
@@ -330,14 +396,9 @@ window.__ModuleLoader__.load({
|
|
|
330
396
|
"}",
|
|
331
397
|
"",
|
|
332
398
|
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) pre {",
|
|
333
|
-
" background: #f5f3ee;",
|
|
334
399
|
" border-color: #e8e6dc;",
|
|
335
400
|
"}",
|
|
336
401
|
"",
|
|
337
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) code:not(pre code) {",
|
|
338
|
-
" background: #e8e6dc;",
|
|
339
|
-
"}",
|
|
340
|
-
"",
|
|
341
402
|
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) table th {",
|
|
342
403
|
" background: #f0eee6;",
|
|
343
404
|
"}",
|
|
@@ -380,15 +441,26 @@ window.__ModuleLoader__.load({
|
|
|
380
441
|
" letter-spacing: -0.015em;",
|
|
381
442
|
"}",
|
|
382
443
|
"",
|
|
383
|
-
"/* ---------- markdown document
|
|
384
|
-
"/*
|
|
385
|
-
"
|
|
386
|
-
"
|
|
387
|
-
"
|
|
388
|
-
"
|
|
389
|
-
"
|
|
390
|
-
"
|
|
391
|
-
"
|
|
444
|
+
"/* ---------- markdown document prose ---------- */",
|
|
445
|
+
"/* Claude sets conversation prose — body and headings alike — in the serif",
|
|
446
|
+
" face and lets Chinese fall through to a sans CJK; the serif display rule",
|
|
447
|
+
" above stays for UI headlines. */",
|
|
448
|
+
"body[data-dsh-claude-style] [class*=\"markdown\"] {",
|
|
449
|
+
" font-family: var(--dsw-font-prose);",
|
|
450
|
+
"}",
|
|
451
|
+
"",
|
|
452
|
+
"/* The host gives its markdown elements their own `font:` shorthand, so the",
|
|
453
|
+
" family has to be re-stated wherever those shorthands land. The heading",
|
|
454
|
+
" shorthand is re-asserted too, so the host's weight, size and line-height",
|
|
455
|
+
" survive the serif display rule above. */",
|
|
456
|
+
"body[data-dsh-claude-style] [class*=\"markdown\"] h1 { font: var(--dsw-font-markdown-h1); font-family: var(--dsw-font-prose); }",
|
|
457
|
+
"body[data-dsh-claude-style] [class*=\"markdown\"] h2 { font: var(--dsw-font-markdown-h2); font-family: var(--dsw-font-prose); }",
|
|
458
|
+
"body[data-dsh-claude-style] [class*=\"markdown\"] h3 { font: var(--dsw-font-markdown-h3); font-family: var(--dsw-font-prose); }",
|
|
459
|
+
"body[data-dsh-claude-style] [class*=\"markdown\"] h4 { font: var(--dsw-font-markdown-h4); font-family: var(--dsw-font-prose); }",
|
|
460
|
+
"",
|
|
461
|
+
"body[data-dsh-claude-style] [class*=\"markdown\"] :is(th, td) {",
|
|
462
|
+
" font-family: var(--dsw-font-prose);",
|
|
463
|
+
"}",
|
|
392
464
|
"",
|
|
393
465
|
"/* Heading rhythm. The host gives every heading a 32px top margin, which stacks",
|
|
394
466
|
" on the previous heading's 16px bottom margin: two consecutive headings open",
|
|
@@ -420,10 +492,10 @@ window.__ModuleLoader__.load({
|
|
|
420
492
|
"}",
|
|
421
493
|
"",
|
|
422
494
|
"/* ---------- editorial markdown ---------- */",
|
|
423
|
-
"/* Claude's quote keeps the
|
|
424
|
-
" wash; the warm accent stays reserved for
|
|
495
|
+
"/* Claude's quote keeps the prose face but stands upright on a neutral bar and",
|
|
496
|
+
" wash; the warm accent stays reserved for controls. */",
|
|
425
497
|
"body[data-dsh-claude-style] blockquote {",
|
|
426
|
-
" font-family: var(--dsw-font-
|
|
498
|
+
" font-family: var(--dsw-font-prose);",
|
|
427
499
|
" font-style: normal;",
|
|
428
500
|
" color: #b0aea5;",
|
|
429
501
|
" border-left: 2px solid var(--dsw-alias-label-caption);",
|
|
@@ -432,19 +504,37 @@ window.__ModuleLoader__.load({
|
|
|
432
504
|
" padding: 0.6em 1em;",
|
|
433
505
|
"}",
|
|
434
506
|
"",
|
|
507
|
+
"/* The fill rides the host's --dsw-alias-markdown-code-block token — the host",
|
|
508
|
+
" pins `pre.shiki` with !important, so a `background` here would never apply.",
|
|
509
|
+
" Only the frame is styled. */",
|
|
435
510
|
"body[data-dsh-claude-style] pre {",
|
|
436
|
-
" background: #1c1b1a;",
|
|
437
511
|
" border: 1px solid #242320;",
|
|
438
512
|
" border-radius: 8px;",
|
|
439
513
|
"}",
|
|
440
514
|
"",
|
|
515
|
+
"/* Claude's inline-code chip: warm red on the same neutral gray the components",
|
|
516
|
+
" hover with — both resolve per theme from the palette blocks. */",
|
|
441
517
|
"body[data-dsh-claude-style] code:not(pre code) {",
|
|
442
|
-
" background:
|
|
518
|
+
" background: var(--dsh-claude-hover-bg);",
|
|
519
|
+
" color: var(--dsh-claude-inline-code-fg);",
|
|
443
520
|
" border-radius: 4px;",
|
|
444
521
|
" padding: 0.15em 0.4em;",
|
|
445
522
|
" font-size: 0.88em;",
|
|
446
523
|
"}",
|
|
447
524
|
"",
|
|
525
|
+
"/* Claude's links: blue, underlined at rest, and without the host's",
|
|
526
|
+
" link-category glyph. */",
|
|
527
|
+
"body[data-dsh-claude-style] [class*=\"linkIcon\"] {",
|
|
528
|
+
" display: none;",
|
|
529
|
+
"}",
|
|
530
|
+
"",
|
|
531
|
+
"body[data-dsh-claude-style] [class*=\"markdown\"] :is(a, a:hover, a:focus) {",
|
|
532
|
+
" color: var(--dsh-claude-link);",
|
|
533
|
+
" text-decoration: underline;",
|
|
534
|
+
" text-decoration-thickness: 1px;",
|
|
535
|
+
" text-underline-offset: 2px;",
|
|
536
|
+
"}",
|
|
537
|
+
"",
|
|
448
538
|
"body[data-dsh-claude-style] hr {",
|
|
449
539
|
" border: none;",
|
|
450
540
|
" border-top: 1px solid rgba(20, 20, 19, 0.14);",
|
|
@@ -608,15 +698,15 @@ window.__ModuleLoader__.load({
|
|
|
608
698
|
" slot wrapper, not always a bare svg — and the mark is painted on the hitbox,",
|
|
609
699
|
" so React keeps owning its own node. The hero keeps the clay fill in both",
|
|
610
700
|
" brands, matching the shipped accent treatment. */",
|
|
611
|
-
"body[data-dsh-claude-style] [class*=\"fishHitbox\"] > * {",
|
|
701
|
+
"body[data-dsh-claude-style]:is([data-dsh-claude-brand=\"claude\"], [data-dsh-claude-brand=\"anthropic\"]) [class*=\"fishHitbox\"] > * {",
|
|
612
702
|
" display: none !important;",
|
|
613
703
|
"}",
|
|
614
704
|
"",
|
|
615
|
-
"body[data-dsh-claude-style] [class*=\"fishHitbox\"] svg {",
|
|
705
|
+
"body[data-dsh-claude-style]:is([data-dsh-claude-brand=\"claude\"], [data-dsh-claude-brand=\"anthropic\"]) [class*=\"fishHitbox\"] svg {",
|
|
616
706
|
" display: none !important;",
|
|
617
707
|
"}",
|
|
618
708
|
"",
|
|
619
|
-
"body[data-dsh-claude-style] [class*=\"fishHitbox\"]::before {",
|
|
709
|
+
"body[data-dsh-claude-style]:is([data-dsh-claude-brand=\"claude\"], [data-dsh-claude-brand=\"anthropic\"]) [class*=\"fishHitbox\"]::before {",
|
|
620
710
|
" content: \"\";",
|
|
621
711
|
" flex: none;",
|
|
622
712
|
" width: 42.5px;",
|
|
@@ -626,7 +716,7 @@ window.__ModuleLoader__.load({
|
|
|
626
716
|
" background-size: contain;",
|
|
627
717
|
"}",
|
|
628
718
|
"",
|
|
629
|
-
"body[data-dsh-claude-style]
|
|
719
|
+
"body[data-dsh-claude-style][data-dsh-claude-brand=\"claude\"] [class*=\"fishHitbox\"]::before {",
|
|
630
720
|
" background-image: url(\"data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%20148.09%20148.18'%3E%3Cg%20transform%3D'translate(-75.96%2C-223.53)'%3E%3Cpath%20fill%3D'%23D97757'%20d%3D'm%20105.01%2C322.07%2029.14%2C-16.35%200.49%2C-1.42%20-0.49%2C-0.79%20h%20-1.42%20l%20-4.87%2C-0.3%20-16.65%2C-0.45%20-14.44%2C-0.6%20-13.99%2C-0.75%20-3.52%2C-0.75%20-3.3%2C-4.35%200.34%2C-2.17%202.96%2C-1.99%204.24%2C0.37%209.37%2C0.64%2014.06%2C0.97%2010.2%2C0.6%2015.11%2C1.57%20h%202.4%20l%200.34%2C-0.97%20-0.82%2C-0.6%20-0.64%2C-0.6%20-14.55%2C-9.86%20-15.75%2C-10.42%20-8.25%2C-6%20-4.46%2C-3.04%20-2.25%2C-2.85%20-0.97%2C-6.22%204.05%2C-4.46%205.44%2C0.37%201.39%2C0.37%205.51%2C4.24%2011.77%2C9.11%2015.37%2C11.32%202.25%2C1.87%200.9%2C-0.64%200.11%2C-0.45%20-1.01%2C-1.69%20-8.36%2C-15.11%20-8.92%2C-15.37%20-3.97%2C-6.37%20-1.05%2C-3.82%20c%20-0.37%2C-1.57%20-0.64%2C-2.89%20-0.64%2C-4.5%20l%204.61%2C-6.26%202.55%2C-0.82%206.15%2C0.82%202.59%2C2.25%203.82%2C8.74%206.19%2C13.76%209.6%2C18.71%202.81%2C5.55%201.5%2C5.14%200.56%2C1.57%20h%200.97%20v%20-0.9%20l%200.79%2C-10.54%201.46%2C-12.94%201.42%2C-16.65%200.49%2C-4.69%202.32%2C-5.62%204.61%2C-3.04%203.6%2C1.72%202.96%2C4.24%20-0.41%2C2.74%20-1.76%2C11.44%20-3.45%2C17.92%20-2.25%2C12%20h%201.31%20l%201.5%2C-1.5%206.07%2C-8.06%2010.2%2C-12.75%204.5%2C-5.06%205.25%2C-5.59%203.37%2C-2.66%20h%206.37%20l%204.69%2C6.97%20-2.1%2C7.2%20-6.56%2C8.32%20-5.44%2C7.05%20-7.8%2C10.5%20-4.87%2C8.4%200.45%2C0.67%201.16%2C-0.11%2017.62%2C-3.75%209.52%2C-1.72%2011.36%2C-1.95%205.14%2C2.4%200.56%2C2.44%20-2.02%2C4.99%20-12.15%2C3%20-14.25%2C2.85%20-21.22%2C5.02%20-0.26%2C0.19%200.3%2C0.37%209.56%2C0.9%204.09%2C0.22%20h%2010.01%20l%2018.64%2C1.39%204.87%2C3.22%202.92%2C3.94%20-0.49%2C3%20-7.5%2C3.82%20-10.12%2C-2.4%20-23.62%2C-5.62%20-8.1%2C-2.02%20h%20-1.12%20v%200.67%20l%206.75%2C6.6%2012.37%2C11.17%2015.49%2C14.4%200.79%2C3.56%20-1.99%2C2.81%20-2.1%2C-0.3%20-13.61%2C-10.24%20-5.25%2C-4.61%20-11.89%2C-10.01%20h%20-0.79%20v%201.05%20l%202.74%2C4.01%2014.47%2C21.75%200.75%2C6.67%20-1.05%2C2.17%20-3.75%2C1.31%20-4.12%2C-0.75%20-8.47%2C-11.89%20-8.74%2C-13.39%20-7.05%2C-12%20-0.86%2C0.49%20-4.16%2C44.81%20-1.95%2C2.29%20-4.5%2C1.72%20-3.75%2C-2.85%20-1.99%2C-4.61%201.99%2C-9.11%202.4%2C-11.89%201.95%2C-9.45%201.76%2C-11.74%201.05%2C-3.9%20-0.07%2C-0.26%20-0.86%2C0.11%20-8.85%2C12.15%20-13.46%2C18.19%20-10.65%2C11.4%20-2.55%2C1.01%20-4.42%2C-2.29%200.41%2C-4.09%202.47%2C-3.64%2014.74%2C-18.75%208.89%2C-11.62%205.74%2C-6.71%20-0.04%2C-0.97%20h%20-0.34%20l%20-39.15%2C25.42%20-6.97%2C0.9%20-3%2C-2.81%200.37%2C-4.61%201.42%2C-1.5%2011.77%2C-8.1%20-0.04%2C0.04%20z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E\");",
|
|
631
721
|
"}",
|
|
632
722
|
"",
|
|
@@ -648,10 +738,17 @@ window.__ModuleLoader__.load({
|
|
|
648
738
|
"}",
|
|
649
739
|
"",
|
|
650
740
|
"/* ---------- Claude Code layout: composer input + buttons ---------- */",
|
|
741
|
+
"/* @composer-gate */",
|
|
742
|
+
"/* Everything from here down is the \"Composer restyle\" preference's territory:",
|
|
743
|
+
" the build stamps `[data-dsh-claude-composer-active]` onto every rule below",
|
|
744
|
+
" this marker, and the skin sets that attribute on <body> only while the page",
|
|
745
|
+
" on screen is a surface the preference covers. Above the marker sits the hero",
|
|
746
|
+
" brand mark and headline, which belong to the brand preference instead — a",
|
|
747
|
+
" composer scope of \"conversation only\" must not revert them. */",
|
|
651
748
|
"/* The composer card is the input box: one step up in type size, pure white",
|
|
652
749
|
" so it separates from the canvas, and an outline 4px tighter than the",
|
|
653
750
|
" shipped 22px. */",
|
|
654
|
-
"body[data-dsh-claude-style] [data-composer-card] {",
|
|
751
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card] {",
|
|
655
752
|
" font-size: 15px;",
|
|
656
753
|
" border-radius: 18px;",
|
|
657
754
|
" border: 1px solid var(--dsw-alias-border-l1);",
|
|
@@ -671,11 +768,11 @@ window.__ModuleLoader__.load({
|
|
|
671
768
|
" --dsh-composer-text-max-height before it starts scrolling. Both hooks are",
|
|
672
769
|
" ancestors of the field, so :is() also keeps the tall field through the",
|
|
673
770
|
" settling frame, while an active composer matches neither. */",
|
|
674
|
-
"body[data-dsh-claude-style] :is([class*=\"composerHero\"], [data-phase=\"hero\"]) [data-composer-input] {",
|
|
771
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] :is([class*=\"composerHero\"], [data-phase=\"hero\"]) [data-composer-input] {",
|
|
675
772
|
" min-height: 86px !important;",
|
|
676
773
|
"}",
|
|
677
774
|
"",
|
|
678
|
-
"body[data-dsh-claude-style] [data-composer-input] {",
|
|
775
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-input] {",
|
|
679
776
|
" min-height: 36px !important;",
|
|
680
777
|
" height: auto !important;",
|
|
681
778
|
"}",
|
|
@@ -684,13 +781,17 @@ window.__ModuleLoader__.load({
|
|
|
684
781
|
" be `[class*=\"_row\"]`: a bare `[class*=\"row\"]` substring-matches the",
|
|
685
782
|
" shipped input growth wrapper `.p_FcLG_grow` (\"grow\" contains \"row\"),",
|
|
686
783
|
" which pins the composer field to the toolbar-row metrics. */",
|
|
687
|
-
"body[data-dsh-claude-style] [data-composer-card] [class*=\"_row\"] {",
|
|
784
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card] [class*=\"_row\"] {",
|
|
688
785
|
" padding-bottom: 2px !important;",
|
|
689
786
|
"}",
|
|
690
787
|
"",
|
|
691
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [data-composer-card] {",
|
|
788
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [data-composer-card] {",
|
|
692
789
|
" background: #ffffff;",
|
|
693
|
-
" box-shadow: 0 4px 12px rgba(20, 20, 19, 0.04), 0 1px 3px rgba(20, 20, 19, 0.02);",
|
|
790
|
+
" box-shadow: 0 4px 12px rgba(20, 20, 19, 0.04), 0 1px 3px rgba(20, 20, 19, 0.02), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base);",
|
|
791
|
+
"}",
|
|
792
|
+
"",
|
|
793
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-ds-dark-theme] [data-composer-card] {",
|
|
794
|
+
" box-shadow: 0 4px 12px rgba(0, 0, 0, 0.30), 0 1px 3px rgba(0, 0, 0, 0.15), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base);",
|
|
694
795
|
"}",
|
|
695
796
|
"",
|
|
696
797
|
"/* Focus: the shipped field has no focus face at all — only the caret moves —",
|
|
@@ -701,27 +802,27 @@ window.__ModuleLoader__.load({
|
|
|
701
802
|
" the focus face inverts to a BRIGHT ivory rim and halo, so the field visibly",
|
|
702
803
|
" lights up instead of deepening. The tray below continues the same hairline,",
|
|
703
804
|
" so its three edges follow whenever the card above it holds focus. */",
|
|
704
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [data-composer-card]:focus-within {",
|
|
705
|
-
" border-color: rgba(20, 20, 19, 0.
|
|
706
|
-
" box-shadow: 0 0 0 1px rgba(20, 20, 19, 0.
|
|
805
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [data-composer-card]:focus-within {",
|
|
806
|
+
" border-color: rgba(20, 20, 19, 0.18);",
|
|
807
|
+
" box-shadow: 0 0 0 1px rgba(20, 20, 19, 0.065), 0 6px 18px rgba(20, 20, 19, 0.03), 0 2px 6px rgba(20, 20, 19, 0.015), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base);",
|
|
707
808
|
"}",
|
|
708
809
|
"",
|
|
709
|
-
"body[data-dsh-claude-style][data-ds-dark-theme] [data-composer-card]:focus-within {",
|
|
710
|
-
" border-color: rgba(250, 249, 245, 0.
|
|
711
|
-
" box-shadow: 0 0 0 1px rgba(250, 249, 245, 0.
|
|
810
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-ds-dark-theme] [data-composer-card]:focus-within {",
|
|
811
|
+
" border-color: rgba(250, 249, 245, 0.22);",
|
|
812
|
+
" box-shadow: 0 0 0 1px rgba(250, 249, 245, 0.09), 0 6px 24px rgba(0, 0, 0, 0.22), 0 2px 8px rgba(0, 0, 0, 0.11), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base);",
|
|
712
813
|
"}",
|
|
713
814
|
"",
|
|
714
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:has([data-composer-card]:focus-within) > [class*=\"heroWorkspaceRow\"] {",
|
|
715
|
-
" border-color: rgba(20, 20, 19, 0.
|
|
815
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:has([data-composer-card]:focus-within) > [class*=\"heroWorkspaceRow\"] {",
|
|
816
|
+
" border-color: rgba(20, 20, 19, 0.18);",
|
|
716
817
|
"}",
|
|
717
818
|
"",
|
|
718
|
-
"body[data-dsh-claude-style][data-ds-dark-theme] [class*=\"composerStack\"]:has([data-composer-card]:focus-within) > [class*=\"heroWorkspaceRow\"] {",
|
|
719
|
-
" border-color: rgba(250, 249, 245, 0.
|
|
819
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-ds-dark-theme] [class*=\"composerStack\"]:has([data-composer-card]:focus-within) > [class*=\"heroWorkspaceRow\"] {",
|
|
820
|
+
" border-color: rgba(250, 249, 245, 0.22);",
|
|
720
821
|
"}",
|
|
721
822
|
"",
|
|
722
823
|
"/* The workspace-trigger variant paints its dashed ring through a masked svg",
|
|
723
824
|
" cut with rx=22; re-cut it so the ring tracks the 18px card. */",
|
|
724
|
-
"body[data-dsh-claude-style] [data-composer-card]:after {",
|
|
825
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card]:after {",
|
|
725
826
|
" border-radius: 18px;",
|
|
726
827
|
" -webkit-mask: url(\"data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27%3E%3Crect width=%27100%25%27 height=%27100%25%27 fill=%27none%27 rx=%2718%27 ry=%2718%27 stroke=%27black%27 stroke-width=%272%27 stroke-dasharray=%274 4%27/%3E%3C/svg%3E\");",
|
|
727
828
|
" mask: url(\"data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27%3E%3Crect width=%27100%25%27 height=%27100%25%27 fill=%27none%27 rx=%2718%27 ry=%2718%27 stroke=%27black%27 stroke-width=%272%27 stroke-dasharray=%274 4%27/%3E%3C/svg%3E\");",
|
|
@@ -729,21 +830,21 @@ window.__ModuleLoader__.load({
|
|
|
729
830
|
"",
|
|
730
831
|
"/* Commands and attach: 7px corners instead of the shipped full circle, no",
|
|
731
832
|
" resting fill, and a warm plate on hover. */",
|
|
732
|
-
"body[data-dsh-claude-style] :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"], button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]) {",
|
|
833
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"], button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]) {",
|
|
733
834
|
" border-radius: 7px;",
|
|
734
835
|
"}",
|
|
735
836
|
"",
|
|
736
837
|
"/* Send, and the stop/queue/steer labels that replace it while running: the",
|
|
737
838
|
" shipped 34px circle becomes a 7px rounded rectangle. */",
|
|
738
|
-
"body[data-dsh-claude-style] :is(button[aria-label=\"发送消息\"], button[aria-label=\"Send message\"], button[aria-label=\"排队发送\"], button[aria-label=\"Queue message\"], button[aria-label=\"插话发送\"], button[aria-label=\"Steer message\"], button[aria-label=\"停止生成\"], button[aria-label=\"Stop generating\"]) {",
|
|
839
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] :is(button[aria-label=\"发送消息\"], button[aria-label=\"Send message\"], button[aria-label=\"排队发送\"], button[aria-label=\"Queue message\"], button[aria-label=\"插话发送\"], button[aria-label=\"Steer message\"], button[aria-label=\"停止生成\"], button[aria-label=\"Stop generating\"]) {",
|
|
739
840
|
" border-radius: 7px;",
|
|
740
841
|
"}",
|
|
741
842
|
"",
|
|
742
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"], button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]) {",
|
|
843
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"], button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]) {",
|
|
743
844
|
" background: transparent;",
|
|
744
845
|
"}",
|
|
745
846
|
"",
|
|
746
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"], button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]):hover:not(:disabled) {",
|
|
847
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"], button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]):hover:not(:disabled) {",
|
|
747
848
|
" background: #f6f6f4;",
|
|
748
849
|
"}",
|
|
749
850
|
"",
|
|
@@ -751,16 +852,16 @@ window.__ModuleLoader__.load({
|
|
|
751
852
|
" same 7px corners; its chevron is dropped while the click target and the",
|
|
752
853
|
" menu it opens stay exactly as shipped. Its shipped hover token is only a",
|
|
753
854
|
" ~6% tint, so the hover plate matches the composer tool buttons. */",
|
|
754
|
-
"body[data-dsh-claude-style] [data-composer-card] [class*=\"trigger\"] {",
|
|
855
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card] [class*=\"trigger\"] {",
|
|
755
856
|
" font-size: 14px;",
|
|
756
857
|
" border-radius: 7px;",
|
|
757
858
|
"}",
|
|
758
859
|
"",
|
|
759
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [data-composer-card] [class*=\"trigger\"]:hover:not(:disabled) {",
|
|
860
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [data-composer-card] [class*=\"trigger\"]:hover:not(:disabled) {",
|
|
760
861
|
" background: #f6f6f4;",
|
|
761
862
|
"}",
|
|
762
863
|
"",
|
|
763
|
-
"body[data-dsh-claude-style] [data-composer-card] [class*=\"_chevron\"] {",
|
|
864
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card] [class*=\"_chevron\"] {",
|
|
764
865
|
" display: none !important;",
|
|
765
866
|
"}",
|
|
766
867
|
"",
|
|
@@ -770,23 +871,23 @@ window.__ModuleLoader__.load({
|
|
|
770
871
|
" equal-width tray (z-index: 1) attached directly to the bottom of the card,",
|
|
771
872
|
" with transparent background (inheriting the canvas tone #fcfcfb),",
|
|
772
873
|
" left/right/bottom border, and 18px rounded bottom corners. */",
|
|
773
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:has([class*=\"heroWorkspaceRow\"]) {",
|
|
874
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:has([class*=\"heroWorkspaceRow\"]) {",
|
|
774
875
|
" --dsh-claude-bar-h: 96px;",
|
|
775
876
|
"}",
|
|
776
877
|
"",
|
|
777
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:has([class*=\"heroWorkspaceRow\"]) *:has([data-composer-card]) {",
|
|
878
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:has([class*=\"heroWorkspaceRow\"]) *:has([data-composer-card]) {",
|
|
778
879
|
" order: 1;",
|
|
779
880
|
" padding-bottom: 0 !important;",
|
|
780
881
|
"}",
|
|
781
882
|
"",
|
|
782
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:has([class*=\"heroWorkspaceRow\"]) [data-composer-card] {",
|
|
883
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:has([class*=\"heroWorkspaceRow\"]) [data-composer-card] {",
|
|
783
884
|
" gap: 8px !important;",
|
|
784
885
|
" padding-bottom: 2px !important;",
|
|
785
886
|
" min-height: 0 !important;",
|
|
786
887
|
" height: auto !important;",
|
|
787
888
|
"}",
|
|
788
889
|
"",
|
|
789
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:has([class*=\"heroWorkspaceRow\"]) > [class*=\"heroWorkspaceRow\"] {",
|
|
890
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:has([class*=\"heroWorkspaceRow\"]) > [class*=\"heroWorkspaceRow\"] {",
|
|
790
891
|
" order: 2;",
|
|
791
892
|
" position: relative;",
|
|
792
893
|
" z-index: 1;",
|
|
@@ -809,14 +910,14 @@ window.__ModuleLoader__.load({
|
|
|
809
910
|
"}",
|
|
810
911
|
"",
|
|
811
912
|
"/* Muted typography and 7px corners for footer controls */",
|
|
812
|
-
"body[data-dsh-claude-style] [class*=\"heroWorkspaceRow\"] :is(button, [role=\"button\"]) {",
|
|
913
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"heroWorkspaceRow\"] :is(button, [role=\"button\"]) {",
|
|
813
914
|
" font-size: 13px;",
|
|
814
915
|
" color: var(--dsw-alias-label-secondary);",
|
|
815
916
|
" border-radius: 7px;",
|
|
816
917
|
"}",
|
|
817
918
|
"",
|
|
818
919
|
"/* Hide chevrons in the footer tray for a clean, minimal Claude Code look */",
|
|
819
|
-
"body[data-dsh-claude-style] [class*=\"heroWorkspaceRow\"] :is([class*=\"chevron\"], [class*=\"Chevron\"]) {",
|
|
920
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"heroWorkspaceRow\"] :is([class*=\"chevron\"], [class*=\"Chevron\"]) {",
|
|
820
921
|
" display: none !important;",
|
|
821
922
|
"}",
|
|
822
923
|
"",
|
|
@@ -828,7 +929,7 @@ window.__ModuleLoader__.load({
|
|
|
828
929
|
" border-box keeps the outer 34px so the row does not shift. The stop/queue/",
|
|
829
930
|
" steer labels are untouched, so a running turn keeps its control even with an",
|
|
830
931
|
" empty draft. */",
|
|
831
|
-
"body[data-dsh-claude-style] [data-composer-card]:has([data-composer-placeholder]) :is(button[aria-label=\"发送消息\"], button[aria-label=\"Send message\"]) {",
|
|
932
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card]:not([data-has-attachments=\"true\"]):has([data-composer-placeholder]) :is(button[aria-label=\"发送消息\"], button[aria-label=\"Send message\"]) {",
|
|
832
933
|
" box-sizing: border-box;",
|
|
833
934
|
" background: transparent;",
|
|
834
935
|
" color: var(--dsw-alias-label-caption);",
|
|
@@ -841,10 +942,10 @@ window.__ModuleLoader__.load({
|
|
|
841
942
|
"/* In an active conversation, compress composer to a single-line input card,",
|
|
842
943
|
" render send button as an enter symbol ↵ inside the card on the right,",
|
|
843
944
|
" and display toolbar controls directly underneath on the canvas. */",
|
|
844
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"],",
|
|
845
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"]:focus-within,",
|
|
846
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card],",
|
|
847
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:focus-within {",
|
|
945
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"],",
|
|
946
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"]:focus-within,",
|
|
947
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card],",
|
|
948
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:focus-within {",
|
|
848
949
|
" background: transparent !important;",
|
|
849
950
|
" border: none !important;",
|
|
850
951
|
" box-shadow: none !important;",
|
|
@@ -868,69 +969,120 @@ window.__ModuleLoader__.load({
|
|
|
868
969
|
" composer seat near the TOP of the scroll content — sticky bottom:0",
|
|
869
970
|
" cannot pull an element down past its normal position, so the composer",
|
|
870
971
|
" appeared mid-scroll and never followed message growth. */",
|
|
871
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) {",
|
|
972
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) {",
|
|
872
973
|
" flex: 0 0 auto !important;",
|
|
873
974
|
" overflow: visible !important;",
|
|
874
975
|
" height: auto !important;",
|
|
875
976
|
" max-height: none !important;",
|
|
876
977
|
"}",
|
|
978
|
+
"/* Message body clearance: 40px placeholder space at the end of the",
|
|
979
|
+
" conversation view so the composer's upward shadow does not obscure",
|
|
980
|
+
" the action buttons (copy, retry, etc.) on the last turn. */",
|
|
981
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"viewArea\"] {",
|
|
982
|
+
" padding-bottom: 40px !important;",
|
|
983
|
+
"}",
|
|
877
984
|
"/* The composer is a chat-view affordance. The host keeps the seat mounted on",
|
|
878
985
|
" every conversation tab (轨迹 / 上下文 even reserve room for it), but it",
|
|
879
986
|
" should only show on the chat tab — drop the whole bottom area otherwise.",
|
|
880
987
|
" Hiding the seat also zeroes the host's --dsh-composer-height, so the",
|
|
881
988
|
" trajectory ledger's bottom clearance collapses with it. */",
|
|
882
|
-
"body[data-dsh-claude-style][data-dsh-claude-composer-hidden] [data-composer-seat] {",
|
|
989
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-dsh-claude-composer-hidden] [data-composer-seat] {",
|
|
883
990
|
" display: none !important;",
|
|
884
991
|
"}",
|
|
885
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"]:not([data-has-attachments=\"true\"]) [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
886
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:not([data-has-attachments=\"true\"]) [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
992
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"]:not([data-has-attachments=\"true\"]) [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
993
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:not([data-has-attachments=\"true\"]) [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
887
994
|
" display: none !important;",
|
|
888
995
|
"}",
|
|
889
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
890
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
996
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
997
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
891
998
|
" background: var(--dsw-specific-input-major, #ffffff) !important;",
|
|
892
999
|
" border: 1px solid var(--dsw-alias-border-l1) !important;",
|
|
893
1000
|
" border-bottom: none !important;",
|
|
894
1001
|
" border-radius: 14px 14px 0 0 !important;",
|
|
895
|
-
" padding:
|
|
1002
|
+
" padding: 12px 14px 10px 14px !important;",
|
|
896
1003
|
" margin: 0 !important;",
|
|
897
1004
|
" width: 100% !important;",
|
|
898
1005
|
" max-width: 100% !important;",
|
|
899
1006
|
" box-sizing: border-box !important;",
|
|
900
|
-
"
|
|
1007
|
+
" min-height: 162px !important;",
|
|
1008
|
+
" height: auto !important;",
|
|
1009
|
+
" overflow: visible !important;",
|
|
1010
|
+
" box-shadow: 0 1px 3px rgba(20, 20, 19, 0.03), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base) !important;",
|
|
1011
|
+
" position: relative !important;",
|
|
1012
|
+
" z-index: 4 !important;",
|
|
901
1013
|
" transition: border-color 0.12s ease, box-shadow 0.12s ease !important;",
|
|
902
1014
|
"}",
|
|
903
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
904
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
1015
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
1016
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
905
1017
|
" background: #ffffff !important;",
|
|
906
1018
|
" border-color: #e8e6dc !important;",
|
|
907
1019
|
"}",
|
|
908
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"]:focus-within [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
909
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:focus-within [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
910
|
-
" border-color: rgba(20, 20, 19, 0.
|
|
911
|
-
" box-shadow: 0 0 0 1px rgba(20, 20, 19, 0.
|
|
1020
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"]:focus-within [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
1021
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:focus-within [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
1022
|
+
" border-color: rgba(20, 20, 19, 0.18) !important;",
|
|
1023
|
+
" box-shadow: 0 0 0 1px rgba(20, 20, 19, 0.065), 0 4px 12px rgba(20, 20, 19, 0.025), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base) !important;",
|
|
912
1024
|
"}",
|
|
913
|
-
"body[data-dsh-claude-style][data-ds-dark-theme] [data-composer-card][data-composer-variant=\"inline\"]:focus-within [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
914
|
-
"body[data-dsh-claude-style][data-ds-dark-theme] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:focus-within [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
915
|
-
" border-color: rgba(250, 249, 245, 0.
|
|
916
|
-
" box-shadow: 0 0 0 1px rgba(250, 249, 245, 0.
|
|
1025
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-ds-dark-theme] [data-composer-card][data-composer-variant=\"inline\"]:focus-within [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
1026
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-ds-dark-theme] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:focus-within [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
1027
|
+
" border-color: rgba(250, 249, 245, 0.22) !important;",
|
|
1028
|
+
" box-shadow: 0 0 0 1px rgba(250, 249, 245, 0.09), 0 4px 16px rgba(0, 0, 0, 0.20), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base) !important;",
|
|
917
1029
|
"}",
|
|
918
1030
|
"/* The attachment rail nests two levels: ComposerAttachments' outer rail wraps",
|
|
919
1031
|
" AttachmentRail's scrolling inner rail, and BOTH substring-match",
|
|
920
1032
|
" `[class*=\"rail\"]`, so the block above would draw the card frame twice —",
|
|
921
1033
|
" one box inside the other. Only the outer shell carries the frame; the",
|
|
922
1034
|
" inner scrolling rail stays frameless. */",
|
|
923
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]) [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
924
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]) [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
1035
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]) [class*=\"rail\"]:not([class*=\"trailing\"]),",
|
|
1036
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"] [class*=\"rail\"]:not([class*=\"trailing\"]) [class*=\"rail\"]:not([class*=\"trailing\"]) {",
|
|
925
1037
|
" background: transparent !important;",
|
|
926
1038
|
" border: none !important;",
|
|
927
1039
|
" box-shadow: none !important;",
|
|
928
1040
|
" border-radius: 0 !important;",
|
|
929
1041
|
" padding: 0 !important;",
|
|
930
1042
|
" margin: 0 !important;",
|
|
1043
|
+
" min-height: 140px !important;",
|
|
1044
|
+
" height: auto !important;",
|
|
1045
|
+
" display: flex !important;",
|
|
1046
|
+
" align-items: center !important;",
|
|
1047
|
+
" gap: 10px !important;",
|
|
1048
|
+
" overflow-x: auto !important;",
|
|
1049
|
+
" overflow-y: hidden !important;",
|
|
1050
|
+
"}",
|
|
1051
|
+
"/* Attachment thumbnail card: enlarged by 75% (~140px), matching non-focus border without shadow */",
|
|
1052
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card] [class*=\"rail\"]:not([class*=\"trailing\"]) :is(._54WpYG_imageItem, [class*=\"imageItem\"], [class*=\"thumbnail\"], [class*=\"FileCard\"], [class*=\"item\"]:has(img), [class*=\"card\"]:has(img), [class*=\"attachment\"]:has(img)) {",
|
|
1053
|
+
" width: 140px !important;",
|
|
1054
|
+
" height: 140px !important;",
|
|
1055
|
+
" min-width: 140px !important;",
|
|
1056
|
+
" min-height: 140px !important;",
|
|
1057
|
+
" max-width: 140px !important;",
|
|
1058
|
+
" max-height: 140px !important;",
|
|
1059
|
+
" border-radius: 12px !important;",
|
|
1060
|
+
" border: 1px solid var(--dsw-alias-border-l1) !important;",
|
|
1061
|
+
" box-shadow: none !important;",
|
|
1062
|
+
" overflow: hidden !important;",
|
|
1063
|
+
" position: relative !important;",
|
|
1064
|
+
" z-index: 5 !important;",
|
|
1065
|
+
" flex: 0 0 140px !important;",
|
|
1066
|
+
" box-sizing: border-box !important;",
|
|
1067
|
+
"}",
|
|
1068
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [data-composer-card] [class*=\"rail\"]:not([class*=\"trailing\"]) :is(._54WpYG_imageItem, [class*=\"imageItem\"], [class*=\"thumbnail\"], [class*=\"FileCard\"], [class*=\"item\"]:has(img), [class*=\"card\"]:has(img), [class*=\"attachment\"]:has(img)) {",
|
|
1069
|
+
" border-color: #e8e6dc !important;",
|
|
1070
|
+
"}",
|
|
1071
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card] [class*=\"rail\"]:not([class*=\"trailing\"]) :is(._54WpYG_imageItem, [class*=\"imageItem\"], [class*=\"thumbnail\"], [class*=\"FileCard\"], [class*=\"item\"]:has(img), [class*=\"card\"]:has(img), [class*=\"attachment\"]:has(img)) :is(img, canvas, [class*=\"preview\"], [class*=\"image\"]) {",
|
|
1072
|
+
" width: 100% !important;",
|
|
1073
|
+
" height: 100% !important;",
|
|
1074
|
+
" max-width: 100% !important;",
|
|
1075
|
+
" max-height: 100% !important;",
|
|
1076
|
+
" object-fit: cover !important;",
|
|
1077
|
+
" display: block !important;",
|
|
1078
|
+
" border-radius: 11px !important;",
|
|
1079
|
+
"}",
|
|
1080
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card] [class*=\"rail\"]:not([class*=\"trailing\"]) :is(._54WpYG_imageItem, [class*=\"imageItem\"], [class*=\"thumbnail\"], [class*=\"FileCard\"], [class*=\"item\"]:has(img), [class*=\"card\"]:has(img), [class*=\"attachment\"]:has(img)) :is(button, [role=\"button\"], [class*=\"close\"], [class*=\"delete\"], [class*=\"remove\"], [class*=\"badge\"], [class*=\"tag\"]) {",
|
|
1081
|
+
" position: absolute !important;",
|
|
1082
|
+
" z-index: 6 !important;",
|
|
931
1083
|
"}",
|
|
932
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [data-input-scroll],",
|
|
933
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [data-input-scroll] {",
|
|
1084
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [data-input-scroll],",
|
|
1085
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [data-input-scroll] {",
|
|
934
1086
|
" background: var(--dsw-specific-input-major, #ffffff) !important;",
|
|
935
1087
|
" border: 1px solid var(--dsw-alias-border-l1) !important;",
|
|
936
1088
|
" border-radius: 14px !important;",
|
|
@@ -946,51 +1098,53 @@ window.__ModuleLoader__.load({
|
|
|
946
1098
|
" padding: 7px 36px 7px 14px !important;",
|
|
947
1099
|
" margin: 0 !important;",
|
|
948
1100
|
" position: relative !important;",
|
|
1101
|
+
" z-index: 2 !important;",
|
|
949
1102
|
" cursor: text !important;",
|
|
1103
|
+
" box-shadow: 0 1px 3px rgba(20, 20, 19, 0.03), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base) !important;",
|
|
950
1104
|
" transition: border-color 0.12s ease, box-shadow 0.12s ease !important;",
|
|
951
1105
|
"}",
|
|
952
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"] [data-input-scroll],",
|
|
953
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"] [data-input-scroll] {",
|
|
1106
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"] [data-input-scroll],",
|
|
1107
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"] [data-input-scroll] {",
|
|
954
1108
|
" border-top: none !important;",
|
|
955
1109
|
" border-radius: 0 0 14px 14px !important;",
|
|
956
|
-
" /*
|
|
957
|
-
"
|
|
958
|
-
" Close it (negative margin pulls the input up onto the rail) and move the",
|
|
959
|
-
" 8px into the top padding, so the text keeps its distance from the",
|
|
960
|
-
" thumbnails and the card's total height is unchanged. */",
|
|
961
|
-
" margin-top: -8px !important;",
|
|
1110
|
+
" /* Seamless join with attachment rail above: 1px negative margin prevents subpixel seam without clipping thumbnails */",
|
|
1111
|
+
" margin-top: -1px !important;",
|
|
962
1112
|
" min-height: 32px !important;",
|
|
963
|
-
" padding:
|
|
1113
|
+
" padding: 8px 36px 6px 14px !important;",
|
|
964
1114
|
"}",
|
|
965
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"] [data-input-scroll],",
|
|
966
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [data-input-scroll] {",
|
|
1115
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"] [data-input-scroll],",
|
|
1116
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [data-input-scroll] {",
|
|
967
1117
|
" background: #ffffff !important;",
|
|
968
1118
|
" border-color: #e8e6dc !important;",
|
|
969
|
-
" box-shadow: 0 1px 3px rgba(20, 20, 19, 0.03) !important;",
|
|
1119
|
+
" box-shadow: 0 1px 3px rgba(20, 20, 19, 0.03), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base) !important;",
|
|
1120
|
+
"}",
|
|
1121
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-ds-dark-theme] [data-composer-card][data-composer-variant=\"inline\"] [data-input-scroll],",
|
|
1122
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-ds-dark-theme] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [data-input-scroll] {",
|
|
1123
|
+
" box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base) !important;",
|
|
970
1124
|
"}",
|
|
971
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"]:focus-within [data-input-scroll],",
|
|
972
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:focus-within [data-input-scroll] {",
|
|
973
|
-
" border-color: rgba(20, 20, 19, 0.
|
|
974
|
-
" box-shadow: 0 0 0 1px rgba(20, 20, 19, 0.
|
|
1125
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"]:focus-within [data-input-scroll],",
|
|
1126
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:focus-within [data-input-scroll] {",
|
|
1127
|
+
" border-color: rgba(20, 20, 19, 0.18) !important;",
|
|
1128
|
+
" box-shadow: 0 0 0 1px rgba(20, 20, 19, 0.065), 0 4px 12px rgba(20, 20, 19, 0.025), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base) !important;",
|
|
975
1129
|
"}",
|
|
976
|
-
"body[data-dsh-claude-style][data-ds-dark-theme] [data-composer-card][data-composer-variant=\"inline\"]:focus-within [data-input-scroll],",
|
|
977
|
-
"body[data-dsh-claude-style][data-ds-dark-theme] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:focus-within [data-input-scroll] {",
|
|
978
|
-
" border-color: rgba(250, 249, 245, 0.
|
|
979
|
-
" box-shadow: 0 0 0 1px rgba(250, 249, 245, 0.
|
|
1130
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-ds-dark-theme] [data-composer-card][data-composer-variant=\"inline\"]:focus-within [data-input-scroll],",
|
|
1131
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-ds-dark-theme] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:focus-within [data-input-scroll] {",
|
|
1132
|
+
" border-color: rgba(250, 249, 245, 0.22) !important;",
|
|
1133
|
+
" box-shadow: 0 0 0 1px rgba(250, 249, 245, 0.09), 0 4px 16px rgba(0, 0, 0, 0.20), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base) !important;",
|
|
980
1134
|
"}",
|
|
981
1135
|
"/* With attachments the rail already carries the card's focus ring, so the",
|
|
982
1136
|
" input keeps only the deepened drop — its own 1px ring would paint a second",
|
|
983
1137
|
" line across the seam between the thumbnails and the text. */",
|
|
984
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"]:focus-within [data-input-scroll],",
|
|
985
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"]:focus-within [data-input-scroll] {",
|
|
986
|
-
" box-shadow: 0 4px 12px rgba(20, 20, 19, 0.
|
|
1138
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"]:focus-within [data-input-scroll],",
|
|
1139
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"]:focus-within [data-input-scroll] {",
|
|
1140
|
+
" box-shadow: 0 4px 12px rgba(20, 20, 19, 0.025), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base) !important;",
|
|
987
1141
|
"}",
|
|
988
|
-
"body[data-dsh-claude-style][data-ds-dark-theme] [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"]:focus-within [data-input-scroll],",
|
|
989
|
-
"body[data-dsh-claude-style][data-ds-dark-theme] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"]:focus-within [data-input-scroll] {",
|
|
990
|
-
" box-shadow: 0 4px 16px rgba(0, 0, 0, 0.
|
|
1142
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-ds-dark-theme] [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"]:focus-within [data-input-scroll],",
|
|
1143
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active][data-ds-dark-theme] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"]:focus-within [data-input-scroll] {",
|
|
1144
|
+
" box-shadow: 0 4px 16px rgba(0, 0, 0, 0.20), 0 0 0 6px var(--dsw-alias-bg-base), 0 0 16px 10px var(--dsw-alias-bg-base), 0 0 48px 16px var(--dsw-alias-bg-base) !important;",
|
|
991
1145
|
"}",
|
|
992
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [data-input-scroll] [class*=\"grow\"],",
|
|
993
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [data-input-scroll] [class*=\"grow\"] {",
|
|
1146
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [data-input-scroll] [class*=\"grow\"],",
|
|
1147
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [data-input-scroll] [class*=\"grow\"] {",
|
|
994
1148
|
" width: 100% !important;",
|
|
995
1149
|
" max-width: 100% !important;",
|
|
996
1150
|
" min-height: 24px !important;",
|
|
@@ -999,8 +1153,8 @@ window.__ModuleLoader__.load({
|
|
|
999
1153
|
" box-sizing: border-box !important;",
|
|
1000
1154
|
" overflow-x: hidden !important;",
|
|
1001
1155
|
"}",
|
|
1002
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [data-composer-input],",
|
|
1003
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [data-composer-input] {",
|
|
1156
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [data-composer-input],",
|
|
1157
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [data-composer-input] {",
|
|
1004
1158
|
" min-height: 24px !important;",
|
|
1005
1159
|
" height: auto !important;",
|
|
1006
1160
|
" line-height: 24px !important;",
|
|
@@ -1016,8 +1170,8 @@ window.__ModuleLoader__.load({
|
|
|
1016
1170
|
" overflow-wrap: anywhere !important;",
|
|
1017
1171
|
" overflow-x: hidden !important;",
|
|
1018
1172
|
"}",
|
|
1019
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [data-composer-placeholder],",
|
|
1020
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [data-composer-placeholder] {",
|
|
1173
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [data-composer-placeholder],",
|
|
1174
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [data-composer-placeholder] {",
|
|
1021
1175
|
" line-height: 24px !important;",
|
|
1022
1176
|
" height: 24px !important;",
|
|
1023
1177
|
" position: absolute !important;",
|
|
@@ -1035,8 +1189,8 @@ window.__ModuleLoader__.load({
|
|
|
1035
1189
|
" user-select: none !important;",
|
|
1036
1190
|
"}",
|
|
1037
1191
|
"/* Pinned send button inside input box */",
|
|
1038
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"], button[aria-label*=\"排队\"], button[aria-label*=\"Queue\"], button[aria-label*=\"插话\"], button[aria-label*=\"Steer\"], [class*=\"sendBtn\"], [class*=\"sendButton\"]),",
|
|
1039
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"], button[aria-label*=\"排队\"], button[aria-label*=\"Queue\"], button[aria-label*=\"插话\"], button[aria-label*=\"Steer\"], [class*=\"sendBtn\"], [class*=\"sendButton\"]) {",
|
|
1192
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"], button[aria-label*=\"排队\"], button[aria-label*=\"Queue\"], button[aria-label*=\"插话\"], button[aria-label*=\"Steer\"], [class*=\"sendBtn\"], [class*=\"sendButton\"]),",
|
|
1193
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"], button[aria-label*=\"排队\"], button[aria-label*=\"Queue\"], button[aria-label*=\"插话\"], button[aria-label*=\"Steer\"], [class*=\"sendBtn\"], [class*=\"sendButton\"]) {",
|
|
1040
1194
|
" position: absolute !important;",
|
|
1041
1195
|
" bottom: 40px !important;",
|
|
1042
1196
|
" right: 8px !important;",
|
|
@@ -1058,11 +1212,11 @@ window.__ModuleLoader__.load({
|
|
|
1058
1212
|
" cursor: pointer !important;",
|
|
1059
1213
|
" transition: color 0.12s ease, background-color 0.12s ease !important;",
|
|
1060
1214
|
"}",
|
|
1061
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"], button[aria-label*=\"排队\"], button[aria-label*=\"Queue\"], button[aria-label*=\"插话\"], button[aria-label*=\"Steer\"], [class*=\"sendBtn\"], [class*=\"sendButton\"]) :is(svg, [class*=\"chevron\"], span) {",
|
|
1215
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"], button[aria-label*=\"排队\"], button[aria-label*=\"Queue\"], button[aria-label*=\"插话\"], button[aria-label*=\"Steer\"], [class*=\"sendBtn\"], [class*=\"sendButton\"]) :is(svg, [class*=\"chevron\"], span) {",
|
|
1062
1216
|
" display: none !important;",
|
|
1063
1217
|
"}",
|
|
1064
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"], button[aria-label*=\"排队\"], button[aria-label*=\"Queue\"], button[aria-label*=\"插话\"], button[aria-label*=\"Steer\"], [class*=\"sendBtn\"], [class*=\"sendButton\"])::after,",
|
|
1065
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"], button[aria-label*=\"排队\"], button[aria-label*=\"Queue\"], button[aria-label*=\"插话\"], button[aria-label*=\"Steer\"], [class*=\"sendBtn\"], [class*=\"sendButton\"])::after {",
|
|
1218
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"], button[aria-label*=\"排队\"], button[aria-label*=\"Queue\"], button[aria-label*=\"插话\"], button[aria-label*=\"Steer\"], [class*=\"sendBtn\"], [class*=\"sendButton\"])::after,",
|
|
1219
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"], button[aria-label*=\"排队\"], button[aria-label*=\"Queue\"], button[aria-label*=\"插话\"], button[aria-label*=\"Steer\"], [class*=\"sendBtn\"], [class*=\"sendButton\"])::after {",
|
|
1066
1220
|
" content: \"↵\" !important;",
|
|
1067
1221
|
" font-family: var(--dsw-font-code, monospace) !important;",
|
|
1068
1222
|
" font-size: 16px !important;",
|
|
@@ -1070,18 +1224,20 @@ window.__ModuleLoader__.load({
|
|
|
1070
1224
|
" line-height: 1 !important;",
|
|
1071
1225
|
" color: currentColor !important;",
|
|
1072
1226
|
"}",
|
|
1073
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"]):not(:disabled):hover,",
|
|
1074
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"]):not(:disabled):hover {",
|
|
1227
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"]):not(:disabled):hover,",
|
|
1228
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"]):not(:disabled):hover {",
|
|
1075
1229
|
" background: var(--dsh-claude-hover-bg, rgba(0, 0, 0, 0.08)) !important;",
|
|
1076
1230
|
" color: var(--dsw-alias-label-primary) !important;",
|
|
1077
1231
|
"}",
|
|
1078
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"]:not(:has([data-composer-placeholder])) :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"]),",
|
|
1079
|
-
"body[data-dsh-claude-style]
|
|
1232
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"]:not(:has([data-composer-placeholder])) :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"]),",
|
|
1233
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"][data-has-attachments=\"true\"] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"]),",
|
|
1234
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card]:not(:has([data-composer-placeholder])) :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"]),",
|
|
1235
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card][data-has-attachments=\"true\"] :is(button[aria-label^=\"发送\"], button[aria-label^=\"Send\"], button[aria-label*=\"发送\"], button[aria-label*=\"Send\"]) {",
|
|
1080
1236
|
" color: var(--dsw-alias-brand-primary, #d97757) !important;",
|
|
1081
1237
|
"}",
|
|
1082
1238
|
"/* Pinned stop button inside input box */",
|
|
1083
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"]),",
|
|
1084
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"]) {",
|
|
1239
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"]),",
|
|
1240
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"]) {",
|
|
1085
1241
|
" position: absolute !important;",
|
|
1086
1242
|
" bottom: 40px !important;",
|
|
1087
1243
|
" right: 8px !important;",
|
|
@@ -1100,22 +1256,22 @@ window.__ModuleLoader__.load({
|
|
|
1100
1256
|
" color: var(--dsw-alias-brand-primary, #d97757) !important;",
|
|
1101
1257
|
" border: none !important;",
|
|
1102
1258
|
"}",
|
|
1103
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"]) svg,",
|
|
1104
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"]) svg {",
|
|
1259
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"]) svg,",
|
|
1260
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"]) svg {",
|
|
1105
1261
|
" display: block !important;",
|
|
1106
1262
|
" width: 12px !important;",
|
|
1107
1263
|
" height: 12px !important;",
|
|
1108
1264
|
"}",
|
|
1109
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"])::after,",
|
|
1110
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"])::after {",
|
|
1265
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"])::after,",
|
|
1266
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label*=\"停止\"], button[aria-label*=\"Stop\"])::after {",
|
|
1111
1267
|
" display: none !important;",
|
|
1112
1268
|
"}",
|
|
1113
1269
|
"/* Toolbar row below input card. `[class*=\"_row\"]` on purpose: a bare",
|
|
1114
1270
|
" `[class*=\"row\"]` substring-matches the shipped `.p_FcLG_grow` input",
|
|
1115
1271
|
" wrapper (\"grow\" contains \"row\"), and the fixed 28px height + flex",
|
|
1116
1272
|
" display here would pin the composer field to one line forever. */",
|
|
1117
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"_row\"],",
|
|
1118
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"_row\"] {",
|
|
1273
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"_row\"],",
|
|
1274
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"_row\"] {",
|
|
1119
1275
|
" display: flex !important;",
|
|
1120
1276
|
" flex-wrap: nowrap !important;",
|
|
1121
1277
|
" justify-content: space-between !important;",
|
|
@@ -1131,6 +1287,8 @@ window.__ModuleLoader__.load({
|
|
|
1131
1287
|
" max-width: 100% !important;",
|
|
1132
1288
|
" box-sizing: border-box !important;",
|
|
1133
1289
|
" overflow: visible !important;",
|
|
1290
|
+
" position: relative !important;",
|
|
1291
|
+
" z-index: 3 !important;",
|
|
1134
1292
|
"}",
|
|
1135
1293
|
"/* The context-occupancy meter renders its click-open panel INSIDE the inline",
|
|
1136
1294
|
" composer card, and its legend classes (`…_rows` / `…_row`) substring-match",
|
|
@@ -1138,8 +1296,8 @@ window.__ModuleLoader__.load({
|
|
|
1138
1296
|
" list into one 28px flex line and wrapped every label/value. Restore the",
|
|
1139
1297
|
" shipped legend layout: the list stacks vertically, each row keeps its",
|
|
1140
1298
|
" natural height and space-between distribution. */",
|
|
1141
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"_rows\"],",
|
|
1142
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"_rows\"] {",
|
|
1299
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"_rows\"],",
|
|
1300
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"_rows\"] {",
|
|
1143
1301
|
" display: block !important;",
|
|
1144
1302
|
" height: auto !important;",
|
|
1145
1303
|
" min-height: 0 !important;",
|
|
@@ -1147,8 +1305,8 @@ window.__ModuleLoader__.load({
|
|
|
1147
1305
|
" max-width: none !important;",
|
|
1148
1306
|
" padding: 0 !important;",
|
|
1149
1307
|
"}",
|
|
1150
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"_rows\"] [class*=\"_row\"],",
|
|
1151
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"_rows\"] [class*=\"_row\"] {",
|
|
1308
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"_rows\"] [class*=\"_row\"],",
|
|
1309
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"_rows\"] [class*=\"_row\"] {",
|
|
1152
1310
|
" display: flex !important;",
|
|
1153
1311
|
" height: auto !important;",
|
|
1154
1312
|
" min-height: 0 !important;",
|
|
@@ -1157,23 +1315,23 @@ window.__ModuleLoader__.load({
|
|
|
1157
1315
|
" padding: 2px 0 !important;",
|
|
1158
1316
|
" margin: 0 !important;",
|
|
1159
1317
|
"}",
|
|
1160
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"tools\"],",
|
|
1161
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"tools\"] {",
|
|
1318
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"tools\"],",
|
|
1319
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"tools\"] {",
|
|
1162
1320
|
" display: flex !important;",
|
|
1163
1321
|
" align-items: center !important;",
|
|
1164
1322
|
" gap: 8px !important;",
|
|
1165
1323
|
" flex: 0 0 auto !important;",
|
|
1166
1324
|
" overflow: visible !important;",
|
|
1167
1325
|
"}",
|
|
1168
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"modes\"],",
|
|
1169
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"modes\"] {",
|
|
1326
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"modes\"],",
|
|
1327
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"modes\"] {",
|
|
1170
1328
|
" order: 1 !important;",
|
|
1171
1329
|
" display: inline-flex !important;",
|
|
1172
1330
|
" align-items: center !important;",
|
|
1173
1331
|
" overflow: visible !important;",
|
|
1174
1332
|
"}",
|
|
1175
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"]),",
|
|
1176
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"]) {",
|
|
1333
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"]),",
|
|
1334
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"]) {",
|
|
1177
1335
|
" order: 2 !important;",
|
|
1178
1336
|
" width: 24px !important;",
|
|
1179
1337
|
" height: 24px !important;",
|
|
@@ -1184,8 +1342,8 @@ window.__ModuleLoader__.load({
|
|
|
1184
1342
|
" align-items: center !important;",
|
|
1185
1343
|
" justify-content: center !important;",
|
|
1186
1344
|
"}",
|
|
1187
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]),",
|
|
1188
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]) {",
|
|
1345
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]),",
|
|
1346
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]) {",
|
|
1189
1347
|
" order: 3 !important;",
|
|
1190
1348
|
" width: 24px !important;",
|
|
1191
1349
|
" height: 24px !important;",
|
|
@@ -1196,13 +1354,13 @@ window.__ModuleLoader__.load({
|
|
|
1196
1354
|
" align-items: center !important;",
|
|
1197
1355
|
" justify-content: center !important;",
|
|
1198
1356
|
"}",
|
|
1199
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"], button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]):hover:not(:disabled),",
|
|
1200
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"], button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]):hover:not(:disabled) {",
|
|
1357
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"], button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]):hover:not(:disabled),",
|
|
1358
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] :is(button[aria-label=\"指令\"], button[aria-label=\"Commands\"], button[aria-label=\"添加附件\"], button[aria-label=\"Add attachment\"]):hover:not(:disabled) {",
|
|
1201
1359
|
" background: var(--dsh-claude-hover-bg, rgba(0, 0, 0, 0.08)) !important;",
|
|
1202
1360
|
" color: var(--dsw-alias-label-primary) !important;",
|
|
1203
1361
|
"}",
|
|
1204
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"trailing\"],",
|
|
1205
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"trailing\"] {",
|
|
1362
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"trailing\"],",
|
|
1363
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"trailing\"] {",
|
|
1206
1364
|
" display: flex !important;",
|
|
1207
1365
|
" align-items: center !important;",
|
|
1208
1366
|
" gap: 8px !important;",
|
|
@@ -1210,8 +1368,8 @@ window.__ModuleLoader__.load({
|
|
|
1210
1368
|
" flex: 0 0 auto !important;",
|
|
1211
1369
|
"}",
|
|
1212
1370
|
"/* Model trigger in trailing */",
|
|
1213
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"trailing\"] > :first-child,",
|
|
1214
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"trailing\"] :is([class*=\"trigger\" i], [class*=\"model\" i], [class*=\"Model\"]) {",
|
|
1371
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"trailing\"] > :first-child,",
|
|
1372
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"trailing\"] :is([class*=\"trigger\" i], [class*=\"model\" i], [class*=\"Model\"]) {",
|
|
1215
1373
|
" display: inline-flex !important;",
|
|
1216
1374
|
" align-items: center !important;",
|
|
1217
1375
|
" font-size: 13px !important;",
|
|
@@ -1221,8 +1379,8 @@ window.__ModuleLoader__.load({
|
|
|
1221
1379
|
" visibility: visible !important;",
|
|
1222
1380
|
" opacity: 1 !important;",
|
|
1223
1381
|
"}",
|
|
1224
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"] [class*=\"trailing\"] > :first-child:hover:not(:disabled),",
|
|
1225
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"] [class*=\"trailing\"] :is([class*=\"trigger\" i], [class*=\"model\" i], [class*=\"Model\"]):hover:not(:disabled) {",
|
|
1382
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"] [class*=\"trailing\"] > :first-child:hover:not(:disabled),",
|
|
1383
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active]:not([data-ds-dark-theme]) [data-composer-card][data-composer-variant=\"inline\"] [class*=\"trailing\"] :is([class*=\"trigger\" i], [class*=\"model\" i], [class*=\"Model\"]):hover:not(:disabled) {",
|
|
1226
1384
|
" background: var(--dsh-claude-hover-bg, rgba(0, 0, 0, 0.06)) !important;",
|
|
1227
1385
|
" color: var(--dsw-alias-label-primary) !important;",
|
|
1228
1386
|
"}",
|
|
@@ -1230,10 +1388,10 @@ window.__ModuleLoader__.load({
|
|
|
1230
1388
|
" root is marked and hidden by syncModelControl). One button, one hover",
|
|
1231
1389
|
" background — the shipped seat stacks an icon + label + effort + chevron,",
|
|
1232
1390
|
" each with its own surface. */",
|
|
1233
|
-
"body[data-dsh-claude-style] [data-dsh-claude-model-host] {",
|
|
1391
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-dsh-claude-model-host] {",
|
|
1234
1392
|
" display: none !important;",
|
|
1235
1393
|
"}",
|
|
1236
|
-
"body[data-dsh-claude-style] [class*=\"trailing\"] .dsh-claude-model-btn {",
|
|
1394
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"trailing\"] .dsh-claude-model-btn {",
|
|
1237
1395
|
" display: inline-flex !important;",
|
|
1238
1396
|
" align-items: center !important;",
|
|
1239
1397
|
" gap: 2px !important;",
|
|
@@ -1251,25 +1409,25 @@ window.__ModuleLoader__.load({
|
|
|
1251
1409
|
" box-sizing: border-box !important;",
|
|
1252
1410
|
" min-width: 0 !important;",
|
|
1253
1411
|
"}",
|
|
1254
|
-
"body[data-dsh-claude-style] [class*=\"trailing\"] .dsh-claude-model-btn-label.dsh-claude-model-btn-loading {",
|
|
1412
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"trailing\"] .dsh-claude-model-btn-label.dsh-claude-model-btn-loading {",
|
|
1255
1413
|
" color: var(--dsw-alias-label-caption, #a6a094) !important;",
|
|
1256
1414
|
"}",
|
|
1257
|
-
"body[data-dsh-claude-style] [class*=\"trailing\"] .dsh-claude-model-btn:hover {",
|
|
1415
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"trailing\"] .dsh-claude-model-btn:hover {",
|
|
1258
1416
|
" background: var(--dsh-claude-hover-bg, rgba(0, 0, 0, 0.08)) !important;",
|
|
1259
1417
|
" color: var(--dsw-alias-label-primary) !important;",
|
|
1260
1418
|
"}",
|
|
1261
|
-
"body[data-dsh-claude-style] [class*=\"trailing\"] .dsh-claude-model-btn-label {",
|
|
1419
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"trailing\"] .dsh-claude-model-btn-label {",
|
|
1262
1420
|
" text-overflow: ellipsis !important;",
|
|
1263
1421
|
" white-space: nowrap !important;",
|
|
1264
1422
|
" min-width: 0 !important;",
|
|
1265
1423
|
" overflow: hidden !important;",
|
|
1266
1424
|
"}",
|
|
1267
|
-
"body[data-dsh-claude-style] [class*=\"trailing\"] .dsh-claude-model-btn-effort {",
|
|
1425
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"trailing\"] .dsh-claude-model-btn-effort {",
|
|
1268
1426
|
" flex: none !important;",
|
|
1269
1427
|
" color: var(--dsw-alias-label-caption, #a6a094) !important;",
|
|
1270
1428
|
" font-weight: 400 !important;",
|
|
1271
1429
|
"}",
|
|
1272
|
-
"body[data-dsh-claude-style] [class*=\"trailing\"] .dsh-claude-model-btn-chevron {",
|
|
1430
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"trailing\"] .dsh-claude-model-btn-chevron {",
|
|
1273
1431
|
" flex: none !important;",
|
|
1274
1432
|
" display: inline-flex !important;",
|
|
1275
1433
|
" align-items: center !important;",
|
|
@@ -1280,8 +1438,10 @@ window.__ModuleLoader__.load({
|
|
|
1280
1438
|
" position (a full-width line under the card); once mergeStatsIntoRow()",
|
|
1281
1439
|
" has moved the pills into the row, the override after it resets every",
|
|
1282
1440
|
" geometry property the host's full-width line depends on. */",
|
|
1283
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] ~ [data-composer-stats],",
|
|
1284
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-stats] {",
|
|
1441
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] ~ [data-composer-stats],",
|
|
1442
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-stats] {",
|
|
1443
|
+
" position: relative !important;",
|
|
1444
|
+
" z-index: 3 !important;",
|
|
1285
1445
|
" display: flex !important;",
|
|
1286
1446
|
" align-items: center !important;",
|
|
1287
1447
|
" justify-content: center !important;",
|
|
@@ -1303,8 +1463,10 @@ window.__ModuleLoader__.load({
|
|
|
1303
1463
|
" tool cluster and the trailing model/status group (the row's space-between",
|
|
1304
1464
|
" centers them). Width, padding and margin come from the host's full-width",
|
|
1305
1465
|
" line, so all of them are reset; the pills keep their own hover/click. */",
|
|
1306
|
-
"body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"_row\"] [data-composer-stats],",
|
|
1307
|
-
"body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"_row\"] [data-composer-stats] {",
|
|
1466
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] [class*=\"_row\"] [data-composer-stats],",
|
|
1467
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-card] [class*=\"_row\"] [data-composer-stats] {",
|
|
1468
|
+
" position: relative !important;",
|
|
1469
|
+
" z-index: 3 !important;",
|
|
1308
1470
|
" width: auto !important;",
|
|
1309
1471
|
" max-width: none !important;",
|
|
1310
1472
|
" margin: 0 8px !important;",
|
|
@@ -1319,20 +1481,20 @@ window.__ModuleLoader__.load({
|
|
|
1319
1481
|
" is hovered, so the toolbar stays clean. Space is preserved — no reflow when",
|
|
1320
1482
|
" they fade in — and because the pills live inside the card, hovering them",
|
|
1321
1483
|
" keeps them visible long enough to click. */",
|
|
1322
|
-
"body[data-dsh-claude-style] [data-composer-card] [class*=\"_row\"] [data-composer-stats] {",
|
|
1484
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card] [class*=\"_row\"] [data-composer-stats] {",
|
|
1323
1485
|
" opacity: 0 !important;",
|
|
1324
1486
|
" visibility: hidden !important;",
|
|
1325
1487
|
" pointer-events: none !important;",
|
|
1326
1488
|
" transition: opacity 0.15s ease, visibility 0.15s ease !important;",
|
|
1327
1489
|
"}",
|
|
1328
|
-
"body[data-dsh-claude-style] [data-composer-card]:hover [class*=\"_row\"] [data-composer-stats] {",
|
|
1490
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card]:hover [class*=\"_row\"] [data-composer-stats] {",
|
|
1329
1491
|
" opacity: 1 !important;",
|
|
1330
1492
|
" visibility: visible !important;",
|
|
1331
1493
|
" pointer-events: auto !important;",
|
|
1332
1494
|
"}",
|
|
1333
1495
|
"@media (max-width: 820px) {",
|
|
1334
|
-
" body[data-dsh-claude-style] [data-composer-card][data-composer-variant=\"inline\"] ~ [data-composer-stats],",
|
|
1335
|
-
" body[data-dsh-claude-style] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-stats] {",
|
|
1496
|
+
" body[data-dsh-claude-style][data-dsh-claude-composer-active] [data-composer-card][data-composer-variant=\"inline\"] ~ [data-composer-stats],",
|
|
1497
|
+
" body[data-dsh-claude-style][data-dsh-claude-composer-active] [class*=\"composerStack\"]:not(:has([class*=\"heroWorkspaceRow\"])) [data-composer-stats] {",
|
|
1336
1498
|
" display: none !important;",
|
|
1337
1499
|
" }",
|
|
1338
1500
|
"}",
|
|
@@ -1348,11 +1510,11 @@ window.__ModuleLoader__.load({
|
|
|
1348
1510
|
" brandName box, and each wordmark takes its natural width from that height",
|
|
1349
1511
|
" via the artwork aspect ratios (Claude 4.214:1, ANTHROPIC ~8.94:1). The",
|
|
1350
1512
|
" wordmark keeps a max-width so a longer brand can never clip the row. */",
|
|
1351
|
-
"body[data-dsh-claude-style] :is([class*=\"brandMark\"], [class*=\"railMark\"]) > * {",
|
|
1513
|
+
"body[data-dsh-claude-style]:is([data-dsh-claude-brand=\"claude\"], [data-dsh-claude-brand=\"anthropic\"]) :is([class*=\"brandMark\"], [class*=\"railMark\"]) > * {",
|
|
1352
1514
|
" display: none !important;",
|
|
1353
1515
|
"}",
|
|
1354
1516
|
"",
|
|
1355
|
-
"body[data-dsh-claude-style] :is([class*=\"brandMark\"], [class*=\"railMark\"])::before {",
|
|
1517
|
+
"body[data-dsh-claude-style]:is([data-dsh-claude-brand=\"claude\"], [data-dsh-claude-brand=\"anthropic\"]) :is([class*=\"brandMark\"], [class*=\"railMark\"])::before {",
|
|
1356
1518
|
" content: \"\";",
|
|
1357
1519
|
" display: block;",
|
|
1358
1520
|
" flex: none;",
|
|
@@ -1363,18 +1525,18 @@ window.__ModuleLoader__.load({
|
|
|
1363
1525
|
"}",
|
|
1364
1526
|
"",
|
|
1365
1527
|
"/* Claude (default): starburst mark + the Claude wordmark. */",
|
|
1366
|
-
"body[data-dsh-claude-style]
|
|
1528
|
+
"body[data-dsh-claude-style][data-dsh-claude-brand=\"claude\"] :is([class*=\"brandMark\"], [class*=\"railMark\"])::before {",
|
|
1367
1529
|
" width: 18px;",
|
|
1368
1530
|
" height: 18px;",
|
|
1369
1531
|
" -webkit-mask: url(\"data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%20148.09%20148.18'%3E%3Cg%20transform%3D'translate(-75.96%2C-223.53)'%3E%3Cpath%20d%3D'm%20105.01%2C322.07%2029.14%2C-16.35%200.49%2C-1.42%20-0.49%2C-0.79%20h%20-1.42%20l%20-4.87%2C-0.3%20-16.65%2C-0.45%20-14.44%2C-0.6%20-13.99%2C-0.75%20-3.52%2C-0.75%20-3.3%2C-4.35%200.34%2C-2.17%202.96%2C-1.99%204.24%2C0.37%209.37%2C0.64%2014.06%2C0.97%2010.2%2C0.6%2015.11%2C1.57%20h%202.4%20l%200.34%2C-0.97%20-0.82%2C-0.6%20-0.64%2C-0.6%20-14.55%2C-9.86%20-15.75%2C-10.42%20-8.25%2C-6%20-4.46%2C-3.04%20-2.25%2C-2.85%20-0.97%2C-6.22%204.05%2C-4.46%205.44%2C0.37%201.39%2C0.37%205.51%2C4.24%2011.77%2C9.11%2015.37%2C11.32%202.25%2C1.87%200.9%2C-0.64%200.11%2C-0.45%20-1.01%2C-1.69%20-8.36%2C-15.11%20-8.92%2C-15.37%20-3.97%2C-6.37%20-1.05%2C-3.82%20c%20-0.37%2C-1.57%20-0.64%2C-2.89%20-0.64%2C-4.5%20l%204.61%2C-6.26%202.55%2C-0.82%206.15%2C0.82%202.59%2C2.25%203.82%2C8.74%206.19%2C13.76%209.6%2C18.71%202.81%2C5.55%201.5%2C5.14%200.56%2C1.57%20h%200.97%20v%20-0.9%20l%200.79%2C-10.54%201.46%2C-12.94%201.42%2C-16.65%200.49%2C-4.69%202.32%2C-5.62%204.61%2C-3.04%203.6%2C1.72%202.96%2C4.24%20-0.41%2C2.74%20-1.76%2C11.44%20-3.45%2C17.92%20-2.25%2C12%20h%201.31%20l%201.5%2C-1.5%206.07%2C-8.06%2010.2%2C-12.75%204.5%2C-5.06%205.25%2C-5.59%203.37%2C-2.66%20h%206.37%20l%204.69%2C6.97%20-2.1%2C7.2%20-6.56%2C8.32%20-5.44%2C7.05%20-7.8%2C10.5%20-4.87%2C8.4%200.45%2C0.67%201.16%2C-0.11%2017.62%2C-3.75%209.52%2C-1.72%2011.36%2C-1.95%205.14%2C2.4%200.56%2C2.44%20-2.02%2C4.99%20-12.15%2C3%20-14.25%2C2.85%20-21.22%2C5.02%20-0.26%2C0.19%200.3%2C0.37%209.56%2C0.9%204.09%2C0.22%20h%2010.01%20l%2018.64%2C1.39%204.87%2C3.22%202.92%2C3.94%20-0.49%2C3%20-7.5%2C3.82%20-10.12%2C-2.4%20-23.62%2C-5.62%20-8.1%2C-2.02%20h%20-1.12%20v%200.67%20l%206.75%2C6.6%2012.37%2C11.17%2015.49%2C14.4%200.79%2C3.56%20-1.99%2C2.81%20-2.1%2C-0.3%20-13.61%2C-10.24%20-5.25%2C-4.61%20-11.89%2C-10.01%20h%20-0.79%20v%201.05%20l%202.74%2C4.01%2014.47%2C21.75%200.75%2C6.67%20-1.05%2C2.17%20-3.75%2C1.31%20-4.12%2C-0.75%20-8.47%2C-11.89%20-8.74%2C-13.39%20-7.05%2C-12%20-0.86%2C0.49%20-4.16%2C44.81%20-1.95%2C2.29%20-4.5%2C1.72%20-3.75%2C-2.85%20-1.99%2C-4.61%201.99%2C-9.11%202.4%2C-11.89%201.95%2C-9.45%201.76%2C-11.74%201.05%2C-3.9%20-0.07%2C-0.26%20-0.86%2C0.11%20-8.85%2C12.15%20-13.46%2C18.19%20-10.65%2C11.4%20-2.55%2C1.01%20-4.42%2C-2.29%200.41%2C-4.09%202.47%2C-3.64%2014.74%2C-18.75%208.89%2C-11.62%205.74%2C-6.71%20-0.04%2C-0.97%20h%20-0.34%20l%20-39.15%2C25.42%20-6.97%2C0.9%20-3%2C-2.81%200.37%2C-4.61%201.42%2C-1.5%2011.77%2C-8.1%20-0.04%2C0.04%20z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E\") center / contain no-repeat;",
|
|
1370
1532
|
" mask: url(\"data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%20148.09%20148.18'%3E%3Cg%20transform%3D'translate(-75.96%2C-223.53)'%3E%3Cpath%20d%3D'm%20105.01%2C322.07%2029.14%2C-16.35%200.49%2C-1.42%20-0.49%2C-0.79%20h%20-1.42%20l%20-4.87%2C-0.3%20-16.65%2C-0.45%20-14.44%2C-0.6%20-13.99%2C-0.75%20-3.52%2C-0.75%20-3.3%2C-4.35%200.34%2C-2.17%202.96%2C-1.99%204.24%2C0.37%209.37%2C0.64%2014.06%2C0.97%2010.2%2C0.6%2015.11%2C1.57%20h%202.4%20l%200.34%2C-0.97%20-0.82%2C-0.6%20-0.64%2C-0.6%20-14.55%2C-9.86%20-15.75%2C-10.42%20-8.25%2C-6%20-4.46%2C-3.04%20-2.25%2C-2.85%20-0.97%2C-6.22%204.05%2C-4.46%205.44%2C0.37%201.39%2C0.37%205.51%2C4.24%2011.77%2C9.11%2015.37%2C11.32%202.25%2C1.87%200.9%2C-0.64%200.11%2C-0.45%20-1.01%2C-1.69%20-8.36%2C-15.11%20-8.92%2C-15.37%20-3.97%2C-6.37%20-1.05%2C-3.82%20c%20-0.37%2C-1.57%20-0.64%2C-2.89%20-0.64%2C-4.5%20l%204.61%2C-6.26%202.55%2C-0.82%206.15%2C0.82%202.59%2C2.25%203.82%2C8.74%206.19%2C13.76%209.6%2C18.71%202.81%2C5.55%201.5%2C5.14%200.56%2C1.57%20h%200.97%20v%20-0.9%20l%200.79%2C-10.54%201.46%2C-12.94%201.42%2C-16.65%200.49%2C-4.69%202.32%2C-5.62%204.61%2C-3.04%203.6%2C1.72%202.96%2C4.24%20-0.41%2C2.74%20-1.76%2C11.44%20-3.45%2C17.92%20-2.25%2C12%20h%201.31%20l%201.5%2C-1.5%206.07%2C-8.06%2010.2%2C-12.75%204.5%2C-5.06%205.25%2C-5.59%203.37%2C-2.66%20h%206.37%20l%204.69%2C6.97%20-2.1%2C7.2%20-6.56%2C8.32%20-5.44%2C7.05%20-7.8%2C10.5%20-4.87%2C8.4%200.45%2C0.67%201.16%2C-0.11%2017.62%2C-3.75%209.52%2C-1.72%2011.36%2C-1.95%205.14%2C2.4%200.56%2C2.44%20-2.02%2C4.99%20-12.15%2C3%20-14.25%2C2.85%20-21.22%2C5.02%20-0.26%2C0.19%200.3%2C0.37%209.56%2C0.9%204.09%2C0.22%20h%2010.01%20l%2018.64%2C1.39%204.87%2C3.22%202.92%2C3.94%20-0.49%2C3%20-7.5%2C3.82%20-10.12%2C-2.4%20-23.62%2C-5.62%20-8.1%2C-2.02%20h%20-1.12%20v%200.67%20l%206.75%2C6.6%2012.37%2C11.17%2015.49%2C14.4%200.79%2C3.56%20-1.99%2C2.81%20-2.1%2C-0.3%20-13.61%2C-10.24%20-5.25%2C-4.61%20-11.89%2C-10.01%20h%20-0.79%20v%201.05%20l%202.74%2C4.01%2014.47%2C21.75%200.75%2C6.67%20-1.05%2C2.17%20-3.75%2C1.31%20-4.12%2C-0.75%20-8.47%2C-11.89%20-8.74%2C-13.39%20-7.05%2C-12%20-0.86%2C0.49%20-4.16%2C44.81%20-1.95%2C2.29%20-4.5%2C1.72%20-3.75%2C-2.85%20-1.99%2C-4.61%201.99%2C-9.11%202.4%2C-11.89%201.95%2C-9.45%201.76%2C-11.74%201.05%2C-3.9%20-0.07%2C-0.26%20-0.86%2C0.11%20-8.85%2C12.15%20-13.46%2C18.19%20-10.65%2C11.4%20-2.55%2C1.01%20-4.42%2C-2.29%200.41%2C-4.09%202.47%2C-3.64%2014.74%2C-18.75%208.89%2C-11.62%205.74%2C-6.71%20-0.04%2C-0.97%20h%20-0.34%20l%20-39.15%2C25.42%20-6.97%2C0.9%20-3%2C-2.81%200.37%2C-4.61%201.42%2C-1.5%2011.77%2C-8.1%20-0.04%2C0.04%20z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E\") center / contain no-repeat;",
|
|
1371
1533
|
"}",
|
|
1372
1534
|
"",
|
|
1373
|
-
"body[data-dsh-claude-style] [class*=\"brandIdentity\"] > [class*=\"brandName\"] > * {",
|
|
1535
|
+
"body[data-dsh-claude-style]:is([data-dsh-claude-brand=\"claude\"], [data-dsh-claude-brand=\"anthropic\"]) [class*=\"brandIdentity\"] > [class*=\"brandName\"] > * {",
|
|
1374
1536
|
" display: none !important;",
|
|
1375
1537
|
"}",
|
|
1376
1538
|
"",
|
|
1377
|
-
"body[data-dsh-claude-style] [class*=\"brandIdentity\"] > [class*=\"brandName\"]::before {",
|
|
1539
|
+
"body[data-dsh-claude-style]:is([data-dsh-claude-brand=\"claude\"], [data-dsh-claude-brand=\"anthropic\"]) [class*=\"brandIdentity\"] > [class*=\"brandName\"]::before {",
|
|
1378
1540
|
" content: \"\";",
|
|
1379
1541
|
" display: block;",
|
|
1380
1542
|
" flex: none;",
|
|
@@ -1384,7 +1546,7 @@ window.__ModuleLoader__.load({
|
|
|
1384
1546
|
" background-size: contain;",
|
|
1385
1547
|
"}",
|
|
1386
1548
|
"",
|
|
1387
|
-
"body[data-dsh-claude-style]
|
|
1549
|
+
"body[data-dsh-claude-style][data-dsh-claude-brand=\"claude\"] [class*=\"brandIdentity\"] > [class*=\"brandName\"]::before {",
|
|
1388
1550
|
" width: 75.9px;",
|
|
1389
1551
|
" max-width: 100%;",
|
|
1390
1552
|
" height: 18px;",
|
|
@@ -1681,8 +1843,8 @@ window.__ModuleLoader__.load({
|
|
|
1681
1843
|
"/* ---------- Claude Code layout: permission segments ---------- */",
|
|
1682
1844
|
"/* The shipped access control is one popup-select button; it is replaced by",
|
|
1683
1845
|
" a Read | Edit | Auto segmented control over the same three presets. */",
|
|
1684
|
-
"body[data-dsh-claude-style] button[aria-label^=\"访问模式\"],",
|
|
1685
|
-
"body[data-dsh-claude-style] button[aria-label^=\"Access mode\"] {",
|
|
1846
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] button[aria-label^=\"访问模式\"],",
|
|
1847
|
+
"body[data-dsh-claude-style][data-dsh-claude-composer-active] button[aria-label^=\"Access mode\"] {",
|
|
1686
1848
|
" display: none !important;",
|
|
1687
1849
|
"}",
|
|
1688
1850
|
"",
|
|
@@ -2025,6 +2187,9 @@ window.__ModuleLoader__.load({
|
|
|
2025
2187
|
" font-weight: 500 !important;",
|
|
2026
2188
|
" line-height: 16px !important;",
|
|
2027
2189
|
"}",
|
|
2190
|
+
"/* The row carries one description line, in the shell's language: the copy",
|
|
2191
|
+
" document is localized rather than stacked, so there is no second-language",
|
|
2192
|
+
" rule to style. */",
|
|
2028
2193
|
"body[data-dsh-claude-style] .dsh-claude-model-desc {",
|
|
2029
2194
|
" font-size: 11px !important;",
|
|
2030
2195
|
" line-height: 14px !important;",
|
|
@@ -2175,13 +2340,39 @@ window.__ModuleLoader__.load({
|
|
|
2175
2340
|
" display: none !important;",
|
|
2176
2341
|
"}",
|
|
2177
2342
|
"",
|
|
2343
|
+
"/* ---------- Footer takeover ----------",
|
|
2344
|
+
" Everything in this block modifies the HOST's own footer (it hides entries and",
|
|
2345
|
+
" zeroes the containers that host them) and exists only because the skin",
|
|
2346
|
+
" replaces that footer with its account row. The \"Collapse the sidebar settings",
|
|
2347
|
+
" area\" preference turns the whole takeover off, so each rule below carries",
|
|
2348
|
+
" data-dsh-claude-footer-takeover — the skin sets it on <body> only while the takeover is on,",
|
|
2349
|
+
" and with it absent the host footer renders exactly as shipped. */",
|
|
2178
2350
|
"/* Hide original trigger buttons in footArea while keeping containers intact for modals */",
|
|
2179
|
-
"body[data-dsh-claude-style] [class*=\"footArea\"] > [class*=\"settingsArea\"] > [class*=\"triggerRow\"],",
|
|
2180
|
-
"body[data-dsh-claude-style] [class*=\"footArea\"] > [class*=\"footerActions\"] :is([class*=\"footerButtons\"], > button) {",
|
|
2351
|
+
"body[data-dsh-claude-style][data-dsh-claude-footer-takeover] [class*=\"footArea\"] > [class*=\"settingsArea\"] > [class*=\"triggerRow\"],",
|
|
2352
|
+
"body[data-dsh-claude-style][data-dsh-claude-footer-takeover] [class*=\"footArea\"] > [class*=\"footerActions\"] :is([class*=\"footerButtons\"], > button) {",
|
|
2181
2353
|
" display: none !important;",
|
|
2182
2354
|
"}",
|
|
2183
|
-
"
|
|
2184
|
-
"
|
|
2355
|
+
"/* Both containers stay mounted at zero size so the overlays they host keep",
|
|
2356
|
+
" painting, but the collapse must stay geometric. font-size and line-height",
|
|
2357
|
+
" inherit, and the settings dialog mounts IN PLACE inside settingsArea (the",
|
|
2358
|
+
" host renders its overlay as a sibling of the trigger row — no portal): the",
|
|
2359
|
+
" dialog inherited font-size: 0 with line-height: 0px, so every text line",
|
|
2360
|
+
" that sets an explicit font-size without its own line-height (the SubAgent",
|
|
2361
|
+
" page's rows, the onboarding overlay) collapsed to a 0px line box and",
|
|
2362
|
+
" vanished. settingsArea hosts nothing besides its display:none'd trigger row",
|
|
2363
|
+
" and those in-place overlays, so it keeps only the geometric collapse and",
|
|
2364
|
+
" hands real inherited metrics down; footerActions still hosts plain plugin",
|
|
2365
|
+
" entries whose stray in-flow text only the zeroing keeps invisible, so the",
|
|
2366
|
+
" full collapse stays there. */",
|
|
2367
|
+
"body[data-dsh-claude-style][data-dsh-claude-footer-takeover] [class*=\"footArea\"] > [class*=\"settingsArea\"] {",
|
|
2368
|
+
" position: static !important;",
|
|
2369
|
+
" width: 0 !important;",
|
|
2370
|
+
" height: 0 !important;",
|
|
2371
|
+
" margin: 0 !important;",
|
|
2372
|
+
" padding: 0 !important;",
|
|
2373
|
+
" overflow: visible !important;",
|
|
2374
|
+
"}",
|
|
2375
|
+
"body[data-dsh-claude-style][data-dsh-claude-footer-takeover] [class*=\"footArea\"] > [class*=\"footerActions\"] {",
|
|
2185
2376
|
" position: static !important;",
|
|
2186
2377
|
" width: 0 !important;",
|
|
2187
2378
|
" height: 0 !important;",
|
|
@@ -2200,10 +2391,10 @@ window.__ModuleLoader__.load({
|
|
|
2200
2391
|
" keep their subtree visible — the overlay must stay reachable after the",
|
|
2201
2392
|
" mirrored popover item opens it — but the entry box itself collapses so it",
|
|
2202
2393
|
" never paints inside the zero-sized footerActions container. */",
|
|
2203
|
-
"body[data-dsh-claude-style] [class*=\"footArea\"] [data-dsh-claude-footer-hidden] {",
|
|
2394
|
+
"body[data-dsh-claude-style][data-dsh-claude-footer-takeover] [class*=\"footArea\"] [data-dsh-claude-footer-hidden] {",
|
|
2204
2395
|
" display: none !important;",
|
|
2205
2396
|
"}",
|
|
2206
|
-
"body[data-dsh-claude-style] [class*=\"footArea\"] [data-dsh-claude-footer-entry] {",
|
|
2397
|
+
"body[data-dsh-claude-style][data-dsh-claude-footer-takeover] [class*=\"footArea\"] [data-dsh-claude-footer-entry] {",
|
|
2207
2398
|
" width: 0 !important;",
|
|
2208
2399
|
" height: 0 !important;",
|
|
2209
2400
|
" min-width: 0 !important;",
|
|
@@ -2229,13 +2420,47 @@ window.__ModuleLoader__.load({
|
|
|
2229
2420
|
"body[data-dsh-claude-style] [class*=\"root\"][class*=\"collapsed\"] :is(.dsh-claude-account-label, .dsh-claude-account-chevron) {",
|
|
2230
2421
|
" display: none !important;",
|
|
2231
2422
|
"}",
|
|
2423
|
+
"/* The rail's popover cannot stay an absolutely positioned child of the footer.",
|
|
2424
|
+
" The sidebar column is 56px wide with `overflow: hidden`, so a panel anchored",
|
|
2425
|
+
" past the rail edge is cut off the moment it crosses it — and the base rule's",
|
|
2426
|
+
" percentage max-width, measured against the 59px footer, squashed it to 43px.",
|
|
2427
|
+
" Fixed positioning lifts it out of that clip (no ancestor is a containing block",
|
|
2428
|
+
" for it), and overrides.js anchors it to the trigger from there. left/right/",
|
|
2429
|
+
" bottom are reset so the base rule's own `!important` anchors cannot fight the",
|
|
2430
|
+
" resolved coordinates. */",
|
|
2232
2431
|
"body[data-dsh-claude-style] [class*=\"root\"][class*=\"collapsed\"] .dsh-claude-account-popover {",
|
|
2233
|
-
"
|
|
2234
|
-
"
|
|
2432
|
+
" position: fixed !important;",
|
|
2433
|
+
" left: auto !important;",
|
|
2235
2434
|
" right: auto !important;",
|
|
2435
|
+
" bottom: auto !important;",
|
|
2436
|
+
" top: auto !important;",
|
|
2236
2437
|
" width: 220px !important;",
|
|
2438
|
+
" max-width: min(220px, calc(100vw - 16px)) !important;",
|
|
2237
2439
|
" transform-origin: bottom left !important;",
|
|
2238
2440
|
"}",
|
|
2441
|
+
"/* The rail opens the panel beside the trigger, not above it, so the hover bridge",
|
|
2442
|
+
" has to span the horizontal gap: the base rule's downward strip would sit under",
|
|
2443
|
+
" the panel and leave the pointer's 8px crossing uncovered. */",
|
|
2444
|
+
"body[data-dsh-claude-style] [class*=\"root\"][class*=\"collapsed\"] .dsh-claude-account-popover::after {",
|
|
2445
|
+
" top: 0 !important;",
|
|
2446
|
+
" bottom: 0 !important;",
|
|
2447
|
+
" left: auto !important;",
|
|
2448
|
+
" right: 100% !important;",
|
|
2449
|
+
" width: 12px !important;",
|
|
2450
|
+
" height: auto !important;",
|
|
2451
|
+
"}",
|
|
2452
|
+
"/* In the rail the account button is the only control; the settings entry lives",
|
|
2453
|
+
" in the popover. The settings container is zero-sized rather than hidden (its",
|
|
2454
|
+
" dialog must stay reachable), which is enough while the sidebar is wide — the",
|
|
2455
|
+
" entry is squeezed to a 4px sliver. A plugin that ships its own rail variant",
|
|
2456
|
+
" escapes that box instead: the settings plugin's `…_rail` trigger keeps its",
|
|
2457
|
+
" full 36px square and lands straight on top of the Claude mark. Hide the entry",
|
|
2458
|
+
" in the rail. Reachability is unaffected — the popover's settings item opens",
|
|
2459
|
+
" the real trigger programmatically (`realTrigger.click()`), which",
|
|
2460
|
+
" display:none does not block. */",
|
|
2461
|
+
"body[data-dsh-claude-style][data-dsh-claude-footer-takeover] [class*=\"root\"][class*=\"collapsed\"] [class*=\"footArea\"] [class*=\"settingsArea\"] :is(button, [class*=\"triggerRow\"]) {",
|
|
2462
|
+
" display: none !important;",
|
|
2463
|
+
"}",
|
|
2239
2464
|
"",
|
|
2240
2465
|
"/* Embedded footer widgets: display-only plugin entries (progress bars,",
|
|
2241
2466
|
" status panels — the cost-meter balance/quota stack is the known case)",
|
|
@@ -2297,10 +2522,12 @@ window.__ModuleLoader__.load({
|
|
|
2297
2522
|
" overflow-x: auto;",
|
|
2298
2523
|
"}",
|
|
2299
2524
|
"",
|
|
2300
|
-
"/* ---------- Claude Code layout: settings
|
|
2301
|
-
"/* The skin's own page in the settings dialog.
|
|
2302
|
-
"
|
|
2303
|
-
"
|
|
2525
|
+
"/* ---------- Claude Code layout: settings page ---------- */",
|
|
2526
|
+
"/* The skin's own page in the settings dialog. Its segmented controls reuse the",
|
|
2527
|
+
" composer permission picker's classes (`.dsh-claude-segments` /",
|
|
2528
|
+
" `.dsh-claude-segment`), so the two are literally one control rather than two",
|
|
2529
|
+
" lookalikes; only the row shell and the switch are new here. */",
|
|
2530
|
+
"body[data-dsh-claude-style] .dsh-claude-settings {",
|
|
2304
2531
|
" display: flex;",
|
|
2305
2532
|
" flex-direction: column;",
|
|
2306
2533
|
" gap: 16px;",
|
|
@@ -2310,13 +2537,13 @@ window.__ModuleLoader__.load({
|
|
|
2310
2537
|
" font-family: var(--dsw-font-family);",
|
|
2311
2538
|
"}",
|
|
2312
2539
|
"",
|
|
2313
|
-
"body[data-dsh-claude-style] .dsh-claude-
|
|
2540
|
+
"body[data-dsh-claude-style] .dsh-claude-settings-title {",
|
|
2314
2541
|
" font-size: 15px;",
|
|
2315
2542
|
" font-weight: 600;",
|
|
2316
2543
|
" color: var(--dsw-alias-label-primary);",
|
|
2317
2544
|
"}",
|
|
2318
2545
|
"",
|
|
2319
|
-
"body[data-dsh-claude-style] .dsh-claude-
|
|
2546
|
+
"body[data-dsh-claude-style] .dsh-claude-settings-row {",
|
|
2320
2547
|
" display: flex;",
|
|
2321
2548
|
" align-items: center;",
|
|
2322
2549
|
" gap: 12px;",
|
|
@@ -2325,72 +2552,73 @@ window.__ModuleLoader__.load({
|
|
|
2325
2552
|
" border-radius: 12px;",
|
|
2326
2553
|
"}",
|
|
2327
2554
|
"",
|
|
2328
|
-
"body[data-dsh-claude-style] .dsh-claude-
|
|
2555
|
+
"body[data-dsh-claude-style] .dsh-claude-settings-row-text {",
|
|
2329
2556
|
" flex: 1;",
|
|
2330
2557
|
" min-width: 0;",
|
|
2331
2558
|
"}",
|
|
2332
2559
|
"",
|
|
2333
|
-
"body[data-dsh-claude-style] .dsh-claude-
|
|
2560
|
+
"body[data-dsh-claude-style] .dsh-claude-settings-row-title {",
|
|
2334
2561
|
" font-size: 13px;",
|
|
2335
2562
|
" font-weight: 600;",
|
|
2336
2563
|
" line-height: 1.5;",
|
|
2337
2564
|
" color: var(--dsw-alias-label-primary);",
|
|
2338
2565
|
"}",
|
|
2339
2566
|
"",
|
|
2340
|
-
"body[data-dsh-claude-style] .dsh-claude-
|
|
2567
|
+
"body[data-dsh-claude-style] .dsh-claude-settings-row-desc {",
|
|
2341
2568
|
" margin-top: 4px;",
|
|
2342
2569
|
" font-size: 12px;",
|
|
2343
2570
|
" line-height: 1.5;",
|
|
2344
2571
|
" color: var(--dsw-alias-label-tertiary);",
|
|
2345
2572
|
"}",
|
|
2346
2573
|
"",
|
|
2347
|
-
"body[data-dsh-claude-style] .dsh-claude-
|
|
2348
|
-
"
|
|
2349
|
-
"
|
|
2350
|
-
"
|
|
2351
|
-
" gap: 2px;",
|
|
2352
|
-
" padding: 2px;",
|
|
2353
|
-
" border-radius: 7px;",
|
|
2354
|
-
" background: var(--dsw-specific-selector);",
|
|
2355
|
-
"}",
|
|
2356
|
-
"",
|
|
2357
|
-
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) .dsh-claude-brand-segments {",
|
|
2358
|
-
" background: #f6f6f4;",
|
|
2574
|
+
"body[data-dsh-claude-style] .dsh-claude-settings-error {",
|
|
2575
|
+
" font-size: 12px;",
|
|
2576
|
+
" line-height: 1.5;",
|
|
2577
|
+
" color: var(--dsw-alias-state-error-primary, #c0392b);",
|
|
2359
2578
|
"}",
|
|
2360
2579
|
"",
|
|
2361
|
-
"
|
|
2580
|
+
"/* The switch borrows the segment track's palette and radius so a page of rows",
|
|
2581
|
+
" reads as one control set rather than two. */",
|
|
2582
|
+
"body[data-dsh-claude-style] .dsh-claude-settings-switch {",
|
|
2583
|
+
" flex: none;",
|
|
2362
2584
|
" appearance: none;",
|
|
2363
2585
|
" margin: 0;",
|
|
2364
2586
|
" border: 0;",
|
|
2365
2587
|
" cursor: pointer;",
|
|
2366
|
-
"
|
|
2367
|
-
"
|
|
2368
|
-
"
|
|
2369
|
-
"
|
|
2370
|
-
"
|
|
2371
|
-
"
|
|
2372
|
-
"
|
|
2373
|
-
" border-radius: 7px;",
|
|
2374
|
-
" transition: background-color .1s, color .1s;",
|
|
2588
|
+
" width: 36px;",
|
|
2589
|
+
" height: 20px;",
|
|
2590
|
+
" padding: 2px;",
|
|
2591
|
+
" box-sizing: border-box;",
|
|
2592
|
+
" border-radius: 10px;",
|
|
2593
|
+
" background: var(--dsw-specific-selector);",
|
|
2594
|
+
" transition: background-color .12s ease;",
|
|
2375
2595
|
"}",
|
|
2376
2596
|
"",
|
|
2377
|
-
"body[data-dsh-claude-style]
|
|
2378
|
-
"
|
|
2597
|
+
"body[data-dsh-claude-style]:not([data-ds-dark-theme]) .dsh-claude-settings-switch {",
|
|
2598
|
+
" background: #f6f6f4;",
|
|
2379
2599
|
"}",
|
|
2380
2600
|
"",
|
|
2381
|
-
"body[data-dsh-claude-style] .dsh-claude-
|
|
2382
|
-
"
|
|
2383
|
-
" background: var(--dsw-alias-bg-layer-3);",
|
|
2601
|
+
"body[data-dsh-claude-style] .dsh-claude-settings-switch[data-on] {",
|
|
2602
|
+
" background: var(--dsw-alias-brand-primary, #d97757);",
|
|
2384
2603
|
"}",
|
|
2385
2604
|
"",
|
|
2386
|
-
"body[data-dsh-claude-style]
|
|
2387
|
-
"
|
|
2388
|
-
"
|
|
2605
|
+
"body[data-dsh-claude-style] .dsh-claude-settings-switch-knob {",
|
|
2606
|
+
" display: block;",
|
|
2607
|
+
" width: 16px;",
|
|
2608
|
+
" height: 16px;",
|
|
2609
|
+
" border-radius: 50%;",
|
|
2610
|
+
" background: var(--dsw-alias-bg-overlay, #ffffff);",
|
|
2611
|
+
" box-shadow: 0 1px 2px rgba(20, 20, 19, 0.18);",
|
|
2612
|
+
" transition: transform .12s ease;",
|
|
2613
|
+
"}",
|
|
2614
|
+
"",
|
|
2615
|
+
"body[data-dsh-claude-style] .dsh-claude-settings-switch[data-on] .dsh-claude-settings-switch-knob {",
|
|
2616
|
+
" transform: translateX(16px);",
|
|
2389
2617
|
"}",
|
|
2390
2618
|
].join('\n')
|
|
2391
2619
|
|
|
2392
2620
|
// ============================================================================
|
|
2393
|
-
//
|
|
2621
|
+
// 宿主上下文访问器与辅助 (Host Context & Helpers)
|
|
2394
2622
|
// ============================================================================
|
|
2395
2623
|
function findAccessTrigger() {
|
|
2396
2624
|
var prefixes = ['访问模式', 'Access mode']
|
|
@@ -2445,50 +2673,6 @@ window.__ModuleLoader__.load({
|
|
|
2445
2673
|
}
|
|
2446
2674
|
}
|
|
2447
2675
|
|
|
2448
|
-
/**
|
|
2449
|
-
* Read the persisted brand choice.
|
|
2450
|
-
*
|
|
2451
|
-
* Storage is the renderer's own localStorage, which DSH backs with the
|
|
2452
|
-
* `persist:dsh-desktop-renderer` partition, so the value survives an app
|
|
2453
|
-
* restart. Every access is guarded: a locked-down or full store must not
|
|
2454
|
-
* break the theme, so an unreadable value simply falls back to the default.
|
|
2455
|
-
*
|
|
2456
|
-
* @returns one of BRAND_CLAUDE / BRAND_ANTHROPIC.
|
|
2457
|
-
*/
|
|
2458
|
-
function readStoredBrand() {
|
|
2459
|
-
try {
|
|
2460
|
-
var raw = window.localStorage.getItem(BRAND_STORAGE_KEY)
|
|
2461
|
-
if (raw === BRAND_ANTHROPIC) return BRAND_ANTHROPIC
|
|
2462
|
-
if (raw === BRAND_CLAUDE) return BRAND_CLAUDE
|
|
2463
|
-
} catch (error) {
|
|
2464
|
-
/* storage unavailable — fall through to the default */
|
|
2465
|
-
}
|
|
2466
|
-
return DEFAULT_BRAND
|
|
2467
|
-
}
|
|
2468
|
-
|
|
2469
|
-
/** Persist the brand choice, ignoring a store that refuses writes. */
|
|
2470
|
-
function writeStoredBrand(brand) {
|
|
2471
|
-
try {
|
|
2472
|
-
window.localStorage.setItem(BRAND_STORAGE_KEY, brand)
|
|
2473
|
-
} catch (error) {
|
|
2474
|
-
/* storage unavailable — the session still shows the chosen brand */
|
|
2475
|
-
}
|
|
2476
|
-
}
|
|
2477
|
-
|
|
2478
|
-
/**
|
|
2479
|
-
* Apply a brand to the document. The stylesheet keys off the attribute, so
|
|
2480
|
-
* this is the single mutation that repaints the sidebar brand; keeping it to
|
|
2481
|
-
* one attribute write is what makes the switch cheap and idempotent.
|
|
2482
|
-
*
|
|
2483
|
-
* @param brand - the brand to show; unknown values fall back to the default.
|
|
2484
|
-
* @returns the brand actually applied.
|
|
2485
|
-
*/
|
|
2486
|
-
function applyBrand(brand) {
|
|
2487
|
-
var next = brand === BRAND_ANTHROPIC ? BRAND_ANTHROPIC : BRAND_CLAUDE
|
|
2488
|
-
document.body.setAttribute(BRAND_ATTR, next)
|
|
2489
|
-
return next
|
|
2490
|
-
}
|
|
2491
|
-
|
|
2492
2676
|
/**
|
|
2493
2677
|
* The client context exposes no user or account service, so the account
|
|
2494
2678
|
* name is inferred from the home-directory segment of a workspace path or
|
|
@@ -2518,21 +2702,388 @@ window.__ModuleLoader__.load({
|
|
|
2518
2702
|
return 'User'
|
|
2519
2703
|
}
|
|
2520
2704
|
|
|
2705
|
+
/**
|
|
2706
|
+
* Host context reference for services that need to read host state
|
|
2707
|
+
* (e.g. locale) outside of apply(ctx)'s direct call stack.
|
|
2708
|
+
*/
|
|
2709
|
+
var hostCtx = null
|
|
2710
|
+
function setHostContext(ctx) {
|
|
2711
|
+
hostCtx = ctx
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2714
|
+
/**
|
|
2715
|
+
* Skin preferences.
|
|
2716
|
+
*
|
|
2717
|
+
* The authoritative store is the host settings namespace `claude-style`,
|
|
2718
|
+
* reached through this plugin's own route: the configuration client
|
|
2719
|
+
* (`settingsScope`) only reaches namespaces the api-proxy exposes to it, and
|
|
2720
|
+
* a plugin's own namespace is not on that list. `src/../lib/index.js` owns
|
|
2721
|
+
* the namespace and the route; this side only reads and writes it.
|
|
2722
|
+
*
|
|
2723
|
+
* Every value is mirrored onto the document as an attribute, so the
|
|
2724
|
+
* stylesheet — not this module — decides what a preference means visually.
|
|
2725
|
+
* Until the first read settles (and if it fails) the defaults below hold,
|
|
2726
|
+
* which is exactly the shipped behaviour.
|
|
2727
|
+
*/
|
|
2728
|
+
var prefs = {
|
|
2729
|
+
brand: DEFAULT_BRAND,
|
|
2730
|
+
collapseFooter: true,
|
|
2731
|
+
autoPopover: true,
|
|
2732
|
+
composerScope: 'all',
|
|
2733
|
+
}
|
|
2734
|
+
var prefsRevision
|
|
2735
|
+
var prefsAvailable = false
|
|
2736
|
+
var prefsListeners = []
|
|
2737
|
+
|
|
2738
|
+
/** The current preferences (live object; treat as read-only). */
|
|
2739
|
+
function readPrefs() {
|
|
2740
|
+
return prefs
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
/** Observe preference changes; returns the unsubscriber. */
|
|
2744
|
+
function subscribePrefs(listener) {
|
|
2745
|
+
prefsListeners.push(listener)
|
|
2746
|
+
return function () {
|
|
2747
|
+
var index = prefsListeners.indexOf(listener)
|
|
2748
|
+
if (index !== -1) prefsListeners.splice(index, 1)
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
|
|
2752
|
+
/**
|
|
2753
|
+
* Adopt a preference set: mirror it onto the document, then notify.
|
|
2754
|
+
* @param next - resolved preferences from the host.
|
|
2755
|
+
*/
|
|
2756
|
+
function adoptPrefs(next) {
|
|
2757
|
+
prefs = next
|
|
2758
|
+
// The brand is one attribute write; the other preferences gate rules the
|
|
2759
|
+
// stylesheet and the scheduler read directly.
|
|
2760
|
+
document.body.setAttribute(BRAND_ATTR, next.brand)
|
|
2761
|
+
if (next.collapseFooter) document.body.setAttribute(FOOTER_ATTR, '')
|
|
2762
|
+
else document.body.removeAttribute(FOOTER_ATTR)
|
|
2763
|
+
var listeners = prefsListeners.slice()
|
|
2764
|
+
for (var i = 0; i < listeners.length; i++) {
|
|
2765
|
+
try {
|
|
2766
|
+
listeners[i](next)
|
|
2767
|
+
} catch (error) { /* one bad listener must not stop the rest */ }
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
/**
|
|
2772
|
+
* Read the preferences once. A failure keeps the defaults and leaves the
|
|
2773
|
+
* settings page to report that the store is unavailable.
|
|
2774
|
+
*/
|
|
2775
|
+
function loadPrefs() {
|
|
2776
|
+
if (typeof fetch !== 'function') return
|
|
2777
|
+
try {
|
|
2778
|
+
fetch(PREFS_ROUTE, {
|
|
2779
|
+
method: 'POST',
|
|
2780
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2781
|
+
credentials: 'same-origin',
|
|
2782
|
+
body: '{}',
|
|
2783
|
+
})
|
|
2784
|
+
.then(function (response) {
|
|
2785
|
+
return response.json()
|
|
2786
|
+
})
|
|
2787
|
+
.then(function (data) {
|
|
2788
|
+
if (!data || data.ok !== true) return
|
|
2789
|
+
prefsRevision = data.revision
|
|
2790
|
+
prefsAvailable = data.available === true
|
|
2791
|
+
adoptPrefs(normalizePrefs(data.value))
|
|
2792
|
+
})
|
|
2793
|
+
.catch(function () { /* defaults stay */ })
|
|
2794
|
+
} catch (error) { /* no fetch: defaults stay */ }
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2797
|
+
/** Clamp one host value into the preference shape (the host already did this). */
|
|
2798
|
+
function normalizePrefs(value) {
|
|
2799
|
+
var section = value && typeof value === 'object' ? value : {}
|
|
2800
|
+
return {
|
|
2801
|
+
brand: section.brand === BRAND_ANTHROPIC || section.brand === BRAND_OFF ? section.brand : BRAND_CLAUDE,
|
|
2802
|
+
collapseFooter: section.collapseFooter !== false,
|
|
2803
|
+
autoPopover: section.autoPopover !== false,
|
|
2804
|
+
composerScope: COMPOSER_SCOPES.indexOf(section.composerScope) === -1 ? 'all' : section.composerScope,
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
|
|
2808
|
+
/**
|
|
2809
|
+
* Write a partial preference change.
|
|
2810
|
+
*
|
|
2811
|
+
* The revision travels with the write so a concurrent move of the namespace
|
|
2812
|
+
* is rejected rather than silently overwritten; on that rejection the
|
|
2813
|
+
* authoritative value is re-read.
|
|
2814
|
+
*
|
|
2815
|
+
* @param patch - preference keys to change.
|
|
2816
|
+
* @returns a promise for the resolved preferences, or null when unavailable.
|
|
2817
|
+
*/
|
|
2818
|
+
function savePrefs(patch) {
|
|
2819
|
+
if (typeof fetch !== 'function') return Promise.resolve(null)
|
|
2820
|
+
var body = { revision: prefsRevision }
|
|
2821
|
+
for (var key in patch) body[key] = patch[key]
|
|
2822
|
+
return fetch(PREFS_ROUTE, {
|
|
2823
|
+
method: 'POST',
|
|
2824
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2825
|
+
credentials: 'same-origin',
|
|
2826
|
+
body: JSON.stringify(body),
|
|
2827
|
+
})
|
|
2828
|
+
.then(function (response) {
|
|
2829
|
+
return response.json().then(function (data) {
|
|
2830
|
+
return { status: response.status, data: data }
|
|
2831
|
+
})
|
|
2832
|
+
})
|
|
2833
|
+
.then(function (result) {
|
|
2834
|
+
var data = result.data
|
|
2835
|
+
if (data && data.ok === true) {
|
|
2836
|
+
prefsRevision = data.revision
|
|
2837
|
+
prefsAvailable = data.available === true
|
|
2838
|
+
adoptPrefs(normalizePrefs(data.value))
|
|
2839
|
+
return prefs
|
|
2840
|
+
}
|
|
2841
|
+
// Conflict or refusal: re-read rather than guess.
|
|
2842
|
+
loadPrefs()
|
|
2843
|
+
return null
|
|
2844
|
+
})
|
|
2845
|
+
.catch(function () {
|
|
2846
|
+
return null
|
|
2847
|
+
})
|
|
2848
|
+
}
|
|
2849
|
+
|
|
2850
|
+
/**
|
|
2851
|
+
* The brand to show. `off` leaves the brand area entirely to the host, so
|
|
2852
|
+
* the stylesheet matches neither brand variant for it.
|
|
2853
|
+
*
|
|
2854
|
+
* @param brand - the stored choice.
|
|
2855
|
+
* @returns the brand actually applied.
|
|
2856
|
+
*/
|
|
2857
|
+
function applyBrand(brand) {
|
|
2858
|
+
var next = brand === BRAND_ANTHROPIC || brand === BRAND_OFF ? brand : BRAND_CLAUDE
|
|
2859
|
+
document.body.setAttribute(BRAND_ATTR, next)
|
|
2860
|
+
return next
|
|
2861
|
+
}
|
|
2862
|
+
|
|
2863
|
+
/**
|
|
2864
|
+
* Model & settings localized copy.
|
|
2865
|
+
*
|
|
2866
|
+
* The copy document ships as `model-descriptions.json` beside the bundle.
|
|
2867
|
+
* Both the model picker (src/overrides/model-picker.js) and the settings section
|
|
2868
|
+
* (src/settings.js) consume this copy, so the state lives in the shared context.
|
|
2869
|
+
* where both zones can reach it.
|
|
2870
|
+
*/
|
|
2871
|
+
var modelCopy = null
|
|
2872
|
+
var modelCopyRequested = false
|
|
2873
|
+
var modelCopyListeners = []
|
|
2874
|
+
|
|
2875
|
+
function onModelCopyLoaded(listener) {
|
|
2876
|
+
modelCopyListeners.push(listener)
|
|
2877
|
+
return function () {
|
|
2878
|
+
var index = modelCopyListeners.indexOf(listener)
|
|
2879
|
+
if (index !== -1) modelCopyListeners.splice(index, 1)
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
|
|
2883
|
+
/**
|
|
2884
|
+
* Fetch the model copy document the host half serves.
|
|
2885
|
+
*/
|
|
2886
|
+
function loadModelCopy() {
|
|
2887
|
+
if (modelCopyRequested) return
|
|
2888
|
+
modelCopyRequested = true
|
|
2889
|
+
if (typeof fetch !== 'function') return
|
|
2890
|
+
try {
|
|
2891
|
+
fetch(MODEL_COPY_ROUTE, { credentials: 'same-origin' })
|
|
2892
|
+
.then(function (response) {
|
|
2893
|
+
if (!response.ok) throw new Error('HTTP ' + response.status)
|
|
2894
|
+
return response.json()
|
|
2895
|
+
})
|
|
2896
|
+
.then(function (doc) {
|
|
2897
|
+
modelCopy = indexModelCopy(doc)
|
|
2898
|
+
if (modelCopy === null) return
|
|
2899
|
+
var listeners = modelCopyListeners.slice()
|
|
2900
|
+
for (var i = 0; i < listeners.length; i++) {
|
|
2901
|
+
try {
|
|
2902
|
+
listeners[i](modelCopy)
|
|
2903
|
+
} catch (error) { /* listener error */ }
|
|
2904
|
+
}
|
|
2905
|
+
})
|
|
2906
|
+
.catch(function () { /* fallback copy stays */ })
|
|
2907
|
+
} catch (error) { /* no fetch: fallback copy stays */ }
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2910
|
+
/**
|
|
2911
|
+
* Compile a copy document into the shape lookups want: a folded id index,
|
|
2912
|
+
* the alias table, and the rule lists with their regexps built once.
|
|
2913
|
+
* @param doc - parsed document; anything malformed is dropped, not fatal.
|
|
2914
|
+
* @returns the index, or null when the document is unusable.
|
|
2915
|
+
*/
|
|
2916
|
+
function indexModelCopy(doc) {
|
|
2917
|
+
if (!doc || typeof doc !== 'object') return null
|
|
2918
|
+
var exact = doc.exact && typeof doc.exact === 'object' ? doc.exact : {}
|
|
2919
|
+
var index = {
|
|
2920
|
+
ui: doc.ui && typeof doc.ui === 'object' ? doc.ui : {},
|
|
2921
|
+
settings: doc.settings && typeof doc.settings === 'object' ? doc.settings : {},
|
|
2922
|
+
exact: exact,
|
|
2923
|
+
aliases: doc.aliases && typeof doc.aliases === 'object' ? doc.aliases : {},
|
|
2924
|
+
fallback: typeof doc.fallback === 'string' && doc.fallback ? doc.fallback : MODEL_COPY_FALLBACK_LOCALE,
|
|
2925
|
+
folded: {},
|
|
2926
|
+
foldedAliases: {},
|
|
2927
|
+
families: [],
|
|
2928
|
+
tiers: [],
|
|
2929
|
+
}
|
|
2930
|
+
for (var id in exact) index.folded[normalizeModelId(id)] = exact[id]
|
|
2931
|
+
for (var a in index.aliases) {
|
|
2932
|
+
index.foldedAliases[normalizeModelId(a)] = index.aliases[a]
|
|
2933
|
+
index.foldedAliases[a.toLowerCase()] = index.aliases[a]
|
|
2934
|
+
}
|
|
2935
|
+
var compile = function (rules) {
|
|
2936
|
+
var out = []
|
|
2937
|
+
for (var i = 0; i < (rules || []).length; i++) {
|
|
2938
|
+
var rule = rules[i]
|
|
2939
|
+
if (!rule || typeof rule.match !== 'string') continue
|
|
2940
|
+
try {
|
|
2941
|
+
out.push({ re: new RegExp(rule.match, 'i'), key: rule.key, text: rule.text })
|
|
2942
|
+
} catch (error) { /* a malformed rule is skipped, not fatal */ }
|
|
2943
|
+
}
|
|
2944
|
+
return out
|
|
2945
|
+
}
|
|
2946
|
+
index.families = compile(doc.families)
|
|
2947
|
+
index.tiers = compile(doc.tiers)
|
|
2948
|
+
return index
|
|
2949
|
+
}
|
|
2950
|
+
|
|
2951
|
+
/** Fold case and separators so `glm-5.3-flash` and `glm-5-3-flash` agree. */
|
|
2952
|
+
function normalizeModelId(id) {
|
|
2953
|
+
return String(id === void 0 || id === null ? '' : id).toLowerCase().replace(/[^a-z0-9]/g, '')
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
/** The shell's active locale id, or the document fallback when it cannot be read. */
|
|
2957
|
+
function activeLocale(ctx) {
|
|
2958
|
+
var c = ctx || hostCtx
|
|
2959
|
+
try {
|
|
2960
|
+
if (c && typeof c.get === 'function') {
|
|
2961
|
+
var locale = c.get('locale')
|
|
2962
|
+
if (locale && typeof locale.getSnapshot === 'function') {
|
|
2963
|
+
var active = locale.getSnapshot().active
|
|
2964
|
+
if (typeof active === 'string' && active) return active
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
} catch (error) { /* no locale service: keep the fallback language */ }
|
|
2968
|
+
return modelCopy === null ? MODEL_COPY_FALLBACK_LOCALE : modelCopy.fallback
|
|
2969
|
+
}
|
|
2970
|
+
|
|
2971
|
+
/** One localized string out of a `{ locale: text }` pair, fallback locale last. */
|
|
2972
|
+
function localized(pair, ctx) {
|
|
2973
|
+
if (!pair || typeof pair !== 'object') return ''
|
|
2974
|
+
var loc = activeLocale(ctx)
|
|
2975
|
+
var text = pair[loc]
|
|
2976
|
+
if (typeof text === 'string' && text) return text
|
|
2977
|
+
var prefix = typeof loc === 'string' && loc.indexOf('-') !== -1 ? loc.split('-')[0] : (typeof loc === 'string' && loc.indexOf('_') !== -1 ? loc.split('_')[0] : '')
|
|
2978
|
+
if (prefix && typeof pair[prefix] === 'string' && pair[prefix]) return pair[prefix]
|
|
2979
|
+
var fallback = modelCopy === null ? MODEL_COPY_FALLBACK_LOCALE : modelCopy.fallback
|
|
2980
|
+
var backstop = pair[fallback]
|
|
2981
|
+
if (typeof backstop === 'string' && backstop) return backstop
|
|
2982
|
+
var fallbackPrefix = typeof fallback === 'string' && fallback.indexOf('-') !== -1 ? fallback.split('-')[0] : ''
|
|
2983
|
+
if (fallbackPrefix && typeof pair[fallbackPrefix] === 'string' && pair[fallbackPrefix]) return pair[fallbackPrefix]
|
|
2984
|
+
return ''
|
|
2985
|
+
}
|
|
2986
|
+
|
|
2987
|
+
/**
|
|
2988
|
+
* One picker label: the document's localized string, else the neutral
|
|
2989
|
+
* English constant the bundle carries. `{name}` placeholders are filled
|
|
2990
|
+
* from `params`, so a label with a slot stays translatable.
|
|
2991
|
+
*/
|
|
2992
|
+
function copyLabel(key, fallback, params) {
|
|
2993
|
+
var text = modelCopy === null || !modelCopy.ui ? '' : localized(modelCopy.ui[key])
|
|
2994
|
+
if (!text) text = fallback
|
|
2995
|
+
if (!params) return text
|
|
2996
|
+
return text.replace(/\{(\w+)\}/g, function (match, name) {
|
|
2997
|
+
return Object.prototype.hasOwnProperty.call(params, name) ? String(params[name]) : match
|
|
2998
|
+
})
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
/**
|
|
3002
|
+
* One settings-page string. The settings copy rides the same document as
|
|
3003
|
+
* the picker copy, so the page follows the shell language too — and the
|
|
3004
|
+
* English constants stay as the fallback for a failed fetch.
|
|
3005
|
+
*/
|
|
3006
|
+
function settingsCopy(key, fallback) {
|
|
3007
|
+
var text = modelCopy === null || !modelCopy.settings ? '' : localized(modelCopy.settings[key])
|
|
3008
|
+
return text || fallback
|
|
3009
|
+
}
|
|
3010
|
+
|
|
2521
3011
|
// ============================================================================
|
|
2522
|
-
//
|
|
3012
|
+
// 弹层共享辅助 (Shared Popover Helpers)
|
|
2523
3013
|
// ============================================================================
|
|
3014
|
+
var POPOVER_MARGIN = 8
|
|
3015
|
+
|
|
3016
|
+
/**
|
|
3017
|
+
* Position a fixed-position popover relative to its trigger.
|
|
3018
|
+
*
|
|
3019
|
+
* `side: 'right'` opens to the trigger's right and bottom-aligns it (the
|
|
3020
|
+
* account popover in the rail). The default `side: 'above'` right-aligns
|
|
3021
|
+
* the popover with the trigger and opens above it with `gap` spacing (the
|
|
3022
|
+
* model picker). `important` switches to `style.setProperty(..., 'important')`
|
|
3023
|
+
* and rounds the coordinates, as the account popover requires.
|
|
3024
|
+
*
|
|
3025
|
+
* @param trigger - element the popover is anchored to.
|
|
3026
|
+
* @param pop - the fixed-position popover element.
|
|
3027
|
+
* @param opts - `{ side, gap, important }`.
|
|
3028
|
+
* @returns the chosen `{ x, y }` in viewport coordinates.
|
|
3029
|
+
*/
|
|
3030
|
+
function positionAnchoredPopover(trigger, pop, opts) {
|
|
3031
|
+
opts = opts || {}
|
|
3032
|
+
var rect = trigger.getBoundingClientRect()
|
|
3033
|
+
var width = pop.offsetWidth
|
|
3034
|
+
var height = pop.offsetHeight
|
|
3035
|
+
var margin = opts.margin || POPOVER_MARGIN
|
|
3036
|
+
var x
|
|
3037
|
+
var y
|
|
3038
|
+
if (opts.side === 'right') {
|
|
3039
|
+
x = rect.right + margin
|
|
3040
|
+
if (x + width > window.innerWidth - margin) {
|
|
3041
|
+
x = Math.max(margin, rect.left - margin - width)
|
|
3042
|
+
}
|
|
3043
|
+
y = Math.min(Math.max(margin, rect.bottom - height), Math.max(margin, window.innerHeight - height - margin))
|
|
3044
|
+
} else {
|
|
3045
|
+
x = Math.max(margin, Math.min(rect.right - width, window.innerWidth - width - margin))
|
|
3046
|
+
y = rect.top - (opts.gap || 0) - height
|
|
3047
|
+
if (y < margin) y = Math.min(rect.bottom + (opts.gap || 0), Math.max(margin, window.innerHeight - height - margin))
|
|
3048
|
+
}
|
|
3049
|
+
if (opts.important) {
|
|
3050
|
+
pop.style.setProperty('left', Math.round(x) + 'px', 'important')
|
|
3051
|
+
pop.style.setProperty('top', Math.round(y) + 'px', 'important')
|
|
3052
|
+
} else {
|
|
3053
|
+
pop.style.left = x + 'px'
|
|
3054
|
+
pop.style.top = y + 'px'
|
|
3055
|
+
}
|
|
3056
|
+
return { x: x, y: y }
|
|
3057
|
+
}
|
|
3058
|
+
|
|
2524
3059
|
/**
|
|
2525
|
-
*
|
|
2526
|
-
*
|
|
2527
|
-
*
|
|
2528
|
-
*
|
|
2529
|
-
*
|
|
2530
|
-
*
|
|
2531
|
-
* idempotent (a node already in the target state is left alone, and the
|
|
2532
|
-
* controls are only inserted when absent), so the observer cannot feed
|
|
2533
|
-
* itself.
|
|
3060
|
+
* Hover-intent helper shared by the model picker and account popover.
|
|
3061
|
+
*
|
|
3062
|
+
* The `open` callback is part of the shared signature but the original
|
|
3063
|
+
* hover behaviour only schedules the close side (mouseenter calls the
|
|
3064
|
+
* feature's open function directly); keeping the parameter makes the two
|
|
3065
|
+
* call sites symmetrical.
|
|
2534
3066
|
*/
|
|
2535
|
-
function
|
|
3067
|
+
function createHoverIntent(open, close, delay) {
|
|
3068
|
+
var timer = null
|
|
3069
|
+
return {
|
|
3070
|
+
cancel: function () {
|
|
3071
|
+
if (timer) {
|
|
3072
|
+
clearTimeout(timer)
|
|
3073
|
+
timer = null
|
|
3074
|
+
}
|
|
3075
|
+
},
|
|
3076
|
+
scheduleClose: function () {
|
|
3077
|
+
if (timer) clearTimeout(timer)
|
|
3078
|
+
timer = setTimeout(close, delay)
|
|
3079
|
+
},
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
|
|
3083
|
+
// ============================================================================
|
|
3084
|
+
// 4.1: 文案改写 (Copy Rewrites)
|
|
3085
|
+
// ============================================================================
|
|
3086
|
+
function installCopy(ctx, ui) {
|
|
2536
3087
|
// --- 4.1 Copy Overrides ---
|
|
2537
3088
|
/** Shipped idle composer hints (zh / en, hero / default) this skin replaces. */
|
|
2538
3089
|
var HINT_SOURCES = [
|
|
@@ -2559,7 +3110,19 @@ window.__ModuleLoader__.load({
|
|
|
2559
3110
|
}
|
|
2560
3111
|
}
|
|
2561
3112
|
|
|
3113
|
+
function isHeroView() {
|
|
3114
|
+
var hasTurns = document.querySelector('[class*="turn"], [class*="message"], [data-turn], [data-message-id]') !== null
|
|
3115
|
+
return !hasTurns && (document.querySelector('[class*="composerHero"], [data-phase="hero"]') !== null)
|
|
3116
|
+
}
|
|
3117
|
+
|
|
3118
|
+
function isComposerActive() {
|
|
3119
|
+
var isHero = isHeroView()
|
|
3120
|
+
var scope = readPrefs().composerScope
|
|
3121
|
+
return scope === 'all' || (isHero ? scope === 'hero' : scope === 'conversation')
|
|
3122
|
+
}
|
|
3123
|
+
|
|
2562
3124
|
function rewriteHint() {
|
|
3125
|
+
if (!isComposerActive()) return
|
|
2563
3126
|
var isHero = document.querySelector('[class*="heroWorkspaceRow"], [class*="titleGroup"]') !== null
|
|
2564
3127
|
var targetHint = isHero ? COMPOSER_HINT : 'Type / for commands'
|
|
2565
3128
|
var hints = document.querySelectorAll('[data-composer-placeholder]')
|
|
@@ -2575,6 +3138,54 @@ window.__ModuleLoader__.load({
|
|
|
2575
3138
|
}
|
|
2576
3139
|
if (idle && text !== targetHint) node.textContent = targetHint
|
|
2577
3140
|
}
|
|
3141
|
+
syncAttachmentPlaceholder()
|
|
3142
|
+
}
|
|
3143
|
+
|
|
3144
|
+
function syncAttachmentPlaceholder() {
|
|
3145
|
+
if (!isComposerActive()) {
|
|
3146
|
+
var synths = document.querySelectorAll('[data-dsh-synthetic-placeholder]')
|
|
3147
|
+
for (var si = 0; si < synths.length; si++) {
|
|
3148
|
+
if (synths[si].parentElement) synths[si].parentElement.removeChild(synths[si])
|
|
3149
|
+
}
|
|
3150
|
+
return
|
|
3151
|
+
}
|
|
3152
|
+
var isHero = document.querySelector('[class*="heroWorkspaceRow"], [class*="titleGroup"]') !== null
|
|
3153
|
+
var targetHint = isHero ? COMPOSER_HINT : 'Type / for commands'
|
|
3154
|
+
var cards = document.querySelectorAll('[data-composer-card]')
|
|
3155
|
+
for (var ci = 0; ci < cards.length; ci++) {
|
|
3156
|
+
var card = cards[ci]
|
|
3157
|
+
var input = card.querySelector('[data-composer-input]')
|
|
3158
|
+
if (!input) continue
|
|
3159
|
+
var text = (input.textContent || '').replace(/[\u200B-\u200D\uFEFF]/g, '').trim()
|
|
3160
|
+
var isEmpty = text.length === 0
|
|
3161
|
+
var placeholder = card.querySelector('[data-composer-placeholder]')
|
|
3162
|
+
var grow = input.closest ? input.closest('[class*="grow"]') : input.parentElement
|
|
3163
|
+
|
|
3164
|
+
if (isEmpty) {
|
|
3165
|
+
if (!placeholder && grow) {
|
|
3166
|
+
placeholder = document.createElement('div')
|
|
3167
|
+
placeholder.setAttribute('data-composer-placeholder', '')
|
|
3168
|
+
placeholder.setAttribute('data-dsh-synthetic-placeholder', 'true')
|
|
3169
|
+
placeholder.textContent = targetHint
|
|
3170
|
+
grow.appendChild(placeholder)
|
|
3171
|
+
} else if (placeholder) {
|
|
3172
|
+
if (placeholder.style.display === 'none') placeholder.style.display = ''
|
|
3173
|
+
var curText = placeholder.textContent || ''
|
|
3174
|
+
var idle = false
|
|
3175
|
+
for (var j = 0; j < HINT_SOURCES.length; j++) {
|
|
3176
|
+
if (curText.indexOf(HINT_SOURCES[j]) === 0) {
|
|
3177
|
+
idle = true
|
|
3178
|
+
break
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
if (idle && curText !== targetHint) placeholder.textContent = targetHint
|
|
3182
|
+
}
|
|
3183
|
+
} else {
|
|
3184
|
+
if (placeholder && placeholder.hasAttribute('data-dsh-synthetic-placeholder')) {
|
|
3185
|
+
if (placeholder.parentElement) placeholder.parentElement.removeChild(placeholder)
|
|
3186
|
+
}
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
2578
3189
|
}
|
|
2579
3190
|
|
|
2580
3191
|
/**
|
|
@@ -2608,6 +3219,28 @@ window.__ModuleLoader__.load({
|
|
|
2608
3219
|
}
|
|
2609
3220
|
}
|
|
2610
3221
|
|
|
3222
|
+
|
|
3223
|
+
ui.copy = {
|
|
3224
|
+
sync: function () {
|
|
3225
|
+
rewriteHeadline()
|
|
3226
|
+
rewriteHint()
|
|
3227
|
+
rewriteTurnStatus()
|
|
3228
|
+
},
|
|
3229
|
+
syncGreeting: function () {
|
|
3230
|
+
rewriteHeadline()
|
|
3231
|
+
},
|
|
3232
|
+
syncAttachmentPlaceholder: syncAttachmentPlaceholder,
|
|
3233
|
+
isHeroView: isHeroView,
|
|
3234
|
+
isComposerActive: isComposerActive
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3237
|
+
return function () {}
|
|
3238
|
+
}
|
|
3239
|
+
|
|
3240
|
+
// ============================================================================
|
|
3241
|
+
// 4.2: 权限段控件与会话内弹层 (Permission Segments & Popover)
|
|
3242
|
+
// ============================================================================
|
|
3243
|
+
function installPermissions(ctx, ui) {
|
|
2611
3244
|
// --- 4.2 Permission Segments & In-Conversation Popover ---
|
|
2612
3245
|
var segments = null
|
|
2613
3246
|
var permContainer = null
|
|
@@ -2620,6 +3253,7 @@ window.__ModuleLoader__.load({
|
|
|
2620
3253
|
group.className = SEGMENTS_CLASS
|
|
2621
3254
|
group.setAttribute('role', 'radiogroup')
|
|
2622
3255
|
group.setAttribute('aria-label', 'Permission')
|
|
3256
|
+
group.setAttribute('data-composer-segments', '')
|
|
2623
3257
|
for (var i = 0; i < PERMISSION_SEGMENTS.length; i++) {
|
|
2624
3258
|
var spec = PERMISSION_SEGMENTS[i]
|
|
2625
3259
|
var item = document.createElement('button')
|
|
@@ -2793,7 +3427,7 @@ window.__ModuleLoader__.load({
|
|
|
2793
3427
|
var session = currentSession(ctx)
|
|
2794
3428
|
if (session === null) return
|
|
2795
3429
|
var settled = session.command('/permission ' + preset)
|
|
2796
|
-
if (settled !== void 0 && typeof settled.then === 'function') settled.then(schedule, schedule)
|
|
3430
|
+
if (settled !== void 0 && typeof settled.then === 'function') settled.then(ui.schedule, ui.schedule)
|
|
2797
3431
|
}
|
|
2798
3432
|
|
|
2799
3433
|
/**
|
|
@@ -2847,9 +3481,16 @@ window.__ModuleLoader__.load({
|
|
|
2847
3481
|
}
|
|
2848
3482
|
|
|
2849
3483
|
function syncAttachmentState() {
|
|
3484
|
+
var active = ui.copy.isComposerActive()
|
|
2850
3485
|
var cards = document.querySelectorAll('[data-composer-card]')
|
|
2851
3486
|
for (var ci = 0; ci < cards.length; ci++) {
|
|
2852
3487
|
var card = cards[ci]
|
|
3488
|
+
if (!active) {
|
|
3489
|
+
if (card.hasAttribute('data-has-attachments')) {
|
|
3490
|
+
card.removeAttribute('data-has-attachments')
|
|
3491
|
+
}
|
|
3492
|
+
continue
|
|
3493
|
+
}
|
|
2853
3494
|
var hasAtt = card.querySelector('._54WpYG_imageItem, [class*="imageItem"], [class*="thumbnail"], [class*="FileCard"], [class*="rail"]:not([class*="trailing"]) [class*="item"], [class*="rail"]:not([class*="trailing"]) img, [class*="rail"]:not([class*="trailing"]) [class*="card"]') !== null
|
|
2854
3495
|
if (hasAtt) {
|
|
2855
3496
|
if (card.getAttribute('data-has-attachments') !== 'true') {
|
|
@@ -2861,6 +3502,7 @@ window.__ModuleLoader__.load({
|
|
|
2861
3502
|
}
|
|
2862
3503
|
}
|
|
2863
3504
|
}
|
|
3505
|
+
if (ui.copy && ui.copy.syncAttachmentPlaceholder) ui.copy.syncAttachmentPlaceholder()
|
|
2864
3506
|
}
|
|
2865
3507
|
|
|
2866
3508
|
/**
|
|
@@ -2875,6 +3517,16 @@ window.__ModuleLoader__.load({
|
|
|
2875
3517
|
function mergeStatsIntoRow() {
|
|
2876
3518
|
var stats = document.querySelector('[data-composer-stats]')
|
|
2877
3519
|
if (!stats) return
|
|
3520
|
+
var active = ui.copy.isComposerActive()
|
|
3521
|
+
if (!active) {
|
|
3522
|
+
if (stats.parentElement && stats.parentElement.matches && stats.parentElement.matches('[class*="_row"]')) {
|
|
3523
|
+
var card = stats.closest('[data-composer-card]')
|
|
3524
|
+
if (card && card.parentElement) {
|
|
3525
|
+
card.parentElement.insertBefore(stats, card.nextSibling)
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
return
|
|
3529
|
+
}
|
|
2878
3530
|
// `[class*="_row"]`, not `[class*="row"]`: the bare substring also
|
|
2879
3531
|
// matches the input growth wrapper (`grow` contains `row`).
|
|
2880
3532
|
var row = null
|
|
@@ -2904,13 +3556,38 @@ window.__ModuleLoader__.load({
|
|
|
2904
3556
|
|
|
2905
3557
|
// Re-insert when a re-render swapped the host row, then mirror the running preset.
|
|
2906
3558
|
function syncSegments() {
|
|
2907
|
-
var
|
|
2908
|
-
var isHero = !hasTurns && (document.querySelector('[class*="composerHero"], [data-phase="hero"]') !== null)
|
|
3559
|
+
var isHero = ui.copy.isHeroView()
|
|
2909
3560
|
var allCards = document.querySelectorAll('[data-composer-card]')
|
|
2910
3561
|
for (var c = 0; c < allCards.length; c++) {
|
|
2911
3562
|
allCards[c].setAttribute('data-composer-variant', isHero ? 'hero' : 'inline')
|
|
2912
3563
|
}
|
|
2913
3564
|
|
|
3565
|
+
var composerOn = ui.copy.isComposerActive()
|
|
3566
|
+
if (composerOn) document.body.setAttribute(COMPOSER_ATTR, '')
|
|
3567
|
+
else document.body.removeAttribute(COMPOSER_ATTR)
|
|
3568
|
+
|
|
3569
|
+
var existingPermContainers = document.querySelectorAll('.dsh-claude-perm-container')
|
|
3570
|
+
var existingSegments = document.querySelectorAll('.' + SEGMENTS_CLASS + '[data-composer-segments]')
|
|
3571
|
+
|
|
3572
|
+
if (!composerOn) {
|
|
3573
|
+
for (var ep = 0; ep < existingPermContainers.length; ep++) {
|
|
3574
|
+
existingPermContainers[ep].remove()
|
|
3575
|
+
}
|
|
3576
|
+
if (permPopover && permPopover.parentElement) {
|
|
3577
|
+
permPopover.parentElement.removeChild(permPopover)
|
|
3578
|
+
}
|
|
3579
|
+
permContainer = null
|
|
3580
|
+
permBtn = null
|
|
3581
|
+
permLabel = null
|
|
3582
|
+
permPopover = null
|
|
3583
|
+
|
|
3584
|
+
for (var es0 = 0; es0 < existingSegments.length; es0++) {
|
|
3585
|
+
existingSegments[es0].remove()
|
|
3586
|
+
}
|
|
3587
|
+
segments = null
|
|
3588
|
+
return
|
|
3589
|
+
}
|
|
3590
|
+
|
|
2914
3591
|
var trigger = findAccessTrigger()
|
|
2915
3592
|
if (trigger === null) return
|
|
2916
3593
|
var host = trigger.parentElement
|
|
@@ -2919,9 +3596,6 @@ window.__ModuleLoader__.load({
|
|
|
2919
3596
|
var session = currentSession(ctx)
|
|
2920
3597
|
var preset = session === null ? null : currentPreset(session)
|
|
2921
3598
|
|
|
2922
|
-
var existingPermContainers = document.querySelectorAll('.dsh-claude-perm-container')
|
|
2923
|
-
var existingSegments = document.querySelectorAll('.' + SEGMENTS_CLASS)
|
|
2924
|
-
|
|
2925
3599
|
if (isHero) {
|
|
2926
3600
|
for (var i = 0; i < existingPermContainers.length; i++) {
|
|
2927
3601
|
existingPermContainers[i].remove()
|
|
@@ -2997,6 +3671,10 @@ window.__ModuleLoader__.load({
|
|
|
2997
3671
|
* single view) means the chat surface is all there is.
|
|
2998
3672
|
*/
|
|
2999
3673
|
function syncChatTabComposer() {
|
|
3674
|
+
if (!ui.copy.isComposerActive()) {
|
|
3675
|
+
document.body.removeAttribute('data-dsh-claude-composer-hidden')
|
|
3676
|
+
return
|
|
3677
|
+
}
|
|
3000
3678
|
var chatActive = true
|
|
3001
3679
|
var seat = document.querySelector('[data-composer-seat]')
|
|
3002
3680
|
var root = seat && seat.closest ? seat.closest('[data-phase]') : null
|
|
@@ -3011,6 +3689,41 @@ window.__ModuleLoader__.load({
|
|
|
3011
3689
|
else document.body.setAttribute('data-dsh-claude-composer-hidden', '')
|
|
3012
3690
|
}
|
|
3013
3691
|
|
|
3692
|
+
|
|
3693
|
+
ui.permissions = {
|
|
3694
|
+
sync: function () {
|
|
3695
|
+
syncAttachmentState()
|
|
3696
|
+
mergeStatsIntoRow()
|
|
3697
|
+
syncSegments()
|
|
3698
|
+
syncChatTabComposer()
|
|
3699
|
+
},
|
|
3700
|
+
closeMenu: closePermMenu
|
|
3701
|
+
}
|
|
3702
|
+
|
|
3703
|
+
return function () {
|
|
3704
|
+
if (permDocPointerListener) {
|
|
3705
|
+
document.removeEventListener('pointerdown', permDocPointerListener)
|
|
3706
|
+
permDocPointerListener = null
|
|
3707
|
+
}
|
|
3708
|
+
if (permResizeListener) {
|
|
3709
|
+
window.removeEventListener('resize', permResizeListener)
|
|
3710
|
+
window.removeEventListener('scroll', permResizeListener, true)
|
|
3711
|
+
permResizeListener = null
|
|
3712
|
+
}
|
|
3713
|
+
if (segments !== null && segments.parentElement !== null) segments.parentElement.removeChild(segments)
|
|
3714
|
+
segments = null
|
|
3715
|
+
if (permPopover !== null && permPopover.parentElement !== null) permPopover.parentElement.removeChild(permPopover)
|
|
3716
|
+
permPopover = null
|
|
3717
|
+
permBtn = null
|
|
3718
|
+
permLabel = null
|
|
3719
|
+
permContainer = null
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3722
|
+
|
|
3723
|
+
// ============================================================================
|
|
3724
|
+
// 4.4: 模型选择器 (Model Picker)
|
|
3725
|
+
// ============================================================================
|
|
3726
|
+
function installModelPicker(ctx, ui) {
|
|
3014
3727
|
// --- 4.4 Model picker: replaces the host's model seat ---
|
|
3015
3728
|
/**
|
|
3016
3729
|
* The host's model seat is a click-triggered two-pane menu (Model /
|
|
@@ -3031,7 +3744,7 @@ window.__ModuleLoader__.load({
|
|
|
3031
3744
|
var modelSubPop = null
|
|
3032
3745
|
var modelBody = null
|
|
3033
3746
|
var modelSubBody = null
|
|
3034
|
-
var
|
|
3747
|
+
var modelHoverIntent = createHoverIntent(openModelPopover, closeModelPopovers, 180)
|
|
3035
3748
|
var modelDir = null
|
|
3036
3749
|
var modelSub = null
|
|
3037
3750
|
var modelSessionId = null
|
|
@@ -3039,18 +3752,63 @@ window.__ModuleLoader__.load({
|
|
|
3039
3752
|
var modelBodySig = ''
|
|
3040
3753
|
var modelSubSig = ''
|
|
3041
3754
|
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3755
|
+
/** Exact entry: `provider/model`, bare id, folded id, then the alias table. */
|
|
3756
|
+
function exactModelCopy(groupId, modelId) {
|
|
3757
|
+
if (modelCopy === null) return null
|
|
3758
|
+
var gid = String(groupId === void 0 || groupId === null ? '' : groupId).toLowerCase()
|
|
3759
|
+
var mid = String(modelId === void 0 || modelId === null ? '' : modelId)
|
|
3760
|
+
var midLower = mid.toLowerCase()
|
|
3761
|
+
var byProvider = modelCopy.exact[groupId + '/' + mid] || modelCopy.exact[gid + '/' + midLower]
|
|
3762
|
+
if (byProvider) return byProvider
|
|
3763
|
+
if (modelCopy.exact[mid]) return modelCopy.exact[mid]
|
|
3764
|
+
if (modelCopy.exact[midLower]) return modelCopy.exact[midLower]
|
|
3765
|
+
var folded = normalizeModelId(mid)
|
|
3766
|
+
if (modelCopy.folded[folded]) return modelCopy.folded[folded]
|
|
3767
|
+
var alias = modelCopy.aliases[mid] || modelCopy.aliases[midLower] || modelCopy.aliases[folded] || (modelCopy.foldedAliases && modelCopy.foldedAliases[folded])
|
|
3768
|
+
if (alias) {
|
|
3769
|
+
if (modelCopy.exact[alias]) return modelCopy.exact[alias]
|
|
3770
|
+
var foldedAlias = normalizeModelId(alias)
|
|
3771
|
+
if (modelCopy.folded[foldedAlias]) return modelCopy.folded[foldedAlias]
|
|
3772
|
+
}
|
|
3773
|
+
return null
|
|
3774
|
+
}
|
|
3775
|
+
|
|
3776
|
+
/**
|
|
3777
|
+
* Family entry. The model id is tried alone first because it is the
|
|
3778
|
+
* stronger signal, then `provider/id` for ids that carry no brand of their
|
|
3779
|
+
* own (`abab6.5s-chat` under a provider called `minimax`).
|
|
3780
|
+
*/
|
|
3781
|
+
function familyModelCopy(groupId, modelId) {
|
|
3782
|
+
if (modelCopy === null) return null
|
|
3783
|
+
var id = String(modelId === void 0 || modelId === null ? '' : modelId).toLowerCase()
|
|
3784
|
+
var haystacks = [id, String(groupId === void 0 || groupId === null ? '' : groupId).toLowerCase() + '/' + id]
|
|
3785
|
+
for (var h = 0; h < haystacks.length; h++) {
|
|
3786
|
+
for (var i = 0; i < modelCopy.families.length; i++) {
|
|
3787
|
+
var rule = modelCopy.families[i]
|
|
3788
|
+
if (!rule.re.test(haystacks[h])) continue
|
|
3789
|
+
if (rule.key) return modelCopy.exact[rule.key] || null
|
|
3790
|
+
return rule.text
|
|
3791
|
+
}
|
|
3792
|
+
}
|
|
3793
|
+
return null
|
|
3794
|
+
}
|
|
3795
|
+
|
|
3796
|
+
/** Last-resort tier rule, read out of the id itself. */
|
|
3797
|
+
function tierModelCopy(modelId) {
|
|
3798
|
+
if (modelCopy === null) return null
|
|
3799
|
+
var id = String(modelId === void 0 || modelId === null ? '' : modelId).toLowerCase()
|
|
3800
|
+
for (var i = 0; i < modelCopy.tiers.length; i++) {
|
|
3801
|
+
if (modelCopy.tiers[i].re.test(id)) return modelCopy.tiers[i].text
|
|
3046
3802
|
}
|
|
3803
|
+
return null
|
|
3804
|
+
}
|
|
3805
|
+
|
|
3806
|
+
function cancelCloseModel() {
|
|
3807
|
+
modelHoverIntent.cancel()
|
|
3047
3808
|
}
|
|
3048
3809
|
|
|
3049
3810
|
function scheduleCloseModel() {
|
|
3050
|
-
|
|
3051
|
-
modelCloseTimer = setTimeout(function () {
|
|
3052
|
-
closeModelPopovers()
|
|
3053
|
-
}, 180)
|
|
3811
|
+
modelHoverIntent.scheduleClose()
|
|
3054
3812
|
}
|
|
3055
3813
|
|
|
3056
3814
|
function closeModelPopovers() {
|
|
@@ -3075,6 +3833,7 @@ window.__ModuleLoader__.load({
|
|
|
3075
3833
|
}
|
|
3076
3834
|
modelSubKind = null
|
|
3077
3835
|
if (modelSubPop) modelSubPop.setAttribute('data-open', 'false')
|
|
3836
|
+
renderModelBody()
|
|
3078
3837
|
positionModelPopovers()
|
|
3079
3838
|
if (modelPop) modelPop.setAttribute('data-open', 'true')
|
|
3080
3839
|
}
|
|
@@ -3082,6 +3841,7 @@ window.__ModuleLoader__.load({
|
|
|
3082
3841
|
function openModelSub(kind) {
|
|
3083
3842
|
cancelCloseModel()
|
|
3084
3843
|
modelSubKind = kind
|
|
3844
|
+
renderModelSub()
|
|
3085
3845
|
positionModelPopovers()
|
|
3086
3846
|
if (modelSubPop) modelSubPop.setAttribute('data-open', 'true')
|
|
3087
3847
|
}
|
|
@@ -3141,7 +3901,7 @@ window.__ModuleLoader__.load({
|
|
|
3141
3901
|
var store = modelDir.store
|
|
3142
3902
|
if (store && typeof store.subscribe === 'function') {
|
|
3143
3903
|
try {
|
|
3144
|
-
modelSub = store.subscribe(function () { schedule() })
|
|
3904
|
+
modelSub = store.subscribe(function () { if (ui.schedule) ui.schedule() })
|
|
3145
3905
|
} catch (error) {
|
|
3146
3906
|
modelSub = null
|
|
3147
3907
|
}
|
|
@@ -3187,10 +3947,23 @@ window.__ModuleLoader__.load({
|
|
|
3187
3947
|
return { reasoning: reasoning, effective: effective, label: label }
|
|
3188
3948
|
}
|
|
3189
3949
|
|
|
3950
|
+
/**
|
|
3951
|
+
* The description line for one catalog model, in the shell's language.
|
|
3952
|
+
*
|
|
3953
|
+
* Resolution descends: exact entry (one model resold by several providers
|
|
3954
|
+
* folds to a single key) → family rule → tier rule → the catalog's own
|
|
3955
|
+
* text. Family rules are ordered and anchored (see
|
|
3956
|
+
* src/model-descriptions.json) so another vendor's flash tier never
|
|
3957
|
+
* borrows DeepSeek's copy. A model this table has never seen and the
|
|
3958
|
+
* catalog does not describe resolves to an empty string on purpose: a
|
|
3959
|
+
* name-only row beats an invented line.
|
|
3960
|
+
*/
|
|
3190
3961
|
function modelDescription(groupId, model) {
|
|
3191
|
-
var
|
|
3192
|
-
|
|
3193
|
-
|
|
3962
|
+
var id = typeof model.id === 'string' ? model.id : ''
|
|
3963
|
+
var pair = exactModelCopy(groupId, id) || familyModelCopy(groupId, id) || tierModelCopy(id)
|
|
3964
|
+
var text = localized(pair, ctx)
|
|
3965
|
+
if (text) return text
|
|
3966
|
+
return typeof model.description === 'string' ? model.description : ''
|
|
3194
3967
|
}
|
|
3195
3968
|
|
|
3196
3969
|
function modelEl(tag, cls, text) {
|
|
@@ -3204,7 +3977,7 @@ window.__ModuleLoader__.load({
|
|
|
3204
3977
|
var MODEL_CHEVRON_SVG = '<svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4l4 4-4 4"/></svg>'
|
|
3205
3978
|
var MODEL_CHEVRON_DOWN_SVG = '<svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6l4 4 4-4"/></svg>'
|
|
3206
3979
|
|
|
3207
|
-
/** One selectable model row: name
|
|
3980
|
+
/** One selectable model row: name, description line and a check when current. */
|
|
3208
3981
|
function buildModelOption(group, model, selected) {
|
|
3209
3982
|
var item = modelEl('button', 'dsh-claude-model-option')
|
|
3210
3983
|
item.type = 'button'
|
|
@@ -3212,6 +3985,8 @@ window.__ModuleLoader__.load({
|
|
|
3212
3985
|
item.setAttribute('aria-checked', selected ? 'true' : 'false')
|
|
3213
3986
|
var copy = modelEl('span', 'dsh-claude-model-copy')
|
|
3214
3987
|
copy.appendChild(modelEl('span', 'dsh-claude-model-name', model.name))
|
|
3988
|
+
// One line, in the shell's language: the copy document is localized, so
|
|
3989
|
+
// the row never stacks two languages.
|
|
3215
3990
|
var desc = modelDescription(group.id, model)
|
|
3216
3991
|
if (desc) copy.appendChild(modelEl('span', 'dsh-claude-model-desc', desc))
|
|
3217
3992
|
item.appendChild(copy)
|
|
@@ -3238,7 +4013,9 @@ window.__ModuleLoader__.load({
|
|
|
3238
4013
|
chevron.innerHTML = MODEL_CHEVRON_SVG
|
|
3239
4014
|
cell.appendChild(chevron)
|
|
3240
4015
|
cell.addEventListener('mouseenter', (function (k) {
|
|
3241
|
-
return function () {
|
|
4016
|
+
return function () {
|
|
4017
|
+
if (readPrefs().autoPopover) openModelSub(k)
|
|
4018
|
+
}
|
|
3242
4019
|
})(kind))
|
|
3243
4020
|
cell.addEventListener('click', (function (k) {
|
|
3244
4021
|
return function (e) {
|
|
@@ -3283,14 +4060,14 @@ window.__ModuleLoader__.load({
|
|
|
3283
4060
|
var groups = (snap && snap.groups) || []
|
|
3284
4061
|
var current = modelCurrent(snap)
|
|
3285
4062
|
var effort = modelEffort(snap)
|
|
3286
|
-
var sig = [status, current ? current.group.id + '/' + current.model.id : '', effort ? String(effort.effective) : ''].join('|')
|
|
4063
|
+
var sig = [status, activeLocale(), current ? current.group.id + '/' + current.model.id : '', effort ? String(effort.effective) : ''].join('|')
|
|
3287
4064
|
for (var g = 0; g < groups.length; g++) sig += ';' + groups[g].id + ':' + groups[g].models.length
|
|
3288
4065
|
if (sig === modelBodySig) return
|
|
3289
4066
|
modelBodySig = sig
|
|
3290
4067
|
while (modelBody.firstChild) modelBody.removeChild(modelBody.firstChild)
|
|
3291
4068
|
|
|
3292
4069
|
if (status === 'idle' || status === 'loading' || status === 'selecting') {
|
|
3293
|
-
modelBody.appendChild(modelEl('div', 'dsh-claude-model-status', MODEL_LOADING_LABEL))
|
|
4070
|
+
modelBody.appendChild(modelEl('div', 'dsh-claude-model-status', copyLabel('loading', MODEL_LOADING_LABEL)))
|
|
3294
4071
|
} else {
|
|
3295
4072
|
var official = null
|
|
3296
4073
|
for (var g2 = 0; g2 < groups.length; g2++) {
|
|
@@ -3305,7 +4082,7 @@ window.__ModuleLoader__.load({
|
|
|
3305
4082
|
}
|
|
3306
4083
|
}
|
|
3307
4084
|
if (rows.length === 0) {
|
|
3308
|
-
modelBody.appendChild(modelEl('div', 'dsh-claude-model-status', MODEL_EMPTY_LABEL))
|
|
4085
|
+
modelBody.appendChild(modelEl('div', 'dsh-claude-model-status', copyLabel('empty', MODEL_EMPTY_LABEL)))
|
|
3309
4086
|
} else {
|
|
3310
4087
|
for (var r = 0; r < rows.length; r++) {
|
|
3311
4088
|
var selected = current !== null && current.group.id === rows[r].group.id && current.model.id === rows[r].model.id
|
|
@@ -3313,8 +4090,8 @@ window.__ModuleLoader__.load({
|
|
|
3313
4090
|
}
|
|
3314
4091
|
}
|
|
3315
4092
|
modelBody.appendChild(modelEl('div', 'dsh-claude-model-divider'))
|
|
3316
|
-
if (effort) modelBody.appendChild(buildModelCell(MODEL_EFFORT_LABEL, effort.label, 'effort'))
|
|
3317
|
-
modelBody.appendChild(buildModelCell(MODEL_MORE_LABEL, '', 'more'))
|
|
4093
|
+
if (effort) modelBody.appendChild(buildModelCell(copyLabel('effortLabel', MODEL_EFFORT_LABEL), effort.label, 'effort'))
|
|
4094
|
+
modelBody.appendChild(buildModelCell(copyLabel('moreLabel', MODEL_MORE_LABEL), '', 'more'))
|
|
3318
4095
|
}
|
|
3319
4096
|
}
|
|
3320
4097
|
|
|
@@ -3329,7 +4106,7 @@ window.__ModuleLoader__.load({
|
|
|
3329
4106
|
modelSubSig = sig
|
|
3330
4107
|
while (modelSubBody.firstChild) modelSubBody.removeChild(modelSubBody.firstChild)
|
|
3331
4108
|
if (effort === null) {
|
|
3332
|
-
modelSubBody.appendChild(modelEl('div', 'dsh-claude-model-status', '
|
|
4109
|
+
modelSubBody.appendChild(modelEl('div', 'dsh-claude-model-status', copyLabel('noEffort', MODEL_NO_EFFORT_LABEL)))
|
|
3333
4110
|
return
|
|
3334
4111
|
}
|
|
3335
4112
|
var levels = []
|
|
@@ -3375,28 +4152,20 @@ window.__ModuleLoader__.load({
|
|
|
3375
4152
|
}
|
|
3376
4153
|
}
|
|
3377
4154
|
if (modelSubBody.firstChild === null) {
|
|
3378
|
-
|
|
4155
|
+
modelSubBody.appendChild(modelEl('div', 'dsh-claude-model-status', copyLabel('empty', MODEL_EMPTY_LABEL)))
|
|
3379
4156
|
}
|
|
3380
4157
|
}
|
|
3381
4158
|
|
|
3382
4159
|
function positionModelPopovers() {
|
|
3383
4160
|
if (!modelBtn || !modelPop) return
|
|
3384
|
-
var
|
|
3385
|
-
var MARGIN = 8
|
|
3386
|
-
var w = modelPop.offsetWidth
|
|
3387
|
-
var h = modelPop.offsetHeight
|
|
3388
|
-
var x = Math.max(MARGIN, Math.min(rect.right - w, window.innerWidth - w - MARGIN))
|
|
3389
|
-
var y = rect.top - 6 - h
|
|
3390
|
-
if (y < MARGIN) y = Math.min(rect.bottom + 6, Math.max(MARGIN, window.innerHeight - h - MARGIN))
|
|
3391
|
-
modelPop.style.left = x + 'px'
|
|
3392
|
-
modelPop.style.top = y + 'px'
|
|
4161
|
+
var pos = positionAnchoredPopover(modelBtn, modelPop, { side: 'above', gap: 6 })
|
|
3393
4162
|
if (modelSubPop && modelSubPop.getAttribute('data-open') === 'true') {
|
|
3394
4163
|
var w2 = modelSubPop.offsetWidth
|
|
3395
4164
|
var h2 = modelSubPop.offsetHeight
|
|
3396
4165
|
// Beside the first level; flip to its left when the viewport is tight.
|
|
3397
|
-
var x2 = x +
|
|
3398
|
-
if (x2 + w2 > window.innerWidth -
|
|
3399
|
-
var y2 = Math.max(
|
|
4166
|
+
var x2 = pos.x + modelPop.offsetWidth + 4
|
|
4167
|
+
if (x2 + w2 > window.innerWidth - POPOVER_MARGIN) x2 = Math.max(POPOVER_MARGIN, pos.x - 4 - w2)
|
|
4168
|
+
var y2 = Math.max(POPOVER_MARGIN, Math.min(pos.y, window.innerHeight - h2 - POPOVER_MARGIN))
|
|
3400
4169
|
modelSubPop.style.left = x2 + 'px'
|
|
3401
4170
|
modelSubPop.style.top = y2 + 'px'
|
|
3402
4171
|
}
|
|
@@ -3431,6 +4200,37 @@ window.__ModuleLoader__.load({
|
|
|
3431
4200
|
|
|
3432
4201
|
/** Build/refresh the trigger, its label and the popover rows. */
|
|
3433
4202
|
function syncModelControl() {
|
|
4203
|
+
if (!ui.copy.isComposerActive()) {
|
|
4204
|
+
var allHosts = document.querySelectorAll('[data-dsh-claude-model-host]')
|
|
4205
|
+
for (var h = 0; h < allHosts.length; h++) {
|
|
4206
|
+
allHosts[h].removeAttribute('data-dsh-claude-model-host')
|
|
4207
|
+
}
|
|
4208
|
+
var allModelBtns = document.querySelectorAll('.dsh-claude-model-btn')
|
|
4209
|
+
for (var mb = 0; mb < allModelBtns.length; mb++) {
|
|
4210
|
+
allModelBtns[mb].remove()
|
|
4211
|
+
}
|
|
4212
|
+
modelBtn = null
|
|
4213
|
+
var allModelPops = document.querySelectorAll('.dsh-claude-model-popover')
|
|
4214
|
+
for (var mp = 0; mp < allModelPops.length; mp++) {
|
|
4215
|
+
allModelPops[mp].remove()
|
|
4216
|
+
}
|
|
4217
|
+
modelPop = null
|
|
4218
|
+
modelSubPop = null
|
|
4219
|
+
modelBody = null
|
|
4220
|
+
modelSubBody = null
|
|
4221
|
+
modelSubKind = null
|
|
4222
|
+
modelBodySig = ''
|
|
4223
|
+
modelSubSig = ''
|
|
4224
|
+
cancelCloseModel()
|
|
4225
|
+
dropModelSubscription()
|
|
4226
|
+
modelDir = null
|
|
4227
|
+
modelSessionId = null
|
|
4228
|
+
return
|
|
4229
|
+
}
|
|
4230
|
+
|
|
4231
|
+
// The copy document is fetched on first paint of the picker rather than
|
|
4232
|
+
// at install, so a session that never opens it never pays for it.
|
|
4233
|
+
loadModelCopy()
|
|
3434
4234
|
modelDirectory()
|
|
3435
4235
|
var slot = document.querySelector('[data-slot="conversation.input.model"]')
|
|
3436
4236
|
if (slot === null) return
|
|
@@ -3448,8 +4248,14 @@ window.__ModuleLoader__.load({
|
|
|
3448
4248
|
modelBtn.innerHTML =
|
|
3449
4249
|
'<span class="dsh-claude-model-btn-label"></span>' +
|
|
3450
4250
|
'<span class="dsh-claude-model-btn-chevron">' + MODEL_CHEVRON_DOWN_SVG + '</span>'
|
|
3451
|
-
|
|
3452
|
-
|
|
4251
|
+
// Same contract as the account trigger: hover unless the preference
|
|
4252
|
+
// says click-only.
|
|
4253
|
+
modelBtn.addEventListener('mouseenter', function () {
|
|
4254
|
+
if (readPrefs().autoPopover) openModelPopover()
|
|
4255
|
+
})
|
|
4256
|
+
modelBtn.addEventListener('mouseleave', function () {
|
|
4257
|
+
if (readPrefs().autoPopover) scheduleCloseModel()
|
|
4258
|
+
})
|
|
3453
4259
|
modelBtn.addEventListener('click', function (e) {
|
|
3454
4260
|
e.stopPropagation()
|
|
3455
4261
|
if (modelPop && modelPop.getAttribute('data-open') === 'true') closeModelPopovers()
|
|
@@ -3462,7 +4268,7 @@ window.__ModuleLoader__.load({
|
|
|
3462
4268
|
var snap = modelSnapshot()
|
|
3463
4269
|
var current = modelCurrent(snap)
|
|
3464
4270
|
var effort = modelEffort(snap)
|
|
3465
|
-
var label = current ? current.model.name : MODEL_FALLBACK_LABEL
|
|
4271
|
+
var label = current ? current.model.name : copyLabel('fallbackLabel', MODEL_FALLBACK_LABEL)
|
|
3466
4272
|
var labelEl = modelBtn.querySelector('.dsh-claude-model-btn-label')
|
|
3467
4273
|
if (labelEl) {
|
|
3468
4274
|
labelEl.textContent = label
|
|
@@ -3478,7 +4284,7 @@ window.__ModuleLoader__.load({
|
|
|
3478
4284
|
} else if (effortEl !== null && effortEl.parentElement) {
|
|
3479
4285
|
effortEl.parentElement.removeChild(effortEl)
|
|
3480
4286
|
}
|
|
3481
|
-
modelBtn.setAttribute('aria-label', '
|
|
4287
|
+
modelBtn.setAttribute('aria-label', copyLabel('triggerLabel', MODEL_TRIGGER_LABEL, { model: label }))
|
|
3482
4288
|
modelBtn.disabled = false
|
|
3483
4289
|
|
|
3484
4290
|
renderModelBody()
|
|
@@ -3489,18 +4295,53 @@ window.__ModuleLoader__.load({
|
|
|
3489
4295
|
if (modelPop && modelPop.getAttribute('data-open') === 'true') positionModelPopovers()
|
|
3490
4296
|
}
|
|
3491
4297
|
|
|
4298
|
+
|
|
4299
|
+
ui.model = {
|
|
4300
|
+
sync: syncModelControl,
|
|
4301
|
+
close: closeModelPopovers,
|
|
4302
|
+
owns: function (target) {
|
|
4303
|
+
if (!target) return false
|
|
4304
|
+
return (modelBtn !== null && modelBtn.contains(target)) ||
|
|
4305
|
+
(modelPop !== null && modelPop.contains(target)) ||
|
|
4306
|
+
(modelSubPop !== null && modelSubPop.contains(target))
|
|
4307
|
+
},
|
|
4308
|
+
reposition: positionModelPopovers,
|
|
4309
|
+
invalidateCopy: function () {
|
|
4310
|
+
modelBodySig = ''
|
|
4311
|
+
modelSubSig = ''
|
|
4312
|
+
},
|
|
4313
|
+
teardown: function () {
|
|
4314
|
+
cancelCloseModel()
|
|
4315
|
+
dropModelSubscription()
|
|
4316
|
+
modelDir = null
|
|
4317
|
+
modelSessionId = null
|
|
4318
|
+
modelBtn = null
|
|
4319
|
+
modelPop = null
|
|
4320
|
+
modelSubPop = null
|
|
4321
|
+
modelBody = null
|
|
4322
|
+
modelSubBody = null
|
|
4323
|
+
modelSubKind = null
|
|
4324
|
+
modelBodySig = ''
|
|
4325
|
+
modelSubSig = ''
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
4328
|
+
|
|
4329
|
+
return ui.model.teardown
|
|
4330
|
+
}
|
|
4331
|
+
|
|
4332
|
+
// ============================================================================
|
|
4333
|
+
// 4.3: 账户页脚与弹层 (Account Footer & Popover)
|
|
4334
|
+
// ============================================================================
|
|
4335
|
+
function installAccountFooter(ctx, ui) {
|
|
3492
4336
|
// --- 4.3 Account Footer & Popover ---
|
|
3493
4337
|
var accountBtn = null
|
|
3494
4338
|
var accountPopover = null
|
|
3495
4339
|
var popoverBody = null
|
|
3496
|
-
var
|
|
4340
|
+
var popoverHoverIntent = createHoverIntent(openPopover, closePopover, 150)
|
|
3497
4341
|
|
|
3498
4342
|
function openPopover() {
|
|
3499
4343
|
if (!accountPopover || !accountBtn) return
|
|
3500
|
-
|
|
3501
|
-
clearTimeout(popoverTimer)
|
|
3502
|
-
popoverTimer = null
|
|
3503
|
-
}
|
|
4344
|
+
cancelClosePopover()
|
|
3504
4345
|
// Mirrors are frozen while the popover is open (syncPopoverItems
|
|
3505
4346
|
// bails), so reconcile them here — before the reveal — to show fresh
|
|
3506
4347
|
// content/order and bind click targets for the upcoming interaction.
|
|
@@ -3508,6 +4349,9 @@ window.__ModuleLoader__.load({
|
|
|
3508
4349
|
var footArea = document.querySelector('[class*="footArea"]')
|
|
3509
4350
|
if (footArea) syncPopoverItems(footArea)
|
|
3510
4351
|
} catch (error) { /* opening must never fail because of a mirror sync */ }
|
|
4352
|
+
// Resolve the rail anchor before the reveal so the panel never paints at
|
|
4353
|
+
// its stale coordinates for a frame.
|
|
4354
|
+
positionAccountPopover()
|
|
3511
4355
|
accountPopover.setAttribute('data-open', 'true')
|
|
3512
4356
|
accountBtn.setAttribute('data-open', 'true')
|
|
3513
4357
|
accountBtn.setAttribute('aria-expanded', 'true')
|
|
@@ -3515,10 +4359,7 @@ window.__ModuleLoader__.load({
|
|
|
3515
4359
|
|
|
3516
4360
|
function closePopover() {
|
|
3517
4361
|
if (!accountPopover || !accountBtn) return
|
|
3518
|
-
|
|
3519
|
-
clearTimeout(popoverTimer)
|
|
3520
|
-
popoverTimer = null
|
|
3521
|
-
}
|
|
4362
|
+
cancelClosePopover()
|
|
3522
4363
|
accountPopover.setAttribute('data-open', 'false')
|
|
3523
4364
|
accountBtn.setAttribute('data-open', 'false')
|
|
3524
4365
|
accountBtn.setAttribute('aria-expanded', 'false')
|
|
@@ -3534,18 +4375,36 @@ window.__ModuleLoader__.load({
|
|
|
3534
4375
|
}
|
|
3535
4376
|
}
|
|
3536
4377
|
|
|
4378
|
+
function cancelClosePopover() {
|
|
4379
|
+
popoverHoverIntent.cancel()
|
|
4380
|
+
}
|
|
4381
|
+
|
|
3537
4382
|
function scheduleClosePopover() {
|
|
3538
|
-
|
|
3539
|
-
popoverTimer = setTimeout(function () {
|
|
3540
|
-
closePopover()
|
|
3541
|
-
}, 150)
|
|
4383
|
+
popoverHoverIntent.scheduleClose()
|
|
3542
4384
|
}
|
|
3543
4385
|
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
4386
|
+
/**
|
|
4387
|
+
* Anchor the account popover to its trigger while the sidebar is a rail.
|
|
4388
|
+
*
|
|
4389
|
+
* In the rail the popover is `position: fixed` (components/account-footer.css): the sidebar
|
|
4390
|
+
* column clips its overflow, so an absolutely positioned panel would be cut
|
|
4391
|
+
* off at the 56px rail edge and never seen. Its coordinates therefore have
|
|
4392
|
+
* to be resolved here — the same contract the model picker's popovers use.
|
|
4393
|
+
* The declarations are written `important` because the stylesheet anchors
|
|
4394
|
+
* the wide-sidebar popover with `!important` as well, and an author
|
|
4395
|
+
* `!important` beats a plain inline declaration.
|
|
4396
|
+
*
|
|
4397
|
+
* With the sidebar wide the CSS anchor is the right one, so the inline
|
|
4398
|
+
* overrides are dropped again and the footer rule takes over.
|
|
4399
|
+
*/
|
|
4400
|
+
function positionAccountPopover() {
|
|
4401
|
+
if (!accountPopover || !accountBtn) return
|
|
4402
|
+
if (accountBtn.closest('[class*="collapsed"]') === null) {
|
|
4403
|
+
accountPopover.style.removeProperty('left')
|
|
4404
|
+
accountPopover.style.removeProperty('top')
|
|
4405
|
+
return
|
|
3548
4406
|
}
|
|
4407
|
+
positionAnchoredPopover(accountBtn, accountPopover, { side: 'right', important: true })
|
|
3549
4408
|
}
|
|
3550
4409
|
|
|
3551
4410
|
var settingsItem = null
|
|
@@ -4015,10 +4874,41 @@ window.__ModuleLoader__.load({
|
|
|
4015
4874
|
return null
|
|
4016
4875
|
}
|
|
4017
4876
|
|
|
4877
|
+
/**
|
|
4878
|
+
* Hand the sidebar footer back to the host.
|
|
4879
|
+
*
|
|
4880
|
+
* The "Collapse the sidebar settings area" preference turns the whole
|
|
4881
|
+
* takeover off, so the skin's own nodes go and every marker it put on the
|
|
4882
|
+
* host's entries is removed — with the stylesheet's takeover rules gated
|
|
4883
|
+
* on the same attribute, the footer then renders exactly as shipped.
|
|
4884
|
+
*/
|
|
4885
|
+
function dropAccountFooter(footArea) {
|
|
4886
|
+
cancelClosePopover()
|
|
4887
|
+
if (accountBtn !== null && accountBtn.parentElement !== null) accountBtn.parentElement.removeChild(accountBtn)
|
|
4888
|
+
if (accountPopover !== null && accountPopover.parentElement !== null) {
|
|
4889
|
+
accountPopover.parentElement.removeChild(accountPopover)
|
|
4890
|
+
}
|
|
4891
|
+
accountBtn = null
|
|
4892
|
+
accountPopover = null
|
|
4893
|
+
popoverBody = null
|
|
4894
|
+
settingsItem = null
|
|
4895
|
+
var marked = footArea.querySelectorAll(
|
|
4896
|
+
'[data-dsh-claude-footer-entry], [data-dsh-claude-footer-hidden], [data-dsh-claude-footer-overlay]',
|
|
4897
|
+
)
|
|
4898
|
+
for (var i = 0; i < marked.length; i++) {
|
|
4899
|
+
marked[i].removeAttribute('data-dsh-claude-footer-entry')
|
|
4900
|
+
marked[i].removeAttribute('data-dsh-claude-footer-hidden')
|
|
4901
|
+
marked[i].removeAttribute('data-dsh-claude-footer-overlay')
|
|
4902
|
+
}
|
|
4903
|
+
}
|
|
4018
4904
|
function syncAccountFooter() {
|
|
4019
4905
|
var footArea = document.querySelector('[class*="footArea"]')
|
|
4020
4906
|
if (footArea === null) return
|
|
4021
4907
|
|
|
4908
|
+
if (!readPrefs().collapseFooter) {
|
|
4909
|
+
dropAccountFooter(footArea)
|
|
4910
|
+
return
|
|
4911
|
+
}
|
|
4022
4912
|
var username = getUsername(ctx)
|
|
4023
4913
|
|
|
4024
4914
|
if (accountBtn === null || !footArea.contains(accountBtn)) {
|
|
@@ -4036,11 +4926,15 @@ window.__ModuleLoader__.load({
|
|
|
4036
4926
|
'</span>' +
|
|
4037
4927
|
'<span class="dsh-claude-account-chevron"></span>'
|
|
4038
4928
|
|
|
4929
|
+
// Hover is the default way in; the "Open popovers on hover"
|
|
4930
|
+
// preference turns it off, leaving the click handler below as the only
|
|
4931
|
+
// way in (and the only way out, so a click-opened popover does not
|
|
4932
|
+
// vanish when the pointer leaves).
|
|
4039
4933
|
accountBtn.addEventListener('mouseenter', function () {
|
|
4040
|
-
openPopover()
|
|
4934
|
+
if (readPrefs().autoPopover) openPopover()
|
|
4041
4935
|
})
|
|
4042
4936
|
accountBtn.addEventListener('mouseleave', function () {
|
|
4043
|
-
scheduleClosePopover()
|
|
4937
|
+
if (readPrefs().autoPopover) scheduleClosePopover()
|
|
4044
4938
|
})
|
|
4045
4939
|
accountBtn.addEventListener('click', function (e) {
|
|
4046
4940
|
e.stopPropagation()
|
|
@@ -4093,28 +4987,58 @@ window.__ModuleLoader__.load({
|
|
|
4093
4987
|
syncPopoverItems(footArea)
|
|
4094
4988
|
}
|
|
4095
4989
|
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4990
|
+
|
|
4991
|
+
ui.footer = {
|
|
4992
|
+
sync: syncAccountFooter,
|
|
4993
|
+
close: closePopover,
|
|
4994
|
+
owns: function (target) {
|
|
4995
|
+
if (!target) return false
|
|
4996
|
+
return (accountBtn !== null && accountBtn.contains(target)) ||
|
|
4997
|
+
(accountPopover !== null && accountPopover.contains(target))
|
|
4998
|
+
},
|
|
4999
|
+
isOpen: function () {
|
|
5000
|
+
return !!(accountPopover && accountPopover.getAttribute('data-open') === 'true')
|
|
5001
|
+
},
|
|
5002
|
+
reposition: positionAccountPopover
|
|
5003
|
+
}
|
|
5004
|
+
|
|
5005
|
+
return function () {
|
|
5006
|
+
cancelClosePopover()
|
|
5007
|
+
var footArea = document.querySelector('[class*="footArea"]')
|
|
5008
|
+
if (footArea) {
|
|
5009
|
+
dropAccountFooter(footArea)
|
|
5010
|
+
} else {
|
|
5011
|
+
if (accountBtn !== null && accountBtn.parentElement !== null) accountBtn.parentElement.removeChild(accountBtn)
|
|
5012
|
+
if (accountPopover !== null && accountPopover.parentElement !== null) accountPopover.parentElement.removeChild(accountPopover)
|
|
5013
|
+
accountBtn = null
|
|
5014
|
+
accountPopover = null
|
|
5015
|
+
popoverBody = null
|
|
5016
|
+
settingsItem = null
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
5019
|
+
}
|
|
5020
|
+
|
|
5021
|
+
// ============================================================================
|
|
5022
|
+
// 响应式调度与生命周期清理 (Scheduler & Teardown)
|
|
5023
|
+
// ============================================================================
|
|
5024
|
+
function installScheduler(ctx, ui) {
|
|
4099
5025
|
function onGlobalPointerDown(e) {
|
|
4100
5026
|
var target = e.target
|
|
4101
5027
|
// The model picker is hover-driven; a press anywhere outside its
|
|
4102
5028
|
// trigger and both levels closes it (same discipline as the perm menu).
|
|
4103
|
-
if (target &&
|
|
4104
|
-
|
|
4105
|
-
(modelSubPop === null || !modelSubPop.contains(target))) {
|
|
4106
|
-
closeModelPopovers()
|
|
5029
|
+
if (target && ui.model && !ui.model.owns(target)) {
|
|
5030
|
+
ui.model.close()
|
|
4107
5031
|
}
|
|
4108
|
-
if (!
|
|
4109
|
-
if (target &&
|
|
4110
|
-
|
|
5032
|
+
if (!ui.footer || !ui.footer.isOpen()) return
|
|
5033
|
+
if (target && ui.footer.owns(target)) return
|
|
5034
|
+
ui.footer.close()
|
|
4111
5035
|
}
|
|
4112
5036
|
|
|
4113
5037
|
function onGlobalKeyDown(e) {
|
|
4114
5038
|
if (e.key === 'Escape') {
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
5039
|
+
if (ui.footer) ui.footer.close()
|
|
5040
|
+
if (ui.permissions) ui.permissions.closeMenu()
|
|
5041
|
+
if (ui.model) ui.model.close()
|
|
4118
5042
|
}
|
|
4119
5043
|
if ((e.ctrlKey || e.metaKey) && e.key === ',') {
|
|
4120
5044
|
e.preventDefault()
|
|
@@ -4152,17 +5076,63 @@ window.__ModuleLoader__.load({
|
|
|
4152
5076
|
}
|
|
4153
5077
|
}
|
|
4154
5078
|
|
|
5079
|
+
function onComposerInput(e) {
|
|
5080
|
+
var target = e.target
|
|
5081
|
+
if (!target) return
|
|
5082
|
+
if (target.hasAttribute && (target.hasAttribute('data-composer-input') || (target.closest && target.closest('[data-composer-input]')))) {
|
|
5083
|
+
if (ui.copy && ui.copy.syncAttachmentPlaceholder) ui.copy.syncAttachmentPlaceholder()
|
|
5084
|
+
}
|
|
5085
|
+
}
|
|
5086
|
+
|
|
4155
5087
|
document.addEventListener('pointerdown', onGlobalPointerDown)
|
|
4156
5088
|
document.addEventListener('pointerdown', onCardPointerDown)
|
|
4157
5089
|
document.addEventListener('keydown', onGlobalKeyDown, true)
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
5090
|
+
document.addEventListener('input', onComposerInput, true)
|
|
5091
|
+
document.addEventListener('compositionend', onComposerInput, true)
|
|
5092
|
+
|
|
5093
|
+
// Both fixed popovers are anchored to their trigger; scroll of the page
|
|
5094
|
+
// (not the conversation's own auto-stick) and resizes move the anchor, so
|
|
5095
|
+
// whichever is open must re-resolve it.
|
|
5096
|
+
function onFixedPopoverViewportChange() {
|
|
5097
|
+
if (ui.model) ui.model.reposition()
|
|
5098
|
+
if (ui.footer && ui.footer.isOpen()) ui.footer.reposition()
|
|
5099
|
+
}
|
|
5100
|
+
window.addEventListener('resize', onFixedPopoverViewportChange)
|
|
5101
|
+
window.addEventListener('scroll', onFixedPopoverViewportChange, true)
|
|
5102
|
+
|
|
5103
|
+
// The picker's copy follows the shell language, so a locale switch has to
|
|
5104
|
+
// rebuild the rows it already painted. Subscribing here (rather than
|
|
5105
|
+
// reading the locale at render time only) is what makes the change land
|
|
5106
|
+
// while a popover is open.
|
|
5107
|
+
var localeUnsubscribe = null
|
|
5108
|
+
function onLocaleChange() {
|
|
5109
|
+
if (ui.model) ui.model.invalidateCopy()
|
|
5110
|
+
schedule()
|
|
4163
5111
|
}
|
|
4164
|
-
|
|
4165
|
-
|
|
5112
|
+
try {
|
|
5113
|
+
var localeService = ctx.get('locale')
|
|
5114
|
+
if (localeService && typeof localeService.subscribe === 'function') {
|
|
5115
|
+
localeUnsubscribe = localeService.subscribe(onLocaleChange)
|
|
5116
|
+
}
|
|
5117
|
+
} catch (error) { /* no locale service: the picker keeps the fallback language */ }
|
|
5118
|
+
|
|
5119
|
+
// Preferences gate the stylesheet and this scheduler both — the footer
|
|
5120
|
+
// takeover adds or removes the account row, and the composer scope flips
|
|
5121
|
+
// an attribute the stylesheet reads — so a change re-runs the pass. The
|
|
5122
|
+
// first read also arrives through here, which is what replaces the
|
|
5123
|
+
// defaults with the stored values.
|
|
5124
|
+
var prefsUnsubscribe = null
|
|
5125
|
+
prefsUnsubscribe = subscribePrefs(function () {
|
|
5126
|
+
if (ui.model) ui.model.invalidateCopy()
|
|
5127
|
+
schedule()
|
|
5128
|
+
})
|
|
5129
|
+
loadPrefs()
|
|
5130
|
+
|
|
5131
|
+
var modelCopyUnsubscribe = null
|
|
5132
|
+
modelCopyUnsubscribe = onModelCopyLoaded(function () {
|
|
5133
|
+
if (ui.model) ui.model.invalidateCopy()
|
|
5134
|
+
schedule()
|
|
5135
|
+
})
|
|
4166
5136
|
|
|
4167
5137
|
// Chat streaming mutates the tree constantly; coalesce to one pass a frame.
|
|
4168
5138
|
var scheduled = false
|
|
@@ -4185,15 +5155,13 @@ window.__ModuleLoader__.load({
|
|
|
4185
5155
|
scheduled = true
|
|
4186
5156
|
requestAnimationFrame(function () {
|
|
4187
5157
|
scheduled = false
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
syncModelControl()
|
|
4196
|
-
syncAccountFooter()
|
|
5158
|
+
if (ui.copy) ui.copy.sync()
|
|
5159
|
+
if (ui.permissions) ui.permissions.sync()
|
|
5160
|
+
if (ui.model) ui.model.sync()
|
|
5161
|
+
if (ui.footer) ui.footer.sync()
|
|
5162
|
+
// Covers the rail toggle (and any reflow) while the popover is open:
|
|
5163
|
+
// its anchor moved without a window resize or a page scroll.
|
|
5164
|
+
if (ui.footer && ui.footer.isOpen()) ui.footer.reposition()
|
|
4197
5165
|
if (composerCardObserver) {
|
|
4198
5166
|
var currentCard = document.querySelector('[data-composer-card]')
|
|
4199
5167
|
if (currentCard !== observedCard) {
|
|
@@ -4204,6 +5172,7 @@ window.__ModuleLoader__.load({
|
|
|
4204
5172
|
}
|
|
4205
5173
|
})
|
|
4206
5174
|
}
|
|
5175
|
+
ui.schedule = schedule
|
|
4207
5176
|
|
|
4208
5177
|
var observer = new MutationObserver(schedule)
|
|
4209
5178
|
observer.observe(document.body, {
|
|
@@ -4221,69 +5190,40 @@ window.__ModuleLoader__.load({
|
|
|
4221
5190
|
// line rolls over on the hour while the app stays open. rewriteHeadline
|
|
4222
5191
|
// skips identical text, so this cannot feed the observer.
|
|
4223
5192
|
var greetingTimer = setInterval(function () {
|
|
4224
|
-
|
|
5193
|
+
if (ui.copy) ui.copy.syncGreeting()
|
|
4225
5194
|
}, 60000)
|
|
4226
5195
|
|
|
4227
5196
|
return function () {
|
|
4228
5197
|
clearInterval(greetingTimer)
|
|
4229
5198
|
greetingTimer = null
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
modelBodySig = ''
|
|
4245
|
-
modelSubSig = ''
|
|
5199
|
+
window.removeEventListener('resize', onFixedPopoverViewportChange)
|
|
5200
|
+
window.removeEventListener('scroll', onFixedPopoverViewportChange, true)
|
|
5201
|
+
if (localeUnsubscribe !== null) {
|
|
5202
|
+
try { localeUnsubscribe() } catch (error) { /* already disposed */ }
|
|
5203
|
+
localeUnsubscribe = null
|
|
5204
|
+
}
|
|
5205
|
+
if (prefsUnsubscribe !== null) {
|
|
5206
|
+
try { prefsUnsubscribe() } catch (error) { /* already disposed */ }
|
|
5207
|
+
prefsUnsubscribe = null
|
|
5208
|
+
}
|
|
5209
|
+
if (modelCopyUnsubscribe !== null) {
|
|
5210
|
+
try { modelCopyUnsubscribe() } catch (error) { /* already disposed */ }
|
|
5211
|
+
modelCopyUnsubscribe = null
|
|
5212
|
+
}
|
|
4246
5213
|
observer.disconnect()
|
|
4247
5214
|
if (composerCardObserver) {
|
|
4248
5215
|
composerCardObserver.disconnect()
|
|
4249
5216
|
composerCardObserver = null
|
|
4250
5217
|
observedCard = null
|
|
4251
5218
|
}
|
|
4252
|
-
if (popoverTimer) {
|
|
4253
|
-
clearTimeout(popoverTimer)
|
|
4254
|
-
popoverTimer = null
|
|
4255
|
-
}
|
|
4256
5219
|
document.removeEventListener('pointerdown', onGlobalPointerDown)
|
|
4257
5220
|
document.removeEventListener('pointerdown', onCardPointerDown)
|
|
4258
5221
|
document.removeEventListener('keydown', onGlobalKeyDown, true)
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
window.removeEventListener('resize', permResizeListener)
|
|
4265
|
-
window.removeEventListener('scroll', permResizeListener, true)
|
|
4266
|
-
permResizeListener = null
|
|
4267
|
-
}
|
|
4268
|
-
if (segments !== null && segments.parentElement !== null) segments.parentElement.removeChild(segments)
|
|
4269
|
-
segments = null
|
|
4270
|
-
if (permPopover !== null && permPopover.parentElement !== null) {
|
|
4271
|
-
permPopover.parentElement.removeChild(permPopover)
|
|
4272
|
-
}
|
|
4273
|
-
permPopover = null
|
|
4274
|
-
permBtn = null
|
|
4275
|
-
permLabel = null
|
|
4276
|
-
permContainer = null
|
|
4277
|
-
if (accountPopover !== null && accountPopover.parentElement !== null) {
|
|
4278
|
-
accountPopover.parentElement.removeChild(accountPopover)
|
|
4279
|
-
}
|
|
4280
|
-
accountPopover = null
|
|
4281
|
-
popoverBody = null
|
|
4282
|
-
if (accountBtn !== null && accountBtn.parentElement !== null) {
|
|
4283
|
-
accountBtn.parentElement.removeChild(accountBtn)
|
|
4284
|
-
}
|
|
4285
|
-
accountBtn = null
|
|
4286
|
-
var leftoverItems = document.querySelectorAll('.dsh-claude-popover-item, .dsh-claude-popover-embed, .dsh-claude-account-popover, .dsh-claude-account-btn, .dsh-claude-perm-container, .dsh-claude-perm-popover, .dsh-claude-segments, .dsh-claude-model-btn, .dsh-claude-model-popover')
|
|
5222
|
+
document.removeEventListener('input', onComposerInput, true)
|
|
5223
|
+
document.removeEventListener('compositionend', onComposerInput, true)
|
|
5224
|
+
// Safety-net DOM sweep. Feature teardowns run after this and tolerate
|
|
5225
|
+
// nodes already being detached.
|
|
5226
|
+
var leftoverItems = document.querySelectorAll('.dsh-claude-popover-item, .dsh-claude-popover-embed, .dsh-claude-account-popover, .dsh-claude-account-btn, .dsh-claude-perm-container, .dsh-claude-perm-popover, .dsh-claude-segments[data-composer-segments], .dsh-claude-model-btn, .dsh-claude-model-popover, [data-dsh-synthetic-placeholder]')
|
|
4287
5227
|
for (var li = 0; li < leftoverItems.length; li++) {
|
|
4288
5228
|
if (leftoverItems[li].parentElement) {
|
|
4289
5229
|
leftoverItems[li].parentElement.removeChild(leftoverItems[li])
|
|
@@ -4300,74 +5240,160 @@ window.__ModuleLoader__.load({
|
|
|
4300
5240
|
}
|
|
4301
5241
|
|
|
4302
5242
|
// ============================================================================
|
|
4303
|
-
//
|
|
5243
|
+
// 设置页 (Settings Section)
|
|
4304
5244
|
// ============================================================================
|
|
4305
5245
|
/**
|
|
4306
5246
|
* The settings page section, mounted by the host into the `settings.section`
|
|
4307
|
-
* slot. That slot hands a section only `{ close }` plus the standard hooks,
|
|
4308
|
-
* this component owns its
|
|
5247
|
+
* slot. That slot hands a section only `{ close }` plus the standard hooks,
|
|
5248
|
+
* so this component owns no store of its own: it reads and writes the skin
|
|
5249
|
+
* preferences through src/context/prefs.js, which owns the host round trip, and
|
|
5250
|
+
* follows changes the same way the rest of the skin does.
|
|
5251
|
+
*
|
|
5252
|
+
* Copy comes from the model copy document's `settings` block, so the page
|
|
5253
|
+
* follows the shell language like every other string the skin paints. The
|
|
5254
|
+
* English literals here are the fallback for a failed fetch.
|
|
4309
5255
|
*
|
|
4310
|
-
*
|
|
4311
|
-
*
|
|
5256
|
+
* Both segmented controls reuse the shared `.dsh-claude-segments` /
|
|
5257
|
+
* `.dsh-claude-segment` classes — the same control the composer's permission
|
|
5258
|
+
* picker uses — so the two read as one design instead of two lookalikes.
|
|
4312
5259
|
*/
|
|
4313
|
-
function
|
|
4314
|
-
var state = React.useState(
|
|
4315
|
-
var
|
|
4316
|
-
var
|
|
4317
|
-
|
|
4318
|
-
var
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
5260
|
+
function ClaudeStyleSettingsSection() {
|
|
5261
|
+
var state = React.useState(readPrefs())
|
|
5262
|
+
var prefs = state[0]
|
|
5263
|
+
var setPrefs = state[1]
|
|
5264
|
+
var errorState = React.useState(null)
|
|
5265
|
+
var error = errorState[0]
|
|
5266
|
+
var setError = errorState[1]
|
|
5267
|
+
|
|
5268
|
+
// The skin's own apply-side writes land here too (a reload, a conflict
|
|
5269
|
+
// re-read), so the page never drifts from what the document says.
|
|
5270
|
+
React.useEffect(function () {
|
|
5271
|
+
var alive = true
|
|
5272
|
+
var unsubscribe = subscribePrefs(function (next) {
|
|
5273
|
+
if (alive) setPrefs(next)
|
|
5274
|
+
})
|
|
5275
|
+
var unsubscribeCopy = onModelCopyLoaded(function () {
|
|
5276
|
+
if (alive) setPrefs(function (p) { return Object.assign({}, p) })
|
|
5277
|
+
})
|
|
5278
|
+
return function () {
|
|
5279
|
+
alive = false
|
|
5280
|
+
unsubscribe()
|
|
5281
|
+
if (unsubscribeCopy) unsubscribeCopy()
|
|
5282
|
+
}
|
|
5283
|
+
}, [])
|
|
4324
5284
|
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
5285
|
+
/**
|
|
5286
|
+
* Apply one change. The control flips immediately and the host write
|
|
5287
|
+
* follows; a refusal re-reads the authoritative value and says so.
|
|
5288
|
+
*/
|
|
5289
|
+
var write = function (patch) {
|
|
5290
|
+
setError(null)
|
|
5291
|
+
setPrefs(Object.assign({}, prefs, patch))
|
|
5292
|
+
savePrefs(patch).then(function (result) {
|
|
5293
|
+
if (result === null) setError(settingsCopy('unavailable', 'The settings store is unavailable, so changes will not be saved.'))
|
|
5294
|
+
})
|
|
5295
|
+
}
|
|
4329
5296
|
|
|
4330
|
-
var
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
React.createElement(
|
|
5297
|
+
var segment = function (options, active, onPick) {
|
|
5298
|
+
var buttons = []
|
|
5299
|
+
for (var i = 0; i < options.length; i++) {
|
|
5300
|
+
buttons.push(React.createElement(
|
|
4334
5301
|
'button',
|
|
4335
5302
|
{
|
|
4336
5303
|
key: options[i].value,
|
|
4337
5304
|
type: 'button',
|
|
4338
|
-
className:
|
|
4339
|
-
'data-active': options[i].value ===
|
|
4340
|
-
'aria-pressed': options[i].value ===
|
|
5305
|
+
className: SEGMENT_CLASS,
|
|
5306
|
+
'data-active': options[i].value === active ? '' : undefined,
|
|
5307
|
+
'aria-pressed': options[i].value === active ? 'true' : 'false',
|
|
4341
5308
|
onClick: (function (value) {
|
|
4342
5309
|
return function () {
|
|
4343
|
-
|
|
5310
|
+
if (value !== active) onPick(value)
|
|
4344
5311
|
}
|
|
4345
5312
|
})(options[i].value),
|
|
4346
5313
|
},
|
|
4347
5314
|
options[i].label,
|
|
4348
|
-
)
|
|
5315
|
+
))
|
|
5316
|
+
}
|
|
5317
|
+
return React.createElement('div', { className: SEGMENTS_CLASS, role: 'group' }, buttons)
|
|
5318
|
+
}
|
|
5319
|
+
|
|
5320
|
+
var toggle = function (on, onPick) {
|
|
5321
|
+
return React.createElement(
|
|
5322
|
+
'button',
|
|
5323
|
+
{
|
|
5324
|
+
type: 'button',
|
|
5325
|
+
className: 'dsh-claude-settings-switch',
|
|
5326
|
+
role: 'switch',
|
|
5327
|
+
'aria-checked': on ? 'true' : 'false',
|
|
5328
|
+
'data-on': on ? '' : undefined,
|
|
5329
|
+
onClick: function () { onPick(!on) },
|
|
5330
|
+
},
|
|
5331
|
+
React.createElement('span', { className: 'dsh-claude-settings-switch-knob' }),
|
|
4349
5332
|
)
|
|
4350
5333
|
}
|
|
4351
5334
|
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
{ className: 'dsh-claude-brand-section' },
|
|
4355
|
-
React.createElement('div', { className: 'dsh-claude-brand-title' }, 'Claude Style'),
|
|
4356
|
-
React.createElement(
|
|
5335
|
+
var row = function (key, title, description, control) {
|
|
5336
|
+
return React.createElement(
|
|
4357
5337
|
'div',
|
|
4358
|
-
{ className: 'dsh-claude-
|
|
5338
|
+
{ className: 'dsh-claude-settings-row', key: key },
|
|
4359
5339
|
React.createElement(
|
|
4360
5340
|
'div',
|
|
4361
|
-
{ className: 'dsh-claude-
|
|
4362
|
-
React.createElement('div', { className: 'dsh-claude-
|
|
4363
|
-
React.createElement(
|
|
4364
|
-
'div',
|
|
4365
|
-
{ className: 'dsh-claude-brand-card-desc' },
|
|
4366
|
-
'Which brand mark the sidebar shows. Claude is the default.',
|
|
4367
|
-
),
|
|
5341
|
+
{ className: 'dsh-claude-settings-row-text' },
|
|
5342
|
+
React.createElement('div', { className: 'dsh-claude-settings-row-title' }, title),
|
|
5343
|
+
React.createElement('div', { className: 'dsh-claude-settings-row-desc' }, description),
|
|
4368
5344
|
),
|
|
4369
|
-
|
|
5345
|
+
control,
|
|
5346
|
+
)
|
|
5347
|
+
}
|
|
5348
|
+
|
|
5349
|
+
var brandOptions = [
|
|
5350
|
+
{ value: BRAND_OFF, label: settingsCopy('brandOff', 'Off') },
|
|
5351
|
+
{ value: BRAND_CLAUDE, label: settingsCopy('brandClaude', 'Claude') },
|
|
5352
|
+
{ value: BRAND_ANTHROPIC, label: settingsCopy('brandAnthropic', 'Anthropic') },
|
|
5353
|
+
]
|
|
5354
|
+
var scopeOptions = [
|
|
5355
|
+
{ value: 'off', label: settingsCopy('scopeOff', 'Off') },
|
|
5356
|
+
{ value: 'hero', label: settingsCopy('scopeHero', 'Home only') },
|
|
5357
|
+
{ value: 'conversation', label: settingsCopy('scopeConversation', 'Conversation only') },
|
|
5358
|
+
{ value: 'all', label: settingsCopy('scopeAll', 'All') },
|
|
5359
|
+
]
|
|
5360
|
+
|
|
5361
|
+
var rows = [
|
|
5362
|
+
row(
|
|
5363
|
+
'brand',
|
|
5364
|
+
settingsCopy('brandTitle', 'Brand mark'),
|
|
5365
|
+
settingsCopy('brandDesc', 'Which brand mark the sidebar shows. "Off" leaves the host\'s own brand area untouched.'),
|
|
5366
|
+
segment(brandOptions, prefs.brand, function (value) { write({ brand: value }) }),
|
|
5367
|
+
),
|
|
5368
|
+
row(
|
|
5369
|
+
'collapseFooter',
|
|
5370
|
+
settingsCopy('collapseTitle', 'Collapse the sidebar settings area'),
|
|
5371
|
+
settingsCopy('collapseDesc', 'Fold the sidebar footer\'s settings entry into the account popover. Off hands the footer back to the host entirely.'),
|
|
5372
|
+
toggle(prefs.collapseFooter, function (value) { write({ collapseFooter: value }) }),
|
|
5373
|
+
),
|
|
5374
|
+
row(
|
|
5375
|
+
'autoPopover',
|
|
5376
|
+
settingsCopy('autoPopoverTitle', 'Open popovers on hover'),
|
|
5377
|
+
settingsCopy('autoPopoverDesc', 'Hover opens the account and model popovers. Off switches them to click-to-open.'),
|
|
5378
|
+
toggle(prefs.autoPopover, function (value) { write({ autoPopover: value }) }),
|
|
5379
|
+
),
|
|
5380
|
+
row(
|
|
5381
|
+
'composerScope',
|
|
5382
|
+
settingsCopy('composerTitle', 'Composer restyle'),
|
|
5383
|
+
settingsCopy('composerDesc', 'Which input area the skin restyles: the new-conversation page, the conversation, or both.'),
|
|
5384
|
+
segment(scopeOptions, prefs.composerScope, function (value) { write({ composerScope: value }) }),
|
|
4370
5385
|
),
|
|
5386
|
+
]
|
|
5387
|
+
|
|
5388
|
+
if (error !== null) {
|
|
5389
|
+
rows.push(React.createElement('div', { className: 'dsh-claude-settings-error', key: 'error' }, error))
|
|
5390
|
+
}
|
|
5391
|
+
|
|
5392
|
+
return React.createElement(
|
|
5393
|
+
'div',
|
|
5394
|
+
{ className: 'dsh-claude-settings' },
|
|
5395
|
+
React.createElement('div', { className: 'dsh-claude-settings-title' }, settingsCopy('title', 'Claude Style')),
|
|
5396
|
+
rows,
|
|
4371
5397
|
)
|
|
4372
5398
|
}
|
|
4373
5399
|
|
|
@@ -4391,6 +5417,7 @@ window.__ModuleLoader__.load({
|
|
|
4391
5417
|
* @returns a disposer that tears the registration down.
|
|
4392
5418
|
*/
|
|
4393
5419
|
function installSettingsSection(ctx) {
|
|
5420
|
+
loadModelCopy()
|
|
4394
5421
|
if (typeof ctx.inject !== 'function') return function () {}
|
|
4395
5422
|
var fiber = ctx.inject(['slots'], function (scope) {
|
|
4396
5423
|
var slots = scope.get('slots')
|
|
@@ -4398,8 +5425,15 @@ window.__ModuleLoader__.load({
|
|
|
4398
5425
|
scope.effect(function () {
|
|
4399
5426
|
return slots.inject('settings.section', function () {
|
|
4400
5427
|
return slots.register(
|
|
4401
|
-
{
|
|
4402
|
-
|
|
5428
|
+
{
|
|
5429
|
+
name: 'settings.section',
|
|
5430
|
+
id: 'claude-style',
|
|
5431
|
+
order: 22,
|
|
5432
|
+
// A function, so the navigation entry localizes once the copy
|
|
5433
|
+
// document has arrived; the literal is the pre-fetch fallback.
|
|
5434
|
+
label: function () { return settingsCopy('title', 'Claude Style') },
|
|
5435
|
+
},
|
|
5436
|
+
ClaudeStyleSettingsSection,
|
|
4403
5437
|
)
|
|
4404
5438
|
})
|
|
4405
5439
|
}, 'dsh-claude-style: settings section')
|
|
@@ -4414,12 +5448,18 @@ window.__ModuleLoader__.load({
|
|
|
4414
5448
|
}
|
|
4415
5449
|
|
|
4416
5450
|
// ============================================================================
|
|
4417
|
-
//
|
|
5451
|
+
// 插件入口与导出 (Plugin Entry & Export)
|
|
4418
5452
|
// ============================================================================
|
|
4419
5453
|
function apply(ctx) {
|
|
4420
5454
|
var body = document.body
|
|
4421
5455
|
body.setAttribute('data-dsh-claude-style', '')
|
|
4422
|
-
|
|
5456
|
+
setHostContext(ctx)
|
|
5457
|
+
loadModelCopy()
|
|
5458
|
+
// Preferences are read asynchronously from the host settings namespace;
|
|
5459
|
+
// applying the defaults first keeps every gated rule in a defined state
|
|
5460
|
+
// for the frames before that read settles, and is exactly the shipped
|
|
5461
|
+
// behaviour when it never does.
|
|
5462
|
+
adoptPrefs(prefs)
|
|
4423
5463
|
|
|
4424
5464
|
var old = document.getElementById(STYLE_ID)
|
|
4425
5465
|
if (old && old.parentElement) old.parentElement.removeChild(old)
|
|
@@ -4430,19 +5470,30 @@ window.__ModuleLoader__.load({
|
|
|
4430
5470
|
style.textContent = CSS
|
|
4431
5471
|
document.head.appendChild(style)
|
|
4432
5472
|
|
|
4433
|
-
var
|
|
5473
|
+
var ui = {}
|
|
5474
|
+
var teardowns = []
|
|
5475
|
+
teardowns.push(installCopy(ctx, ui))
|
|
5476
|
+
teardowns.push(installPermissions(ctx, ui))
|
|
5477
|
+
teardowns.push(installModelPicker(ctx, ui))
|
|
5478
|
+
teardowns.push(installAccountFooter(ctx, ui))
|
|
5479
|
+
teardowns.push(installScheduler(ctx, ui)) // 最后装,回调中惰性读 ui 句柄
|
|
4434
5480
|
var stopSettings = installSettingsSection(ctx)
|
|
4435
5481
|
|
|
4436
5482
|
ctx.effect(function () {
|
|
4437
5483
|
return function () {
|
|
4438
|
-
|
|
5484
|
+
for (var i = teardowns.length - 1; i >= 0; i--) {
|
|
5485
|
+
try { teardowns[i]() } catch (error) { /* one teardown must not block the rest */ }
|
|
5486
|
+
}
|
|
4439
5487
|
stopSettings()
|
|
5488
|
+
setHostContext(null)
|
|
4440
5489
|
body.removeAttribute('data-dsh-claude-style')
|
|
4441
5490
|
body.removeAttribute(BRAND_ATTR)
|
|
5491
|
+
body.removeAttribute(FOOTER_ATTR)
|
|
5492
|
+
body.removeAttribute(COMPOSER_ATTR)
|
|
4442
5493
|
var el = document.getElementById(STYLE_ID)
|
|
4443
5494
|
if (el) el.remove()
|
|
4444
5495
|
}
|
|
4445
|
-
}, 'dsh-claude-style: Claude Code
|
|
5496
|
+
}, 'dsh-claude-style: Claude Code desktop theme')
|
|
4446
5497
|
}
|
|
4447
5498
|
|
|
4448
5499
|
exports.apply = apply
|