dsh-mega-chat-nav 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.en.md +149 -0
- package/README.md +149 -0
- package/cordis.patch.yml +4 -0
- package/lib/client/NavOverlay.js +35 -0
- package/lib/client/NavRail.js +12 -0
- package/lib/client/QuestionNavSettingsTab.js +26 -0
- package/lib/client/QuestionNavStrip.js +555 -0
- package/lib/client/components/ConfigPanel.js +14 -0
- package/lib/client/components/DotRail.js +62 -0
- package/lib/client/components/NavOverlay.js +121 -0
- package/lib/client/components/NavRail.js +97 -0
- package/lib/client/components/RailDispatch.js +22 -0
- package/lib/client/components/RailHost.js +79 -0
- package/lib/client/components/SearchBox.js +66 -0
- package/lib/client/components/SettingsPage.js +46 -0
- package/lib/client/components/StandaloneSettings.js +16 -0
- package/lib/client/components/codex/CodexRail.js +139 -0
- package/lib/client/components/deepseek/DeepseekRail.js +264 -0
- package/lib/client/components/minimal/MinimalRail.js +135 -0
- package/lib/client/components/minimal/cards.js +32 -0
- package/lib/client/components/minimal/dot.js +11 -0
- package/lib/client/components/minimal/hint.js +30 -0
- package/lib/client/components/minimal/paging.js +5 -0
- package/lib/client/components/minimal/quick-settings.js +28 -0
- package/lib/client/components/minimal/search.js +67 -0
- package/lib/client/components/minimal/useRail.js +716 -0
- package/lib/client/components/rail/cards.js +32 -0
- package/lib/client/components/rail/hint.js +30 -0
- package/lib/client/components/rail/paging.js +5 -0
- package/lib/client/components/rail/quick-settings.js +28 -0
- package/lib/client/components/rail/search.js +76 -0
- package/lib/client/components/rail/useRail.js +845 -0
- package/lib/client/components/settings/SettingsPage.js +46 -0
- package/lib/client/components/settings/SettingsTab.js +17 -0
- package/lib/client/components/settings/StandaloneSettings.js +16 -0
- package/lib/client/components/shared/Cascade.js +26 -0
- package/lib/client/components/shared/ConfigPanel.js +27 -0
- package/lib/client/components/shared/Dot.js +8 -0
- package/lib/client/components/shared/Hint.js +5 -0
- package/lib/client/components/shared/PagingButton.js +5 -0
- package/lib/client/components/shared/RailShell.js +78 -0
- package/lib/client/components/shared/SearchBox.js +63 -0
- package/lib/client/components/shared/hooks.js +427 -0
- package/lib/client/components/shared/types.js +1 -0
- package/lib/client/config.js +1 -0
- package/lib/client/engines/jump.js +34 -0
- package/lib/client/engines/useAtBottom.js +25 -0
- package/lib/client/engines/useJump.js +40 -0
- package/lib/client/engines/useScrollSpy.js +88 -0
- package/lib/client/hooks.js +11 -0
- package/lib/client/index.js +312 -0
- package/lib/client/jump.js +255 -0
- package/lib/client/locales.js +142 -0
- package/lib/client/pure.js +61 -0
- package/lib/client/settings.js +369 -0
- package/lib/client/virtual/VirtualList.js +21 -0
- package/lib/client.js +3213 -0
- package/lib/compat.js +145 -0
- package/lib/config.js +37 -0
- package/lib/core/active-dot.js +17 -0
- package/lib/core/align.js +9 -0
- package/lib/core/config.js +37 -0
- package/lib/core/focus.js +38 -0
- package/lib/core/jump.js +98 -0
- package/lib/core/logic/active-dot.js +16 -0
- package/lib/core/logic/focus.js +34 -0
- package/lib/core/logic/jump.js +188 -0
- package/lib/core/logic/nodes.js +59 -0
- package/lib/core/model/nav-item.js +1 -0
- package/lib/core/model/turns.js +73 -0
- package/lib/core/nav-item.js +1 -0
- package/lib/core/nodes.js +57 -0
- package/lib/core/page-size.js +7 -0
- package/lib/core/question-entry.js +1 -0
- package/lib/core/time.js +23 -0
- package/lib/core/turn-dots.js +85 -0
- package/lib/core/utils/measure.js +24 -0
- package/lib/core/utils/time.js +26 -0
- package/lib/index.js +64 -0
- package/lib/nav-item.js +1 -0
- package/lib/nodes.js +59 -0
- package/lib/projection.js +126 -0
- package/lib/schema.js +26 -0
- package/lib/search.js +285 -0
- package/lib/settings.js +89 -0
- package/lib/types/client/NavOverlay.d.ts +18 -0
- package/lib/types/client/NavRail.d.ts +7 -0
- package/lib/types/client/QuestionNavSettingsTab.d.ts +16 -0
- package/lib/types/client/QuestionNavStrip.d.ts +48 -0
- package/lib/types/client/components/ConfigPanel.d.ts +14 -0
- package/lib/types/client/components/DotRail.d.ts +15 -0
- package/lib/types/client/components/NavOverlay.d.ts +30 -0
- package/lib/types/client/components/NavRail.d.ts +16 -0
- package/lib/types/client/components/RailDispatch.d.ts +8 -0
- package/lib/types/client/components/RailHost.d.ts +27 -0
- package/lib/types/client/components/SearchBox.d.ts +9 -0
- package/lib/types/client/components/SettingsPage.d.ts +9 -0
- package/lib/types/client/components/StandaloneSettings.d.ts +13 -0
- package/lib/types/client/components/codex/CodexRail.d.ts +3 -0
- package/lib/types/client/components/deepseek/DeepseekRail.d.ts +3 -0
- package/lib/types/client/components/minimal/MinimalRail.d.ts +8 -0
- package/lib/types/client/components/minimal/cards.d.ts +19 -0
- package/lib/types/client/components/minimal/dot.d.ts +14 -0
- package/lib/types/client/components/minimal/hint.d.ts +11 -0
- package/lib/types/client/components/minimal/paging.d.ts +10 -0
- package/lib/types/client/components/minimal/quick-settings.d.ts +8 -0
- package/lib/types/client/components/minimal/search.d.ts +27 -0
- package/lib/types/client/components/minimal/useRail.d.ts +90 -0
- package/lib/types/client/components/rail/cards.d.ts +19 -0
- package/lib/types/client/components/rail/hint.d.ts +11 -0
- package/lib/types/client/components/rail/paging.d.ts +10 -0
- package/lib/types/client/components/rail/quick-settings.d.ts +8 -0
- package/lib/types/client/components/rail/search.d.ts +34 -0
- package/lib/types/client/components/rail/useRail.d.ts +132 -0
- package/lib/types/client/components/settings/SettingsPage.d.ts +9 -0
- package/lib/types/client/components/settings/SettingsTab.d.ts +6 -0
- package/lib/types/client/components/settings/StandaloneSettings.d.ts +13 -0
- package/lib/types/client/components/shared/Cascade.d.ts +14 -0
- package/lib/types/client/components/shared/ConfigPanel.d.ts +8 -0
- package/lib/types/client/components/shared/Dot.d.ts +17 -0
- package/lib/types/client/components/shared/Hint.d.ts +6 -0
- package/lib/types/client/components/shared/PagingButton.d.ts +10 -0
- package/lib/types/client/components/shared/RailShell.d.ts +43 -0
- package/lib/types/client/components/shared/SearchBox.d.ts +18 -0
- package/lib/types/client/components/shared/hooks.d.ts +64 -0
- package/lib/types/client/components/shared/types.d.ts +101 -0
- package/lib/types/client/config.d.ts +9 -0
- package/lib/types/client/engines/jump.d.ts +17 -0
- package/lib/types/client/engines/useAtBottom.d.ts +1 -0
- package/lib/types/client/engines/useJump.d.ts +16 -0
- package/lib/types/client/engines/useScrollSpy.d.ts +12 -0
- package/lib/types/client/hooks.d.ts +7 -0
- package/lib/types/client/index.d.ts +31 -0
- package/lib/types/client/jump.d.ts +47 -0
- package/lib/types/client/locales.d.ts +142 -0
- package/lib/types/client/pure.d.ts +21 -0
- package/lib/types/client/settings.d.ts +173 -0
- package/lib/types/client/virtual/VirtualList.d.ts +15 -0
- package/lib/types/compat.d.ts +44 -0
- package/lib/types/config.d.ts +44 -0
- package/lib/types/core/active-dot.d.ts +15 -0
- package/lib/types/core/align.d.ts +10 -0
- package/lib/types/core/config.d.ts +44 -0
- package/lib/types/core/focus.d.ts +24 -0
- package/lib/types/core/jump.d.ts +39 -0
- package/lib/types/core/logic/active-dot.d.ts +15 -0
- package/lib/types/core/logic/focus.d.ts +22 -0
- package/lib/types/core/logic/jump.d.ts +39 -0
- package/lib/types/core/logic/nodes.d.ts +48 -0
- package/lib/types/core/model/nav-item.d.ts +12 -0
- package/lib/types/core/model/turns.d.ts +30 -0
- package/lib/types/core/nav-item.d.ts +12 -0
- package/lib/types/core/nodes.d.ts +43 -0
- package/lib/types/core/page-size.d.ts +8 -0
- package/lib/types/core/question-entry.d.ts +12 -0
- package/lib/types/core/time.d.ts +4 -0
- package/lib/types/core/turn-dots.d.ts +29 -0
- package/lib/types/core/utils/measure.d.ts +12 -0
- package/lib/types/core/utils/time.d.ts +4 -0
- package/lib/types/index.d.ts +4 -0
- package/lib/types/nav-item.d.ts +12 -0
- package/lib/types/nodes.d.ts +48 -0
- package/lib/types/projection.d.ts +71 -0
- package/lib/types/schema.d.ts +37 -0
- package/lib/types/search.d.ts +42 -0
- package/lib/types/settings.d.ts +99 -0
- package/package.json +71 -0
- package/src/client/components/RailDispatch.tsx +27 -0
- package/src/client/components/codex/CodexRail.tsx +348 -0
- package/src/client/components/deepseek/DeepseekRail.tsx +522 -0
- package/src/client/components/minimal/MinimalRail.tsx +324 -0
- package/src/client/components/minimal/dot.tsx +32 -0
- package/src/client/components/rail/cards.tsx +102 -0
- package/src/client/components/rail/hint.tsx +50 -0
- package/src/client/components/rail/paging.tsx +26 -0
- package/src/client/components/rail/quick-settings.tsx +130 -0
- package/src/client/components/rail/search.tsx +147 -0
- package/src/client/components/rail/useRail.ts +906 -0
- package/src/client/components/settings/SettingsPage.tsx +198 -0
- package/src/client/components/settings/StandaloneSettings.tsx +28 -0
- package/src/client/components/shared/types.ts +99 -0
- package/src/client/index.ts +388 -0
- package/src/client/jump.ts +293 -0
- package/src/client/locales.ts +143 -0
- package/src/client/settings.ts +482 -0
- package/src/client/styles.css +1580 -0
- package/src/compat.ts +161 -0
- package/src/index.ts +66 -0
- package/src/projection.ts +174 -0
- package/src/search.ts +291 -0
- package/src/settings.ts +169 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// 完整配置页(mega-settings 成员页与自足入口共用)
|
|
2
|
+
import { useEffect, useState, type ReactNode } from 'react'
|
|
3
|
+
import { ALIGN_OPTIONS, CARD_ITEM_OPTIONS, CARD_OPTIONS, MARK_TONE_OPTIONS, SCROLL_OPTIONS, SEARCH_SCOPE_OPTIONS, SHOW_OPTIONS, STYLE_OPTIONS, STYLE_CAPABILITIES, type MarkTone } from '../../settings.ts'
|
|
4
|
+
import type { NavInjected, Translate } from '../shared/types.ts'
|
|
5
|
+
|
|
6
|
+
export interface SettingsPageProps {
|
|
7
|
+
injected: NavInjected
|
|
8
|
+
t: Translate
|
|
9
|
+
/** 已收纳至 mega-settings 时仅显示提示(自足入口让位) */
|
|
10
|
+
hosted?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function Seg<T extends string | number>(props: { options: readonly T[]; value: T; labels: Record<string, string>; onPick: (v: T) => void }): ReactNode {
|
|
14
|
+
return (
|
|
15
|
+
<div className="mgcn-segmented" role="radiogroup">
|
|
16
|
+
{props.options.map((o) => (
|
|
17
|
+
<button
|
|
18
|
+
key={String(o)}
|
|
19
|
+
type="button"
|
|
20
|
+
role="radio"
|
|
21
|
+
aria-checked={props.value === o}
|
|
22
|
+
className={props.value === o ? 'mgcn-segment mgcn-segmentActive' : 'mgcn-segment'}
|
|
23
|
+
onClick={() => props.onPick(o)}
|
|
24
|
+
>
|
|
25
|
+
{props.labels[String(o)] ?? String(o)}
|
|
26
|
+
</button>
|
|
27
|
+
))}
|
|
28
|
+
</div>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function Field({ label, desc, children }: { label: string; desc?: string; children: ReactNode }): ReactNode {
|
|
33
|
+
return (
|
|
34
|
+
<div className="mgcn-settingsRow">
|
|
35
|
+
<div className="mgcn-settingsLabel">
|
|
36
|
+
<p className="mgcn-settingsTitle">{label}</p>
|
|
37
|
+
{desc !== undefined ? <p className="mgcn-settingsDesc">{desc}</p> : null}
|
|
38
|
+
</div>
|
|
39
|
+
<div className="mgcn-settingsControl">{children}</div>
|
|
40
|
+
</div>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function useSettingsTick(subscribe: NavInjected['subscribeSettings']): void {
|
|
45
|
+
const [, bump] = useState(0)
|
|
46
|
+
useEffect(() => subscribe(() => bump((n) => n + 1)), [subscribe])
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function SettingsPage(props: SettingsPageProps): ReactNode {
|
|
50
|
+
const { injected, t, hosted } = props
|
|
51
|
+
useSettingsTick(injected.subscribeSettings)
|
|
52
|
+
if (hosted === true) {
|
|
53
|
+
return <div className="mgcn-settings">{t('settings.hosted')}</div>
|
|
54
|
+
}
|
|
55
|
+
return (
|
|
56
|
+
<div className="mgcn-settings">
|
|
57
|
+
<Field label={t('config.style')}>
|
|
58
|
+
<Seg
|
|
59
|
+
options={STYLE_OPTIONS}
|
|
60
|
+
value={injected.style()}
|
|
61
|
+
labels={{ minimal: t('config.style.minimal'), codex: t('config.style.codex'), deepseek: t('config.style.deepseek') }}
|
|
62
|
+
onPick={(v) => injected.setStyle(v)}
|
|
63
|
+
/>
|
|
64
|
+
</Field>
|
|
65
|
+
<Field label={t('config.railOffset')} desc={t('config.railOffset.desc')}>
|
|
66
|
+
<div className="mgcn-sliderRow">
|
|
67
|
+
<input
|
|
68
|
+
type="range"
|
|
69
|
+
min="0"
|
|
70
|
+
max="32"
|
|
71
|
+
step="1"
|
|
72
|
+
value={injected.railOffset()}
|
|
73
|
+
onChange={(e) => injected.setRailOffset(Number(e.target.value))}
|
|
74
|
+
/>
|
|
75
|
+
<span className="mgcn-sliderValue">{injected.railOffset()}px</span>
|
|
76
|
+
</div>
|
|
77
|
+
</Field>
|
|
78
|
+
<Field label={t('config.align')} desc={t('settings.align.desc')}>
|
|
79
|
+
<Seg
|
|
80
|
+
options={ALIGN_OPTIONS}
|
|
81
|
+
value={injected.align()}
|
|
82
|
+
labels={{ left: t('settings.align.left'), right: t('settings.align.right') }}
|
|
83
|
+
onPick={(v) => injected.setAlign(v)}
|
|
84
|
+
/>
|
|
85
|
+
</Field>
|
|
86
|
+
<Field label={t('config.scrollBehavior')} desc={t('config.scrollBehavior.desc')}>
|
|
87
|
+
<Seg
|
|
88
|
+
options={SCROLL_OPTIONS}
|
|
89
|
+
value={injected.scrollBehavior()}
|
|
90
|
+
labels={{ smooth: t('config.scrollBehavior.smooth'), instant: t('config.scrollBehavior.instant') }}
|
|
91
|
+
onPick={(v) => injected.setScrollMode(v)}
|
|
92
|
+
/>
|
|
93
|
+
</Field>
|
|
94
|
+
{STYLE_CAPABILITIES[injected.style()].hoverCards ? (
|
|
95
|
+
<>
|
|
96
|
+
<Field label={t('config.cardCount')} desc={t('config.cardCount.desc')}>
|
|
97
|
+
<Seg
|
|
98
|
+
options={CARD_OPTIONS}
|
|
99
|
+
value={injected.cardCount()}
|
|
100
|
+
labels={{ 1: '1', 3: '3', 5: '5' }}
|
|
101
|
+
onPick={(v) => injected.setCardCount(v)}
|
|
102
|
+
/>
|
|
103
|
+
</Field>
|
|
104
|
+
<Field label={t('config.cardItems')} desc={t('config.cardItems.desc')}>
|
|
105
|
+
<div className="mgcn-checkGroup">
|
|
106
|
+
{CARD_ITEM_OPTIONS.map((item) => {
|
|
107
|
+
const on = injected.cardItems().includes(item)
|
|
108
|
+
return (
|
|
109
|
+
<label key={item} className="mgcn-checkItem">
|
|
110
|
+
<input
|
|
111
|
+
type="checkbox"
|
|
112
|
+
checked={on}
|
|
113
|
+
onChange={(e) => {
|
|
114
|
+
const items = e.target.checked
|
|
115
|
+
? [...injected.cardItems(), item]
|
|
116
|
+
: injected.cardItems().filter((x) => x !== item)
|
|
117
|
+
injected.setCardItems(items)
|
|
118
|
+
}}
|
|
119
|
+
/>
|
|
120
|
+
<span>{t('config.cardItems.' + item)}</span>
|
|
121
|
+
</label>
|
|
122
|
+
)
|
|
123
|
+
})}
|
|
124
|
+
</div>
|
|
125
|
+
</Field>
|
|
126
|
+
</>
|
|
127
|
+
) : null}
|
|
128
|
+
|
|
129
|
+
{injected.style() === 'codex' ? (
|
|
130
|
+
<Field label={t('config.markTone')} desc={t('config.markTone.desc')}>
|
|
131
|
+
<Seg
|
|
132
|
+
options={MARK_TONE_OPTIONS}
|
|
133
|
+
value={injected.markTone()}
|
|
134
|
+
labels={{ soft: t('config.markTone.soft'), deep: t('config.markTone.deep') }}
|
|
135
|
+
onPick={(v: MarkTone) => injected.setMarkTone(v)}
|
|
136
|
+
/>
|
|
137
|
+
</Field>
|
|
138
|
+
) : null}
|
|
139
|
+
|
|
140
|
+
<Field label={t('config.searchScopes')} desc={t('config.searchScopes.desc')}>
|
|
141
|
+
<div className="mgcn-checkGroup">
|
|
142
|
+
{SEARCH_SCOPE_OPTIONS.map((scope) => {
|
|
143
|
+
const on = injected.searchScopes().includes(scope)
|
|
144
|
+
const locked = scope === 'user' // 用户必选,不可取消
|
|
145
|
+
return (
|
|
146
|
+
<label key={scope} className="mgcn-checkItem">
|
|
147
|
+
<input
|
|
148
|
+
type="checkbox"
|
|
149
|
+
checked={on}
|
|
150
|
+
disabled={locked}
|
|
151
|
+
onChange={(e) => {
|
|
152
|
+
const items = e.target.checked
|
|
153
|
+
? [...injected.searchScopes(), scope]
|
|
154
|
+
: injected.searchScopes().filter((x) => x !== scope)
|
|
155
|
+
injected.setSearchScopes(items)
|
|
156
|
+
}}
|
|
157
|
+
/>
|
|
158
|
+
<span>{t('config.searchScopes.' + scope)}</span>
|
|
159
|
+
</label>
|
|
160
|
+
)
|
|
161
|
+
})}
|
|
162
|
+
</div>
|
|
163
|
+
</Field>
|
|
164
|
+
<Field label={t('config.showQuickSettings')}>
|
|
165
|
+
<ModeSeg value={injected.showQuickSettings()} onChange={(v) => injected.setShowQuickSettings(v)} t={t} />
|
|
166
|
+
</Field>
|
|
167
|
+
<Field label={t('config.showSearch')}>
|
|
168
|
+
<ModeSeg value={injected.showSearch()} onChange={(v) => injected.setShowSearch(v)} t={t} />
|
|
169
|
+
</Field>
|
|
170
|
+
<Field label={t('config.showFavorites')}>
|
|
171
|
+
<ModeSeg value={injected.showFavorites()} onChange={(v) => injected.setShowFavorites(v)} t={t} />
|
|
172
|
+
</Field>
|
|
173
|
+
<Field label={t('config.showCount')}>
|
|
174
|
+
<ModeSeg value={injected.showCount()} onChange={(v) => injected.setShowCount(v)} t={t} />
|
|
175
|
+
</Field>
|
|
176
|
+
{STYLE_CAPABILITIES[injected.style()].paging ? (
|
|
177
|
+
<Field label={t('config.showPaging')}>
|
|
178
|
+
<ModeSeg value={injected.showPaging()} onChange={(v) => injected.setShowPaging(v)} t={t} />
|
|
179
|
+
</Field>
|
|
180
|
+
) : null}
|
|
181
|
+
</div>
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function ModeSeg({ value, onChange, t }: { value: 'show' | 'peek' | 'hide'; onChange(v: 'show' | 'peek' | 'hide'): void; t: Translate }): ReactNode {
|
|
186
|
+
return (
|
|
187
|
+
<Seg
|
|
188
|
+
options={SHOW_OPTIONS}
|
|
189
|
+
value={value}
|
|
190
|
+
labels={{
|
|
191
|
+
show: t('config.showMode.show'),
|
|
192
|
+
peek: t('config.showMode.peek'),
|
|
193
|
+
hide: t('config.showMode.hide'),
|
|
194
|
+
}}
|
|
195
|
+
onPick={(v) => onChange(v)}
|
|
196
|
+
/>
|
|
197
|
+
)
|
|
198
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// 自足完整配置入口:宿主(mega-settings)已收纳时让位提示,否则渲染完整配置页
|
|
2
|
+
import { useEffect, useState, type ReactNode } from 'react'
|
|
3
|
+
import type { NavInjected, Translate } from '../shared/types.ts'
|
|
4
|
+
import { SettingsPage } from './SettingsPage.tsx'
|
|
5
|
+
|
|
6
|
+
interface SlotsLike {
|
|
7
|
+
entries?(key: string): readonly unknown[]
|
|
8
|
+
subscribe?(key: string, fn: () => void): () => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface StandaloneSettingsProps {
|
|
12
|
+
injected: NavInjected
|
|
13
|
+
slots?: SlotsLike
|
|
14
|
+
t: Translate
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function StandaloneSettings(props: StandaloneSettingsProps): ReactNode {
|
|
18
|
+
const [hosted, setHosted] = useState(false)
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
const check = () => {
|
|
21
|
+
const n = props.slots?.entries?.('mega.settings.member')?.length ?? 0
|
|
22
|
+
setHosted(n > 0)
|
|
23
|
+
}
|
|
24
|
+
check()
|
|
25
|
+
return props.slots?.subscribe?.('mega.settings.member', check)
|
|
26
|
+
}, [props.slots])
|
|
27
|
+
return <SettingsPage injected={props.injected} t={props.t} hosted={hosted} />
|
|
28
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// 跨风格契约:注入面 / 数据形态 / 工具面(仅此——风格实现各自自治)
|
|
2
|
+
import type { BandHeight, CardCount, CardItem, MarkTone, NavStyle, RailAlign, ScrollMode, SearchScope, ShowMode } from '../../settings.ts'
|
|
3
|
+
|
|
4
|
+
/** 会话投影 face 最小面 */
|
|
5
|
+
export interface ObservableFace {
|
|
6
|
+
getSnapshot: () => unknown
|
|
7
|
+
subscribe: (listener: () => void) => () => void
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** 回合标记:某回合的提问组(或一条未入投影的活提问) */
|
|
11
|
+
export interface RailMarker {
|
|
12
|
+
/** 归属回合;活提问(投影未收)为 null */
|
|
13
|
+
readonly turn: number | null
|
|
14
|
+
/** 跳转锚点:组内首问的聊天 key */
|
|
15
|
+
readonly key: string
|
|
16
|
+
/** 首问锚点序号 */
|
|
17
|
+
readonly seq: number
|
|
18
|
+
/** 首问时间 */
|
|
19
|
+
readonly time: number
|
|
20
|
+
/** 组内全部提问文本(按序) */
|
|
21
|
+
readonly texts: readonly string[]
|
|
22
|
+
/** 组内全部聊天 key(活合并去重用) */
|
|
23
|
+
readonly members: readonly string[]
|
|
24
|
+
/** 该轮性能指标(投影附带;缺数据时省略) */
|
|
25
|
+
readonly metrics?: { durationMs: number; firstTokenMs: number; tokensPerSec: number }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** 注册注入面(client/index.ts 装配;各风格经此拿数据与动作) */
|
|
29
|
+
export interface NavInjected {
|
|
30
|
+
readQuestions: (sessionId: string) => { key: string; anchorSeq: number; seq: number; time: number; text: string }[]
|
|
31
|
+
subscribeList: (cb: () => void) => () => void
|
|
32
|
+
subscribeContent: (sessionId: string, cb: () => void) => () => void
|
|
33
|
+
questionProjection: (sessionId: string) => ObservableFace | undefined
|
|
34
|
+
/** seq:目标轮序号(方向判定);currentSeq:当前阅读位置序号(可选,下方判定优先用) */
|
|
35
|
+
jump: (sessionId: string, key: string, seq?: number, currentSeq?: number) => void
|
|
36
|
+
style: () => NavStyle
|
|
37
|
+
setStyle: (style: NavStyle) => void
|
|
38
|
+
align: () => RailAlign
|
|
39
|
+
subscribeSettings: (cb: () => void) => () => void
|
|
40
|
+
setAlign: (align: RailAlign) => void
|
|
41
|
+
bandHeight: () => BandHeight
|
|
42
|
+
setBandHeight: (band: BandHeight) => void
|
|
43
|
+
scrollBehavior: () => ScrollMode
|
|
44
|
+
setScrollMode: (mode: ScrollMode) => void
|
|
45
|
+
showCount: () => ShowMode
|
|
46
|
+
setShowCount: (mode: ShowMode) => void
|
|
47
|
+
showSearch: () => ShowMode
|
|
48
|
+
setShowSearch: (mode: ShowMode) => void
|
|
49
|
+
showQuickSettings: () => ShowMode
|
|
50
|
+
setShowQuickSettings: (mode: ShowMode) => void
|
|
51
|
+
showFavorites: () => ShowMode
|
|
52
|
+
setShowFavorites: (mode: ShowMode) => void
|
|
53
|
+
showPaging: () => ShowMode
|
|
54
|
+
setShowPaging: (mode: ShowMode) => void
|
|
55
|
+
searchScopes: () => SearchScope[]
|
|
56
|
+
setSearchScopes: (scopes: SearchScope[]) => void
|
|
57
|
+
railOffset: () => number
|
|
58
|
+
setRailOffset: (offset: number) => void
|
|
59
|
+
cardCount: () => CardCount
|
|
60
|
+
setCardCount: (count: CardCount) => void
|
|
61
|
+
cardItems: () => CardItem[]
|
|
62
|
+
setCardItems: (items: CardItem[]) => void
|
|
63
|
+
markTone: () => MarkTone
|
|
64
|
+
setMarkTone: (tone: MarkTone) => void
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** 悬停聚焦窗口项 */
|
|
68
|
+
export interface FocusWindowItem {
|
|
69
|
+
dot: RailMarker
|
|
70
|
+
distance: number
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** 聚焦状态:卡片呈现所需几何 */
|
|
74
|
+
export interface FocusState {
|
|
75
|
+
key: string
|
|
76
|
+
items: FocusWindowItem[]
|
|
77
|
+
centerY: number
|
|
78
|
+
left?: number
|
|
79
|
+
right?: number
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** 会话列表最小面(useSessions selector) */
|
|
83
|
+
export interface SessionListLike {
|
|
84
|
+
current?: unknown
|
|
85
|
+
byId?: Record<string, { blank?: boolean }>
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** 翻译函数面 */
|
|
89
|
+
export type Translate = (key: string, vars?: Record<string, string | number>) => string
|
|
90
|
+
|
|
91
|
+
/** 会话选择器面(useSessions 最小面,宿主按风格组件注入) */
|
|
92
|
+
export type SessionSelector = <S>(selector: (s: SessionListLike) => S) => S
|
|
93
|
+
|
|
94
|
+
/** 风格组件统一 props 面(各风格自治实现,但入参一致) */
|
|
95
|
+
export interface RailProps {
|
|
96
|
+
injected: NavInjected | undefined
|
|
97
|
+
useSessions?: SessionSelector
|
|
98
|
+
t: Translate
|
|
99
|
+
}
|