dsh-ide-git 0.13.3 → 0.13.4
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 +121 -22
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-external/dsh-ide-git",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.4",
|
|
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.13.
|
|
3
|
+
"version": "0.13.4",
|
|
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
|
@@ -154,6 +154,8 @@ window.__ModuleLoader__.load({
|
|
|
154
154
|
'action.details': '提交详情',
|
|
155
155
|
'menu.sendToChat': '发送到对话',
|
|
156
156
|
'menu.sendFilePathToChat': '发送文件路径到对话',
|
|
157
|
+
'send.commitText': 'git 提交 {hash}「{subject}」(仓库 {repo})',
|
|
158
|
+
'send.branchText': 'git 分支 {name}(仓库 {repo})',
|
|
157
159
|
'history.empty': '这个仓库还没有提交',
|
|
158
160
|
'history.loadMore': '加载更多',
|
|
159
161
|
'history.filter': '文本或哈希',
|
|
@@ -354,6 +356,8 @@ window.__ModuleLoader__.load({
|
|
|
354
356
|
'action.details': 'Commit details',
|
|
355
357
|
'menu.sendToChat': 'Send to chat',
|
|
356
358
|
'menu.sendFilePathToChat': 'Send file path to chat',
|
|
359
|
+
'send.commitText': 'git commit {hash} "{subject}" (repo {repo})',
|
|
360
|
+
'send.branchText': 'git branch {name} (repo {repo})',
|
|
357
361
|
'history.empty': 'This repository has no commits yet',
|
|
358
362
|
'history.loadMore': 'Load more',
|
|
359
363
|
'history.filter': 'Text or hash',
|
|
@@ -562,6 +566,8 @@ window.__ModuleLoader__.load({
|
|
|
562
566
|
'action.details': '提交詳情',
|
|
563
567
|
'menu.sendToChat': '傳送到對話',
|
|
564
568
|
'menu.sendFilePathToChat': '傳送檔案路徑至對話',
|
|
569
|
+
'send.commitText': 'git 提交 {hash}「{subject}」(存放庫 {repo})',
|
|
570
|
+
'send.branchText': 'git 分支 {name}(存放庫 {repo})',
|
|
565
571
|
'history.empty': '呢個存放庫仲未有提交',
|
|
566
572
|
'history.loadMore': '載入更多',
|
|
567
573
|
'history.filter': '文字或雜湊',
|
|
@@ -762,6 +768,8 @@ window.__ModuleLoader__.load({
|
|
|
762
768
|
'action.details': '提交詳情',
|
|
763
769
|
'menu.sendToChat': '傳送至對話',
|
|
764
770
|
'menu.sendFilePathToChat': '傳送檔案路徑至對話',
|
|
771
|
+
'send.commitText': 'git 提交 {hash}「{subject}」(版本庫 {repo})',
|
|
772
|
+
'send.branchText': 'git 分支 {name}(版本庫 {repo})',
|
|
765
773
|
'history.empty': '這個版本庫還沒有提交',
|
|
766
774
|
'history.loadMore': '載入更多',
|
|
767
775
|
'history.filter': '文字或雜湊',
|
|
@@ -962,6 +970,8 @@ window.__ModuleLoader__.load({
|
|
|
962
970
|
'action.details': '提交詳情',
|
|
963
971
|
'menu.sendToChat': '傳送至對話',
|
|
964
972
|
'menu.sendFilePathToChat': '傳送檔案路徑至對話',
|
|
973
|
+
'send.commitText': 'git 提交 {hash}「{subject}」(存放庫 {repo})',
|
|
974
|
+
'send.branchText': 'git 分支 {name}(存放庫 {repo})',
|
|
965
975
|
'history.empty': '呢個存放庫仲未有提交',
|
|
966
976
|
'history.loadMore': '載入更多',
|
|
967
977
|
'history.filter': '文字或雜湊',
|
|
@@ -1162,6 +1172,8 @@ window.__ModuleLoader__.load({
|
|
|
1162
1172
|
'action.details': 'コミットの詳細',
|
|
1163
1173
|
'menu.sendToChat': 'チャットへ送る',
|
|
1164
1174
|
'menu.sendFilePathToChat': 'ファイルパスをチャットへ送る',
|
|
1175
|
+
'send.commitText': 'git コミット {hash}「{subject}」(リポジトリ {repo})',
|
|
1176
|
+
'send.branchText': 'git ブランチ {name}(リポジトリ {repo})',
|
|
1165
1177
|
'history.empty': 'このリポジトリにはまだコミットがありません',
|
|
1166
1178
|
'history.loadMore': 'さらに読み込む',
|
|
1167
1179
|
'history.filter': 'テキストまたはハッシュ',
|
|
@@ -1362,6 +1374,8 @@ window.__ModuleLoader__.load({
|
|
|
1362
1374
|
'action.details': '커밋 상세',
|
|
1363
1375
|
'menu.sendToChat': '대화로 보내기',
|
|
1364
1376
|
'menu.sendFilePathToChat': '파일 경로를 대화로 보내기',
|
|
1377
|
+
'send.commitText': 'git 커밋 {hash} "{subject}" (저장소 {repo})',
|
|
1378
|
+
'send.branchText': 'git 브랜치 {name} (저장소 {repo})',
|
|
1365
1379
|
'history.empty': '이 저장소에는 아직 커밋이 없습니다',
|
|
1366
1380
|
'history.loadMore': '더 불러오기',
|
|
1367
1381
|
'history.filter': '텍스트 또는 해시',
|
|
@@ -1562,6 +1576,8 @@ window.__ModuleLoader__.load({
|
|
|
1562
1576
|
'action.details': 'Commit-Details',
|
|
1563
1577
|
'menu.sendToChat': 'Im Chat senden',
|
|
1564
1578
|
'menu.sendFilePathToChat': 'Dateipfad im Chat senden',
|
|
1579
|
+
'send.commitText': 'git-Commit {hash} "{subject}" (Repository {repo})',
|
|
1580
|
+
'send.branchText': 'git-Branch {name} (Repository {repo})',
|
|
1565
1581
|
'history.empty': 'Dieses Repository hat noch keine Commits',
|
|
1566
1582
|
'history.loadMore': 'Mehr laden',
|
|
1567
1583
|
'history.filter': 'Text oder Hash',
|
|
@@ -1762,6 +1778,8 @@ window.__ModuleLoader__.load({
|
|
|
1762
1778
|
'action.details': 'Détails du commit',
|
|
1763
1779
|
'menu.sendToChat': 'Envoyer dans la conversation',
|
|
1764
1780
|
'menu.sendFilePathToChat': 'Envoyer le chemin du fichier dans la conversation',
|
|
1781
|
+
'send.commitText': 'commit git {hash} « {subject} » (dépôt {repo})',
|
|
1782
|
+
'send.branchText': 'branche git {name} (dépôt {repo})',
|
|
1765
1783
|
'history.empty': 'Ce dépôt n\'a pas encore de commit',
|
|
1766
1784
|
'history.loadMore': 'Charger plus',
|
|
1767
1785
|
'history.filter': 'Texte ou empreinte',
|
|
@@ -1962,6 +1980,8 @@ window.__ModuleLoader__.load({
|
|
|
1962
1980
|
'action.details': 'Сведения о коммите',
|
|
1963
1981
|
'menu.sendToChat': 'Отправить в чат',
|
|
1964
1982
|
'menu.sendFilePathToChat': 'Отправить путь к файлу в чат',
|
|
1983
|
+
'send.commitText': 'git-коммит {hash} «{subject}» (репозиторий {repo})',
|
|
1984
|
+
'send.branchText': 'git-ветка {name} (репозиторий {repo})',
|
|
1965
1985
|
'history.empty': 'В этом репозитории ещё нет коммитов',
|
|
1966
1986
|
'history.loadMore': 'Загрузить ещё',
|
|
1967
1987
|
'history.filter': 'Текст или хеш',
|
|
@@ -2162,6 +2182,8 @@ window.__ModuleLoader__.load({
|
|
|
2162
2182
|
'action.details': 'Detalhes do commit',
|
|
2163
2183
|
'menu.sendToChat': 'Enviar para a conversa',
|
|
2164
2184
|
'menu.sendFilePathToChat': 'Enviar caminho do arquivo para a conversa',
|
|
2185
|
+
'send.commitText': 'commit git {hash} "{subject}" (repositório {repo})',
|
|
2186
|
+
'send.branchText': 'branch git {name} (repositório {repo})',
|
|
2165
2187
|
'history.empty': 'Este repositório ainda não tem commits',
|
|
2166
2188
|
'history.loadMore': 'Carregar mais',
|
|
2167
2189
|
'history.filter': 'Texto ou hash',
|
|
@@ -2362,6 +2384,8 @@ window.__ModuleLoader__.load({
|
|
|
2362
2384
|
'action.details': 'Dettagli del commit',
|
|
2363
2385
|
'menu.sendToChat': 'Invia alla conversazione',
|
|
2364
2386
|
'menu.sendFilePathToChat': 'Invia il percorso del file alla conversazione',
|
|
2387
|
+
'send.commitText': 'commit git {hash} "{subject}" (repository {repo})',
|
|
2388
|
+
'send.branchText': 'branch git {name} (repository {repo})',
|
|
2365
2389
|
'history.empty': 'Questo repository non ha ancora commit',
|
|
2366
2390
|
'history.loadMore': 'Carica altro',
|
|
2367
2391
|
'history.filter': 'Testo o hash',
|
|
@@ -2562,6 +2586,8 @@ window.__ModuleLoader__.load({
|
|
|
2562
2586
|
'action.details': 'Commit-details',
|
|
2563
2587
|
'menu.sendToChat': 'Naar het gesprek verzenden',
|
|
2564
2588
|
'menu.sendFilePathToChat': 'Bestandspad naar het gesprek verzenden',
|
|
2589
|
+
'send.commitText': 'git-commit {hash} "{subject}" (repository {repo})',
|
|
2590
|
+
'send.branchText': 'git-branch {name} (repository {repo})',
|
|
2565
2591
|
'history.empty': 'Deze repository heeft nog geen commits',
|
|
2566
2592
|
'history.loadMore': 'Meer laden',
|
|
2567
2593
|
'history.filter': 'Tekst of hash',
|
|
@@ -2762,6 +2788,8 @@ window.__ModuleLoader__.load({
|
|
|
2762
2788
|
'action.details': 'Szczegóły commita',
|
|
2763
2789
|
'menu.sendToChat': 'Wyślij do rozmowy',
|
|
2764
2790
|
'menu.sendFilePathToChat': 'Wyślij ścieżkę pliku do rozmowy',
|
|
2791
|
+
'send.commitText': 'commit git {hash} „{subject}" (repozytorium {repo})',
|
|
2792
|
+
'send.branchText': 'gałąź git {name} (repozytorium {repo})',
|
|
2765
2793
|
'history.empty': 'To repozytorium nie ma jeszcze commitów',
|
|
2766
2794
|
'history.loadMore': 'Wczytaj więcej',
|
|
2767
2795
|
'history.filter': 'Tekst lub hash',
|
|
@@ -2962,6 +2990,8 @@ window.__ModuleLoader__.load({
|
|
|
2962
2990
|
'action.details': 'Commit-detaljer',
|
|
2963
2991
|
'menu.sendToChat': 'Skicka till samtalet',
|
|
2964
2992
|
'menu.sendFilePathToChat': 'Skicka filsökvägen till samtalet',
|
|
2993
|
+
'send.commitText': 'git-commit {hash} ”{subject}” (arkiv {repo})',
|
|
2994
|
+
'send.branchText': 'git-gren {name} (arkiv {repo})',
|
|
2965
2995
|
'history.empty': 'Det här arkivet har inga commits ännu',
|
|
2966
2996
|
'history.loadMore': 'Ladda mer',
|
|
2967
2997
|
'history.filter': 'Text eller hash',
|
|
@@ -3162,6 +3192,8 @@ window.__ModuleLoader__.load({
|
|
|
3162
3192
|
'action.details': 'Commit ayrıntıları',
|
|
3163
3193
|
'menu.sendToChat': 'Sohbete gönder',
|
|
3164
3194
|
'menu.sendFilePathToChat': 'Dosya yolunu sohbete gönder',
|
|
3195
|
+
'send.commitText': 'git commit {hash} "{subject}" (depo {repo})',
|
|
3196
|
+
'send.branchText': 'git dalı {name} (depo {repo})',
|
|
3165
3197
|
'history.empty': 'Bu depoda henüz commit yok',
|
|
3166
3198
|
'history.loadMore': 'Daha fazla yükle',
|
|
3167
3199
|
'history.filter': 'Metin veya hash',
|
|
@@ -3362,6 +3394,8 @@ window.__ModuleLoader__.load({
|
|
|
3362
3394
|
'action.details': 'Detail commit',
|
|
3363
3395
|
'menu.sendToChat': 'Kirim ke obrolan',
|
|
3364
3396
|
'menu.sendFilePathToChat': 'Kirim jalur berkas ke obrolan',
|
|
3397
|
+
'send.commitText': 'commit git {hash} "{subject}" (repositori {repo})',
|
|
3398
|
+
'send.branchText': 'cabang git {name} (repositori {repo})',
|
|
3365
3399
|
'history.empty': 'Repositori ini belum punya commit',
|
|
3366
3400
|
'history.loadMore': 'Muat lebih banyak',
|
|
3367
3401
|
'history.filter': 'Teks atau hash',
|
|
@@ -3562,6 +3596,8 @@ window.__ModuleLoader__.load({
|
|
|
3562
3596
|
'action.details': 'Chi tiết commit',
|
|
3563
3597
|
'menu.sendToChat': 'Gửi vào hội thoại',
|
|
3564
3598
|
'menu.sendFilePathToChat': 'Gửi đường dẫn tệp vào hội thoại',
|
|
3599
|
+
'send.commitText': 'git commit {hash} "{subject}" (kho {repo})',
|
|
3600
|
+
'send.branchText': 'nhánh git {name} (kho {repo})',
|
|
3565
3601
|
'history.empty': 'Kho này chưa có commit nào',
|
|
3566
3602
|
'history.loadMore': 'Tải thêm',
|
|
3567
3603
|
'history.filter': 'Văn bản hoặc hash',
|
|
@@ -3762,6 +3798,8 @@ window.__ModuleLoader__.load({
|
|
|
3762
3798
|
'action.details': 'تفاصيل الالتزام',
|
|
3763
3799
|
'menu.sendToChat': 'إرسال إلى المحادثة',
|
|
3764
3800
|
'menu.sendFilePathToChat': 'إرسال مسار الملف إلى المحادثة',
|
|
3801
|
+
'send.commitText': 'التزام git {hash} "{subject}" (المستودع {repo})',
|
|
3802
|
+
'send.branchText': 'فرع git {name} (المستودع {repo})',
|
|
3765
3803
|
'history.empty': 'لا توجد التزامات في هذا المستودع بعد',
|
|
3766
3804
|
'history.loadMore': 'تحميل المزيد',
|
|
3767
3805
|
'history.filter': 'نص أو تجزئة',
|
|
@@ -3962,6 +4000,8 @@ window.__ModuleLoader__.load({
|
|
|
3962
4000
|
'action.details': 'कमिट विवरण',
|
|
3963
4001
|
'menu.sendToChat': 'बातचीत में भेजें',
|
|
3964
4002
|
'menu.sendFilePathToChat': 'फ़ाइल पथ बातचीत में भेजें',
|
|
4003
|
+
'send.commitText': 'git कमिट {hash} "{subject}" (रिपॉज़िटरी {repo})',
|
|
4004
|
+
'send.branchText': 'git ब्रांच {name} (रिपॉज़िटरी {repo})',
|
|
3965
4005
|
'history.empty': 'इस रिपॉज़िटरी में अभी कोई कमिट नहीं है',
|
|
3966
4006
|
'history.loadMore': 'और लोड करें',
|
|
3967
4007
|
'history.filter': 'टेक्स्ट या हैश',
|
|
@@ -4162,6 +4202,8 @@ window.__ModuleLoader__.load({
|
|
|
4162
4202
|
'action.details': 'รายละเอียดคอมมิต',
|
|
4163
4203
|
'menu.sendToChat': 'ส่งไปยังบทสนทนา',
|
|
4164
4204
|
'menu.sendFilePathToChat': 'ส่งพาธไฟล์ไปยังบทสนทนา',
|
|
4205
|
+
'send.commitText': 'git คอมมิต {hash} "{subject}" (รีโพซิทอรี {repo})',
|
|
4206
|
+
'send.branchText': 'git บรานช์ {name} (รีโพซิทอรี {repo})',
|
|
4165
4207
|
'history.empty': 'รีโพซิทอรีนี้ยังไม่มีคอมมิต',
|
|
4166
4208
|
'history.loadMore': 'โหลดเพิ่ม',
|
|
4167
4209
|
'history.filter': 'ข้อความหรือแฮช',
|
|
@@ -7610,6 +7652,21 @@ window.__ModuleLoader__.load({
|
|
|
7610
7652
|
})
|
|
7611
7653
|
}, [sendToComposer])
|
|
7612
7654
|
|
|
7655
|
+
/* Self-describing text payloads for the commit/branch sends (v0.13.3 user
|
|
7656
|
+
feedback): a bare short hash or branch name is noise out of context —
|
|
7657
|
+
the text must say WHAT it is and WHERE from. The wording rides the
|
|
7658
|
+
fill() templates send.commitText / send.branchText; `repo` is the repo
|
|
7659
|
+
root's basename. An unknown root degrades to a neutral dash — fill()
|
|
7660
|
+
leaves unknown keys verbatim, so the callers must never let an
|
|
7661
|
+
undefined repo reach the template. The file @-chip is already
|
|
7662
|
+
self-describing and stays untouched. */
|
|
7663
|
+
const repoLabel = repoRoot === null ? '' : baseName(repoRoot)
|
|
7664
|
+
const sendGitSummaryToChat = useCallback((key, values) => {
|
|
7665
|
+
const repo = values.repo === undefined || values.repo === '' ? '—' : values.repo
|
|
7666
|
+
const text = fill(t(key), Object.assign({}, values, { repo: repo }))
|
|
7667
|
+
sendToComposer({ text: text, fallback: text })
|
|
7668
|
+
}, [t, sendToComposer])
|
|
7669
|
+
|
|
7613
7670
|
const branchMenu = useCallback((event, entry) => {
|
|
7614
7671
|
const current = branches === null ? '' : branches.branch
|
|
7615
7672
|
const isLocal = entry.remote !== true && entry.tag !== true
|
|
@@ -7619,7 +7676,7 @@ window.__ModuleLoader__.load({
|
|
|
7619
7676
|
isLocal ? { id: 'rebase', icon: 'compare', tone: 'violet', label: t('action.rebaseCurrentOnto'), disabled: entry.head === true || blocked, reason: blocked ? t('operation.hint') : reason, run: () => { void run('rebase', { onto: entry.name }) } } : null,
|
|
7620
7677
|
isLocal ? { id: 'merge', icon: 'compare', tone: 'accent', label: t('action.mergeIntoCurrent'), disabled: entry.head === true || blocked, reason: blocked ? t('operation.hint') : reason, run: () => { void run('merge', { branch: entry.name }) } } : null,
|
|
7621
7678
|
{ id: 'compare', icon: 'filter', tone: 'violet', label: t('action.compare'), disabled: entry.head === true || current === '', reason: reason, run: () => { void compareWith(current, entry.name) } },
|
|
7622
|
-
{ id: 'send', icon: 'send', tone: 'accent', label: t('menu.sendToChat'), run: () =>
|
|
7679
|
+
{ id: 'send', icon: 'send', tone: 'accent', label: t('menu.sendToChat'), run: () => sendGitSummaryToChat('send.branchText', { name: entry.name, repo: repoLabel }) },
|
|
7623
7680
|
null,
|
|
7624
7681
|
{ id: 'favorite', icon: 'star', tone: 'warn', label: t('action.favorite'), active: favorites.indexOf(entry.name) >= 0, run: () => toggleFavoriteBranch(entry.name) },
|
|
7625
7682
|
{ id: 'newBranch', icon: 'plus', tone: 'success', label: t('action.newBranchFrom'), run: () => setDialog({ kind: 'newBranch', from: entry.name }) },
|
|
@@ -7630,14 +7687,20 @@ window.__ModuleLoader__.load({
|
|
|
7630
7687
|
{ id: 'push', icon: 'push', tone: 'success', label: t('action.push'), disabled: blocked, reason: t('operation.hint'), run: () => setDialog({ kind: 'push' }) },
|
|
7631
7688
|
].filter((item) => item !== null)
|
|
7632
7689
|
openMenuAt(event, items)
|
|
7633
|
-
}, [branches, checkout, run, t, compareWith, toggleFavoriteBranch, openMenuAt, favorites, blocked,
|
|
7690
|
+
}, [branches, checkout, run, t, compareWith, toggleFavoriteBranch, openMenuAt, favorites, blocked, sendGitSummaryToChat, repoLabel])
|
|
7634
7691
|
|
|
7635
7692
|
const commitMenu = useCallback((event, commit) => {
|
|
7636
7693
|
const shortHash = commit.hash.slice(0, 7)
|
|
7637
7694
|
const items = [
|
|
7638
7695
|
{ id: 'details', icon: 'file', tone: 'primary', label: t('action.details'), run: () => { void selectCommit(commit) } },
|
|
7639
7696
|
{ id: 'copy', icon: 'tag', tone: 'secondary', label: t('action.copyHash'), run: () => { copyText(commit.hash) } },
|
|
7640
|
-
{ id: 'send', icon: 'send', tone: 'accent', label: t('menu.sendToChat'), run: () =>
|
|
7697
|
+
{ id: 'send', icon: 'send', tone: 'accent', label: t('menu.sendToChat'), run: () => {
|
|
7698
|
+
// A commit whose subject is empty (git tolerates empty messages)
|
|
7699
|
+
// degrades to the old bare-hash payload instead of faking one.
|
|
7700
|
+
const subject = typeof commit.subject === 'string' ? commit.subject.trim() : ''
|
|
7701
|
+
if (subject === '') { sendToComposer({ text: shortHash, fallback: shortHash }); return }
|
|
7702
|
+
sendGitSummaryToChat('send.commitText', { hash: shortHash, subject: subject, repo: repoLabel })
|
|
7703
|
+
} },
|
|
7641
7704
|
null,
|
|
7642
7705
|
{ id: 'checkout', icon: 'checkout', tone: 'accent', label: t('action.checkout'), run: () => setDialog({ kind: 'checkoutCommit', hash: commit.hash }) },
|
|
7643
7706
|
{ id: 'branch', icon: 'plus', tone: 'success', label: t('action.newBranchHere'), run: () => setDialog({ kind: 'newBranch', from: commit.hash }) },
|
|
@@ -7650,7 +7713,7 @@ window.__ModuleLoader__.load({
|
|
|
7650
7713
|
{ id: 'resetHard', icon: 'trash', tone: 'danger', label: t('action.resetHard'), danger: true, disabled: blocked, reason: t('operation.hint'), run: () => setDialog({ kind: 'reset', hash: commit.hash, mode: 'hard' }) },
|
|
7651
7714
|
]
|
|
7652
7715
|
openMenuAt(event, items)
|
|
7653
|
-
}, [run, selectCommit, t, openMenuAt, blocked, sendToComposer])
|
|
7716
|
+
}, [run, selectCommit, t, openMenuAt, blocked, sendToComposer, sendGitSummaryToChat, repoLabel])
|
|
7654
7717
|
|
|
7655
7718
|
const changeMenu = useCallback((event, item, group) => {
|
|
7656
7719
|
const items = [
|
|
@@ -8695,30 +8758,48 @@ window.__ModuleLoader__.load({
|
|
|
8695
8758
|
with the panel seat pinned to the visible height the scrollHeight
|
|
8696
8759
|
stays clientHeight + that flow space — the wheel could still scroll
|
|
8697
8760
|
the whole window by exactly that leftover (user report: the layout
|
|
8698
|
-
fits, yet the page keeps scrolling).
|
|
8699
|
-
the
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8761
|
+
fits, yet the page keeps scrolling). v0.13.3 report: content mounts
|
|
8762
|
+
or changes AFTER the first pass (the composer, the hero, a diff), and
|
|
8763
|
+
a single feedback convergence is not enough. measure() therefore
|
|
8764
|
+
recomputes the UNCORRECTED base (base.current) and hands off to the
|
|
8765
|
+
CONTROLLED CONVERGER below, which is re-run by every trigger: the
|
|
8766
|
+
initial mount, rAF/timeout follow-ups, the scrollport's own resize
|
|
8767
|
+
(ResizeObserver) and window resizes, and — new — the scrollport's
|
|
8768
|
+
content mutations (MutationObserver, debounced), because content
|
|
8769
|
+
growing later re-opens the overflow without resizing the scrollport
|
|
8770
|
+
itself. */
|
|
8706
8771
|
const leftover = { current: 0 }
|
|
8772
|
+
const base = { current: 0 }
|
|
8773
|
+
/* The converger: up to FOUR rAF-spaced rounds. Each round reads
|
|
8774
|
+
scroll.scrollHeight - scroll.clientHeight; anything over 1px shrinks
|
|
8775
|
+
the seat by exactly that amount and OVERWRITES the leftover record
|
|
8776
|
+
(never adds — every corrected height derives from the fresh base, so
|
|
8777
|
+
repeated rounds cannot compound), clamped at the same 240 floor.
|
|
8778
|
+
Shrink-only: nothing here grows the seat back. A host without the
|
|
8779
|
+
conversation scrollport never reaches this code — measure() skips it
|
|
8780
|
+
all, silently, and never throws. */
|
|
8781
|
+
const converge = (scroll) => {
|
|
8782
|
+
let rounds = 0
|
|
8783
|
+
const step = () => {
|
|
8784
|
+
rounds += 1
|
|
8785
|
+
if (el.isConnected !== true) return
|
|
8786
|
+
const overflow = scroll.scrollHeight - scroll.clientHeight
|
|
8787
|
+
if (overflow <= 1) return
|
|
8788
|
+
leftover.current = overflow
|
|
8789
|
+
setSeatHeight(Math.max(240, base.current - overflow))
|
|
8790
|
+
if (rounds < 4) requestAnimationFrame(step)
|
|
8791
|
+
}
|
|
8792
|
+
requestAnimationFrame(step)
|
|
8793
|
+
}
|
|
8707
8794
|
const measure = () => {
|
|
8708
8795
|
let scroll = null
|
|
8709
8796
|
try { scroll = el.closest('[data-conversation-scroll]') } catch (error) { void error }
|
|
8710
8797
|
if (scroll === null || scroll === undefined) return
|
|
8711
8798
|
const offset = Math.max(0, el.getBoundingClientRect().top - scroll.getBoundingClientRect().top)
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
const overflow = scroll.scrollHeight - scroll.clientHeight
|
|
8717
|
-
if (overflow > 0) {
|
|
8718
|
-
leftover.current = overflow
|
|
8719
|
-
setSeatHeight(Math.max(240, available - overflow))
|
|
8720
|
-
}
|
|
8721
|
-
})
|
|
8799
|
+
base.current = Math.round(scroll.clientHeight - offset - 8)
|
|
8800
|
+
const corrected = base.current - leftover.current
|
|
8801
|
+
if (corrected >= 240) setSeatHeight(corrected)
|
|
8802
|
+
converge(scroll)
|
|
8722
8803
|
}
|
|
8723
8804
|
measure()
|
|
8724
8805
|
const raf = requestAnimationFrame(() => { measure() })
|
|
@@ -8731,10 +8812,28 @@ window.__ModuleLoader__.load({
|
|
|
8731
8812
|
observer.observe(scroll)
|
|
8732
8813
|
}
|
|
8733
8814
|
} catch (error) { void error }
|
|
8815
|
+
/* Content that mounts or changes later does not resize the scrollport,
|
|
8816
|
+
so the ResizeObserver stays silent while the overflow re-opens; the
|
|
8817
|
+
mutation watcher re-measures for it. Debounced ~120ms so a mount
|
|
8818
|
+
burst converges once instead of once per node. */
|
|
8819
|
+
let mutationObserver
|
|
8820
|
+
let mutationTimer = null
|
|
8821
|
+
try {
|
|
8822
|
+
const scroll = el.closest('[data-conversation-scroll]')
|
|
8823
|
+
if (scroll !== null && scroll !== undefined && typeof MutationObserver === 'function') {
|
|
8824
|
+
mutationObserver = new MutationObserver(() => {
|
|
8825
|
+
if (mutationTimer !== null) clearTimeout(mutationTimer)
|
|
8826
|
+
mutationTimer = setTimeout(() => { mutationTimer = null; measure() }, 120)
|
|
8827
|
+
})
|
|
8828
|
+
mutationObserver.observe(scroll, { childList: true, subtree: true })
|
|
8829
|
+
}
|
|
8830
|
+
} catch (error) { void error }
|
|
8734
8831
|
window.addEventListener('resize', measure)
|
|
8735
8832
|
return () => {
|
|
8736
8833
|
cancelAnimationFrame(raf)
|
|
8737
8834
|
clearTimeout(late)
|
|
8835
|
+
if (mutationTimer !== null) clearTimeout(mutationTimer)
|
|
8836
|
+
if (mutationObserver !== undefined) mutationObserver.disconnect()
|
|
8738
8837
|
if (observer !== undefined) observer.disconnect()
|
|
8739
8838
|
window.removeEventListener('resize', measure)
|
|
8740
8839
|
}
|