dsh-ide-git 0.13.5 → 0.14.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/dsh.plugin.json +1 -1
- package/package.json +1 -1
- package/src/client.js +524 -50
- package/src/index.js +7 -0
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-external/dsh-ide-git",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"description": "IDE 级 Git 操作面板:分支树 + 提交图谱 + 变更/暂存/提交 + 提交详情。装了 dsh-better-sidebar 时挂成它的原生 tab(右侧栏 + 底部工作台);没装时直接挂 DSH 原生右侧栏,单独安装即可用。JetBrains 风格 Git 工具窗口 for DeepSeek Harness.",
|
|
6
6
|
"engines": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-ide-git",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "DSH plugin: an IDE-grade Git tool window as a native dsh-better-sidebar tab — branch tree, commit graph, changes, commit details, JetBrains-style actions, in the right sidebar and the bottom panel. | DSH 插件:IDE 级 Git 工具窗口,以 dsh-better-sidebar 原生 Tab 挂载——分支树 / 提交图谱 / 变更与提交详情 / JetBrains 风格操作,右侧栏与底部面板双布局自适应。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
package/src/client.js
CHANGED
|
@@ -153,7 +153,6 @@ window.__ModuleLoader__.load({
|
|
|
153
153
|
'action.copyHash': '复制修订号',
|
|
154
154
|
'action.details': '提交详情',
|
|
155
155
|
'menu.sendToChat': '发送到对话',
|
|
156
|
-
'menu.sendFilePathToChat': '发送文件路径到对话',
|
|
157
156
|
'send.commitText': 'git 提交 {hash}「{subject}」(仓库 {repo})',
|
|
158
157
|
'send.branchText': 'git 分支 {name}(仓库 {repo})',
|
|
159
158
|
'menu.sendDiffLinesToChat': '发送选中行到对话',
|
|
@@ -195,6 +194,11 @@ window.__ModuleLoader__.load({
|
|
|
195
194
|
'settings.placement.title': '面板放置',
|
|
196
195
|
'settings.placement.tab': '在主对话区显示 Git 标签页',
|
|
197
196
|
'settings.placement.tabHint': '关闭后仍可从右侧栏或底部面板打开。',
|
|
197
|
+
'settings.placement.immersive': '沉浸模式(占满全高,隐藏输入框)',
|
|
198
|
+
'settings.placement.immersiveHint': '开启后 Git 标签页占满整个会话区高度,输入框自动收起;审批与提问仍会正常显示。',
|
|
199
|
+
'preview.openFile': '打开文件预览',
|
|
200
|
+
'preview.title': 'Git 预览',
|
|
201
|
+
'preview.hint': '点击文件或提交的「显示差异」,差异会在侧边栏这里打开。',
|
|
198
202
|
'settings.rail.title': '动作条按钮',
|
|
199
203
|
'settings.rail.hint': '勾选要显示在动作条上的动作;顺序固定为默认顺序,取消勾选即隐藏。',
|
|
200
204
|
'settings.rail.unavailable': '当前宿主没有设置服务,请用面板内的「动作条设置」。',
|
|
@@ -364,7 +368,6 @@ window.__ModuleLoader__.load({
|
|
|
364
368
|
'action.copyHash': 'Copy revision number',
|
|
365
369
|
'action.details': 'Commit details',
|
|
366
370
|
'menu.sendToChat': 'Send to chat',
|
|
367
|
-
'menu.sendFilePathToChat': 'Send file path to chat',
|
|
368
371
|
'send.commitText': 'git commit {hash} "{subject}" (repo {repo})',
|
|
369
372
|
'send.branchText': 'git branch {name} (repo {repo})',
|
|
370
373
|
'menu.sendDiffLinesToChat': 'Send selected lines to chat',
|
|
@@ -406,6 +409,11 @@ window.__ModuleLoader__.load({
|
|
|
406
409
|
'settings.placement.title': 'Placement',
|
|
407
410
|
'settings.placement.tab': 'Show the Git tab in the conversation area',
|
|
408
411
|
'settings.placement.tabHint': 'Off, the panel stays reachable from the right sidebar and the bottom panel.',
|
|
412
|
+
'settings.placement.immersive': 'Immersive mode (full height, hidden composer)',
|
|
413
|
+
'settings.placement.immersiveHint': 'On, the Git tab fills the whole conversation area and the composer steps aside; approvals and questions still show.',
|
|
414
|
+
'preview.openFile': 'Open in the file preview',
|
|
415
|
+
'preview.title': 'Git Preview',
|
|
416
|
+
'preview.hint': 'Click “Show diff” on a file or commit — the diff opens here in the sidebar.',
|
|
409
417
|
'settings.rail.title': 'Action rail buttons',
|
|
410
418
|
'settings.rail.hint': 'Tick the actions shown on the rail. The order is fixed; unticking one hides it.',
|
|
411
419
|
'settings.rail.unavailable': 'This host has no settings service; use the in-panel “Action rail settings”.',
|
|
@@ -583,7 +591,6 @@ window.__ModuleLoader__.load({
|
|
|
583
591
|
'action.copyHash': '複製修訂號',
|
|
584
592
|
'action.details': '提交詳情',
|
|
585
593
|
'menu.sendToChat': '傳送到對話',
|
|
586
|
-
'menu.sendFilePathToChat': '傳送檔案路徑至對話',
|
|
587
594
|
'send.commitText': 'git 提交 {hash}「{subject}」(存放庫 {repo})',
|
|
588
595
|
'send.branchText': 'git 分支 {name}(存放庫 {repo})',
|
|
589
596
|
'menu.sendDiffLinesToChat': '傳送選中行到對話',
|
|
@@ -625,6 +632,11 @@ window.__ModuleLoader__.load({
|
|
|
625
632
|
'settings.placement.title': '面板放置',
|
|
626
633
|
'settings.placement.tab': '喺主對話區顯示 Git 分頁',
|
|
627
634
|
'settings.placement.tabHint': '關閉之後仍可從右側欄或底部面板開啟。',
|
|
635
|
+
'settings.placement.immersive': '沉浸模式(佔滿全高,隱藏輸入框)',
|
|
636
|
+
'settings.placement.immersiveHint': '開啟之後 Git 分頁會佔滿整個會話區高度,輸入框自動收起;審批與提問仍會正常顯示。',
|
|
637
|
+
'preview.openFile': '開啟檔案預覽',
|
|
638
|
+
'preview.title': 'Git 預覽',
|
|
639
|
+
'preview.hint': '喺檔案或提交撳「顯示差異」,差異就會喺側邊欄度開啟。',
|
|
628
640
|
'settings.rail.title': '動作列按鈕',
|
|
629
641
|
'settings.rail.hint': '勾選要顯示在動作列上的動作;順序固定,取消勾選即隱藏。',
|
|
630
642
|
'settings.rail.unavailable': '目前宿主沒有設定服務,請用面板內的「動作條設定」。',
|
|
@@ -794,7 +806,6 @@ window.__ModuleLoader__.load({
|
|
|
794
806
|
'action.copyHash': '複製修訂編號',
|
|
795
807
|
'action.details': '提交詳情',
|
|
796
808
|
'menu.sendToChat': '傳送至對話',
|
|
797
|
-
'menu.sendFilePathToChat': '傳送檔案路徑至對話',
|
|
798
809
|
'send.commitText': 'git 提交 {hash}「{subject}」(版本庫 {repo})',
|
|
799
810
|
'send.branchText': 'git 分支 {name}(版本庫 {repo})',
|
|
800
811
|
'menu.sendDiffLinesToChat': '傳送選取行至對話',
|
|
@@ -836,6 +847,11 @@ window.__ModuleLoader__.load({
|
|
|
836
847
|
'settings.placement.title': '面板放置',
|
|
837
848
|
'settings.placement.tab': '在主對話區顯示 Git 分頁',
|
|
838
849
|
'settings.placement.tabHint': '關閉之後仍可從右側欄或底部面板開啟。',
|
|
850
|
+
'settings.placement.immersive': '沉浸模式(佔滿全高,隱藏輸入框)',
|
|
851
|
+
'settings.placement.immersiveHint': '開啟之後 Git 分頁會佔滿整個對話區高度,輸入框自動收起;審核與提問仍會正常顯示。',
|
|
852
|
+
'preview.openFile': '開啟檔案預覽',
|
|
853
|
+
'preview.title': 'Git 預覽',
|
|
854
|
+
'preview.hint': '點選檔案或提交的「顯示差異」,差異就會在側邊欄開啟。',
|
|
839
855
|
'settings.rail.title': '動作列按鈕',
|
|
840
856
|
'settings.rail.hint': '勾選要顯示在動作列上的動作;順序固定,取消勾選即隱藏。',
|
|
841
857
|
'settings.rail.unavailable': '目前宿主沒有設定服務,請用面板內的「動作條設定」。',
|
|
@@ -1005,7 +1021,6 @@ window.__ModuleLoader__.load({
|
|
|
1005
1021
|
'action.copyHash': '複製修訂號',
|
|
1006
1022
|
'action.details': '提交詳情',
|
|
1007
1023
|
'menu.sendToChat': '傳送至對話',
|
|
1008
|
-
'menu.sendFilePathToChat': '傳送檔案路徑至對話',
|
|
1009
1024
|
'send.commitText': 'git 提交 {hash}「{subject}」(存放庫 {repo})',
|
|
1010
1025
|
'send.branchText': 'git 分支 {name}(存放庫 {repo})',
|
|
1011
1026
|
'menu.sendDiffLinesToChat': '傳送選中行至對話',
|
|
@@ -1047,6 +1062,11 @@ window.__ModuleLoader__.load({
|
|
|
1047
1062
|
'settings.placement.title': '面板放置',
|
|
1048
1063
|
'settings.placement.tab': '喺主對話區顯示 Git 分頁',
|
|
1049
1064
|
'settings.placement.tabHint': '關閉之後仍可從右側欄或底部面板開啟。',
|
|
1065
|
+
'settings.placement.immersive': '沉浸模式(佔滿全高,隱藏輸入框)',
|
|
1066
|
+
'settings.placement.immersiveHint': '開啟之後 Git 分頁會佔滿整個會話區高度,輸入框自動收起;審批與提問仍會正常顯示。',
|
|
1067
|
+
'preview.openFile': '開啟檔案預覽',
|
|
1068
|
+
'preview.title': 'Git 預覽',
|
|
1069
|
+
'preview.hint': '喺檔案或提交撳「顯示差異」,差異就會喺側邊欄度開啟。',
|
|
1050
1070
|
'settings.rail.title': '動作列按鈕',
|
|
1051
1071
|
'settings.rail.hint': '勾選要顯示在動作列上的動作;順序固定,取消勾選即隱藏。',
|
|
1052
1072
|
'settings.rail.unavailable': '目前宿主沒有設定服務,請用面板內的「動作條設定」。',
|
|
@@ -1216,7 +1236,6 @@ window.__ModuleLoader__.load({
|
|
|
1216
1236
|
'action.copyHash': 'リビジョン番号をコピー',
|
|
1217
1237
|
'action.details': 'コミットの詳細',
|
|
1218
1238
|
'menu.sendToChat': 'チャットへ送る',
|
|
1219
|
-
'menu.sendFilePathToChat': 'ファイルパスをチャットへ送る',
|
|
1220
1239
|
'send.commitText': 'git コミット {hash}「{subject}」(リポジトリ {repo})',
|
|
1221
1240
|
'send.branchText': 'git ブランチ {name}(リポジトリ {repo})',
|
|
1222
1241
|
'menu.sendDiffLinesToChat': '選択した行をチャットへ送る',
|
|
@@ -1258,6 +1277,11 @@ window.__ModuleLoader__.load({
|
|
|
1258
1277
|
'settings.placement.title': 'パネル配置',
|
|
1259
1278
|
'settings.placement.tab': '会話エリアに Git タブを表示',
|
|
1260
1279
|
'settings.placement.tabHint': 'オフにしても右サイドバーと下部パネルから開けます。',
|
|
1280
|
+
'settings.placement.immersive': '没入モード(全高表示・入力欄を非表示)',
|
|
1281
|
+
'settings.placement.immersiveHint': 'オンにすると Git タブが会話エリアの高さいっぱいに広がり、入力欄は引っ込みます。承認や質問は通常どおり表示されます。',
|
|
1282
|
+
'preview.openFile': 'ファイルプレビューを開く',
|
|
1283
|
+
'preview.title': 'Git プレビュー',
|
|
1284
|
+
'preview.hint': 'ファイルやコミットの「差分を表示」をクリックすると、差分がここに開きます。',
|
|
1261
1285
|
'settings.rail.title': 'アクションレールのボタン',
|
|
1262
1286
|
'settings.rail.hint': 'レールに表示する操作にチェックを入れてください。順序は固定で、チェックを外すと非表示になります。',
|
|
1263
1287
|
'settings.rail.unavailable': 'このホストには設定サービスがないため、パネル内の「アクションレール設定」を使ってください。',
|
|
@@ -1427,7 +1451,6 @@ window.__ModuleLoader__.load({
|
|
|
1427
1451
|
'action.copyHash': '리비전 번호 복사',
|
|
1428
1452
|
'action.details': '커밋 상세',
|
|
1429
1453
|
'menu.sendToChat': '대화로 보내기',
|
|
1430
|
-
'menu.sendFilePathToChat': '파일 경로를 대화로 보내기',
|
|
1431
1454
|
'send.commitText': 'git 커밋 {hash} "{subject}" (저장소 {repo})',
|
|
1432
1455
|
'send.branchText': 'git 브랜치 {name} (저장소 {repo})',
|
|
1433
1456
|
'menu.sendDiffLinesToChat': '선택한 줄 대화로 보내기',
|
|
@@ -1469,6 +1492,11 @@ window.__ModuleLoader__.load({
|
|
|
1469
1492
|
'settings.placement.title': '패널 배치',
|
|
1470
1493
|
'settings.placement.tab': '대화 영역에 Git 탭 표시',
|
|
1471
1494
|
'settings.placement.tabHint': '꺼도 오른쪽 사이드바와 하단 패널에서 열 수 있습니다.',
|
|
1495
|
+
'settings.placement.immersive': '몰입 모드(전체 높이, 입력창 숨김)',
|
|
1496
|
+
'settings.placement.immersiveHint': '켜면 Git 탭이 대화 영역 전체 높이를 차지하고 입력창은 숨겨집니다. 승인과 질문은 정상적으로 표시됩니다.',
|
|
1497
|
+
'preview.openFile': '파일 미리보기로 열기',
|
|
1498
|
+
'preview.title': 'Git 미리보기',
|
|
1499
|
+
'preview.hint': '파일이나 커밋의 「차이 보기」를 클릭하면 차이가 사이드바 여기에 열립니다.',
|
|
1472
1500
|
'settings.rail.title': '액션 레일 버튼',
|
|
1473
1501
|
'settings.rail.hint': '레일에 표시할 동작을 선택하세요. 순서는 고정이며 선택을 해제하면 숨겨집니다.',
|
|
1474
1502
|
'settings.rail.unavailable': '이 호스트에는 설정 서비스가 없으므로 패널의 "액션 레일 설정"을 사용하세요.',
|
|
@@ -1638,7 +1666,6 @@ window.__ModuleLoader__.load({
|
|
|
1638
1666
|
'action.copyHash': 'Revisionsnummer kopieren',
|
|
1639
1667
|
'action.details': 'Commit-Details',
|
|
1640
1668
|
'menu.sendToChat': 'Im Chat senden',
|
|
1641
|
-
'menu.sendFilePathToChat': 'Dateipfad im Chat senden',
|
|
1642
1669
|
'send.commitText': 'git-Commit {hash} "{subject}" (Repository {repo})',
|
|
1643
1670
|
'send.branchText': 'git-Branch {name} (Repository {repo})',
|
|
1644
1671
|
'menu.sendDiffLinesToChat': 'Ausgewählte Zeilen in den Chat senden',
|
|
@@ -1680,6 +1707,11 @@ window.__ModuleLoader__.load({
|
|
|
1680
1707
|
'settings.placement.title': 'Panel-Platzierung',
|
|
1681
1708
|
'settings.placement.tab': 'Git-Tab im Gesprächsbereich anzeigen',
|
|
1682
1709
|
'settings.placement.tabHint': 'Ausgeschaltet bleibt das Panel über rechte Seitenleiste und unteres Panel erreichbar.',
|
|
1710
|
+
'settings.placement.immersive': 'Immersiver Modus (volle Höhe, ausgeblendetes Eingabefeld)',
|
|
1711
|
+
'settings.placement.immersiveHint': 'Eingeschaltet füllt der Git-Tab die gesamte Gesprächshöhe und das Eingabefeld weicht zurück; Freigaben und Rückfragen bleiben sichtbar.',
|
|
1712
|
+
'preview.openFile': 'In der Dateivorschau öffnen',
|
|
1713
|
+
'preview.title': 'Git-Vorschau',
|
|
1714
|
+
'preview.hint': '„Diff anzeigen“ an einer Datei oder einem Commit öffnet den Diff hier in der Seitenleiste.',
|
|
1683
1715
|
'settings.rail.title': 'Schaltflächen der Aktionsleiste',
|
|
1684
1716
|
'settings.rail.hint': 'Die auf der Leiste sichtbaren Aktionen ankreuzen. Die Reihenfolge ist fest; abwählen blendet eine aus.',
|
|
1685
1717
|
'settings.rail.unavailable': 'Dieser Host hat keinen Einstellungsdienst; nutze die „Aktionsleisten-Einstellungen“ im Panel.',
|
|
@@ -1849,7 +1881,6 @@ window.__ModuleLoader__.load({
|
|
|
1849
1881
|
'action.copyHash': 'Copier le numéro de révision',
|
|
1850
1882
|
'action.details': 'Détails du commit',
|
|
1851
1883
|
'menu.sendToChat': 'Envoyer dans la conversation',
|
|
1852
|
-
'menu.sendFilePathToChat': 'Envoyer le chemin du fichier dans la conversation',
|
|
1853
1884
|
'send.commitText': 'commit git {hash} « {subject} » (dépôt {repo})',
|
|
1854
1885
|
'send.branchText': 'branche git {name} (dépôt {repo})',
|
|
1855
1886
|
'menu.sendDiffLinesToChat': 'Envoyer les lignes sélectionnées dans la conversation',
|
|
@@ -1891,6 +1922,11 @@ window.__ModuleLoader__.load({
|
|
|
1891
1922
|
'settings.placement.title': 'Placement du panneau',
|
|
1892
1923
|
'settings.placement.tab': 'Afficher l’onglet Git dans la zone de conversation',
|
|
1893
1924
|
'settings.placement.tabHint': 'Désactivé, le panneau reste accessible depuis la barre latérale droite et le panneau inférieur.',
|
|
1925
|
+
'settings.placement.immersive': 'Mode immersif (pleine hauteur, zone de saisie masquée)',
|
|
1926
|
+
'settings.placement.immersiveHint': 'Activé, l’onglet Git occupe toute la hauteur de la conversation et la zone de saisie s’efface ; approbations et questions restent visibles.',
|
|
1927
|
+
'preview.openFile': 'Ouvrir dans l’aperçu du fichier',
|
|
1928
|
+
'preview.title': 'Aperçu Git',
|
|
1929
|
+
'preview.hint': 'Cliquez sur « Afficher le diff » sur un fichier ou un commit : le diff s’ouvre ici, dans la barre latérale.',
|
|
1894
1930
|
'settings.rail.title': 'Boutons de la barre d’actions',
|
|
1895
1931
|
'settings.rail.hint': 'Cochez les actions affichées sur la barre. L’ordre est fixe ; décocher masque une action.',
|
|
1896
1932
|
'settings.rail.unavailable': 'Cet hôte n’a pas de service de réglages ; utilisez « Réglages de la barre d’actions » dans le panneau.',
|
|
@@ -2060,7 +2096,6 @@ window.__ModuleLoader__.load({
|
|
|
2060
2096
|
'action.copyHash': 'Скопировать номер ревизии',
|
|
2061
2097
|
'action.details': 'Сведения о коммите',
|
|
2062
2098
|
'menu.sendToChat': 'Отправить в чат',
|
|
2063
|
-
'menu.sendFilePathToChat': 'Отправить путь к файлу в чат',
|
|
2064
2099
|
'send.commitText': 'git-коммит {hash} «{subject}» (репозиторий {repo})',
|
|
2065
2100
|
'send.branchText': 'git-ветка {name} (репозиторий {repo})',
|
|
2066
2101
|
'menu.sendDiffLinesToChat': 'Отправить выбранные строки в чат',
|
|
@@ -2102,6 +2137,11 @@ window.__ModuleLoader__.load({
|
|
|
2102
2137
|
'settings.placement.title': 'Размещение панели',
|
|
2103
2138
|
'settings.placement.tab': 'Показывать вкладку Git в области диалога',
|
|
2104
2139
|
'settings.placement.tabHint': 'В выключенном виде панель доступна из правой боковой панели и нижней панели.',
|
|
2140
|
+
'settings.placement.immersive': 'Полноэкранный режим (во всю высоту, без поля ввода)',
|
|
2141
|
+
'settings.placement.immersiveHint': 'Во включённом виде вкладка Git занимает всю высоту области диалога, поле ввода скрывается; подтверждения и вопросы остаются на виду.',
|
|
2142
|
+
'preview.openFile': 'Открыть в предпросмотре файла',
|
|
2143
|
+
'preview.title': 'Git-предпросмотр',
|
|
2144
|
+
'preview.hint': 'Нажмите «Показать различия» у файла или коммита — различия откроются здесь, в боковой панели.',
|
|
2105
2145
|
'settings.rail.title': 'Кнопки панели действий',
|
|
2106
2146
|
'settings.rail.hint': 'Отметьте действия, показываемые на панели. Порядок фиксирован; снятие флажка скрывает действие.',
|
|
2107
2147
|
'settings.rail.unavailable': 'На этом хосте нет службы настроек; используйте «Настройки панели действий» в панели.',
|
|
@@ -2271,7 +2311,6 @@ window.__ModuleLoader__.load({
|
|
|
2271
2311
|
'action.copyHash': 'Copiar número da revisão',
|
|
2272
2312
|
'action.details': 'Detalhes do commit',
|
|
2273
2313
|
'menu.sendToChat': 'Enviar para a conversa',
|
|
2274
|
-
'menu.sendFilePathToChat': 'Enviar caminho do arquivo para a conversa',
|
|
2275
2314
|
'send.commitText': 'commit git {hash} "{subject}" (repositório {repo})',
|
|
2276
2315
|
'send.branchText': 'branch git {name} (repositório {repo})',
|
|
2277
2316
|
'menu.sendDiffLinesToChat': 'Enviar linhas selecionadas para a conversa',
|
|
@@ -2313,6 +2352,11 @@ window.__ModuleLoader__.load({
|
|
|
2313
2352
|
'settings.placement.title': 'Posição do painel',
|
|
2314
2353
|
'settings.placement.tab': 'Mostrar a aba Git na área de conversa',
|
|
2315
2354
|
'settings.placement.tabHint': 'Desligado, o painel continua disponível na barra lateral direita e no painel inferior.',
|
|
2355
|
+
'settings.placement.immersive': 'Modo imersivo (altura total, campo de entrada oculto)',
|
|
2356
|
+
'settings.placement.immersiveHint': 'Ativado, a aba Git ocupa toda a altura da conversa e o campo de entrada fica de lado; aprovações e perguntas continuam visíveis.',
|
|
2357
|
+
'preview.openFile': 'Abrir na pré-visualização do arquivo',
|
|
2358
|
+
'preview.title': 'Pré-visualização do Git',
|
|
2359
|
+
'preview.hint': 'Clique em “Mostrar diff” num arquivo ou commit — o diff abre aqui, na barra lateral.',
|
|
2316
2360
|
'settings.rail.title': 'Botões da barra de ações',
|
|
2317
2361
|
'settings.rail.hint': 'Marque as ações exibidas na barra. A ordem é fixa; desmarcar oculta uma ação.',
|
|
2318
2362
|
'settings.rail.unavailable': 'Este host não tem serviço de configurações; use «Configurações da barra de ações» no painel.',
|
|
@@ -2482,7 +2526,6 @@ window.__ModuleLoader__.load({
|
|
|
2482
2526
|
'action.copyHash': 'Copia il numero di revisione',
|
|
2483
2527
|
'action.details': 'Dettagli del commit',
|
|
2484
2528
|
'menu.sendToChat': 'Invia alla conversazione',
|
|
2485
|
-
'menu.sendFilePathToChat': 'Invia il percorso del file alla conversazione',
|
|
2486
2529
|
'send.commitText': 'commit git {hash} "{subject}" (repository {repo})',
|
|
2487
2530
|
'send.branchText': 'branch git {name} (repository {repo})',
|
|
2488
2531
|
'menu.sendDiffLinesToChat': 'Invia le righe selezionate alla conversazione',
|
|
@@ -2524,6 +2567,11 @@ window.__ModuleLoader__.load({
|
|
|
2524
2567
|
'settings.placement.title': 'Posizione del pannello',
|
|
2525
2568
|
'settings.placement.tab': 'Mostra la scheda Git nell’area conversazione',
|
|
2526
2569
|
'settings.placement.tabHint': 'Da spento, il pannello resta raggiungibile dalla barra laterale destra e dal pannello inferiore.',
|
|
2570
|
+
'settings.placement.immersive': 'Modalità immersiva (altezza piena, input nascosto)',
|
|
2571
|
+
'settings.placement.immersiveHint': 'Attiva, la scheda Git occupa tutta l’altezza della conversazione e la barra di input resta nascosta; approvazioni e domande restano visibili.',
|
|
2572
|
+
'preview.openFile': 'Apri nell’anteprima del file',
|
|
2573
|
+
'preview.title': 'Anteprima Git',
|
|
2574
|
+
'preview.hint': 'Fai clic su «Mostra diff» su un file o un commit: il diff si apre qui, nella barra laterale.',
|
|
2527
2575
|
'settings.rail.title': 'Pulsanti della barra azioni',
|
|
2528
2576
|
'settings.rail.hint': 'Seleziona le azioni mostrate sulla barra. L’ordine è fisso; deselezionando se ne nasconde una.',
|
|
2529
2577
|
'settings.rail.unavailable': 'Questo host non ha un servizio di impostazioni; usa «Impostazioni barra azioni» nel pannello.',
|
|
@@ -2693,7 +2741,6 @@ window.__ModuleLoader__.load({
|
|
|
2693
2741
|
'action.copyHash': 'Revisienummer kopiëren',
|
|
2694
2742
|
'action.details': 'Commit-details',
|
|
2695
2743
|
'menu.sendToChat': 'Naar het gesprek verzenden',
|
|
2696
|
-
'menu.sendFilePathToChat': 'Bestandspad naar het gesprek verzenden',
|
|
2697
2744
|
'send.commitText': 'git-commit {hash} "{subject}" (repository {repo})',
|
|
2698
2745
|
'send.branchText': 'git-branch {name} (repository {repo})',
|
|
2699
2746
|
'menu.sendDiffLinesToChat': 'Geselecteerde regels naar het gesprek verzenden',
|
|
@@ -2735,6 +2782,11 @@ window.__ModuleLoader__.load({
|
|
|
2735
2782
|
'settings.placement.title': 'Paneelplaatsing',
|
|
2736
2783
|
'settings.placement.tab': 'Git-tabblad in het gespreksgebied tonen',
|
|
2737
2784
|
'settings.placement.tabHint': 'Uitgeschakeld blijft het paneel bereikbaar via de rechterzijbalk en het onderpaneel.',
|
|
2785
|
+
'settings.placement.immersive': 'Meeslepende modus (volledige hoogte, verborgen invoerveld)',
|
|
2786
|
+
'settings.placement.immersiveHint': 'Aan: het Git-tabblad vult de hele gespreksruimte en het invoerveld wijkt; goedkeuringen en vragen blijven zichtbaar.',
|
|
2787
|
+
'preview.openFile': 'Openen in de bestandsvoorbeeld',
|
|
2788
|
+
'preview.title': 'Git-voorbeeld',
|
|
2789
|
+
'preview.hint': 'Klik op „Diff tonen“ bij een bestand of commit — de diff opent hier in de zijbalk.',
|
|
2738
2790
|
'settings.rail.title': 'Knoppen van de actiebalk',
|
|
2739
2791
|
'settings.rail.hint': 'Vink de acties aan die op de balk verschijnen. De volgorde ligt vast; uitvinken verbergt er een.',
|
|
2740
2792
|
'settings.rail.unavailable': 'Deze host heeft geen instellingenservice; gebruik "Actiebalk-instellingen" in het paneel.',
|
|
@@ -2904,7 +2956,6 @@ window.__ModuleLoader__.load({
|
|
|
2904
2956
|
'action.copyHash': 'Kopiuj numer wersji',
|
|
2905
2957
|
'action.details': 'Szczegóły commita',
|
|
2906
2958
|
'menu.sendToChat': 'Wyślij do rozmowy',
|
|
2907
|
-
'menu.sendFilePathToChat': 'Wyślij ścieżkę pliku do rozmowy',
|
|
2908
2959
|
'send.commitText': 'commit git {hash} „{subject}" (repozytorium {repo})',
|
|
2909
2960
|
'send.branchText': 'gałąź git {name} (repozytorium {repo})',
|
|
2910
2961
|
'menu.sendDiffLinesToChat': 'Wyślij zaznaczone wiersze do rozmowy',
|
|
@@ -2946,6 +2997,11 @@ window.__ModuleLoader__.load({
|
|
|
2946
2997
|
'settings.placement.title': 'Rozmieszczenie panelu',
|
|
2947
2998
|
'settings.placement.tab': 'Pokazuj kartę Git w obszarze rozmowy',
|
|
2948
2999
|
'settings.placement.tabHint': 'Po wyłączeniu panel pozostaje dostępny z prawego paska bocznego i dolnego panelu.',
|
|
3000
|
+
'settings.placement.immersive': 'Tryb immersyjny (pełna wysokość, ukryte pole wpisywania)',
|
|
3001
|
+
'settings.placement.immersiveHint': 'Po włączeniu karta Git wypełnia całą wysokość rozmowy, a pole wpisywania się chowa; zatwierdzenia i pytania pozostają widoczne.',
|
|
3002
|
+
'preview.openFile': 'Otwórz w podglądzie pliku',
|
|
3003
|
+
'preview.title': 'Podgląd Git',
|
|
3004
|
+
'preview.hint': 'Kliknij „Pokaż różnice” przy pliku lub commicie — różnice otworzą się tutaj, na pasku bocznym.',
|
|
2949
3005
|
'settings.rail.title': 'Przyciski paska akcji',
|
|
2950
3006
|
'settings.rail.hint': 'Zaznacz akcje widoczne na pasku. Kolejność jest stała; odznaczenie ukrywa akcję.',
|
|
2951
3007
|
'settings.rail.unavailable': 'Ten host nie ma usługi ustawień; użyj „Ustawienia paska akcji” w panelu.',
|
|
@@ -3115,7 +3171,6 @@ window.__ModuleLoader__.load({
|
|
|
3115
3171
|
'action.copyHash': 'Kopiera revisionsnummer',
|
|
3116
3172
|
'action.details': 'Commit-detaljer',
|
|
3117
3173
|
'menu.sendToChat': 'Skicka till samtalet',
|
|
3118
|
-
'menu.sendFilePathToChat': 'Skicka filsökvägen till samtalet',
|
|
3119
3174
|
'send.commitText': 'git-commit {hash} ”{subject}” (arkiv {repo})',
|
|
3120
3175
|
'send.branchText': 'git-gren {name} (arkiv {repo})',
|
|
3121
3176
|
'menu.sendDiffLinesToChat': 'Skicka markerade rader till samtalet',
|
|
@@ -3157,6 +3212,11 @@ window.__ModuleLoader__.load({
|
|
|
3157
3212
|
'settings.placement.title': 'Panelplacering',
|
|
3158
3213
|
'settings.placement.tab': 'Visa Git-fliken i konversationsytan',
|
|
3159
3214
|
'settings.placement.tabHint': 'Avstängd finns panelen kvar via höger sidopanel och nedre panelen.',
|
|
3215
|
+
'settings.placement.immersive': 'Uppslukande läge (full höjd, dolt inmatningsfält)',
|
|
3216
|
+
'settings.placement.immersiveHint': 'På: Git-fliken fyller hela konversationsytan och inmatningsfältet träder åt sidan; godkännanden och frågor visas fortfarande.',
|
|
3217
|
+
'preview.openFile': 'Öppna i filförhandsvisningen',
|
|
3218
|
+
'preview.title': 'Git-förhandsvisning',
|
|
3219
|
+
'preview.hint': 'Klicka på ”Visa diff” på en fil eller en commit — diffen öppnas här i sidopanelen.',
|
|
3160
3220
|
'settings.rail.title': 'Knappar i åtgärdsfältet',
|
|
3161
3221
|
'settings.rail.hint': 'Markera de åtgärder som visas i fältet. Ordningen är fast; avmarkering döljer en.',
|
|
3162
3222
|
'settings.rail.unavailable': 'Denna värd saknar inställningstjänst; använd ”Åtgärdsfältets inställningar” i panelen.',
|
|
@@ -3326,7 +3386,6 @@ window.__ModuleLoader__.load({
|
|
|
3326
3386
|
'action.copyHash': 'Revizyon numarasını kopyala',
|
|
3327
3387
|
'action.details': 'Commit ayrıntıları',
|
|
3328
3388
|
'menu.sendToChat': 'Sohbete gönder',
|
|
3329
|
-
'menu.sendFilePathToChat': 'Dosya yolunu sohbete gönder',
|
|
3330
3389
|
'send.commitText': 'git commit {hash} "{subject}" (depo {repo})',
|
|
3331
3390
|
'send.branchText': 'git dalı {name} (depo {repo})',
|
|
3332
3391
|
'menu.sendDiffLinesToChat': 'Seçili satırları sohbete gönder',
|
|
@@ -3368,6 +3427,11 @@ window.__ModuleLoader__.load({
|
|
|
3368
3427
|
'settings.placement.title': 'Panel yerleşimi',
|
|
3369
3428
|
'settings.placement.tab': 'Konuşma alanında Git sekmesini göster',
|
|
3370
3429
|
'settings.placement.tabHint': 'Kapatıldığında panel sağ kenar çubuğundan ve alt panelden açılabilir.',
|
|
3430
|
+
'settings.placement.immersive': 'Odaklanma modu (tam yükseklik, gizli giriş alanı)',
|
|
3431
|
+
'settings.placement.immersiveHint': 'Açıkken Git sekmesi tüm konuşma alanını kaplar ve giriş alanı gizlenir; onaylar ve sorular yine de görünür.',
|
|
3432
|
+
'preview.openFile': 'Dosya önizlemesinde aç',
|
|
3433
|
+
'preview.title': 'Git Önizlemesi',
|
|
3434
|
+
'preview.hint': 'Bir dosya veya commit üzerinde „Farkı göster”e tıklayın — fark burada, kenar çubuğunda açılır.',
|
|
3371
3435
|
'settings.rail.title': 'Eylem çubuğu düğmeleri',
|
|
3372
3436
|
'settings.rail.hint': 'Çubukta gösterilecek eylemleri işaretleyin. Sıra sabittir; işareti kaldırmak eylemi gizler.',
|
|
3373
3437
|
'settings.rail.unavailable': 'Bu ana bilgisayarda ayar hizmeti yok; paneldeki "Eylem çubuğu ayarları"nı kullanın.',
|
|
@@ -3537,7 +3601,6 @@ window.__ModuleLoader__.load({
|
|
|
3537
3601
|
'action.copyHash': 'Salin nomor revisi',
|
|
3538
3602
|
'action.details': 'Detail commit',
|
|
3539
3603
|
'menu.sendToChat': 'Kirim ke obrolan',
|
|
3540
|
-
'menu.sendFilePathToChat': 'Kirim jalur berkas ke obrolan',
|
|
3541
3604
|
'send.commitText': 'commit git {hash} "{subject}" (repositori {repo})',
|
|
3542
3605
|
'send.branchText': 'cabang git {name} (repositori {repo})',
|
|
3543
3606
|
'menu.sendDiffLinesToChat': 'Kirim baris terpilih ke obrolan',
|
|
@@ -3579,6 +3642,11 @@ window.__ModuleLoader__.load({
|
|
|
3579
3642
|
'settings.placement.title': 'Penempatan panel',
|
|
3580
3643
|
'settings.placement.tab': 'Tampilkan tab Git di area percakapan',
|
|
3581
3644
|
'settings.placement.tabHint': 'Dimatikan, panel tetap bisa dibuka dari bilah sisi kanan dan panel bawah.',
|
|
3645
|
+
'settings.placement.immersive': 'Mode imersif (tinggi penuh, kolom masukan tersembunyi)',
|
|
3646
|
+
'settings.placement.immersiveHint': 'Aktif: tab Git memenuhi seluruh tinggi area percakapan dan kolom masukan mengalah; persetujuan dan pertanyaan tetap tampil.',
|
|
3647
|
+
'preview.openFile': 'Buka di pratinjau berkas',
|
|
3648
|
+
'preview.title': 'Pratinjau Git',
|
|
3649
|
+
'preview.hint': 'Klik “Tampilkan diff” pada file atau commit — diff terbuka di sini, di bilah sisi.',
|
|
3582
3650
|
'settings.rail.title': 'Tombol bilah aksi',
|
|
3583
3651
|
'settings.rail.hint': 'Centang aksi yang ditampilkan di bilah. Urutannya tetap; menghapus centang menyembunyikannya.',
|
|
3584
3652
|
'settings.rail.unavailable': 'Host ini tidak punya layanan pengaturan; gunakan "Pengaturan bilah aksi" di panel.',
|
|
@@ -3748,7 +3816,6 @@ window.__ModuleLoader__.load({
|
|
|
3748
3816
|
'action.copyHash': 'Sao chép số hiệu bản sửa',
|
|
3749
3817
|
'action.details': 'Chi tiết commit',
|
|
3750
3818
|
'menu.sendToChat': 'Gửi vào hội thoại',
|
|
3751
|
-
'menu.sendFilePathToChat': 'Gửi đường dẫn tệp vào hội thoại',
|
|
3752
3819
|
'send.commitText': 'git commit {hash} "{subject}" (kho {repo})',
|
|
3753
3820
|
'send.branchText': 'nhánh git {name} (kho {repo})',
|
|
3754
3821
|
'menu.sendDiffLinesToChat': 'Gửi các dòng đã chọn vào hội thoại',
|
|
@@ -3790,6 +3857,11 @@ window.__ModuleLoader__.load({
|
|
|
3790
3857
|
'settings.placement.title': 'Vị trí bảng',
|
|
3791
3858
|
'settings.placement.tab': 'Hiện thẻ Git trong vùng hội thoại',
|
|
3792
3859
|
'settings.placement.tabHint': 'Tắt rồi, bảng vẫn mở được từ thanh bên phải và bảng dưới.',
|
|
3860
|
+
'settings.placement.immersive': 'Chế độ đắm chìm (chiều cao đầy đủ, ẩn ô nhập)',
|
|
3861
|
+
'settings.placement.immersiveHint': 'Bật: thẻ Git chiếm toàn bộ chiều cao vùng hội thoại và ô nhập thu vào; phê duyệt và câu hỏi vẫn hiển thị bình thường.',
|
|
3862
|
+
'preview.openFile': 'Mở trong xem trước tệp',
|
|
3863
|
+
'preview.title': 'Xem trước Git',
|
|
3864
|
+
'preview.hint': 'Bấm “Xem diff” trên tệp hoặc commit — diff sẽ mở ở đây, trên thanh bên.',
|
|
3793
3865
|
'settings.rail.title': 'Nút thanh tác vụ',
|
|
3794
3866
|
'settings.rail.hint': 'Chọn các tác vụ hiển thị trên thanh. Thứ tự cố định; bỏ chọn sẽ ẩn tác vụ đó.',
|
|
3795
3867
|
'settings.rail.unavailable': 'Máy chủ này không có dịch vụ cài đặt; hãy dùng “Cài đặt thanh tác vụ” trong bảng điều khiển.',
|
|
@@ -3959,7 +4031,6 @@ window.__ModuleLoader__.load({
|
|
|
3959
4031
|
'action.copyHash': 'نسخ رقم المراجعة',
|
|
3960
4032
|
'action.details': 'تفاصيل الالتزام',
|
|
3961
4033
|
'menu.sendToChat': 'إرسال إلى المحادثة',
|
|
3962
|
-
'menu.sendFilePathToChat': 'إرسال مسار الملف إلى المحادثة',
|
|
3963
4034
|
'send.commitText': 'التزام git {hash} "{subject}" (المستودع {repo})',
|
|
3964
4035
|
'send.branchText': 'فرع git {name} (المستودع {repo})',
|
|
3965
4036
|
'menu.sendDiffLinesToChat': 'إرسال الأسطر المحددة إلى المحادثة',
|
|
@@ -4001,6 +4072,11 @@ window.__ModuleLoader__.load({
|
|
|
4001
4072
|
'settings.placement.title': 'موضع اللوحة',
|
|
4002
4073
|
'settings.placement.tab': 'إظهار تبويب Git في منطقة المحادثة',
|
|
4003
4074
|
'settings.placement.tabHint': 'عند الإيقاف تبقى اللوحة متاحة من الشريط الجانبي الأيمن واللوحة السفلية.',
|
|
4075
|
+
'settings.placement.immersive': 'الوضع الغامر (ارتفاع كامل، إخفاء صندوق الكتابة)',
|
|
4076
|
+
'settings.placement.immersiveHint': 'عند التشغيل يملأ تبويب Git منطقة المحادثة بكامل ارتفاعها ويتراجع صندوق الكتابة؛ تظل الموافقات والأسئلة ظاهرة كالمعتاد.',
|
|
4077
|
+
'preview.openFile': 'افتح في معاينة الملف',
|
|
4078
|
+
'preview.title': 'معاينة Git',
|
|
4079
|
+
'preview.hint': 'انقر «عرض الفروق» على ملف أو commit — تُفتح الفروق هنا في الشريط الجانبي.',
|
|
4004
4080
|
'settings.rail.title': 'أزرار شريط الإجراءات',
|
|
4005
4081
|
'settings.rail.hint': 'حدّد الإجراءات المعروضة على الشريط. الترتيب ثابت، وإلغاء التحديد يخفي الإجراء.',
|
|
4006
4082
|
'settings.rail.unavailable': 'لا تتوفر خدمة إعدادات على هذا المضيف؛ استخدم «إعدادات شريط الإجراءات» في اللوحة.',
|
|
@@ -4170,7 +4246,6 @@ window.__ModuleLoader__.load({
|
|
|
4170
4246
|
'action.copyHash': 'रिवीज़न संख्या कॉपी करें',
|
|
4171
4247
|
'action.details': 'कमिट विवरण',
|
|
4172
4248
|
'menu.sendToChat': 'बातचीत में भेजें',
|
|
4173
|
-
'menu.sendFilePathToChat': 'फ़ाइल पथ बातचीत में भेजें',
|
|
4174
4249
|
'send.commitText': 'git कमिट {hash} "{subject}" (रिपॉज़िटरी {repo})',
|
|
4175
4250
|
'send.branchText': 'git ब्रांच {name} (रिपॉज़िटरी {repo})',
|
|
4176
4251
|
'menu.sendDiffLinesToChat': 'चयनित पंक्तियाँ बातचीत में भेजें',
|
|
@@ -4212,6 +4287,11 @@ window.__ModuleLoader__.load({
|
|
|
4212
4287
|
'settings.placement.title': 'पैनल प्लेसमेंट',
|
|
4213
4288
|
'settings.placement.tab': 'संवाद क्षेत्र में Git टैब दिखाएँ',
|
|
4214
4289
|
'settings.placement.tabHint': 'बंद करने पर भी पैनल दाएँ साइडबार और निचले पैनल से खुलता है।',
|
|
4290
|
+
'settings.placement.immersive': 'इमर्सिव मोड (पूरी ऊँचाई, छिपा इनपुट बॉक्स)',
|
|
4291
|
+
'settings.placement.immersiveHint': 'चालू होने पर Git टैब पूरे संवाद क्षेत्र की ऊँचाई घेर लेता है और इनपुट बॉक्स हट जाता है; अनुमोदन और प्रश्न फिर भी दिखते हैं।',
|
|
4292
|
+
'preview.openFile': 'फ़ाइल पूर्वावलोकन में खोलें',
|
|
4293
|
+
'preview.title': 'Git पूर्वावलोकन',
|
|
4294
|
+
'preview.hint': 'फ़ाइल या कमिट पर “अंतर दिखाएँ” पर क्लिक करें — अंतर यहीं साइडबार में खुलेगा।',
|
|
4215
4295
|
'settings.rail.title': 'एक्शन रेल बटन',
|
|
4216
4296
|
'settings.rail.hint': 'रेल पर दिखने वाली क्रियाएँ चुनें। क्रम निश्चित है; चुनाव हटाने पर वह छिप जाती है।',
|
|
4217
4297
|
'settings.rail.unavailable': 'इस होस्ट में सेटिंग सेवा नहीं है; पैनल में «एक्शन रेल सेटिंग» का उपयोग करें।',
|
|
@@ -4381,7 +4461,6 @@ window.__ModuleLoader__.load({
|
|
|
4381
4461
|
'action.copyHash': 'คัดลอกเลขรีวิชัน',
|
|
4382
4462
|
'action.details': 'รายละเอียดคอมมิต',
|
|
4383
4463
|
'menu.sendToChat': 'ส่งไปยังบทสนทนา',
|
|
4384
|
-
'menu.sendFilePathToChat': 'ส่งพาธไฟล์ไปยังบทสนทนา',
|
|
4385
4464
|
'send.commitText': 'git คอมมิต {hash} "{subject}" (รีโพซิทอรี {repo})',
|
|
4386
4465
|
'send.branchText': 'git บรานช์ {name} (รีโพซิทอรี {repo})',
|
|
4387
4466
|
'menu.sendDiffLinesToChat': 'ส่งบรรทัดที่เลือกไปยังบทสนทนา',
|
|
@@ -4423,6 +4502,11 @@ window.__ModuleLoader__.load({
|
|
|
4423
4502
|
'settings.placement.title': 'ตำแหน่งแผง',
|
|
4424
4503
|
'settings.placement.tab': 'แสดงแท็บ Git ในพื้นที่บทสนทนา',
|
|
4425
4504
|
'settings.placement.tabHint': 'ปิดแล้วยังเปิดแผงจากแถบข้างขวาหรือแผงล่างได้',
|
|
4505
|
+
'settings.placement.immersive': 'โหมดดื่มด่ำ (เต็มความสูง, ซ่อนกล่องพิมพ์)',
|
|
4506
|
+
'settings.placement.immersiveHint': 'เมื่อเปิด แท็บ Git จะกินพื้นที่สูงทั้งหมดของบทสนทนาและกล่องพิมพ์จะถอยออก; การอนุมัติและคำถามยังแสดงตามปกติ',
|
|
4507
|
+
'preview.openFile': 'เปิดในตัวอย่างไฟล์',
|
|
4508
|
+
'preview.title': 'ดูตัวอย่าง Git',
|
|
4509
|
+
'preview.hint': 'คลิก “แสดงความต่าง” ที่ไฟล์หรือคอมมิต — ความต่างจะเปิดที่นี่ในแถบข้าง',
|
|
4426
4510
|
'settings.rail.title': 'ปุ่มแถบการทำงาน',
|
|
4427
4511
|
'settings.rail.hint': 'ทำเครื่องหมายการทำงานที่จะแสดงบนแถบ ลำดับคงที่; ยกเลิกเครื่องหมายเพื่อซ่อน',
|
|
4428
4512
|
'settings.rail.unavailable': 'โฮสต์นี้ไม่มีบริการตั้งค่า ให้ใช้ «ตั้งค่าแถบการทำงาน» ในแผง',
|
|
@@ -4677,16 +4761,19 @@ window.__ModuleLoader__.load({
|
|
|
4677
4761
|
is still essentially correct, so it seeds the states and a background
|
|
4678
4762
|
refresh lands the fresh data a moment later. Pure functions; the panel
|
|
4679
4763
|
only ever reads them at effect time and writes after a fetch. */
|
|
4680
|
-
/* Two
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4764
|
+
/* Two seeds age very differently. The repos scan is the SLOW part (a
|
|
4765
|
+
multi-repo workspace walks directories) and its result barely changes,
|
|
4766
|
+
so its seed keeps a 10-minute TTL: freshness is the background refresh's
|
|
4767
|
+
job — every mount refreshes anyway — the TTL only decides how old a seed
|
|
4768
|
+
may be to still paint the first screen. The page seed (summary /
|
|
4769
|
+
branches / log) used to expire after 30s, which is exactly the user
|
|
4770
|
+
complaint this queue answers ("come back to the panel after a while and
|
|
4771
|
+
everything re-loads"): it is a KEEP-WARM QUEUE now — no expiry at all,
|
|
4772
|
+
an LRU of three workspaces. Every page in the queue paints instantly no
|
|
4773
|
+
matter how long the panel stayed closed; the mount refresh re-proves
|
|
4774
|
+
every field silently right after, so freshness never regresses. */
|
|
4688
4775
|
const PAINT_REPOS_TTL_MS = 600_000
|
|
4689
|
-
const
|
|
4776
|
+
const PAINT_PAGE_KEEP_WARM = 3
|
|
4690
4777
|
const paintRepos = new Map() /* cwd -> { at, data } */
|
|
4691
4778
|
const paintPage = new Map() /* repoRoot -> { at, summary, branches, commits, hasMore } */
|
|
4692
4779
|
const paintRoot = new Map() /* cwd -> last repoRoot the user was looking at */
|
|
@@ -4726,6 +4813,13 @@ window.__ModuleLoader__.load({
|
|
|
4726
4813
|
}
|
|
4727
4814
|
feed(paintRepos, parsed.repos)
|
|
4728
4815
|
feed(paintPage, parsed.page)
|
|
4816
|
+
/* The queue cap applies to restored pages too: storage may hold more
|
|
4817
|
+
than the live queue does (an older build wrote 16), trim to the same
|
|
4818
|
+
three — restored insertion order mirrors the order that was in
|
|
4819
|
+
memory, so the survivors are the most recent pages. */
|
|
4820
|
+
while (paintPage.size > PAINT_PAGE_KEEP_WARM) {
|
|
4821
|
+
paintPage.delete(paintPage.keys().next().value)
|
|
4822
|
+
}
|
|
4729
4823
|
}
|
|
4730
4824
|
|
|
4731
4825
|
function persistPaint() {
|
|
@@ -4755,13 +4849,24 @@ window.__ModuleLoader__.load({
|
|
|
4755
4849
|
function readPaintPage(repoRoot) {
|
|
4756
4850
|
hydratePaint()
|
|
4757
4851
|
const entry = paintPage.get(repoRoot)
|
|
4758
|
-
if (entry === undefined
|
|
4852
|
+
if (entry === undefined) return undefined
|
|
4853
|
+
/* A read is a USE: re-insert at the tail so eviction tracks what the
|
|
4854
|
+
user actually visits, not which page happened to be written last. */
|
|
4855
|
+
paintPage.delete(repoRoot)
|
|
4856
|
+
paintPage.set(repoRoot, entry)
|
|
4759
4857
|
return entry
|
|
4760
4858
|
}
|
|
4761
4859
|
|
|
4762
4860
|
function writePaintPage(repoRoot, page) {
|
|
4763
4861
|
paintPage.set(repoRoot, Object.assign({ at: Date.now() }, page))
|
|
4764
|
-
|
|
4862
|
+
/* The keep-warm queue cap: three workspaces stay painted, the fourth
|
|
4863
|
+
evicts the least-recently-used one. Pure LRU over insertion order —
|
|
4864
|
+
reads re-tail themselves (readPaintPage), so the survivor set is the
|
|
4865
|
+
three repo pages the user actually keeps coming back to. */
|
|
4866
|
+
while (paintPage.size > PAINT_PAGE_KEEP_WARM) {
|
|
4867
|
+
const oldest = paintPage.keys().next().value
|
|
4868
|
+
paintPage.delete(oldest)
|
|
4869
|
+
}
|
|
4765
4870
|
persistPaint()
|
|
4766
4871
|
}
|
|
4767
4872
|
|
|
@@ -5018,6 +5123,19 @@ window.__ModuleLoader__.load({
|
|
|
5018
5123
|
return snapshot
|
|
5019
5124
|
}
|
|
5020
5125
|
|
|
5126
|
+
/* The conversation seat's immersive mode (issue #8 round 3, placement
|
|
5127
|
+
group): the view rides the host's composer-overlay contract so it fills
|
|
5128
|
+
the WHOLE conversation height, and the composer seat hides while the Git
|
|
5129
|
+
view owns the ring. Default ON — that full-height space is why the tab
|
|
5130
|
+
placement exists at all; the settings card flips it live. A host without
|
|
5131
|
+
the row Config keeps the immersive seat (same policy as the tab switch). */
|
|
5132
|
+
function conversationImmersiveEnabled() {
|
|
5133
|
+
const ready = railFormReady()
|
|
5134
|
+
if (ready === null) return true
|
|
5135
|
+
const value = ready.value !== null && typeof ready.value === 'object' ? ready.value.immersive : undefined
|
|
5136
|
+
return value !== false
|
|
5137
|
+
}
|
|
5138
|
+
|
|
5021
5139
|
function readRailConfig() {
|
|
5022
5140
|
const ready = railFormReady()
|
|
5023
5141
|
if (ready !== null) return railConfigOfValues(ready.value)
|
|
@@ -6082,7 +6200,10 @@ window.__ModuleLoader__.load({
|
|
|
6082
6200
|
/* Host-rendered first (v0.14): the ui-primitives diff card brings the
|
|
6083
6201
|
shared toolbar (copy / wrap / language) and the product's diff colors.
|
|
6084
6202
|
A patch we cannot replay into a hunk (binary, mode-only) or a host
|
|
6085
|
-
without the seed module falls back to the hand-drawn rows below.
|
|
6203
|
+
without the seed module falls back to the hand-drawn rows below. This
|
|
6204
|
+
IS the official diff renderer (the platform seed table ships it, the
|
|
6205
|
+
host's own surfaces render diffs through it) — the external preview
|
|
6206
|
+
tab uses the same one, so every diff in the product reads alike. */
|
|
6086
6207
|
if (UIPrimitives !== null && typeof UIPrimitives.DiffBlock === 'function') {
|
|
6087
6208
|
const hunk = patchToHunk(props.patch)
|
|
6088
6209
|
if (hunk !== null) {
|
|
@@ -6156,6 +6277,7 @@ window.__ModuleLoader__.load({
|
|
|
6156
6277
|
grip: ['M5.6 4.6h4.8', 'M5.6 8h4.8', 'M5.6 11.4h4.8'],
|
|
6157
6278
|
filter: ['M2 3.6h12l-4.6 5.2v4.2l-2.8-1.4V8.8z'],
|
|
6158
6279
|
check: ['M3.2 8.4 6.4 11.6 12.8 4.6'],
|
|
6280
|
+
copy: ['M5.5 5.5h8v8h-8z', 'M10.5 5.5v-3h-8v8h3'],
|
|
6159
6281
|
// dock actions (official right sidebar): lift a panel out, drop it back into
|
|
6160
6282
|
// the dock, split the pane, and the full-screen pair reuses expand/collapse.
|
|
6161
6283
|
float: ['M2.5 6.5v7h7v-3', 'M6 10 13.2 2.8', 'M9.4 2.8h3.8v3.8'],
|
|
@@ -6655,6 +6777,50 @@ window.__ModuleLoader__.load({
|
|
|
6655
6777
|
E('span', { id: inputId + '-label', className: 'dig-settings-label', onClick: toggle }, t('settings.placement.tab'))),
|
|
6656
6778
|
E('div', { className: 'dig-settings-subnote' }, t('settings.placement.tabHint')))
|
|
6657
6779
|
})(),
|
|
6780
|
+
(() => {
|
|
6781
|
+
/* Immersive mode (issue #8 round 3): the conversation seat's
|
|
6782
|
+
full-height overlay layout + hidden composer. Default ON — the
|
|
6783
|
+
full-height space is what the tab placement is for; flipping it
|
|
6784
|
+
re-renders the seat live (the ConversationPanel subscribes to the
|
|
6785
|
+
same config). */
|
|
6786
|
+
const field = 'immersive'
|
|
6787
|
+
const inputId = 'dig-placement-' + field
|
|
6788
|
+
const shown = Object.prototype.hasOwnProperty.call(intent.current, field)
|
|
6789
|
+
? intent.current[field] === true
|
|
6790
|
+
: values[field] !== false
|
|
6791
|
+
const toggle = (event) => {
|
|
6792
|
+
if (readOnly === true) { setNote(t('settings.rail.readonly')); return }
|
|
6793
|
+
const fromControl = event !== undefined && event !== null && event.target !== null
|
|
6794
|
+
&& event.target !== undefined && typeof event.target.checked === 'boolean'
|
|
6795
|
+
? event.target.checked
|
|
6796
|
+
: null
|
|
6797
|
+
const wanted = fromControl !== null
|
|
6798
|
+
? fromControl
|
|
6799
|
+
: (Object.prototype.hasOwnProperty.call(intent.current, field)
|
|
6800
|
+
? intent.current[field] !== true
|
|
6801
|
+
: values[field] !== false) !== true
|
|
6802
|
+
intent.current[field] = wanted
|
|
6803
|
+
dirty.current.set(field, wanted)
|
|
6804
|
+
setPending((now) => Object.assign({}, now, { [field]: wanted }))
|
|
6805
|
+
setNote('')
|
|
6806
|
+
bump()
|
|
6807
|
+
scheduleFlush()
|
|
6808
|
+
}
|
|
6809
|
+
return E('div', { key: field },
|
|
6810
|
+
E('div', { className: 'dig-settings-row', 'data-placement-row': field },
|
|
6811
|
+
E('input', {
|
|
6812
|
+
id: inputId,
|
|
6813
|
+
type: 'checkbox',
|
|
6814
|
+
className: 'dig-settings-check',
|
|
6815
|
+
'aria-labelledby': inputId + '-label',
|
|
6816
|
+
checked: shown,
|
|
6817
|
+
disabled: readOnly === true,
|
|
6818
|
+
onChange: toggle,
|
|
6819
|
+
}),
|
|
6820
|
+
E('span', { className: 'dig-settings-glyph' }, E(Icon, { name: 'commit', size: 13 })),
|
|
6821
|
+
E('span', { id: inputId + '-label', className: 'dig-settings-label', onClick: toggle }, t('settings.placement.immersive'))),
|
|
6822
|
+
E('div', { className: 'dig-settings-subnote' }, t('settings.placement.immersiveHint')))
|
|
6823
|
+
})(),
|
|
6658
6824
|
E('div', { className: 'dig-settings-sub' }, t('settings.commit.title')),
|
|
6659
6825
|
(() => {
|
|
6660
6826
|
/* The model row is a picker over the host's provider catalog; while
|
|
@@ -7682,8 +7848,23 @@ window.__ModuleLoader__.load({
|
|
|
7682
7848
|
props.openSettings()
|
|
7683
7849
|
}
|
|
7684
7850
|
|
|
7851
|
+
/* The immersive conversation seat (v0.14) hands the panel a SQUARE-ish
|
|
7852
|
+
box by construction: the conversation column clamps content width
|
|
7853
|
+
(~920px) while the seat fills the view's whole height, so the
|
|
7854
|
+
bottom-workbench-vs-sidebar ratio (`width >= height * 1.15`) can never
|
|
7855
|
+
hold there and the panel would flip to the stacked layout. The seat is
|
|
7856
|
+
a tool window — neither a horizontal dock nor a narrow rail — so it
|
|
7857
|
+
always takes the columns chrome (compact still wins: a truly narrow
|
|
7858
|
+
viewport keeps the single-row layout). */
|
|
7859
|
+
const [immersiveSeat, setImmersiveSeat] = useState(false)
|
|
7860
|
+
useMeasureLayoutEffect(() => {
|
|
7861
|
+
const node = hostRef.current
|
|
7862
|
+
const holder = node === null || typeof node.closest !== 'function' ? null : node.closest('.dig-conversation-seat[data-immersive="1"]')
|
|
7863
|
+
setImmersiveSeat(holder !== null)
|
|
7864
|
+
})
|
|
7685
7865
|
const compact = size.width > 0 && size.width < COMPACT_MAX_WIDTH
|
|
7686
|
-
const columns =
|
|
7866
|
+
const columns = (immersiveSeat === true && compact === false)
|
|
7867
|
+
|| (!compact && size.width >= 600 && size.width >= size.height * 1.15)
|
|
7687
7868
|
|
|
7688
7869
|
/* ---------- draggable panes (issue #5) ---------- */
|
|
7689
7870
|
|
|
@@ -8010,6 +8191,87 @@ window.__ModuleLoader__.load({
|
|
|
8010
8191
|
}
|
|
8011
8192
|
}, [base])
|
|
8012
8193
|
|
|
8194
|
+
/* ---------- external diff preview (user request, 2026-10-08) ---------- */
|
|
8195
|
+
/* 「点击文件预览」不再内嵌:预览交给 better-sidebar 内置的 diff tab
|
|
8196
|
+
(type 'diff',Hidden 内置页,DiffTab 自己经它自家 git 通道拉 patch,
|
|
8197
|
+
我们只递引用)。placement 跟随点击发生的容器——底部工作台里点开在
|
|
8198
|
+
底部、右栏里点开在右栏,走底座的官方 onOpenDiff 交接(props 注入,
|
|
8199
|
+
placement 由底座 store 决定);主对话区座位与原生座位没有该通道,
|
|
8200
|
+
直接 betterSidebar.openTab 定向右栏(target: 'right')。两通道皆
|
|
8201
|
+
不可用(无底座 / 老底座)→ 返回 false,调用方落回内嵌 diff 窗。
|
|
8202
|
+
ref 的 worktree + repoRoot 都填本面板的仓库根:DiffTab 的加载器把
|
|
8203
|
+
repoRoot 并进它自己的 git 调用,多仓库工作区不会落错仓库。 */
|
|
8204
|
+
const previewDiff = useCallback((seed) => {
|
|
8205
|
+
if (repoRoot === null) return false
|
|
8206
|
+
const commitHash = seed.hash !== undefined && seed.hash !== null ? String(seed.hash) : null
|
|
8207
|
+
const ref = commitHash !== null
|
|
8208
|
+
? { kind: 'commit', hash: commitHash.slice(0, 7), hashFull: commitHash, subject: seed.subject || '', worktree: repoRoot, repoRoot: repoRoot }
|
|
8209
|
+
: { kind: 'worktree', path: seed.path, staged: seed.staged === true, untracked: seed.untracked === true ? true : undefined, worktree: repoRoot, repoRoot: repoRoot }
|
|
8210
|
+
const title = commitHash !== null
|
|
8211
|
+
? commitHash.slice(0, 7) + (seed.subject ? ' ' + seed.subject : '')
|
|
8212
|
+
: baseName(String(seed.path))
|
|
8213
|
+
const id = commitHash !== null
|
|
8214
|
+
? 'diff:c:' + encodeURIComponent(repoRoot) + ':' + commitHash
|
|
8215
|
+
: 'diff:w:' + encodeURIComponent(repoRoot) + ':' + (seed.staged === true ? 's' : 'u') + ':' + seed.path
|
|
8216
|
+
const tab = { id: id, type: 'diff', title: title, diff: ref }
|
|
8217
|
+
/* Seat channel first — the bottom workbench opens its own diff tab,
|
|
8218
|
+
the right column opens it there; placement is the base's call. */
|
|
8219
|
+
if (typeof props.openDiffExternal === 'function') {
|
|
8220
|
+
try {
|
|
8221
|
+
props.openDiffExternal(tab)
|
|
8222
|
+
return true
|
|
8223
|
+
} catch (error) { void error }
|
|
8224
|
+
}
|
|
8225
|
+
/* Conversation seat / native seat: aim at the right sidebar. The
|
|
8226
|
+
capability gate keeps an older base (pre-targetedOpen) from
|
|
8227
|
+
receiving a field it cannot place; any refusal falls through to
|
|
8228
|
+
the inline pane below. */
|
|
8229
|
+
let betterSidebar = undefined
|
|
8230
|
+
try { betterSidebar = props.ctx === undefined || props.ctx === null ? undefined : props.ctx.get('betterSidebar') } catch (error) { void error }
|
|
8231
|
+
if (betterSidebar !== undefined && betterSidebar !== null && typeof betterSidebar.openTab === 'function') {
|
|
8232
|
+
const capabilities = betterSidebar.capabilities
|
|
8233
|
+
const targeted = capabilities === undefined || capabilities === null || (Array.isArray(capabilities) && capabilities.indexOf('targetedOpen') >= 0)
|
|
8234
|
+
if (targeted === true) {
|
|
8235
|
+
try {
|
|
8236
|
+
const scopeObject = scope || {}
|
|
8237
|
+
betterSidebar.openTab({ type: 'diff', title: title, id: id, diff: ref, target: 'right' }, { sessionId: scopeObject.sessionId, cwd: scopeObject.cwd })
|
|
8238
|
+
return true
|
|
8239
|
+
} catch (error) { void error }
|
|
8240
|
+
}
|
|
8241
|
+
}
|
|
8242
|
+
/* Native preview tab: the base is absent (or too old), so the plugin's
|
|
8243
|
+
OWN second native right-sidebar type takes the preview. The seed
|
|
8244
|
+
carries cwd (the route requires it) + repoRoot (skips the rev-parse);
|
|
8245
|
+
the tab is a singleton per pane — a second click re-seeds it in
|
|
8246
|
+
place instead of stacking tabs. */
|
|
8247
|
+
let sidebarRight = undefined
|
|
8248
|
+
try { sidebarRight = props.ctx === undefined || props.ctx === null ? undefined : props.ctx.get('sidebarRight') } catch (error) { void error }
|
|
8249
|
+
if (sidebarRight !== undefined && sidebarRight !== null && typeof sidebarRight.openTab === 'function') {
|
|
8250
|
+
try {
|
|
8251
|
+
const scopeObject = scope || {}
|
|
8252
|
+
previewStore.set(commitHash !== null
|
|
8253
|
+
? { hash: commitHash, subject: seed.subject || '', cwd: scopeObject.cwd, repoRoot: repoRoot, sessionId: scopeObject.sessionId }
|
|
8254
|
+
: { path: seed.path, staged: seed.staged === true, cwd: scopeObject.cwd, repoRoot: repoRoot, sessionId: scopeObject.sessionId })
|
|
8255
|
+
sidebarRight.openTab(NATIVE_PREVIEW_KIND)
|
|
8256
|
+
return true
|
|
8257
|
+
} catch (error) { void error }
|
|
8258
|
+
}
|
|
8259
|
+
return false
|
|
8260
|
+
}, [repoRoot, scope, props.openDiffExternal, props.ctx])
|
|
8261
|
+
|
|
8262
|
+
/* The one diff verb every surface calls (row click, row menu, detail
|
|
8263
|
+
file menu, working-diff shortcut): external first, inline fallback. */
|
|
8264
|
+
const showDiff = useCallback((seed) => {
|
|
8265
|
+
if (previewDiff(seed) === true) return
|
|
8266
|
+
if (seed.hash !== undefined && seed.hash !== null) {
|
|
8267
|
+
setDiffContext({ kind: 'commit', hash: seed.hash, subject: seed.subject || '' })
|
|
8268
|
+
void openDiff({ hash: seed.hash, path: seed.path })
|
|
8269
|
+
return
|
|
8270
|
+
}
|
|
8271
|
+
setDiffContext({ kind: 'worktree', staged: seed.staged === true })
|
|
8272
|
+
void openDiff({ path: seed.path, staged: seed.staged === true })
|
|
8273
|
+
}, [previewDiff, openDiff])
|
|
8274
|
+
|
|
8013
8275
|
const selectCommit = useCallback(async (commit) => {
|
|
8014
8276
|
setSelectedHash(commit.hash)
|
|
8015
8277
|
setSelectedPath(null)
|
|
@@ -8223,9 +8485,8 @@ window.__ModuleLoader__.load({
|
|
|
8223
8485
|
|
|
8224
8486
|
const changeMenu = useCallback((event, item, group) => {
|
|
8225
8487
|
const items = [
|
|
8226
|
-
{ id: 'diff', icon: 'file', tone: 'primary', label: t('action.showDiff'), run: () => {
|
|
8488
|
+
{ id: 'diff', icon: 'file', tone: 'primary', label: t('action.showDiff'), run: () => { showDiff({ path: item.path, staged: group === 'staged', untracked: group === 'untracked' }) } },
|
|
8227
8489
|
{ id: 'sendRef', icon: 'send', tone: 'accent', label: t('menu.sendToChat'), run: () => sendFileReferenceToChat(item.path) },
|
|
8228
|
-
{ id: 'sendPath', icon: 'file', tone: 'secondary', label: t('menu.sendFilePathToChat'), run: () => sendToComposer({ text: item.path, fallback: item.path }) },
|
|
8229
8490
|
null,
|
|
8230
8491
|
group === 'staged'
|
|
8231
8492
|
? { id: 'unstage', icon: 'minus', tone: 'warn', label: t('action.unstage'), run: () => { void run('unstage', { paths: [item.path] }) } }
|
|
@@ -8235,7 +8496,7 @@ window.__ModuleLoader__.load({
|
|
|
8235
8496
|
{ id: 'copy', icon: 'tag', tone: 'secondary', label: t('action.copyPath'), run: () => { copyText(item.path) } },
|
|
8236
8497
|
]
|
|
8237
8498
|
openMenuAt(event, items)
|
|
8238
|
-
}, [
|
|
8499
|
+
}, [showDiff, run, t, openMenuAt, sendFileReferenceToChat, sendToComposer])
|
|
8239
8500
|
|
|
8240
8501
|
/* The commit-detail file list shares the working-tree row menu, minus the
|
|
8241
8502
|
staging verbs: a committed file's diff replays against its commit. */
|
|
@@ -8243,16 +8504,18 @@ window.__ModuleLoader__.load({
|
|
|
8243
8504
|
openMenuAt(event, [
|
|
8244
8505
|
{ id: 'diff', icon: 'file', tone: 'primary', label: t('action.showDiff'), run: () => {
|
|
8245
8506
|
setSelectedPath(file.path)
|
|
8246
|
-
|
|
8247
|
-
|
|
8507
|
+
showDiff({
|
|
8508
|
+
hash: detail === null || detail === undefined ? undefined : detail.hash,
|
|
8509
|
+
subject: detail === null || detail === undefined ? '' : detail.subject,
|
|
8510
|
+
path: file.path,
|
|
8511
|
+
})
|
|
8248
8512
|
} },
|
|
8249
8513
|
null,
|
|
8250
8514
|
{ id: 'sendRef', icon: 'send', tone: 'accent', label: t('menu.sendToChat'), run: () => sendFileReferenceToChat(file.path) },
|
|
8251
|
-
{ id: 'sendPath', icon: 'file', tone: 'secondary', label: t('menu.sendFilePathToChat'), run: () => sendToComposer({ text: file.path, fallback: file.path }) },
|
|
8252
8515
|
null,
|
|
8253
8516
|
{ id: 'copy', icon: 'tag', tone: 'secondary', label: t('action.copyPath'), run: () => { copyText(file.path) } },
|
|
8254
8517
|
])
|
|
8255
|
-
}, [detail,
|
|
8518
|
+
}, [detail, showDiff, openMenuAt, sendFileReferenceToChat, sendToComposer, t])
|
|
8256
8519
|
|
|
8257
8520
|
/* The diff pane's own context menu (v0.13.5): select text in the diff,
|
|
8258
8521
|
right-click, send a self-describing line reference to the composer.
|
|
@@ -8485,7 +8748,7 @@ window.__ModuleLoader__.load({
|
|
|
8485
8748
|
onStageAll: (entries) => { void run('stage', { paths: entries.map((entry) => entry.path) }) },
|
|
8486
8749
|
onUnstageAll: () => { void run('unstage', { paths: (summary === null ? [] : summary.changes.staged).map((entry) => entry.path) }) },
|
|
8487
8750
|
onDiscard: (item, group) => setDialog({ kind: 'discard', item: item, group: group }),
|
|
8488
|
-
onDiff: (item, group) => {
|
|
8751
|
+
onDiff: (item, group) => { showDiff({ path: item.path, staged: group === 'staged', untracked: group === 'untracked' }) },
|
|
8489
8752
|
onChangeMenu: changeMenu,
|
|
8490
8753
|
})
|
|
8491
8754
|
|
|
@@ -8495,8 +8758,11 @@ window.__ModuleLoader__.load({
|
|
|
8495
8758
|
onBack: () => { setView('history'); setSelectedPath(null); setPatch(''); setDiffContext(null) },
|
|
8496
8759
|
onSelectFile: (file) => {
|
|
8497
8760
|
setSelectedPath(file.path)
|
|
8498
|
-
|
|
8499
|
-
|
|
8761
|
+
showDiff({
|
|
8762
|
+
hash: detail === null || detail === undefined ? undefined : detail.hash,
|
|
8763
|
+
subject: detail === null || detail === undefined ? '' : detail.subject,
|
|
8764
|
+
path: file.path,
|
|
8765
|
+
})
|
|
8500
8766
|
},
|
|
8501
8767
|
onFileMenu: detailFileMenu,
|
|
8502
8768
|
})
|
|
@@ -8547,7 +8813,7 @@ window.__ModuleLoader__.load({
|
|
|
8547
8813
|
['untracked', changes.untracked, false],
|
|
8548
8814
|
]
|
|
8549
8815
|
for (const entry of order) {
|
|
8550
|
-
if (entry[1].length > 0) {
|
|
8816
|
+
if (entry[1].length > 0) { showDiff({ path: entry[1][0].path, staged: entry[2] }); return }
|
|
8551
8817
|
}
|
|
8552
8818
|
setNote(t('note.noChanges'))
|
|
8553
8819
|
}
|
|
@@ -9228,6 +9494,40 @@ window.__ModuleLoader__.load({
|
|
|
9228
9494
|
'.dig-menu-danger,.dig-menu-danger .dig-menu-label{color:var(--dsw-alias-state-error-primary)}',
|
|
9229
9495
|
'.dig-menu-disabled{opacity:.38;cursor:default}',
|
|
9230
9496
|
'.dig-menu-sep{height:1px;margin:3px 6px;background:var(--dsw-alias-hairline,var(--dsw-alias-border-l1))}',
|
|
9497
|
+
/* ---- immersive conversation seat (issue #8 round 3) ---- */
|
|
9498
|
+
/* The seat itself carries `data-conversation-composer-overlay` (the
|
|
9499
|
+
host's own opt-in, what TrajectoryView rides): the host CSS flips the
|
|
9500
|
+
view area to `flex: 1 1 0; min-height: 0; overflow: hidden` and the
|
|
9501
|
+
composer seat to an overlay. What the host does NOT do is hide the
|
|
9502
|
+
composer — that is ours, and it is a single structural rule patterned
|
|
9503
|
+
after dsh-context's `.lc-root` rule: while a Git view owns the
|
|
9504
|
+
conversation ring, the composer seat displays none. The :not() chain
|
|
9505
|
+
is the SAFETY VALVE and its attribute names are verified against the
|
|
9506
|
+
host sources (ui-approval ApprovalPanel `data-approval-key`,
|
|
9507
|
+
ui-user-questions QuestionComposer `data-question-key`, PlanReviewPanel
|
|
9508
|
+
`data-plan-review-key`): a blocking interaction riding the seat must
|
|
9509
|
+
stay reachable even though the plain input card is hidden, or a user
|
|
9510
|
+
sitting in the Git view could never approve anything. */
|
|
9511
|
+
'[data-conversation-scroll]:has(.dig-conversation-seat[data-immersive="1"]) > [data-composer-seat]:not(:has([data-approval-key],[data-question-key],[data-plan-review-key])){display:none}',
|
|
9512
|
+
/* The transcript-width drag strips are FOLLOWING SIBLINGS of the shared
|
|
9513
|
+
scroller (children of the conversation body), full-height and
|
|
9514
|
+
z-index 8: over a full-bleed Git pane they glow and drag straight
|
|
9515
|
+
through it. Same sibling combinator lesson dsh-context recorded in
|
|
9516
|
+
its own issue #50 — a descendant combinator here matches nothing. */
|
|
9517
|
+
'[data-conversation-scroll]:has(.dig-conversation-seat[data-immersive="1"]) ~ [data-width-handle]{display:none}',
|
|
9518
|
+
/* ---- native preview tab (external diff preview) ---- */
|
|
9519
|
+
/* The body mounts straight into the right-sidebar pane: full height,
|
|
9520
|
+
internal scrolling in the body region, a one-line header for the
|
|
9521
|
+
subject/path. Same tokens as the rest of the panel — no hard-coded
|
|
9522
|
+
surfaces. */
|
|
9523
|
+
'.dig-preview-root{position:relative;height:100%;display:flex;flex-direction:column;min-height:0;background:var(--dsw-alias-bg-base)}',
|
|
9524
|
+
'.dig-preview-head{flex:none;padding:8px 12px;border-bottom:1px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-l1));font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
|
9525
|
+
'.dig-preview-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
|
|
9526
|
+
'.dig-preview-body{flex:1;min-height:0;overflow:auto;padding:8px 12px;display:flex;flex-direction:column}',
|
|
9527
|
+
'.dig-preview-body .dig-diff-host,.dig-preview-body .dig-diff{flex:1;min-height:0}',
|
|
9528
|
+
'.dig-preview-actions{display:flex;align-items:center;gap:4px;flex:none}',
|
|
9529
|
+
'.dig-preview-btn{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;border-radius:var(--dsw-radius-sm,8px);background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer}',
|
|
9530
|
+
'.dig-preview-btn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}',
|
|
9231
9531
|
].join('\n')
|
|
9232
9532
|
|
|
9233
9533
|
/* ============================== plugin ============================== */
|
|
@@ -9243,6 +9543,34 @@ window.__ModuleLoader__.load({
|
|
|
9243
9543
|
Chat (0) and Trajectory (10), and after dsh-context's tab (20) when both
|
|
9244
9544
|
are installed. */
|
|
9245
9545
|
const CONVERSATION_VIEW_ID = 'ide-git'
|
|
9546
|
+
/* The native preview tab (external diff preview, 2026-10-08): a SECOND
|
|
9547
|
+
native right-sidebar type that exists only to show one diff. It carries
|
|
9548
|
+
no guide entry on purpose — nothing on the start page opens it; it opens
|
|
9549
|
+
itself when a diff verb fires with no better-sidebar to hand off to.
|
|
9550
|
+
Content follows the module-level store below, so every seat (the
|
|
9551
|
+
conversation tab, the native panel) feeds the same single preview. */
|
|
9552
|
+
const NATIVE_PREVIEW_ID = 'dsh-ide-git-preview'
|
|
9553
|
+
const NATIVE_PREVIEW_KIND = 'ide-git-preview'
|
|
9554
|
+
|
|
9555
|
+
/* The one diff seed the native preview tab shows. set() bumps a monotonous
|
|
9556
|
+
counter so a re-click of the SAME file still re-fetches; subscribers get
|
|
9557
|
+
the barest notify and re-read .seed themselves. Memory-only: after a
|
|
9558
|
+
reload the tab (if the layout restored it) shows the empty hint again —
|
|
9559
|
+
the next click re-seeds it. */
|
|
9560
|
+
const previewStore = {
|
|
9561
|
+
seed: null,
|
|
9562
|
+
listeners: new Set(),
|
|
9563
|
+
set(seed) {
|
|
9564
|
+
this.seed = seed
|
|
9565
|
+
for (const listener of [...this.listeners]) {
|
|
9566
|
+
try { listener() } catch (error) { void error }
|
|
9567
|
+
}
|
|
9568
|
+
},
|
|
9569
|
+
subscribe(listener) {
|
|
9570
|
+
this.listeners.add(listener)
|
|
9571
|
+
return () => { this.listeners.delete(listener) }
|
|
9572
|
+
},
|
|
9573
|
+
}
|
|
9246
9574
|
|
|
9247
9575
|
/* The native seat hands a tab the standard props; the panel wants
|
|
9248
9576
|
`{ scope, t }`. A session's working directory is the path of the
|
|
@@ -9272,7 +9600,7 @@ window.__ModuleLoader__.load({
|
|
|
9272
9600
|
const openSettings = navigation !== undefined && navigation !== null && typeof navigation.openBundle === 'function'
|
|
9273
9601
|
? () => { navigation.openBundle(SETTINGS_BUNDLE) }
|
|
9274
9602
|
: null
|
|
9275
|
-
return E(Panel, { scope: props.scope, t: props.t, visible: props.visible, dock: props.dock, openSettings: openSettings, ctx: props.ctx })
|
|
9603
|
+
return E(Panel, { scope: props.scope, t: props.t, visible: props.visible, dock: props.dock, openSettings: openSettings, ctx: props.ctx, openDiffExternal: props.openDiffExternal })
|
|
9276
9604
|
}
|
|
9277
9605
|
|
|
9278
9606
|
/* The conversation-area seat (issue #8): the same panel as a view tab
|
|
@@ -9310,6 +9638,21 @@ window.__ModuleLoader__.load({
|
|
|
9310
9638
|
const ctx = props.ctx
|
|
9311
9639
|
const sessionId = typeof props.sessionId === 'string' ? props.sessionId : ''
|
|
9312
9640
|
const [cwd, setCwd] = useState(() => sessionCwdOf(ctx, sessionId))
|
|
9641
|
+
/* Immersive mode (issue #8 round 3): when on, the seat declares the
|
|
9642
|
+
host's composer-overlay contract (`data-conversation-composer-overlay`)
|
|
9643
|
+
and the conversation view area goes `flex: 1 1 0; min-height: 0;
|
|
9644
|
+
overflow: hidden` — the panel fills the WHOLE conversation height and
|
|
9645
|
+
scrolls inside itself, with the composer seat hidden away (CSS keeps
|
|
9646
|
+
the blocking approvals visible). The v0.13.2 pin-to-scrollport
|
|
9647
|
+
machinery below is the FALLBACK for immersive-off: it exists because
|
|
9648
|
+
the active view area is `flex: 1 0 auto` (content height) in the
|
|
9649
|
+
normal layout, which is exactly what the overlay contract replaces. */
|
|
9650
|
+
const [immersive, setImmersive] = useState(() => conversationImmersiveEnabled())
|
|
9651
|
+
useEffect(() => {
|
|
9652
|
+
const sync = () => { setImmersive(conversationImmersiveEnabled()) }
|
|
9653
|
+
sync()
|
|
9654
|
+
return subscribeRailConfig(sync)
|
|
9655
|
+
}, [])
|
|
9313
9656
|
/* The active conversation's view area is `flex: 1 0 auto; min-height:
|
|
9314
9657
|
auto` — it GROWS with content and scrolls inside the shared
|
|
9315
9658
|
conversation scrollport. An auto-height panel there measured
|
|
@@ -9324,6 +9667,12 @@ window.__ModuleLoader__.load({
|
|
|
9324
9667
|
useEffect(() => {
|
|
9325
9668
|
const el = seatRef.current
|
|
9326
9669
|
if (el === null) return undefined
|
|
9670
|
+
/* Immersive ON: the host's overlay layout owns this seat's height
|
|
9671
|
+
(the view area is the flex child now) — no pinning, no convergence,
|
|
9672
|
+
none of the scrollport arithmetic below applies. Toggling the
|
|
9673
|
+
setting re-runs this effect through the dependency below, so the
|
|
9674
|
+
fallback machinery spins back up on the way off. */
|
|
9675
|
+
if (immersive === true) return undefined
|
|
9327
9676
|
/* Leftover wheel scroll, root cause: the composer seat is sticky, but a
|
|
9328
9677
|
sticky box still occupies FLOW space inside the scrollport, so even
|
|
9329
9678
|
with the panel seat pinned to the visible height the scrollHeight
|
|
@@ -9408,7 +9757,7 @@ window.__ModuleLoader__.load({
|
|
|
9408
9757
|
if (observer !== undefined) observer.disconnect()
|
|
9409
9758
|
window.removeEventListener('resize', measure)
|
|
9410
9759
|
}
|
|
9411
|
-
}, [])
|
|
9760
|
+
}, [immersive])
|
|
9412
9761
|
useEffect(() => {
|
|
9413
9762
|
let alive = true
|
|
9414
9763
|
const sync = () => { if (alive === true) setCwd(sessionCwdOf(ctx, sessionId)) }
|
|
@@ -9432,11 +9781,20 @@ window.__ModuleLoader__.load({
|
|
|
9432
9781
|
}
|
|
9433
9782
|
}, [ctx, sessionId])
|
|
9434
9783
|
const scope = useMemo(() => ({ cwd: cwd, sessionId: sessionId }), [cwd, sessionId])
|
|
9435
|
-
|
|
9784
|
+
/* The overlay marker rides the SEAT element (a viewArea descendant): the
|
|
9785
|
+
host's `.scrollBody:has([data-conversation-composer-overlay])` rules
|
|
9786
|
+
pick it up from anywhere inside, flipping the view area to
|
|
9787
|
+
`flex: 1 1 0; min-height: 0; overflow: hidden` (full-height, internal
|
|
9788
|
+
scrolling) and the composer seat to an overlay. `data-immersive`
|
|
9789
|
+
drives the plugin's own CSS (composer hide + width-handle hide). */
|
|
9790
|
+
const immersiveAttrs = immersive === true
|
|
9791
|
+
? { 'data-conversation-composer-overlay': '', 'data-immersive': '1' }
|
|
9792
|
+
: {}
|
|
9793
|
+
return E('div', Object.assign({
|
|
9436
9794
|
ref: seatRef,
|
|
9437
9795
|
className: 'dig-conversation-seat',
|
|
9438
|
-
style: seatHeight === null ? undefined : { height: seatHeight + 'px' },
|
|
9439
|
-
}, E(LocaleLive, { ctx: ctx, scope: scope, t: props.t, visible: true }))
|
|
9796
|
+
style: immersive === true ? { height: '100%' } : (seatHeight === null ? undefined : { height: seatHeight + 'px' }),
|
|
9797
|
+
}, immersiveAttrs), E(LocaleLive, { ctx: ctx, scope: scope, t: props.t, visible: true }))
|
|
9440
9798
|
}, (prev, next) => prev.sessionId === next.sessionId && prev.t === next.t && prev.ctx === next.ctx)
|
|
9441
9799
|
|
|
9442
9800
|
function NativePanel(props) {
|
|
@@ -9461,6 +9819,98 @@ window.__ModuleLoader__.load({
|
|
|
9461
9819
|
return E(LocaleLive, { ctx: props.ctx, scope: scope, t: props.t, visible: true, dock: dock })
|
|
9462
9820
|
}
|
|
9463
9821
|
|
|
9822
|
+
/* The native preview tab's body (external diff preview): shows exactly one
|
|
9823
|
+
diff — whatever the store holds — fetched fresh from the host route on
|
|
9824
|
+
every seed. The seed carries cwd + repoRoot so a multi-root workspace
|
|
9825
|
+
lands on the right repository (the route requires cwd; repoRoot skips
|
|
9826
|
+
the rev-parse). Rendered through the SAME DiffBody the inline pane uses,
|
|
9827
|
+
so host DiffBlock reuse, the hand-drawn fallback and the binary/empty
|
|
9828
|
+
states are all identical. */
|
|
9829
|
+
function NativePreviewPanel(props) {
|
|
9830
|
+
const t = props.t
|
|
9831
|
+
const [seed, setSeed] = useState(() => previewStore.seed)
|
|
9832
|
+
useEffect(() => previewStore.subscribe(() => { setSeed(previewStore.seed) }), [])
|
|
9833
|
+
const seedKey = seed === null
|
|
9834
|
+
? ''
|
|
9835
|
+
: (seed.hash !== undefined && seed.hash !== null ? 'c:' + String(seed.hash) : 'w:' + String(seed.staged === true) + ':' + String(seed.path))
|
|
9836
|
+
const [state, setState] = useState({ loading: false, patch: '', error: null })
|
|
9837
|
+
const [refreshTick, setRefreshTick] = useState(0)
|
|
9838
|
+
const [copied, setCopied] = useState(false)
|
|
9839
|
+
const copyTimer = useRef(null)
|
|
9840
|
+
useEffect(() => () => { if (copyTimer.current !== null) clearTimeout(copyTimer.current) }, [])
|
|
9841
|
+
useEffect(() => {
|
|
9842
|
+
if (seed === null) return undefined
|
|
9843
|
+
let alive = true
|
|
9844
|
+
setState({ loading: true, patch: '', error: null })
|
|
9845
|
+
void (async () => {
|
|
9846
|
+
try {
|
|
9847
|
+
const payload = { cwd: seed.cwd }
|
|
9848
|
+
if (seed.repoRoot !== undefined && seed.repoRoot !== null && seed.repoRoot !== '') payload.repoRoot = seed.repoRoot
|
|
9849
|
+
if (seed.hash !== undefined && seed.hash !== null && seed.hash !== '') payload.hash = seed.hash
|
|
9850
|
+
else { payload.path = seed.path; payload.staged = seed.staged === true }
|
|
9851
|
+
const data = await request('diff', payload)
|
|
9852
|
+
if (alive === true) setState({ loading: false, patch: data === undefined || data === null || typeof data.patch !== 'string' ? '' : data.patch, error: null })
|
|
9853
|
+
} catch (error) {
|
|
9854
|
+
if (alive === true) setState({ loading: false, patch: '', error: error instanceof Error ? error.message : String(error) })
|
|
9855
|
+
}
|
|
9856
|
+
})()
|
|
9857
|
+
return () => { alive = false }
|
|
9858
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
9859
|
+
}, [seedKey, refreshTick])
|
|
9860
|
+
const title = seed === null
|
|
9861
|
+
? ''
|
|
9862
|
+
: (seed.hash !== undefined && seed.hash !== null
|
|
9863
|
+
? String(seed.hash).slice(0, 7) + (seed.subject ? ' ' + seed.subject : '')
|
|
9864
|
+
: String(seed.path))
|
|
9865
|
+
/* Header controls mirror the base's own diff tab: a refresh button
|
|
9866
|
+
(worktree diffs change under staging/discard), plus a copy button —
|
|
9867
|
+
the official card's toolbar already covers wrap/copy inside the body;
|
|
9868
|
+
these two act on the WHOLE preview. */
|
|
9869
|
+
const copyPatch = () => {
|
|
9870
|
+
try {
|
|
9871
|
+
void navigator.clipboard.writeText(state.patch).then(() => {
|
|
9872
|
+
setCopied(true)
|
|
9873
|
+
if (copyTimer.current !== null) clearTimeout(copyTimer.current)
|
|
9874
|
+
copyTimer.current = setTimeout(() => { setCopied(false); copyTimer.current = null }, 1600)
|
|
9875
|
+
})
|
|
9876
|
+
} catch (error) { void error }
|
|
9877
|
+
}
|
|
9878
|
+
/* Hand the file to the HOST'S own file preview (ReadBlock chrome: path
|
|
9879
|
+
banner, line numbers, syntax colors) — the official openResource
|
|
9880
|
+
channel, the same one every @-mention file click rides. The diff stays
|
|
9881
|
+
the place to read the CHANGE; this jumps to the whole file with the
|
|
9882
|
+
product's line-numbered reader. Address grammar (workspace-path):
|
|
9883
|
+
`dsh-resource://file/session/<sessionId>/<per-segment encoded rel>`. */
|
|
9884
|
+
const openInFilePreview = () => {
|
|
9885
|
+
if (seed === null || seed.path === undefined || seed.path === null || seed.path === '') return
|
|
9886
|
+
let sidebarRight = undefined
|
|
9887
|
+
try { sidebarRight = props.ctx === undefined || props.ctx === null ? undefined : props.ctx.get('sidebarRight') } catch (error) { void error }
|
|
9888
|
+
if (sidebarRight === undefined || sidebarRight === null || typeof sidebarRight.openResource !== 'function') return
|
|
9889
|
+
try {
|
|
9890
|
+
const relative = String(seed.path)
|
|
9891
|
+
const address = 'dsh-resource://file/session/' + encodeURIComponent(String(seed.sessionId || '')) + '/' + relative.split('/').map((segment) => encodeURIComponent(segment)).join('/')
|
|
9892
|
+
sidebarRight.openResource(address)
|
|
9893
|
+
} catch (error) { void error }
|
|
9894
|
+
}
|
|
9895
|
+
return E('div', { className: 'dig-preview-root' },
|
|
9896
|
+
E('div', { className: 'dig-preview-head' },
|
|
9897
|
+
E('span', { className: 'dig-preview-title', title: title }, title === '' ? t('preview.title') : title),
|
|
9898
|
+
seed === null ? null : E('div', { className: 'dig-preview-actions' },
|
|
9899
|
+
seed.path !== undefined && seed.path !== null && seed.path !== ''
|
|
9900
|
+
? E('button', { type: 'button', className: 'dig-preview-btn', 'aria-label': t('preview.openFile'), title: t('preview.openFile'), onClick: openInFilePreview },
|
|
9901
|
+
E(Icon, { name: 'file', size: 13 }))
|
|
9902
|
+
: null,
|
|
9903
|
+
E('button', { type: 'button', className: 'dig-preview-btn', 'aria-label': t('diff.copy'), title: t('diff.copy'), onClick: copyPatch },
|
|
9904
|
+
E(Icon, { name: copied === true ? 'check' : 'copy', size: 13 })),
|
|
9905
|
+
E('button', { type: 'button', className: 'dig-preview-btn', 'aria-label': t('toolbar.refresh'), title: t('toolbar.refresh'), onClick: () => { setRefreshTick((n) => n + 1) } },
|
|
9906
|
+
E(Icon, { name: 'refresh', size: 13 })))),
|
|
9907
|
+
seed === null
|
|
9908
|
+
? E('div', { className: 'dig-preview-body' }, E('div', { className: 'dig-empty' }, t('preview.hint')))
|
|
9909
|
+
: state.error !== null
|
|
9910
|
+
? E('div', { className: 'dig-preview-body' }, E('div', { className: 'dig-empty' }, state.error))
|
|
9911
|
+
: E('div', { className: 'dig-preview-body' }, E(DiffBody, { patch: state.patch, loading: state.loading, binary: false, t: t })))
|
|
9912
|
+
}
|
|
9913
|
+
|
|
9464
9914
|
function apply(ctx) {
|
|
9465
9915
|
const style = document.createElement('style')
|
|
9466
9916
|
style.setAttribute('data-dsh-ide-git', '')
|
|
@@ -9524,7 +9974,24 @@ window.__ModuleLoader__.load({
|
|
|
9524
9974
|
{ name: 'sidebar.right.pane.tab', key: NATIVE_ID },
|
|
9525
9975
|
(tabProps) => E(NativePanel, Object.assign({}, tabProps, { t: t, ctx: ctx })),
|
|
9526
9976
|
))
|
|
9977
|
+
/* The preview type has NO guide entry on purpose (start-page
|
|
9978
|
+
destinations are the main panel's job): it exists to receive the
|
|
9979
|
+
openTab this plugin fires when a diff verb runs without a
|
|
9980
|
+
better-sidebar to hand off to. Omitting `guide` is the registry's
|
|
9981
|
+
documented way to stay off the guide page. */
|
|
9982
|
+
const offPreviewType = tabs.register({
|
|
9983
|
+
id: NATIVE_PREVIEW_ID,
|
|
9984
|
+
kind: NATIVE_PREVIEW_KIND,
|
|
9985
|
+
title: () => t('preview.title'),
|
|
9986
|
+
keepMounted: true,
|
|
9987
|
+
})
|
|
9988
|
+
const offPreviewBody = slots.inject('sidebar.right.pane.tab', () => slots.register(
|
|
9989
|
+
{ name: 'sidebar.right.pane.tab', key: NATIVE_PREVIEW_ID },
|
|
9990
|
+
(tabProps) => E(NativePreviewPanel, Object.assign({}, tabProps, { t: t, ctx: ctx })),
|
|
9991
|
+
))
|
|
9527
9992
|
return () => {
|
|
9993
|
+
try { offPreviewBody() } catch (error) { void error }
|
|
9994
|
+
try { offPreviewType() } catch (error) { void error }
|
|
9528
9995
|
try { offBody() } catch (error) { void error }
|
|
9529
9996
|
try { offType() } catch (error) { void error }
|
|
9530
9997
|
}
|
|
@@ -9557,6 +10024,13 @@ window.__ModuleLoader__.load({
|
|
|
9557
10024
|
scope: tabProps.scope,
|
|
9558
10025
|
t: t,
|
|
9559
10026
|
visible: tabProps.visible,
|
|
10027
|
+
/* The base's own diff-tab hand-off (OpenTabSeed type 'diff').
|
|
10028
|
+
Where the diff tab lands — bottom workbench vs right column —
|
|
10029
|
+
is the base's store decision, made where the click happened:
|
|
10030
|
+
exactly the "preview beside this panel" behavior the seat
|
|
10031
|
+
should have. Absent on an older base; previewDiff falls back
|
|
10032
|
+
to the service openTab, then to the inline pane. */
|
|
10033
|
+
openDiffExternal: typeof tabProps.onOpenDiff === 'function' ? tabProps.onOpenDiff : undefined,
|
|
9560
10034
|
}),
|
|
9561
10035
|
})
|
|
9562
10036
|
/* The base can go away at RUNTIME (disabled in the plugin panel, or
|
package/src/index.js
CHANGED
|
@@ -70,6 +70,13 @@ function railConfigSchema(schema) {
|
|
|
70
70
|
conversation.view seat at all" — the sidebar and dock seats are not
|
|
71
71
|
affected; a missing field means the default (shown). */
|
|
72
72
|
shape.conversationTab = live(schema.boolean().default(true))
|
|
73
|
+
/* Immersive conversation seat (issue #8 round 3): on by default. false means
|
|
74
|
+
the seat falls back to the pin-to-scrollport layout with a visible
|
|
75
|
+
composer; a missing field means the default (on). NOTE: the field MUST be
|
|
76
|
+
declared here — the Host rejects row-Config writes for paths the schema
|
|
77
|
+
does not mark volatile ("Config field … is not volatile"), and the settings
|
|
78
|
+
switch then rolls back silently. */
|
|
79
|
+
shape.immersive = live(schema.boolean().default(true))
|
|
73
80
|
return schema.object(shape)
|
|
74
81
|
}
|
|
75
82
|
|