tavern-harness 0.1.24 → 0.1.25
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 +15 -0
- package/package.json +1 -1
- package/src/App.tsx +4 -3
- package/src/components/CharactersView.tsx +13 -13
- package/src/components/ChatView.tsx +1 -1
- package/src/components/ConfirmationDialog.tsx +3 -3
- package/src/components/DeleteConfirmDialog.tsx +1 -1
- package/src/components/FileDisplayModal.tsx +1 -1
- package/src/components/GameplayDialogs.tsx +2 -2
- package/src/components/NewSessionMenu.tsx +2 -2
- package/src/components/SettingsView.tsx +4 -4
- package/src/components/Sidebar.tsx +2 -2
- package/src/components/StatsView.tsx +5 -5
- package/src/components/VersionHistoryModal.tsx +1 -1
- package/src/components/WorkspaceFileManagerModal.tsx +1 -1
- package/src/generated/changelog.json +25 -1
- package/src/theme/chat.css +165 -159
- package/src/theme/global.css +289 -140
- package/src/theme/views.css +237 -200
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
> 本文件由 `scripts/changelog.mjs` 从 `changelog/v*.md` 生成,请勿手动编辑。
|
|
4
4
|
> 版本对比链接见文末;源文件位于仓库 `changelog/` 目录。
|
|
5
5
|
|
|
6
|
+
## [0.1.25] - 2026-10-27
|
|
7
|
+
|
|
8
|
+
### 中文
|
|
9
|
+
|
|
10
|
+
#### 内部
|
|
11
|
+
|
|
12
|
+
- 统一了标题、对话框、工具卡片等界面文字的字体排印样式,改用共享的排版类和样式变量,后续调整字号、字重只需改一处
|
|
13
|
+
|
|
14
|
+
### English
|
|
15
|
+
|
|
16
|
+
#### Internal
|
|
17
|
+
|
|
18
|
+
- Unified the typography of headings, dialogs, tool cards, and other interface text behind shared classes and style variables, so future font-size and weight changes happen in one place
|
|
19
|
+
|
|
6
20
|
## [0.1.24] - 2026-10-27
|
|
7
21
|
|
|
8
22
|
### 中文
|
|
@@ -702,6 +716,7 @@
|
|
|
702
716
|
- Vite + React + Zustand + Dexie stack with browser-side local persistence
|
|
703
717
|
|
|
704
718
|
<!-- 链接定义 -->
|
|
719
|
+
[0.1.25]: https://github.com/Rannichan/Tavern-Harness/compare/v0.1.24...v0.1.25
|
|
705
720
|
[0.1.24]: https://github.com/Rannichan/Tavern-Harness/compare/v0.1.23...v0.1.24
|
|
706
721
|
[0.1.23]: https://github.com/Rannichan/Tavern-Harness/compare/v0.1.22...v0.1.23
|
|
707
722
|
[0.1.22]: https://github.com/Rannichan/Tavern-Harness/compare/v0.1.21...v0.1.22
|
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -165,7 +165,8 @@ export default function App() {
|
|
|
165
165
|
type="button"
|
|
166
166
|
disabled={takingControl}
|
|
167
167
|
onClick={() => void handleTakeOverControl()}
|
|
168
|
-
|
|
168
|
+
className="control-takeover-btn"
|
|
169
|
+
style={{ cursor: takingControl ? 'wait' : 'pointer' }}
|
|
169
170
|
>
|
|
170
171
|
{t('control.takeOverHere')}
|
|
171
172
|
</button>
|
|
@@ -448,7 +449,7 @@ function SessionHeader({
|
|
|
448
449
|
{confirmReset && (
|
|
449
450
|
<Modal onClose={() => setConfirmReset(false)} size="compact">
|
|
450
451
|
<div className="modal-head">
|
|
451
|
-
<span
|
|
452
|
+
<span className="typo-dialog-title">{t('header.resetSessionTitle')}</span>
|
|
452
453
|
<button className="icon-btn" onClick={() => setConfirmReset(false)}><Icon name="x" /></button>
|
|
453
454
|
</div>
|
|
454
455
|
<div className="modal-body">
|
|
@@ -473,7 +474,7 @@ function SessionHeader({
|
|
|
473
474
|
{confirmDelete && (
|
|
474
475
|
<Modal onClose={() => setConfirmDelete(false)} size="compact">
|
|
475
476
|
<div className="modal-head">
|
|
476
|
-
<span
|
|
477
|
+
<span className="typo-dialog-title">{t('header.deleteTitle')}</span>
|
|
477
478
|
<button className="icon-btn" onClick={() => setConfirmDelete(false)}><Icon name="x" /></button>
|
|
478
479
|
</div>
|
|
479
480
|
<div className="modal-body">
|
|
@@ -316,7 +316,7 @@ function CharacterEditorModal({ npc, isNew, onClose, onSaved }: { npc: NpcCharac
|
|
|
316
316
|
return (
|
|
317
317
|
<Modal onClose={onClose} className="modal-editor editor-modal-with-tabs character-editor-modal">
|
|
318
318
|
<div className="modal-head">
|
|
319
|
-
<span
|
|
319
|
+
<span className="typo-dialog-title">{isNew ? t('workshop.newCharTitle') : t('workshop.editCharTitle')}</span>
|
|
320
320
|
<div className="raw-tabs">
|
|
321
321
|
<button className={`raw-tab ${editorTab === 'character' ? 'active' : ''}`} onClick={() => setEditorTab('character')}>{t('workshop.characterTab')}</button>
|
|
322
322
|
<button
|
|
@@ -371,7 +371,7 @@ function CharacterEditorModal({ npc, isNew, onClose, onSaved }: { npc: NpcCharac
|
|
|
371
371
|
<textarea className="textarea grow-textarea" value={prompt} onChange={(e) => setPrompt(e.target.value)} placeholder={t('workshop.promptPh')} />
|
|
372
372
|
) : (
|
|
373
373
|
<div className="bubble preview-scroll wb-render-pane char-prompt-render-pane">
|
|
374
|
-
{prompt ? <Markdown text={prompt} /> : <span
|
|
374
|
+
{prompt ? <Markdown text={prompt} /> : <span className="typo-label text-muted">{t('workshop.promptPh')}</span>}
|
|
375
375
|
</div>
|
|
376
376
|
)}
|
|
377
377
|
</div>
|
|
@@ -391,7 +391,7 @@ function CharacterEditorModal({ npc, isNew, onClose, onSaved }: { npc: NpcCharac
|
|
|
391
391
|
/>
|
|
392
392
|
) : (
|
|
393
393
|
<div className="bubble preview-scroll wb-render-pane greeting-render-pane">
|
|
394
|
-
{g ? <Markdown text={g} /> : <span
|
|
394
|
+
{g ? <Markdown text={g} /> : <span className="typo-label text-muted">{t('workshop.greetingPh')}</span>}
|
|
395
395
|
</div>
|
|
396
396
|
)}
|
|
397
397
|
{!renderMarkdown && (
|
|
@@ -415,7 +415,7 @@ function CharacterEditorModal({ npc, isNew, onClose, onSaved }: { npc: NpcCharac
|
|
|
415
415
|
<div className="field" style={{ flexShrink: 0 }}>
|
|
416
416
|
<label>{t('workshop.enableSkills', { a: enabledToolNames.filter((s) => tools.some((t) => t.name === s)).length, b: tools.length })}</label>
|
|
417
417
|
{tools.length === 0 ? (
|
|
418
|
-
<div
|
|
418
|
+
<div className="typo-label text-muted">{t('workshop.noSkills')}</div>
|
|
419
419
|
) : (
|
|
420
420
|
<div className="skill-list-scroll">
|
|
421
421
|
{tools.map((t) => (
|
|
@@ -595,7 +595,7 @@ function WorldBookList({ books, onChanged }: {
|
|
|
595
595
|
return (
|
|
596
596
|
<div key={b.id} className="char-card wb-card fade-up">
|
|
597
597
|
<div className="cname">
|
|
598
|
-
<span
|
|
598
|
+
<span className="character-book-icon">📖</span>
|
|
599
599
|
<ScrollingCardName name={b.name} />
|
|
600
600
|
{isBuiltin && <span className="tag">{t('common.builtin')}</span>}
|
|
601
601
|
</div>
|
|
@@ -712,7 +712,7 @@ function WorldBookForm({
|
|
|
712
712
|
return (
|
|
713
713
|
<>
|
|
714
714
|
<div className="modal-head">
|
|
715
|
-
<span
|
|
715
|
+
<span className="typo-dialog-title">
|
|
716
716
|
{isEditing ? t('workshop.editWbTitle') : t('workshop.newWbTitle')}
|
|
717
717
|
</span>
|
|
718
718
|
<div className="raw-tabs">
|
|
@@ -755,7 +755,7 @@ function WorldBookForm({
|
|
|
755
755
|
<textarea className="textarea grow-textarea" value={content} onChange={(e) => setContent(e.target.value)} placeholder={t('workshop.wbContentPh')} />
|
|
756
756
|
) : (
|
|
757
757
|
<div className="bubble preview-scroll wb-render-pane">
|
|
758
|
-
{content ? <Markdown text={content} /> : <span
|
|
758
|
+
{content ? <Markdown text={content} /> : <span className="typo-label text-muted">{t('workshop.wbContentPh')}</span>}
|
|
759
759
|
</div>
|
|
760
760
|
)}
|
|
761
761
|
</div>
|
|
@@ -960,14 +960,14 @@ function SkillSortItem({
|
|
|
960
960
|
{...attributes}
|
|
961
961
|
{...listeners}
|
|
962
962
|
>
|
|
963
|
-
<div
|
|
963
|
+
<div className="tool-type-icon">{tool.isBuiltIn ? '🧰' : '⚙️'}</div>
|
|
964
964
|
<div className="l-main">
|
|
965
965
|
<div className="l-title">
|
|
966
966
|
<span className="skill-card-name">{tool.name}</span>
|
|
967
967
|
{tool.isBuiltIn && <span className="tag">{t('common.builtin')}</span>}
|
|
968
968
|
</div>
|
|
969
969
|
<div className="l-sub">{desc}</div>
|
|
970
|
-
{tool.isBuiltIn && impl !== 'native' && <div
|
|
970
|
+
{tool.isBuiltIn && impl !== 'native' && <div className="tool-implementation-type">{t('workshop.implType', { t: impl })}</div>}
|
|
971
971
|
</div>
|
|
972
972
|
<div className="skill-item-actions">
|
|
973
973
|
<button className="btn btn-sm" onClick={(e) => { e.stopPropagation(); onDetail(); }} title={t('workshop.viewDetails')}>
|
|
@@ -1063,7 +1063,7 @@ function SkillDetailModal({ tool, onClose }: { tool: McpTool; onClose: () => voi
|
|
|
1063
1063
|
return (
|
|
1064
1064
|
<Modal onClose={onClose}>
|
|
1065
1065
|
<div className="modal-head">
|
|
1066
|
-
<span
|
|
1066
|
+
<span className="typo-dialog-title">
|
|
1067
1067
|
{t('workshop.skillDetails')}
|
|
1068
1068
|
{tool.isBuiltIn && <span className="tag" style={{ marginLeft: 8 }}>{t('common.builtin')}</span>}
|
|
1069
1069
|
{!tool.isBuiltIn && execType !== 'native' && <span className="tag" style={{ marginLeft: 8 }}>{t('workshop.implType', { t: execType })}</span>}
|
|
@@ -1081,17 +1081,17 @@ function SkillDetailModal({ tool, onClose }: { tool: McpTool; onClose: () => voi
|
|
|
1081
1081
|
</div>
|
|
1082
1082
|
<div className="field">
|
|
1083
1083
|
<label>{t('workshop.skillParameters')}</label>
|
|
1084
|
-
{editable ? <textarea className="textarea mono skill-detail-textarea" value={parametersText} wrap="soft" spellCheck={false} onChange={(e) => setParametersText(e.target.value)} /> : parametersText ? <pre className="skill-detail-json">{parametersText}</pre> : <div className="skill-detail-text
|
|
1084
|
+
{editable ? <textarea className="textarea mono skill-detail-textarea" value={parametersText} wrap="soft" spellCheck={false} onChange={(e) => setParametersText(e.target.value)} /> : parametersText ? <pre className="skill-detail-json">{parametersText}</pre> : <div className="skill-detail-text text-muted">{t('workshop.skillNoParams')}</div>}
|
|
1085
1085
|
</div>
|
|
1086
1086
|
<div className="field">
|
|
1087
1087
|
<label>{t('workshop.skillExecution')}</label>
|
|
1088
|
-
{exec ? <pre className="skill-detail-json">{JSON.stringify(exec, null, 2)}</pre> : <div className="skill-detail-text
|
|
1088
|
+
{exec ? <pre className="skill-detail-json">{JSON.stringify(exec, null, 2)}</pre> : <div className="skill-detail-text text-muted">{t('workshop.skillNoExecution')}</div>}
|
|
1089
1089
|
</div>
|
|
1090
1090
|
<div className="field">
|
|
1091
1091
|
<label>{t('workshop.skillRawJson')}</label>
|
|
1092
1092
|
<pre className={`skill-detail-json${rawJson ? '' : ' err'}`}>{rawJson ?? schema.error}</pre>
|
|
1093
1093
|
</div>
|
|
1094
|
-
{error && <div className="field-hint
|
|
1094
|
+
{error && <div className="field-hint text-danger">{error}</div>}
|
|
1095
1095
|
</div>
|
|
1096
1096
|
<div className="modal-foot">
|
|
1097
1097
|
<button className="btn" onClick={onClose}>{t('common.cancel')}</button>
|
|
@@ -1465,7 +1465,7 @@ export function MessageMenu() {
|
|
|
1465
1465
|
<Icon name={a.icon} size={13} /> {a.label}
|
|
1466
1466
|
</button>
|
|
1467
1467
|
))}
|
|
1468
|
-
{actions.length === 0 && <div
|
|
1468
|
+
{actions.length === 0 && <div className="chat-no-actions">{t('chat.noActions')}</div>}
|
|
1469
1469
|
</PopoverMenu>
|
|
1470
1470
|
);
|
|
1471
1471
|
}
|
|
@@ -23,16 +23,16 @@ export function ConfirmationDialog() {
|
|
|
23
23
|
<div className="modal-root">
|
|
24
24
|
<div className="modal card confirm fade-up">
|
|
25
25
|
<div className="modal-head">
|
|
26
|
-
<span
|
|
26
|
+
<span className="typo-dialog-title dialog-title-inline dialog-title-compact">
|
|
27
27
|
<Icon name="settings" size={15} /> {isLimit ? pending.title : t('confirm.title')}
|
|
28
28
|
</span>
|
|
29
29
|
</div>
|
|
30
30
|
<div className="modal-body" style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
|
|
31
|
-
{!isLimit && <div
|
|
31
|
+
{!isLimit && <div className="confirmation-tool-name">{t('confirm.tool')}<span className="mono text-accent">{pending.toolName}</span></div>}
|
|
32
32
|
{!pending.inlineCode && <pre className="confirm-args mono">{argsText}</pre>}
|
|
33
33
|
<div className={isLimit ? undefined : 'confirm-reason'}>
|
|
34
34
|
{!isLimit && <div className="confirm-reason-title">{pending.title}</div>}
|
|
35
|
-
<div
|
|
35
|
+
<div className="typo-confirm-reason">
|
|
36
36
|
{pending.inlineCode && <code className="confirm-inline-code">{pending.inlineCode}</code>}
|
|
37
37
|
{pending.message || (isLimit ? '' : t('confirm.modify'))}
|
|
38
38
|
</div>
|
|
@@ -25,7 +25,7 @@ export function DeleteConfirmDialog({
|
|
|
25
25
|
return (
|
|
26
26
|
<Modal onClose={onCancel} size="compact">
|
|
27
27
|
<div className="modal-head">
|
|
28
|
-
<span
|
|
28
|
+
<span className="typo-dialog-title">{title}</span>
|
|
29
29
|
<button className="icon-btn" onClick={onCancel}><Icon name="x" /></button>
|
|
30
30
|
</div>
|
|
31
31
|
<div className="modal-body">
|
|
@@ -466,7 +466,7 @@ export function FileDisplayModal() {
|
|
|
466
466
|
>
|
|
467
467
|
<span className="display-modal-title">
|
|
468
468
|
<Icon name="file" size={15} />
|
|
469
|
-
<span className="mono
|
|
469
|
+
<span className="mono typo-body-sm text-secondary">{active.path}</span>
|
|
470
470
|
<span className="display-title-text">{title}</span>
|
|
471
471
|
</span>
|
|
472
472
|
<div className="display-head-actions">
|
|
@@ -50,7 +50,7 @@ export function GameplayExportModal({
|
|
|
50
50
|
return (
|
|
51
51
|
<Modal onClose={onClose} size="compact">
|
|
52
52
|
<div className="modal-head">
|
|
53
|
-
<span
|
|
53
|
+
<span className="typo-dialog-title dialog-title-inline">
|
|
54
54
|
<Icon name="share" size={15} /> {t('gameplay.exportTitle')}
|
|
55
55
|
</span>
|
|
56
56
|
<button className="icon-btn" onClick={onClose}><Icon name="x" /></button>
|
|
@@ -155,7 +155,7 @@ export function GameplayImportModal({
|
|
|
155
155
|
return (
|
|
156
156
|
<Modal onClose={onClose} size="compact">
|
|
157
157
|
<div className="modal-head">
|
|
158
|
-
<span
|
|
158
|
+
<span className="typo-dialog-title dialog-title-inline">
|
|
159
159
|
<Icon name="import" size={15} /> {t('gameplay.importTitle')}
|
|
160
160
|
</span>
|
|
161
161
|
<button className="icon-btn" onClick={onClose}><Icon name="x" /></button>
|
|
@@ -160,7 +160,7 @@ export function NewSessionMenu({ onClose, editingSession }: { onClose: () => voi
|
|
|
160
160
|
return (
|
|
161
161
|
<Modal onClose={onClose} className="new-session-modal">
|
|
162
162
|
<div className="modal-head">
|
|
163
|
-
<span
|
|
163
|
+
<span className="typo-dialog-title">{isEditing ? t('nav.editSession') : t('newSession.title')}</span>
|
|
164
164
|
<button className="icon-btn" onClick={onClose}><Icon name="x" /></button>
|
|
165
165
|
</div>
|
|
166
166
|
<div className="modal-body" style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
|
|
@@ -203,7 +203,7 @@ export function NewSessionMenu({ onClose, editingSession }: { onClose: () => voi
|
|
|
203
203
|
</SortableContext>
|
|
204
204
|
</DndContext>
|
|
205
205
|
{npcs.length === 0 ? (
|
|
206
|
-
<div
|
|
206
|
+
<div className="new-session-warning">
|
|
207
207
|
{t('newSession.noNpcWarn')}
|
|
208
208
|
</div>
|
|
209
209
|
) : (
|
|
@@ -323,7 +323,7 @@ export const SettingsView = memo(function SettingsView() {
|
|
|
323
323
|
{showResetConfirm && (
|
|
324
324
|
<Modal onClose={() => !resetting && setShowResetConfirm(false)} size="compact">
|
|
325
325
|
<div className="modal-head">
|
|
326
|
-
<span
|
|
326
|
+
<span className="typo-dialog-title">{t('settings.resetConfirmTitle')}</span>
|
|
327
327
|
<button className="icon-btn" disabled={resetting} onClick={() => setShowResetConfirm(false)}><Icon name="x" /></button>
|
|
328
328
|
</div>
|
|
329
329
|
<div className="modal-body">{t('settings.resetConfirm')}</div>
|
|
@@ -435,7 +435,7 @@ function ProviderManager({ providers, onChanged }: { providers: ApiProvider[]; o
|
|
|
435
435
|
<div className="set-section">
|
|
436
436
|
<h3>{t('settings.providerTitle')}</h3>
|
|
437
437
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
|
|
438
|
-
{providers.length === 0 && <div
|
|
438
|
+
{providers.length === 0 && <div className="typo-body-sm text-muted">{t('settings.noProvider')}</div>}
|
|
439
439
|
{providers.map((p) => {
|
|
440
440
|
const aliases = modelAliases(p);
|
|
441
441
|
const enabledModels = enabledModelIds(p);
|
|
@@ -457,7 +457,7 @@ function ProviderManager({ providers, onChanged }: { providers: ApiProvider[]; o
|
|
|
457
457
|
</div>
|
|
458
458
|
</div>
|
|
459
459
|
<div className="p-url">{p.baseUrl}</div>
|
|
460
|
-
<div
|
|
460
|
+
<div className="provider-inline-detail">
|
|
461
461
|
<b>{t('settings.models')}</b>
|
|
462
462
|
{visibleModels.length > 0
|
|
463
463
|
? visibleModels.slice(0, 12).map((model) => aliases[model]?.trim() || model).join(', ')
|
|
@@ -475,7 +475,7 @@ function ProviderManager({ providers, onChanged }: { providers: ApiProvider[]; o
|
|
|
475
475
|
{editing && (
|
|
476
476
|
<Modal onClose={() => setEditing(null)}>
|
|
477
477
|
<div className="modal-head">
|
|
478
|
-
<span
|
|
478
|
+
<span className="typo-dialog-title">{editing.id != null ? t('settings.editProvider') : t('settings.addProvider')}</span>
|
|
479
479
|
<button className="icon-btn" onClick={() => setEditing(null)}><Icon name="x" /></button>
|
|
480
480
|
</div>
|
|
481
481
|
<ProviderForm
|
|
@@ -527,13 +527,13 @@ export function Sidebar() {
|
|
|
527
527
|
{confirmDelete && (
|
|
528
528
|
<Modal onClose={() => setConfirmDelete(null)} size="compact">
|
|
529
529
|
<div className="modal-head">
|
|
530
|
-
<span
|
|
530
|
+
<span className="typo-dialog-title dialog-title-inline">
|
|
531
531
|
<Icon name="trash" size={15} /> {t('nav.deleteSession')}
|
|
532
532
|
</span>
|
|
533
533
|
<button className="icon-btn" onClick={() => setConfirmDelete(null)}><Icon name="x" /></button>
|
|
534
534
|
</div>
|
|
535
535
|
<div className="modal-body">
|
|
536
|
-
<div
|
|
536
|
+
<div className="sidebar-import-description">
|
|
537
537
|
{t('nav.deleteSessionConfirm', { title: confirmDelete.title })}
|
|
538
538
|
</div>
|
|
539
539
|
</div>
|
|
@@ -134,18 +134,18 @@ function StatCards({ data }: { data: StatsData }) {
|
|
|
134
134
|
{(() => {
|
|
135
135
|
const mostActive = [...data.npcStats].sort((a, b) => b.rounds - a.rounds)[0];
|
|
136
136
|
return (
|
|
137
|
-
<div
|
|
138
|
-
<div
|
|
137
|
+
<div className="stats-most-active">
|
|
138
|
+
<div className="stats-most-active-icon">🎭</div>
|
|
139
139
|
<div>
|
|
140
|
-
<div
|
|
141
|
-
<div
|
|
140
|
+
<div className="stats-most-active-name">{mostActive.npcName}</div>
|
|
141
|
+
<div className="stats-most-active-rounds">{t('stats.roundsCount', { n: mostActive.rounds })}</div>
|
|
142
142
|
</div>
|
|
143
143
|
</div>
|
|
144
144
|
);
|
|
145
145
|
})()}
|
|
146
146
|
</>
|
|
147
147
|
) : (
|
|
148
|
-
<div
|
|
148
|
+
<div className="stats-no-data">{t('stats.noData')}</div>
|
|
149
149
|
)}
|
|
150
150
|
</div>
|
|
151
151
|
|
|
@@ -93,7 +93,7 @@ export function VersionHistoryModal({ onClose }: { onClose: () => void }) {
|
|
|
93
93
|
return (
|
|
94
94
|
<Modal onClose={onClose} size="wide">
|
|
95
95
|
<div className="modal-head">
|
|
96
|
-
<span
|
|
96
|
+
<span className="typo-dialog-title">{t('changelog.title')}</span>
|
|
97
97
|
<button className="icon-btn" onClick={onClose} aria-label={t('common.close')}>
|
|
98
98
|
<Icon name="x" />
|
|
99
99
|
</button>
|
|
@@ -241,7 +241,7 @@ export function WorkspaceFileManagerModal({ sessionId, onClose }: { sessionId: n
|
|
|
241
241
|
<div className="ws-fm-delete-layer" role="dialog" aria-modal="true" aria-labelledby="ws-fm-delete-title">
|
|
242
242
|
<div className="ws-fm-delete-dialog card fade-up">
|
|
243
243
|
<div className="modal-head">
|
|
244
|
-
<span id="ws-fm-delete-title"
|
|
244
|
+
<span id="ws-fm-delete-title" className="typo-dialog-title">{t('header.fileManagerDeleteTitle')}</span>
|
|
245
245
|
<button className="icon-btn" onClick={() => setPendingDelete(null)} disabled={deleting} title={t('common.close')}>
|
|
246
246
|
<Icon name="x" />
|
|
247
247
|
</button>
|
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
{
|
|
2
|
-
"latest": "0.1.
|
|
2
|
+
"latest": "0.1.25",
|
|
3
3
|
"repo": "https://github.com/Rannichan/Tavern-Harness",
|
|
4
4
|
"entries": [
|
|
5
|
+
{
|
|
6
|
+
"version": "0.1.25",
|
|
7
|
+
"date": "2026-10-27",
|
|
8
|
+
"breaking": false,
|
|
9
|
+
"compare": "v0.1.24...v0.1.25",
|
|
10
|
+
"groups": {
|
|
11
|
+
"zh-CN": [
|
|
12
|
+
{
|
|
13
|
+
"kind": "internal",
|
|
14
|
+
"items": [
|
|
15
|
+
"统一了标题、对话框、工具卡片等界面文字的字体排印样式,改用共享的排版类和样式变量,后续调整字号、字重只需改一处"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"en": [
|
|
20
|
+
{
|
|
21
|
+
"kind": "internal",
|
|
22
|
+
"items": [
|
|
23
|
+
"Unified the typography of headings, dialogs, tool cards, and other interface text behind shared classes and style variables, so future font-size and weight changes happen in one place"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
},
|
|
5
29
|
{
|
|
6
30
|
"version": "0.1.24",
|
|
7
31
|
"date": "2026-10-27",
|