tavern-harness 0.1.20 → 0.1.21
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 +21 -0
- package/package.json +1 -1
- package/src/App.tsx +44 -2
- package/src/core/i18n.ts +6 -0
- package/src/generated/changelog.json +31 -1
- package/src/theme/global.css +61 -3
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,26 @@
|
|
|
3
3
|
> 本文件由 `scripts/changelog.mjs` 从 `changelog/v*.md` 生成,请勿手动编辑。
|
|
4
4
|
> 版本对比链接见文末;源文件位于仓库 `changelog/` 目录。
|
|
5
5
|
|
|
6
|
+
## [0.1.21] - 2026-10-26
|
|
7
|
+
|
|
8
|
+
### 中文
|
|
9
|
+
|
|
10
|
+
#### 改进
|
|
11
|
+
|
|
12
|
+
- 移动端会话头部的操作按钮收进「更多操作」菜单(工作区文件、编辑对话、重置对话、导出游玩记录、删除对话),头部不再拥挤;主题切换按钮仍然直接显示
|
|
13
|
+
- 移动端会话标题可用的横向空间明显变大,长标题能显示更多内容
|
|
14
|
+
- 会话列表中的标题和副标题过长时改为末尾渐隐,不再用省略号生硬截断
|
|
15
|
+
- 会话头部的上下文用量标签字号略微收小,和标题搭配更协调
|
|
16
|
+
|
|
17
|
+
### English
|
|
18
|
+
|
|
19
|
+
#### Changed
|
|
20
|
+
|
|
21
|
+
- On mobile, session header actions now collapse into a "More actions" menu (workspace files, edit, reset, export gameplay, delete), so the header is no longer cramped; the theme toggle stays one tap away
|
|
22
|
+
- Mobile session titles get noticeably more horizontal room, so long titles reveal more of their text
|
|
23
|
+
- Long session list titles and subtitles now fade out at the end instead of being cut off with an ellipsis
|
|
24
|
+
- The context usage badge in the session header uses a slightly smaller font so it sits better next to the title
|
|
25
|
+
|
|
6
26
|
## [0.1.20] - 2026-10-26
|
|
7
27
|
|
|
8
28
|
### 中文
|
|
@@ -588,6 +608,7 @@
|
|
|
588
608
|
- Vite + React + Zustand + Dexie stack with browser-side local persistence
|
|
589
609
|
|
|
590
610
|
<!-- 链接定义 -->
|
|
611
|
+
[0.1.21]: https://github.com/Rannichan/Tavern-Harness/compare/v0.1.20...v0.1.21
|
|
591
612
|
[0.1.20]: https://github.com/Rannichan/Tavern-Harness/compare/v0.1.19...v0.1.20
|
|
592
613
|
[0.1.19]: https://github.com/Rannichan/Tavern-Harness/compare/v0.1.18...v0.1.19
|
|
593
614
|
[0.1.18]: https://github.com/Rannichan/Tavern-Harness/compare/v0.1.17...v0.1.18
|
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -327,6 +327,8 @@ function SessionHeader({
|
|
|
327
327
|
const [confirmDelete, setConfirmDelete] = useState(false);
|
|
328
328
|
const [exportOpen, setExportOpen] = useState(false);
|
|
329
329
|
const [showWorkspace, setShowWorkspace] = useState(false);
|
|
330
|
+
const [showMobileActions, setShowMobileActions] = useState(false);
|
|
331
|
+
const mobileActionsRef = useRef<HTMLDivElement>(null);
|
|
330
332
|
|
|
331
333
|
const messages = useStore((s) => s.messages[session.id!] ?? []);
|
|
332
334
|
const contextTokens = useMemo(() => {
|
|
@@ -350,6 +352,17 @@ function SessionHeader({
|
|
|
350
352
|
|| (themeMode === 'system' && document.documentElement.dataset.theme === 'dark');
|
|
351
353
|
const toggleTheme = () => void setSettings({ themeMode: isDarkTheme ? 'light' : 'dark' });
|
|
352
354
|
|
|
355
|
+
useEffect(() => {
|
|
356
|
+
if (!showMobileActions) return;
|
|
357
|
+
const closeOnOutsidePointerDown = (event: PointerEvent) => {
|
|
358
|
+
if (!mobileActionsRef.current?.contains(event.target as Node)) {
|
|
359
|
+
setShowMobileActions(false);
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
document.addEventListener('pointerdown', closeOnOutsidePointerDown);
|
|
363
|
+
return () => document.removeEventListener('pointerdown', closeOnOutsidePointerDown);
|
|
364
|
+
}, [showMobileActions]);
|
|
365
|
+
|
|
353
366
|
return (
|
|
354
367
|
<div className="chat-header">
|
|
355
368
|
<SessionVisual mode={session.mode} npcName={npcRef?.name ?? undefined} hue={npcRef?.avatarColorOrdinal ?? 0} imageUrl={npcRef?.avatarDataUrl} members={session.mode === 'GROUP' ? groupMemberAvatars : undefined} size="lg" />
|
|
@@ -361,7 +374,7 @@ function SessionHeader({
|
|
|
361
374
|
</div>
|
|
362
375
|
)}
|
|
363
376
|
</div>
|
|
364
|
-
<div className="chat-actions">
|
|
377
|
+
<div className="chat-actions" ref={mobileActionsRef}>
|
|
365
378
|
<button className="btn-ghost icon-tooltip" title={t(usesPublicWorkspace ? 'header.workspaceRootHint' : 'header.workspaceHint')} onClick={() => setShowWorkspace(true)}>
|
|
366
379
|
<Icon name="folder" size={17} />
|
|
367
380
|
</button>
|
|
@@ -378,7 +391,17 @@ function SessionHeader({
|
|
|
378
391
|
<Icon name="trash" size={17} />
|
|
379
392
|
</button>
|
|
380
393
|
<button
|
|
381
|
-
className="btn-ghost icon-tooltip"
|
|
394
|
+
className="btn-ghost icon-tooltip chat-actions-more"
|
|
395
|
+
type="button"
|
|
396
|
+
title={t('header.moreActions')}
|
|
397
|
+
aria-label={t('header.moreActions')}
|
|
398
|
+
aria-expanded={showMobileActions}
|
|
399
|
+
onClick={() => setShowMobileActions(!showMobileActions)}
|
|
400
|
+
>
|
|
401
|
+
<Icon name="more" size={18} />
|
|
402
|
+
</button>
|
|
403
|
+
<button
|
|
404
|
+
className="btn-ghost icon-tooltip chat-theme-toggle"
|
|
382
405
|
type="button"
|
|
383
406
|
title={t(isDarkTheme ? 'header.switchToLightTip' : 'header.switchToDarkTip')}
|
|
384
407
|
aria-label={t(isDarkTheme ? 'header.switchToLightTip' : 'header.switchToDarkTip')}
|
|
@@ -386,6 +409,25 @@ function SessionHeader({
|
|
|
386
409
|
>
|
|
387
410
|
<Icon name={isDarkTheme ? 'sun' : 'moon'} size={17} />
|
|
388
411
|
</button>
|
|
412
|
+
{showMobileActions && (
|
|
413
|
+
<div className="chat-actions-menu card">
|
|
414
|
+
<button onClick={() => { setShowWorkspace(true); setShowMobileActions(false); }}>
|
|
415
|
+
<Icon name="folder" size={15} /> {t('header.workspaceAction')}
|
|
416
|
+
</button>
|
|
417
|
+
<button onClick={() => { setShowEdit(true); setShowMobileActions(false); }}>
|
|
418
|
+
<Icon name="pencil" size={15} /> {t('nav.editSession')}
|
|
419
|
+
</button>
|
|
420
|
+
<button onClick={() => { setConfirmReset(true); setShowMobileActions(false); }}>
|
|
421
|
+
<Icon name="refresh" size={15} /> {t('header.resetSessionTip')}
|
|
422
|
+
</button>
|
|
423
|
+
<button onClick={() => { setExportOpen(true); setShowMobileActions(false); }}>
|
|
424
|
+
<Icon name="share" size={15} /> {t('nav.exportGameplay')}
|
|
425
|
+
</button>
|
|
426
|
+
<button className="danger" onClick={() => { setConfirmDelete(true); setShowMobileActions(false); }}>
|
|
427
|
+
<Icon name="trash" size={15} /> {t('header.deleteTip')}
|
|
428
|
+
</button>
|
|
429
|
+
</div>
|
|
430
|
+
)}
|
|
389
431
|
</div>
|
|
390
432
|
|
|
391
433
|
{showEdit && <NewSessionMenu editingSession={session} onClose={() => setShowEdit(false)} />}
|
package/src/core/i18n.ts
CHANGED
|
@@ -81,6 +81,8 @@ const MESSAGES: Record<LangKey, Record<string, string>> = {
|
|
|
81
81
|
'header.modeStandard': '标准对话',
|
|
82
82
|
'header.modeNpc': '角色对话',
|
|
83
83
|
'header.modeGroup': '群聊',
|
|
84
|
+
'header.moreActions': '更多操作',
|
|
85
|
+
'header.workspaceAction': '工作区文件',
|
|
84
86
|
'header.editSessionTip': '编辑对话设置',
|
|
85
87
|
'header.resetSessionTip': '重置对话',
|
|
86
88
|
'header.resetSessionTitle': '重置对话',
|
|
@@ -605,6 +607,8 @@ const MESSAGES: Record<LangKey, Record<string, string>> = {
|
|
|
605
607
|
'header.modeStandard': '標準對話',
|
|
606
608
|
'header.modeNpc': '角色對話',
|
|
607
609
|
'header.modeGroup': '群聊',
|
|
610
|
+
'header.moreActions': '更多操作',
|
|
611
|
+
'header.workspaceAction': '工作區檔案',
|
|
608
612
|
'header.editSessionTip': '編輯對話設定',
|
|
609
613
|
'header.resetSessionTip': '重置對話',
|
|
610
614
|
'header.resetSessionTitle': '重置對話',
|
|
@@ -1117,6 +1121,8 @@ const MESSAGES: Record<LangKey, Record<string, string>> = {
|
|
|
1117
1121
|
'header.modeStandard': 'Standard chat',
|
|
1118
1122
|
'header.modeNpc': 'Character chat',
|
|
1119
1123
|
'header.modeGroup': 'Group chat',
|
|
1124
|
+
'header.moreActions': 'More actions',
|
|
1125
|
+
'header.workspaceAction': 'Workspace files',
|
|
1120
1126
|
'header.editSessionTip': 'Edit conversation settings',
|
|
1121
1127
|
'header.resetSessionTip': 'Reset conversation',
|
|
1122
1128
|
'header.resetSessionTitle': 'Reset conversation',
|
|
@@ -1,7 +1,37 @@
|
|
|
1
1
|
{
|
|
2
|
-
"latest": "0.1.
|
|
2
|
+
"latest": "0.1.21",
|
|
3
3
|
"repo": "https://github.com/Rannichan/Tavern-Harness",
|
|
4
4
|
"entries": [
|
|
5
|
+
{
|
|
6
|
+
"version": "0.1.21",
|
|
7
|
+
"date": "2026-10-26",
|
|
8
|
+
"breaking": false,
|
|
9
|
+
"compare": "v0.1.20...v0.1.21",
|
|
10
|
+
"groups": {
|
|
11
|
+
"zh-CN": [
|
|
12
|
+
{
|
|
13
|
+
"kind": "changed",
|
|
14
|
+
"items": [
|
|
15
|
+
"移动端会话头部的操作按钮收进「更多操作」菜单(工作区文件、编辑对话、重置对话、导出游玩记录、删除对话),头部不再拥挤;主题切换按钮仍然直接显示",
|
|
16
|
+
"移动端会话标题可用的横向空间明显变大,长标题能显示更多内容",
|
|
17
|
+
"会话列表中的标题和副标题过长时改为末尾渐隐,不再用省略号生硬截断",
|
|
18
|
+
"会话头部的上下文用量标签字号略微收小,和标题搭配更协调"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"en": [
|
|
23
|
+
{
|
|
24
|
+
"kind": "changed",
|
|
25
|
+
"items": [
|
|
26
|
+
"On mobile, session header actions now collapse into a \"More actions\" menu (workspace files, edit, reset, export gameplay, delete), so the header is no longer cramped; the theme toggle stays one tap away",
|
|
27
|
+
"Mobile session titles get noticeably more horizontal room, so long titles reveal more of their text",
|
|
28
|
+
"Long session list titles and subtitles now fade out at the end instead of being cut off with an ellipsis",
|
|
29
|
+
"The context usage badge in the session header uses a slightly smaller font so it sits better next to the title"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
5
35
|
{
|
|
6
36
|
"version": "0.1.20",
|
|
7
37
|
"date": "2026-10-26",
|
package/src/theme/global.css
CHANGED
|
@@ -573,9 +573,10 @@ body.resizing .sidebar-resizer {
|
|
|
573
573
|
}
|
|
574
574
|
.session-item .stitle-text {
|
|
575
575
|
overflow: hidden;
|
|
576
|
-
text-overflow: ellipsis;
|
|
577
576
|
white-space: nowrap;
|
|
578
577
|
min-width: 0;
|
|
578
|
+
-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
|
|
579
|
+
mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
|
|
579
580
|
}
|
|
580
581
|
.session-item .spinned {
|
|
581
582
|
display: inline-flex;
|
|
@@ -615,7 +616,8 @@ body.resizing .sidebar-resizer {
|
|
|
615
616
|
color: var(--text-faint);
|
|
616
617
|
white-space: nowrap;
|
|
617
618
|
overflow: hidden;
|
|
618
|
-
|
|
619
|
+
-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
|
|
620
|
+
mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent);
|
|
619
621
|
}
|
|
620
622
|
/* ---------- 会话区域(头部 + 滚动列表) ---------- */
|
|
621
623
|
.session-section {
|
|
@@ -1072,6 +1074,7 @@ body.resizing .sidebar-resizer {
|
|
|
1072
1074
|
}
|
|
1073
1075
|
.chat-header .tsub-mode {
|
|
1074
1076
|
flex-shrink: 0;
|
|
1077
|
+
font-size: 12px;
|
|
1075
1078
|
font-weight: 700;
|
|
1076
1079
|
color: var(--primary);
|
|
1077
1080
|
}
|
|
@@ -1111,6 +1114,10 @@ body.resizing .sidebar-resizer {
|
|
|
1111
1114
|
color: var(--danger);
|
|
1112
1115
|
background: var(--danger-soft);
|
|
1113
1116
|
}
|
|
1117
|
+
.chat-actions .chat-actions-more,
|
|
1118
|
+
.chat-actions-menu {
|
|
1119
|
+
display: none;
|
|
1120
|
+
}
|
|
1114
1121
|
|
|
1115
1122
|
/* ---------- 卡片/仪表盘 ---------- */
|
|
1116
1123
|
.dash-scroll {
|
|
@@ -1799,7 +1806,7 @@ hr.sep {
|
|
|
1799
1806
|
}
|
|
1800
1807
|
|
|
1801
1808
|
.chat-header .ttitle {
|
|
1802
|
-
max-width: min(
|
|
1809
|
+
max-width: min(52vw, 260px);
|
|
1803
1810
|
font-size: 15px;
|
|
1804
1811
|
}
|
|
1805
1812
|
|
|
@@ -1808,16 +1815,67 @@ hr.sep {
|
|
|
1808
1815
|
}
|
|
1809
1816
|
|
|
1810
1817
|
.chat-actions {
|
|
1818
|
+
position: relative;
|
|
1811
1819
|
flex: 0 0 auto;
|
|
1812
1820
|
gap: 0;
|
|
1813
1821
|
}
|
|
1814
1822
|
|
|
1823
|
+
.chat-actions .icon-tooltip:not(.chat-actions-more, .chat-theme-toggle) {
|
|
1824
|
+
display: none;
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
.chat-actions .chat-actions-more {
|
|
1828
|
+
display: inline-flex;
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1815
1831
|
.chat-actions .icon-tooltip {
|
|
1816
1832
|
width: 34px;
|
|
1817
1833
|
height: 34px;
|
|
1818
1834
|
flex-shrink: 0;
|
|
1819
1835
|
}
|
|
1820
1836
|
|
|
1837
|
+
.chat-actions-menu {
|
|
1838
|
+
position: absolute;
|
|
1839
|
+
top: calc(100% + 6px);
|
|
1840
|
+
right: 0;
|
|
1841
|
+
z-index: 60;
|
|
1842
|
+
display: flex;
|
|
1843
|
+
flex-direction: column;
|
|
1844
|
+
min-width: 164px;
|
|
1845
|
+
padding: 6px;
|
|
1846
|
+
background: var(--surface);
|
|
1847
|
+
border: 1px solid var(--border);
|
|
1848
|
+
border-radius: 12px;
|
|
1849
|
+
box-shadow: var(--shadow-lg);
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
.chat-actions-menu button {
|
|
1853
|
+
display: flex;
|
|
1854
|
+
align-items: center;
|
|
1855
|
+
gap: 9px;
|
|
1856
|
+
width: 100%;
|
|
1857
|
+
padding: 8px 10px;
|
|
1858
|
+
border: none;
|
|
1859
|
+
border-radius: 8px;
|
|
1860
|
+
background: none;
|
|
1861
|
+
color: var(--text);
|
|
1862
|
+
font-size: 13px;
|
|
1863
|
+
font-weight: 600;
|
|
1864
|
+
text-align: left;
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1867
|
+
.chat-actions-menu button:hover {
|
|
1868
|
+
background: var(--surface-2);
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
.chat-actions-menu button.danger {
|
|
1872
|
+
color: var(--danger);
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
.chat-actions-menu button.danger:hover {
|
|
1876
|
+
background: var(--danger-soft);
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1821
1879
|
.chat-scroll {
|
|
1822
1880
|
padding-top: 14px;
|
|
1823
1881
|
}
|