diff --git a/apps/desktop/l10n/bundle.l10n.json b/apps/desktop/l10n/bundle.l10n.json index dcbd6dec..1cc5fc1d 100644 --- a/apps/desktop/l10n/bundle.l10n.json +++ b/apps/desktop/l10n/bundle.l10n.json @@ -4088,6 +4088,7 @@ "no matches": "no matches", "no model set": "no model set", "no one": "no one", + "no room": "no room", "no sha": "no sha", "not a pull request number: {0}": "not a pull request number: {0}", "not a worktree": "not a worktree", @@ -4458,6 +4459,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} has {1} that pull request #{2} doesn't — made here, or from before ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.", "{0} hidden · drag header edges to resize": "{0} hidden · drag header edges to resize", + "{0} hidden — panel too narrow": "{0} hidden — panel too narrow", "{0} in Theirs": "{0} in Theirs", "{0} in Yours": "{0} in Yours", "{0} in the Result, marked so you can check {1}.": "{0} in the Result, marked so you can check {1}.", diff --git a/apps/extension/l10n/bundle.l10n.cs.json b/apps/extension/l10n/bundle.l10n.cs.json index efc1b3cb..84df7d41 100644 --- a/apps/extension/l10n/bundle.l10n.cs.json +++ b/apps/extension/l10n/bundle.l10n.cs.json @@ -2784,6 +2784,7 @@ "no email recorded": "žádný zaznamenaný e-mail", "no one": "nikdo", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "žádný vzdálený repozitář tohoto repozitáře ({0}) není adresa GitHub, GitLab nebo Bitbucket.", + "no room": "není místo", "not a pull request number: {0}": "nejedná se o číslo pull requestu: {0}", "not a worktree": "není pracovní strom", "not published": "nezveřejněno", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} má {1}, které {2} nemá, a {3} má {4}, které {5} nemá — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} mají změny, které nejsou připravené. Nejdřív je připravte nebo stashněte — git nebude pokračovat v rebase s nepřipravenými změnami.", "{0} hidden · drag header edges to resize": "{0} skryto · velikost změníte tažením okrajů záhlaví", + "{0} hidden — panel too narrow": "{0} skryto — panel je příliš úzký", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} narazilo na konflikty. Vyřešte je, pak pokračujte nebo to zrušte.", "{0} in Theirs": "{0} v Jejich", "{0} in Yours": "{0} ve Vašem", diff --git a/apps/extension/l10n/bundle.l10n.de.json b/apps/extension/l10n/bundle.l10n.de.json index d950794d..01fcc0a0 100644 --- a/apps/extension/l10n/bundle.l10n.de.json +++ b/apps/extension/l10n/bundle.l10n.de.json @@ -2784,6 +2784,7 @@ "no email recorded": "keine E-Mail hinterlegt", "no one": "niemand", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "kein Remote dieses Repositorys ({0}) ist eine GitHub-, GitLab- oder Bitbucket-Adresse.", + "no room": "kein Platz", "not a pull request number: {0}": "keine Pull-Request-Nummer: {0}", "not a worktree": "kein Worktree", "not published": "nicht veröffentlicht", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} hat {1}, was {2} nicht hat, und {3} hat {4}, was {5} nicht hat — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} haben nicht bereitgestellte Änderungen. Zuerst bereitstellen oder stashen — Git setzt einen Rebase nicht mit nicht bereitgestellten Änderungen fort.", "{0} hidden · drag header edges to resize": "{0} ausgeblendet · Kopfzeilenränder ziehen, um die Größe anzupassen", + "{0} hidden — panel too narrow": "{0} ausgeblendet — Bereich zu schmal", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} ist auf Konflikte gestoßen. Lösen, dann fortsetzen oder abbrechen.", "{0} in Theirs": "{0} in deren Version", "{0} in Yours": "{0} in Ihrer Version", diff --git a/apps/extension/l10n/bundle.l10n.es.json b/apps/extension/l10n/bundle.l10n.es.json index c7b86c94..51c80541 100644 --- a/apps/extension/l10n/bundle.l10n.es.json +++ b/apps/extension/l10n/bundle.l10n.es.json @@ -2784,6 +2784,7 @@ "no email recorded": "sin correo electrónico registrado", "no one": "nadie", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "ningún remoto de este repositorio ({0}) es una dirección de GitHub, GitLab o Bitbucket.", + "no room": "sin espacio", "not a pull request number: {0}": "no es un número de pull request: {0}", "not a worktree": "no es un worktree", "not published": "no publicado", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} tiene {1} que {2} no tiene, y {3} tiene {4} que {5} no tiene — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} tienen cambios que no están preparados. Prepáralos o guárdalos en el stash primero — git no continuará un rebase con cambios sin preparar.", "{0} hidden · drag header edges to resize": "{0} oculto · arrastra los bordes del encabezado para cambiar el tamaño", + "{0} hidden — panel too narrow": "{0} oculto — panel demasiado estrecho", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} tuvo conflictos. Resuélvelos, y luego continúa o aborta.", "{0} in Theirs": "{0} en Suyos", "{0} in Yours": "{0} en Tuyos", diff --git a/apps/extension/l10n/bundle.l10n.fr.json b/apps/extension/l10n/bundle.l10n.fr.json index 51045aa5..b374e71a 100644 --- a/apps/extension/l10n/bundle.l10n.fr.json +++ b/apps/extension/l10n/bundle.l10n.fr.json @@ -2784,6 +2784,7 @@ "no email recorded": "aucun e-mail enregistré", "no one": "personne", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "aucun dépôt distant de ce dépôt ({0}) n'est une adresse GitHub, GitLab ou Bitbucket.", + "no room": "pas de place", "not a pull request number: {0}": "pas un numéro de pull request : {0}", "not a worktree": "pas une arborescence de travail", "not published": "non publiée", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} a {1} que {2} n'a pas, et {3} a {4} que {5} n'a pas — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} ont des modifications non indexées. Indexez-les ou remisez-les d'abord — git ne continuera pas un rebase avec des modifications non indexées.", "{0} hidden · drag header edges to resize": "{0} masqué(e)s · faites glisser les bords de l'en-tête pour redimensionner", + "{0} hidden — panel too narrow": "{0} masqué(e)s — panneau trop étroit", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} a rencontré des conflits. Résolvez-les, puis continuez ou abandonnez.", "{0} in Theirs": "{0} dans la leur", "{0} in Yours": "{0} dans la vôtre", diff --git a/apps/extension/l10n/bundle.l10n.it.json b/apps/extension/l10n/bundle.l10n.it.json index 3cef1fe7..3383a770 100644 --- a/apps/extension/l10n/bundle.l10n.it.json +++ b/apps/extension/l10n/bundle.l10n.it.json @@ -2784,6 +2784,7 @@ "no email recorded": "nessuna email registrata", "no one": "nessuno", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "nessun remoto di questo repository ({0}) è un indirizzo GitHub, GitLab o Bitbucket.", + "no room": "spazio insufficiente", "not a pull request number: {0}": "non è un numero di pull request: {0}", "not a worktree": "non è un worktree", "not published": "non pubblicato", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} ha {1} che {2} non ha, e {3} ha {4} che {5} non ha — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} hanno modifiche non in stage. Mettile prima in stage o in stash — git non continuerà un rebase con modifiche non in stage.", "{0} hidden · drag header edges to resize": "{0} nascosti · trascina i bordi dell'intestazione per ridimensionare", + "{0} hidden — panel too narrow": "{0} nascosti — pannello troppo stretto", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} ha incontrato conflitti. Risolvili, poi continua o interrompi.", "{0} in Theirs": "{0} in Loro", "{0} in Yours": "{0} in Tuo", diff --git a/apps/extension/l10n/bundle.l10n.ja.json b/apps/extension/l10n/bundle.l10n.ja.json index 8ee9d280..502ab4d7 100644 --- a/apps/extension/l10n/bundle.l10n.ja.json +++ b/apps/extension/l10n/bundle.l10n.ja.json @@ -2784,6 +2784,7 @@ "no email recorded": "メールアドレスが記録されていません", "no one": "だれもいません", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "このリポジトリ ({0}) のリモートに、GitHub、GitLab、Bitbucketのアドレスはありません。", + "no room": "スペース不足", "not a pull request number: {0}": "プルリクエスト番号ではありません: {0}", "not a worktree": "ワークツリーではありません", "not published": "公開されていません", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} には {2} にはない {1} があり、{3} には {5} にはない {4} があります —", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} にはステージされていない変更があります。先にステージまたはスタッシュしてください — gitは未ステージの変更があるとリベースを続行できません。", "{0} hidden · drag header edges to resize": "{0} 個を非表示 · ヘッダーの端をドラッグしてサイズ変更", + "{0} hidden — panel too narrow": "{0} を非表示 — パネルが狭すぎます", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} でコンフリクトが発生しました。解決してから続行するか、中止してください。", "{0} in Theirs": "相手の {0}", "{0} in Yours": "自分の {0}", diff --git a/apps/extension/l10n/bundle.l10n.json b/apps/extension/l10n/bundle.l10n.json index 6fb3cf91..7fb1a920 100644 --- a/apps/extension/l10n/bundle.l10n.json +++ b/apps/extension/l10n/bundle.l10n.json @@ -2784,6 +2784,7 @@ "no email recorded": "no email recorded", "no one": "no one", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.", + "no room": "no room", "not a pull request number: {0}": "not a pull request number: {0}", "not a worktree": "not a worktree", "not published": "not published", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.", "{0} hidden · drag header edges to resize": "{0} hidden · drag header edges to resize", + "{0} hidden — panel too narrow": "{0} hidden — panel too narrow", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} hit conflicts. Resolve them, then continue or abort.", "{0} in Theirs": "{0} in Theirs", "{0} in Yours": "{0} in Yours", diff --git a/apps/extension/l10n/bundle.l10n.ko.json b/apps/extension/l10n/bundle.l10n.ko.json index 59cc5350..9549c540 100644 --- a/apps/extension/l10n/bundle.l10n.ko.json +++ b/apps/extension/l10n/bundle.l10n.ko.json @@ -2784,6 +2784,7 @@ "no email recorded": "기록된 이메일 없음", "no one": "없음", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "이 리포지토리의 원격({0}) 중 GitHub, GitLab 또는 Bitbucket 주소인 것이 없습니다.", + "no room": "공간 부족", "not a pull request number: {0}": "풀 리퀘스트 번호가 아님: {0}", "not a worktree": "작업 폴더가 아님", "not published": "게시되지 않음", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0}에는 {2}에 없는 {1}이 있고, {3}에는 {5}에 없는 {4}이 있습니다 — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0}에 스테이징되지 않은 변경 내용이 있습니다. 먼저 스테이지에 추가하거나 스태시하세요 — git은 스테이징되지 않은 변경 내용이 있으면 리베이스를 계속하지 않습니다.", "{0} hidden · drag header edges to resize": "{0} 숨겨짐 · 헤더 경계를 드래그하여 크기 조절", + "{0} hidden — panel too narrow": "{0} 숨겨짐 — 패널이 너무 좁음", "{0} hit conflicts. Resolve them, then continue or abort.": "{0}에서 충돌이 발생했습니다. 해결 후 계속하거나 중단하세요.", "{0} in Theirs": "상대 변경 내용의 {0}", "{0} in Yours": "내 변경 내용의 {0}", diff --git a/apps/extension/l10n/bundle.l10n.pl.json b/apps/extension/l10n/bundle.l10n.pl.json index 890844de..3a5f6b92 100644 --- a/apps/extension/l10n/bundle.l10n.pl.json +++ b/apps/extension/l10n/bundle.l10n.pl.json @@ -2784,6 +2784,7 @@ "no email recorded": "nie zapisano adresu e-mail", "no one": "nikt", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "żadne zdalne repozytorium tego repozytorium ({0}) nie jest adresem GitHub, GitLab ani Bitbucket.", + "no room": "brak miejsca", "not a pull request number: {0}": "nie jest numerem pull requesta: {0}", "not a worktree": "to nie worktree", "not published": "nieopublikowany", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} ma {1}, których {2} nie ma, a {3} ma {4}, których {5} nie ma — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} mają zmiany, które nie są przygotowane. Najpierw je przygotuj albo zapisz w schowku — git nie kontynuuje rebase z nieprzygotowanymi zmianami.", "{0} hidden · drag header edges to resize": "{0} ukryte · przeciągnij krawędzie nagłówka, aby zmienić rozmiar", + "{0} hidden — panel too narrow": "{0} ukryte — panel jest za wąski", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} natrafiło na konflikty. Rozwiąż je, a potem kontynuuj albo przerwij.", "{0} in Theirs": "{0} w Ich", "{0} in Yours": "{0} w Twoich", diff --git a/apps/extension/l10n/bundle.l10n.pt-br.json b/apps/extension/l10n/bundle.l10n.pt-br.json index 69d83221..fdd99b78 100644 --- a/apps/extension/l10n/bundle.l10n.pt-br.json +++ b/apps/extension/l10n/bundle.l10n.pt-br.json @@ -2784,6 +2784,7 @@ "no email recorded": "nenhum e-mail registrado", "no one": "ninguém", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "nenhum remoto deste repositório ({0}) é um endereço do GitHub, GitLab ou Bitbucket.", + "no room": "sem espaço", "not a pull request number: {0}": "não é um número de pull request: {0}", "not a worktree": "não é um worktree", "not published": "não publicado", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} tem {1} que {2} não tem, e {3} tem {4} que {5} não tem — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} têm alterações que não estão em stage. Coloque-as em stage ou guarde-as no stash primeiro — o git não continua um rebase com alterações fora do stage.", "{0} hidden · drag header edges to resize": "{0} ocultos · arraste as bordas do cabeçalho para redimensionar", + "{0} hidden — panel too narrow": "{0} ocultos — painel estreito demais", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} encontrou conflitos. Resolva-os, depois continue ou aborte.", "{0} in Theirs": "{0} em Deles", "{0} in Yours": "{0} em Seu", diff --git a/apps/extension/l10n/bundle.l10n.ru.json b/apps/extension/l10n/bundle.l10n.ru.json index 3090c18c..6e683865 100644 --- a/apps/extension/l10n/bundle.l10n.ru.json +++ b/apps/extension/l10n/bundle.l10n.ru.json @@ -2784,6 +2784,7 @@ "no email recorded": "email не записан", "no one": "никто", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "ни один удалённый репозиторий этого репозитория ({0}) не является адресом GitHub, GitLab или Bitbucket.", + "no room": "нет места", "not a pull request number: {0}": "не номер pull request: {0}", "not a worktree": "не рабочий каталог", "not published": "не опубликовано", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "В {0} есть {1}, которых нет в {2}, а в {3} есть {4}, которых нет в {5} — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "В {0} есть изменения, не добавленные в индекс. Сначала добавьте их в индекс или спрячьте — git не продолжит перебазирование с неиндексированными изменениями.", "{0} hidden · drag header edges to resize": "{0} скрыто · перетащите края заголовка для изменения размера", + "{0} hidden — panel too narrow": "{0} скрыто — панель слишком узкая", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} привело к конфликтам. Разрешите их, затем продолжите или прервите.", "{0} in Theirs": "{0} в «Их»", "{0} in Yours": "{0} в «Ваши»", diff --git a/apps/extension/l10n/bundle.l10n.tr.json b/apps/extension/l10n/bundle.l10n.tr.json index b786efa7..e729e5fc 100644 --- a/apps/extension/l10n/bundle.l10n.tr.json +++ b/apps/extension/l10n/bundle.l10n.tr.json @@ -2784,6 +2784,7 @@ "no email recorded": "e-posta kaydedilmemiş", "no one": "hiç kimse", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "bu deponun hiçbir uzak konumu ({0}) bir GitHub, GitLab veya Bitbucket adresi değil.", + "no room": "yer yok", "not a pull request number: {0}": "bir çekme isteği numarası değil: {0}", "not a worktree": "bir çalışma alanı değil", "not published": "yayınlanmadı", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0}'da {2}'de olmayan {1} var ve {3}'de {5}'de olmayan {4} var — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0}'da hazırlanmamış değişiklikler var. Önce hazırlayın veya zulalayın — git hazırlanmamış değişikliklerle bir yeniden temellendirmeyi sürdürmez.", "{0} hidden · drag header edges to resize": "{0} gizli · boyutlandırmak için başlık kenarlarını sürükleyin", + "{0} hidden — panel too narrow": "{0} gizli — panel çok dar", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} çakışmalara çarptı. Çözün, sonra sürdürün veya iptal edin.", "{0} in Theirs": "Onlarınki'nde {0}", "{0} in Yours": "Sizinki'nde {0}", diff --git a/apps/extension/l10n/bundle.l10n.zh-cn.json b/apps/extension/l10n/bundle.l10n.zh-cn.json index 512de70f..6dfe19dd 100644 --- a/apps/extension/l10n/bundle.l10n.zh-cn.json +++ b/apps/extension/l10n/bundle.l10n.zh-cn.json @@ -2784,6 +2784,7 @@ "no email recorded": "未记录邮箱", "no one": "无人", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "此仓库的所有远程仓库({0})都不是 GitHub、GitLab 或 Bitbucket 地址。", + "no room": "空间不足", "not a pull request number: {0}": "不是拉取请求编号:{0}", "not a worktree": "不是工作树", "not published": "未发布", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} 有 {1} 是 {2} 没有的,而 {3} 有 {4} 是 {5} 没有的 — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} 有未暂存的更改。请先暂存或贮藏它们 — git 不会带着未暂存的更改继续变基。", "{0} hidden · drag header edges to resize": "已隐藏 {0} · 拖动表头边缘可调整大小", + "{0} hidden — panel too narrow": "已隐藏 {0} — 面板太窄", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} 遇到冲突。请解决它们,然后继续或中止。", "{0} in Theirs": "{0} 在“他们的”中", "{0} in Yours": "{0} 在“你的”中", diff --git a/apps/extension/l10n/bundle.l10n.zh-tw.json b/apps/extension/l10n/bundle.l10n.zh-tw.json index 4e49fed4..5d51e3b1 100644 --- a/apps/extension/l10n/bundle.l10n.zh-tw.json +++ b/apps/extension/l10n/bundle.l10n.zh-tw.json @@ -2784,6 +2784,7 @@ "no email recorded": "未記錄郵箱", "no one": "無人", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "此儲存庫的所有遠端儲存庫({0})都不是 GitHub、GitLab 或 Bitbucket 地址。", + "no room": "空間不足", "not a pull request number: {0}": "不是拉取請求編號:{0}", "not a worktree": "不是工作樹", "not published": "未釋出", @@ -3080,6 +3081,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} 有 {1} 是 {2} 沒有的,而 {3} 有 {4} 是 {5} 沒有的 — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} 有未暫存的更改。請先暫存或儲藏它們 — git 不會帶著未暫存的更改繼續變基。", "{0} hidden · drag header edges to resize": "已隱藏 {0} · 拖動表頭邊緣可調整大小", + "{0} hidden — panel too narrow": "已隱藏 {0} — 面板太窄", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} 遇到衝突。請解決它們,然後繼續或中止。", "{0} in Theirs": "{0} 在“他們的”中", "{0} in Yours": "{0} 在“你的”中", diff --git a/apps/merge-studio/l10n/bundle.l10n.cs.json b/apps/merge-studio/l10n/bundle.l10n.cs.json index 5f58f97e..61ee3195 100644 --- a/apps/merge-studio/l10n/bundle.l10n.cs.json +++ b/apps/merge-studio/l10n/bundle.l10n.cs.json @@ -1508,6 +1508,7 @@ "no commits yet": "zatím žádné commity", "no email recorded": "žádný zaznamenaný e-mail", "no one": "nikdo", + "no room": "není místo", "not a pull request number: {0}": "nejedná se o číslo pull requestu: {0}", "not a worktree": "není pracovní strom", "not pushed": "nenahráno (push)", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} má {1}, které pull request #{2} nemá — vytvořené tady, nebo odtud dřív ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} mají změny, které nejsou připravené. Nejdřív je připravte nebo stashněte — git nebude pokračovat v rebase s nepřipravenými změnami.", "{0} hidden · drag header edges to resize": "{0} skryto · velikost změníte tažením okrajů záhlaví", + "{0} hidden — panel too narrow": "{0} skryto — panel je příliš úzký", "{0} in Theirs": "{0} v Jejich", "{0} in Yours": "{0} ve Vašem", "{0} in the Result, marked so you can check {1}.": "{0} ve Výsledku, označeno tak, abyste to mohli zkontrolovat {1}.", diff --git a/apps/merge-studio/l10n/bundle.l10n.de.json b/apps/merge-studio/l10n/bundle.l10n.de.json index c537c5d2..b6350c09 100644 --- a/apps/merge-studio/l10n/bundle.l10n.de.json +++ b/apps/merge-studio/l10n/bundle.l10n.de.json @@ -1508,6 +1508,7 @@ "no commits yet": "noch keine Commits", "no email recorded": "keine E-Mail hinterlegt", "no one": "niemand", + "no room": "kein Platz", "not a pull request number: {0}": "keine Pull-Request-Nummer: {0}", "not a worktree": "kein Worktree", "not pushed": "nicht gepusht", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} hat {1}, was Pull Request #{2} nicht hat — hier gemacht, oder von davor ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} haben nicht bereitgestellte Änderungen. Zuerst bereitstellen oder stashen — Git setzt einen Rebase nicht mit nicht bereitgestellten Änderungen fort.", "{0} hidden · drag header edges to resize": "{0} ausgeblendet · Kopfzeilenränder ziehen, um die Größe anzupassen", + "{0} hidden — panel too narrow": "{0} ausgeblendet — Bereich zu schmal", "{0} in Theirs": "{0} in deren Version", "{0} in Yours": "{0} in Ihrer Version", "{0} in the Result, marked so you can check {1}.": "{0} im Ergebnis, markiert, damit {1} geprüft werden kann.", diff --git a/apps/merge-studio/l10n/bundle.l10n.es.json b/apps/merge-studio/l10n/bundle.l10n.es.json index 058c3cc9..03e99991 100644 --- a/apps/merge-studio/l10n/bundle.l10n.es.json +++ b/apps/merge-studio/l10n/bundle.l10n.es.json @@ -1508,6 +1508,7 @@ "no commits yet": "sin commits todavía", "no email recorded": "sin correo electrónico registrado", "no one": "nadie", + "no room": "sin espacio", "not a pull request number: {0}": "no es un número de pull request: {0}", "not a worktree": "no es un worktree", "not pushed": "no publicado con push", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} tiene {1} que el pull request #{2} no tiene — hechos aquí, o de antes de ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} tienen cambios que no están preparados. Prepáralos o guárdalos en el stash primero — git no continuará un rebase con cambios sin preparar.", "{0} hidden · drag header edges to resize": "{0} oculto · arrastra los bordes del encabezado para cambiar el tamaño", + "{0} hidden — panel too narrow": "{0} oculto — panel demasiado estrecho", "{0} in Theirs": "{0} en Suyos", "{0} in Yours": "{0} en Tuyos", "{0} in the Result, marked so you can check {1}.": "{0} en el Resultado, marcados para que puedas revisar {1}.", diff --git a/apps/merge-studio/l10n/bundle.l10n.fr.json b/apps/merge-studio/l10n/bundle.l10n.fr.json index a8bfd5fb..fc89f0f0 100644 --- a/apps/merge-studio/l10n/bundle.l10n.fr.json +++ b/apps/merge-studio/l10n/bundle.l10n.fr.json @@ -1508,6 +1508,7 @@ "no commits yet": "aucun commit pour l'instant", "no email recorded": "aucun e-mail enregistré", "no one": "personne", + "no room": "pas de place", "not a pull request number: {0}": "pas un numéro de pull request : {0}", "not a worktree": "pas une arborescence de travail", "not pushed": "non poussé", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} a {1} que la pull request #{2} n'a pas — faits ici, ou d'avant ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} ont des modifications non indexées. Indexez-les ou remisez-les d'abord — git ne continuera pas un rebase avec des modifications non indexées.", "{0} hidden · drag header edges to resize": "{0} masqué(e)s · faites glisser les bords de l'en-tête pour redimensionner", + "{0} hidden — panel too narrow": "{0} masqué(e)s — panneau trop étroit", "{0} in Theirs": "{0} dans la leur", "{0} in Yours": "{0} dans la vôtre", "{0} in the Result, marked so you can check {1}.": "{0} dans le résultat, marqué pour que vous puissiez vérifier {1}.", diff --git a/apps/merge-studio/l10n/bundle.l10n.it.json b/apps/merge-studio/l10n/bundle.l10n.it.json index 965e3458..5e424cec 100644 --- a/apps/merge-studio/l10n/bundle.l10n.it.json +++ b/apps/merge-studio/l10n/bundle.l10n.it.json @@ -1508,6 +1508,7 @@ "no commits yet": "ancora nessun commit", "no email recorded": "nessuna email registrata", "no one": "nessuno", + "no room": "spazio insufficiente", "not a pull request number: {0}": "non è un numero di pull request: {0}", "not a worktree": "non è un worktree", "not pushed": "non sottoposto a push", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} ha {1} che la pull request #{2} non ha — fatti qui, o da prima ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} hanno modifiche non in stage. Mettile prima in stage o in stash — git non continuerà un rebase con modifiche non in stage.", "{0} hidden · drag header edges to resize": "{0} nascosti · trascina i bordi dell'intestazione per ridimensionare", + "{0} hidden — panel too narrow": "{0} nascosti — pannello troppo stretto", "{0} in Theirs": "{0} in Loro", "{0} in Yours": "{0} in Tuo", "{0} in the Result, marked so you can check {1}.": "{0} nel Risultato, segnati così puoi verificare {1}.", diff --git a/apps/merge-studio/l10n/bundle.l10n.ja.json b/apps/merge-studio/l10n/bundle.l10n.ja.json index aac8f065..ba76392e 100644 --- a/apps/merge-studio/l10n/bundle.l10n.ja.json +++ b/apps/merge-studio/l10n/bundle.l10n.ja.json @@ -1508,6 +1508,7 @@ "no commits yet": "まだコミットがありません", "no email recorded": "メールアドレスが記録されていません", "no one": "だれもいません", + "no room": "スペース不足", "not a pull request number: {0}": "プルリクエスト番号ではありません: {0}", "not a worktree": "ワークツリーではありません", "not pushed": "プッシュされていません", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} には プルリクエスト #{2} にはない {1} があります — ここで行われたか、それ以前のものです", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} にはステージされていない変更があります。先にステージまたはスタッシュしてください — gitは未ステージの変更があるとリベースを続行できません。", "{0} hidden · drag header edges to resize": "{0} 個を非表示 · ヘッダーの端をドラッグしてサイズ変更", + "{0} hidden — panel too narrow": "{0} を非表示 — パネルが狭すぎます", "{0} in Theirs": "相手の {0}", "{0} in Yours": "自分の {0}", "{0} in the Result, marked so you can check {1}.": "結果内の {0} は、{1} を確認できるようにマークされています。", diff --git a/apps/merge-studio/l10n/bundle.l10n.json b/apps/merge-studio/l10n/bundle.l10n.json index 201bfe6c..69240aeb 100644 --- a/apps/merge-studio/l10n/bundle.l10n.json +++ b/apps/merge-studio/l10n/bundle.l10n.json @@ -1508,6 +1508,7 @@ "no commits yet": "no commits yet", "no email recorded": "no email recorded", "no one": "no one", + "no room": "no room", "not a pull request number: {0}": "not a pull request number: {0}", "not a worktree": "not a worktree", "not pushed": "not pushed", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} has {1} that pull request #{2} doesn't — made here, or from before ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.", "{0} hidden · drag header edges to resize": "{0} hidden · drag header edges to resize", + "{0} hidden — panel too narrow": "{0} hidden — panel too narrow", "{0} in Theirs": "{0} in Theirs", "{0} in Yours": "{0} in Yours", "{0} in the Result, marked so you can check {1}.": "{0} in the Result, marked so you can check {1}.", diff --git a/apps/merge-studio/l10n/bundle.l10n.ko.json b/apps/merge-studio/l10n/bundle.l10n.ko.json index 2e362380..d107938e 100644 --- a/apps/merge-studio/l10n/bundle.l10n.ko.json +++ b/apps/merge-studio/l10n/bundle.l10n.ko.json @@ -1508,6 +1508,7 @@ "no commits yet": "아직 커밋 없음", "no email recorded": "기록된 이메일 없음", "no one": "없음", + "no room": "공간 부족", "not a pull request number: {0}": "풀 리퀘스트 번호가 아님: {0}", "not a worktree": "작업 폴더가 아님", "not pushed": "푸시되지 않음", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0}에는 풀 리퀘스트 #{1}에 없는 {2}이 있습니다 — 여기서 만들어졌거나 ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0}에 스테이징되지 않은 변경 내용이 있습니다. 먼저 스테이지에 추가하거나 스태시하세요 — git은 스테이징되지 않은 변경 내용이 있으면 리베이스를 계속하지 않습니다.", "{0} hidden · drag header edges to resize": "{0} 숨겨짐 · 헤더 경계를 드래그하여 크기 조절", + "{0} hidden — panel too narrow": "{0} 숨겨짐 — 패널이 너무 좁음", "{0} in Theirs": "상대 변경 내용의 {0}", "{0} in Yours": "내 변경 내용의 {0}", "{0} in the Result, marked so you can check {1}.": "결과의 {0}은 확인할 수 있도록 표시되어 있습니다 {1}.", diff --git a/apps/merge-studio/l10n/bundle.l10n.pl.json b/apps/merge-studio/l10n/bundle.l10n.pl.json index 341351a0..74d0d91e 100644 --- a/apps/merge-studio/l10n/bundle.l10n.pl.json +++ b/apps/merge-studio/l10n/bundle.l10n.pl.json @@ -1508,6 +1508,7 @@ "no commits yet": "brak commitów", "no email recorded": "nie zapisano adresu e-mail", "no one": "nikt", + "no room": "brak miejsca", "not a pull request number: {0}": "nie jest numerem pull requesta: {0}", "not a worktree": "to nie worktree", "not pushed": "nie wypchnięto", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} ma {1}, których pull request #{2} nie ma — zrobione tutaj albo sprzed ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} mają zmiany, które nie są przygotowane. Najpierw je przygotuj albo zapisz w schowku — git nie kontynuuje rebase z nieprzygotowanymi zmianami.", "{0} hidden · drag header edges to resize": "{0} ukryte · przeciągnij krawędzie nagłówka, aby zmienić rozmiar", + "{0} hidden — panel too narrow": "{0} ukryte — panel jest za wąski", "{0} in Theirs": "{0} w Ich", "{0} in Yours": "{0} w Twoich", "{0} in the Result, marked so you can check {1}.": "{0} w Wyniku, oznaczone, abyś mógł sprawdzić {1}.", diff --git a/apps/merge-studio/l10n/bundle.l10n.pt-br.json b/apps/merge-studio/l10n/bundle.l10n.pt-br.json index bf97779b..6f45a99b 100644 --- a/apps/merge-studio/l10n/bundle.l10n.pt-br.json +++ b/apps/merge-studio/l10n/bundle.l10n.pt-br.json @@ -1508,6 +1508,7 @@ "no commits yet": "ainda sem commits", "no email recorded": "nenhum e-mail registrado", "no one": "ninguém", + "no room": "sem espaço", "not a pull request number: {0}": "não é um número de pull request: {0}", "not a worktree": "não é um worktree", "not pushed": "sem push", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} tem {1} que a pull request #{2} não tem — feito aqui, ou de antes ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} têm alterações que não estão em stage. Coloque-as em stage ou guarde-as no stash primeiro — o git não continua um rebase com alterações fora do stage.", "{0} hidden · drag header edges to resize": "{0} ocultos · arraste as bordas do cabeçalho para redimensionar", + "{0} hidden — panel too narrow": "{0} ocultos — painel estreito demais", "{0} in Theirs": "{0} em Deles", "{0} in Yours": "{0} em Seu", "{0} in the Result, marked so you can check {1}.": "{0} no Resultado, marcado para que você possa verificar {1}.", diff --git a/apps/merge-studio/l10n/bundle.l10n.ru.json b/apps/merge-studio/l10n/bundle.l10n.ru.json index fb63dd3f..9c5b83ba 100644 --- a/apps/merge-studio/l10n/bundle.l10n.ru.json +++ b/apps/merge-studio/l10n/bundle.l10n.ru.json @@ -1508,6 +1508,7 @@ "no commits yet": "пока нет коммитов", "no email recorded": "email не записан", "no one": "никто", + "no room": "нет места", "not a pull request number: {0}": "не номер pull request: {0}", "not a worktree": "не рабочий каталог", "not pushed": "не отправлено", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "В {0} есть {1}, которых нет в pull request #{2} — сделанные здесь, или из состояния до ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "В {0} есть изменения, не добавленные в индекс. Сначала добавьте их в индекс или спрячьте — git не продолжит перебазирование с неиндексированными изменениями.", "{0} hidden · drag header edges to resize": "{0} скрыто · перетащите края заголовка для изменения размера", + "{0} hidden — panel too narrow": "{0} скрыто — панель слишком узкая", "{0} in Theirs": "{0} в «Их»", "{0} in Yours": "{0} в «Ваши»", "{0} in the Result, marked so you can check {1}.": "{0} в Результате, отмечены, чтобы вы могли проверить {1}.", diff --git a/apps/merge-studio/l10n/bundle.l10n.tr.json b/apps/merge-studio/l10n/bundle.l10n.tr.json index 07f0ceaa..d763c682 100644 --- a/apps/merge-studio/l10n/bundle.l10n.tr.json +++ b/apps/merge-studio/l10n/bundle.l10n.tr.json @@ -1508,6 +1508,7 @@ "no commits yet": "henüz işleme yok", "no email recorded": "e-posta kaydedilmemiş", "no one": "hiç kimse", + "no room": "yer yok", "not a pull request number: {0}": "bir çekme isteği numarası değil: {0}", "not a worktree": "bir çalışma alanı değil", "not pushed": "gönderilmedi", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0}'da #{2} çekme isteğinde olmayan {1} var — burada yapılmış veya ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0}'da hazırlanmamış değişiklikler var. Önce hazırlayın veya zulalayın — git hazırlanmamış değişikliklerle bir yeniden temellendirmeyi sürdürmez.", "{0} hidden · drag header edges to resize": "{0} gizli · boyutlandırmak için başlık kenarlarını sürükleyin", + "{0} hidden — panel too narrow": "{0} gizli — panel çok dar", "{0} in Theirs": "Onlarınki'nde {0}", "{0} in Yours": "Sizinki'nde {0}", "{0} in the Result, marked so you can check {1}.": "Sonuç'ta {0}, kontrol edebilmeniz için {1} işaretli.", diff --git a/apps/merge-studio/l10n/bundle.l10n.zh-cn.json b/apps/merge-studio/l10n/bundle.l10n.zh-cn.json index c6389da6..35919d68 100644 --- a/apps/merge-studio/l10n/bundle.l10n.zh-cn.json +++ b/apps/merge-studio/l10n/bundle.l10n.zh-cn.json @@ -1508,6 +1508,7 @@ "no commits yet": "尚无提交", "no email recorded": "未记录邮箱", "no one": "无人", + "no room": "空间不足", "not a pull request number: {0}": "不是拉取请求编号:{0}", "not a worktree": "不是工作树", "not pushed": "未推送", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} 有 {1},而拉取请求 #{2} 没有 — 在此处创建的,或来自之前 ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} 有未暂存的更改。请先暂存或贮藏它们 — git 不会带着未暂存的更改继续变基。", "{0} hidden · drag header edges to resize": "已隐藏 {0} · 拖动表头边缘可调整大小", + "{0} hidden — panel too narrow": "已隐藏 {0} — 面板太窄", "{0} in Theirs": "{0} 在“他们的”中", "{0} in Yours": "{0} 在“你的”中", "{0} in the Result, marked so you can check {1}.": "{0} 在结果中,已标记,便于你检查 {1}。", diff --git a/apps/merge-studio/l10n/bundle.l10n.zh-tw.json b/apps/merge-studio/l10n/bundle.l10n.zh-tw.json index 7ffd4bfc..7629518d 100644 --- a/apps/merge-studio/l10n/bundle.l10n.zh-tw.json +++ b/apps/merge-studio/l10n/bundle.l10n.zh-tw.json @@ -1508,6 +1508,7 @@ "no commits yet": "尚無提交", "no email recorded": "未記錄郵箱", "no one": "無人", + "no room": "空間不足", "not a pull request number: {0}": "不是拉取請求編號:{0}", "not a worktree": "不是工作樹", "not pushed": "未推送", @@ -1703,6 +1704,7 @@ "{0} has {1} that pull request #{2} doesn't — made here, or from before ": "{0} 有 {1},而拉取請求 #{2} 沒有 — 在此處建立的,或來自之前 ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} 有未暫存的更改。請先暫存或儲藏它們 — git 不會帶著未暫存的更改繼續變基。", "{0} hidden · drag header edges to resize": "已隱藏 {0} · 拖動表頭邊緣可調整大小", + "{0} hidden — panel too narrow": "已隱藏 {0} — 面板太窄", "{0} in Theirs": "{0} 在“他們的”中", "{0} in Yours": "{0} 在“你的”中", "{0} in the Result, marked so you can check {1}.": "{0} 在結果中,已標記,便於你檢查 {1}。", diff --git a/l10n/cs.json b/l10n/cs.json index ce229e18..d54dfaf0 100644 --- a/l10n/cs.json +++ b/l10n/cs.json @@ -5268,6 +5268,7 @@ "no model set": "žádný model nastaven", "no one": "nikdo", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "žádný vzdálený repozitář tohoto repozitáře ({0}) není adresa GitHub, GitLab nebo Bitbucket.", + "no room": "není místo", "no sha": "žádné sha", "not a pull request number: {0}": "nejedná se o číslo pull requestu: {0}", "not a worktree": "není pracovní strom", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} má {1}, které {2} nemá, a {3} má {4}, které {5} nemá — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} mají změny, které nejsou připravené. Nejdřív je připravte nebo stashněte — git nebude pokračovat v rebase s nepřipravenými změnami.", "{0} hidden · drag header edges to resize": "{0} skryto · velikost změníte tažením okrajů záhlaví", + "{0} hidden — panel too narrow": "{0} skryto — panel je příliš úzký", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} narazilo na konflikty. Vyřešte je, pak pokračujte nebo to zrušte.", "{0} in Theirs": "{0} v Jejich", "{0} in Yours": "{0} ve Vašem", diff --git a/l10n/de.json b/l10n/de.json index 4d3dc64d..6b074cd2 100644 --- a/l10n/de.json +++ b/l10n/de.json @@ -5268,6 +5268,7 @@ "no model set": "kein Modell festgelegt", "no one": "niemand", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "kein Remote dieses Repositorys ({0}) ist eine GitHub-, GitLab- oder Bitbucket-Adresse.", + "no room": "kein Platz", "no sha": "kein SHA", "not a pull request number: {0}": "keine Pull-Request-Nummer: {0}", "not a worktree": "kein Worktree", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} hat {1}, was {2} nicht hat, und {3} hat {4}, was {5} nicht hat — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} haben nicht bereitgestellte Änderungen. Zuerst bereitstellen oder stashen — Git setzt einen Rebase nicht mit nicht bereitgestellten Änderungen fort.", "{0} hidden · drag header edges to resize": "{0} ausgeblendet · Kopfzeilenränder ziehen, um die Größe anzupassen", + "{0} hidden — panel too narrow": "{0} ausgeblendet — Bereich zu schmal", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} ist auf Konflikte gestoßen. Lösen, dann fortsetzen oder abbrechen.", "{0} in Theirs": "{0} in deren Version", "{0} in Yours": "{0} in Ihrer Version", diff --git a/l10n/es.json b/l10n/es.json index 88e2c6bd..dbb6a710 100644 --- a/l10n/es.json +++ b/l10n/es.json @@ -5268,6 +5268,7 @@ "no model set": "sin modelo establecido", "no one": "nadie", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "ningún remoto de este repositorio ({0}) es una dirección de GitHub, GitLab o Bitbucket.", + "no room": "sin espacio", "no sha": "sin sha", "not a pull request number: {0}": "no es un número de pull request: {0}", "not a worktree": "no es un worktree", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} tiene {1} que {2} no tiene, y {3} tiene {4} que {5} no tiene — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} tienen cambios que no están preparados. Prepáralos o guárdalos en el stash primero — git no continuará un rebase con cambios sin preparar.", "{0} hidden · drag header edges to resize": "{0} oculto · arrastra los bordes del encabezado para cambiar el tamaño", + "{0} hidden — panel too narrow": "{0} oculto — panel demasiado estrecho", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} tuvo conflictos. Resuélvelos, y luego continúa o aborta.", "{0} in Theirs": "{0} en Suyos", "{0} in Yours": "{0} en Tuyos", diff --git a/l10n/fr.json b/l10n/fr.json index 3b8d7d5c..b17da7a2 100644 --- a/l10n/fr.json +++ b/l10n/fr.json @@ -5268,6 +5268,7 @@ "no model set": "aucun modèle défini", "no one": "personne", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "aucun dépôt distant de ce dépôt ({0}) n'est une adresse GitHub, GitLab ou Bitbucket.", + "no room": "pas de place", "no sha": "pas de sha", "not a pull request number: {0}": "pas un numéro de pull request : {0}", "not a worktree": "pas une arborescence de travail", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} a {1} que {2} n'a pas, et {3} a {4} que {5} n'a pas — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} ont des modifications non indexées. Indexez-les ou remisez-les d'abord — git ne continuera pas un rebase avec des modifications non indexées.", "{0} hidden · drag header edges to resize": "{0} masqué(e)s · faites glisser les bords de l'en-tête pour redimensionner", + "{0} hidden — panel too narrow": "{0} masqué(e)s — panneau trop étroit", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} a rencontré des conflits. Résolvez-les, puis continuez ou abandonnez.", "{0} in Theirs": "{0} dans la leur", "{0} in Yours": "{0} dans la vôtre", diff --git a/l10n/it.json b/l10n/it.json index 3e9941f8..650da755 100644 --- a/l10n/it.json +++ b/l10n/it.json @@ -5268,6 +5268,7 @@ "no model set": "nessun modello impostato", "no one": "nessuno", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "nessun remoto di questo repository ({0}) è un indirizzo GitHub, GitLab o Bitbucket.", + "no room": "spazio insufficiente", "no sha": "nessun sha", "not a pull request number: {0}": "non è un numero di pull request: {0}", "not a worktree": "non è un worktree", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} ha {1} che {2} non ha, e {3} ha {4} che {5} non ha — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} hanno modifiche non in stage. Mettile prima in stage o in stash — git non continuerà un rebase con modifiche non in stage.", "{0} hidden · drag header edges to resize": "{0} nascosti · trascina i bordi dell'intestazione per ridimensionare", + "{0} hidden — panel too narrow": "{0} nascosti — pannello troppo stretto", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} ha incontrato conflitti. Risolvili, poi continua o interrompi.", "{0} in Theirs": "{0} in Loro", "{0} in Yours": "{0} in Tuo", diff --git a/l10n/ja.json b/l10n/ja.json index 4b94fa0e..fb8cc27c 100644 --- a/l10n/ja.json +++ b/l10n/ja.json @@ -5268,6 +5268,7 @@ "no model set": "モデル未設定", "no one": "だれもいません", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "このリポジトリ ({0}) のリモートに、GitHub、GitLab、Bitbucketのアドレスはありません。", + "no room": "スペース不足", "no sha": "SHA なし", "not a pull request number: {0}": "プルリクエスト番号ではありません: {0}", "not a worktree": "ワークツリーではありません", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} には {2} にはない {1} があり、{3} には {5} にはない {4} があります —", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} にはステージされていない変更があります。先にステージまたはスタッシュしてください — gitは未ステージの変更があるとリベースを続行できません。", "{0} hidden · drag header edges to resize": "{0} 個を非表示 · ヘッダーの端をドラッグしてサイズ変更", + "{0} hidden — panel too narrow": "{0} を非表示 — パネルが狭すぎます", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} でコンフリクトが発生しました。解決してから続行するか、中止してください。", "{0} in Theirs": "相手の {0}", "{0} in Yours": "自分の {0}", diff --git a/l10n/ko.json b/l10n/ko.json index 2425bd4e..3770dd1f 100644 --- a/l10n/ko.json +++ b/l10n/ko.json @@ -5268,6 +5268,7 @@ "no model set": "설정된 모델 없음", "no one": "없음", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "이 리포지토리의 원격({0}) 중 GitHub, GitLab 또는 Bitbucket 주소인 것이 없습니다.", + "no room": "공간 부족", "no sha": "SHA 없음", "not a pull request number: {0}": "풀 리퀘스트 번호가 아님: {0}", "not a worktree": "작업 폴더가 아님", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0}에는 {2}에 없는 {1}이 있고, {3}에는 {5}에 없는 {4}이 있습니다 — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0}에 스테이징되지 않은 변경 내용이 있습니다. 먼저 스테이지에 추가하거나 스태시하세요 — git은 스테이징되지 않은 변경 내용이 있으면 리베이스를 계속하지 않습니다.", "{0} hidden · drag header edges to resize": "{0} 숨겨짐 · 헤더 경계를 드래그하여 크기 조절", + "{0} hidden — panel too narrow": "{0} 숨겨짐 — 패널이 너무 좁음", "{0} hit conflicts. Resolve them, then continue or abort.": "{0}에서 충돌이 발생했습니다. 해결 후 계속하거나 중단하세요.", "{0} in Theirs": "상대 변경 내용의 {0}", "{0} in Yours": "내 변경 내용의 {0}", diff --git a/l10n/pl.json b/l10n/pl.json index 82b740ca..bf9066fa 100644 --- a/l10n/pl.json +++ b/l10n/pl.json @@ -5268,6 +5268,7 @@ "no model set": "brak ustawionego modelu", "no one": "nikt", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "żadne zdalne repozytorium tego repozytorium ({0}) nie jest adresem GitHub, GitLab ani Bitbucket.", + "no room": "brak miejsca", "no sha": "brak sha", "not a pull request number: {0}": "nie jest numerem pull requesta: {0}", "not a worktree": "to nie worktree", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} ma {1}, których {2} nie ma, a {3} ma {4}, których {5} nie ma — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} mają zmiany, które nie są przygotowane. Najpierw je przygotuj albo zapisz w schowku — git nie kontynuuje rebase z nieprzygotowanymi zmianami.", "{0} hidden · drag header edges to resize": "{0} ukryte · przeciągnij krawędzie nagłówka, aby zmienić rozmiar", + "{0} hidden — panel too narrow": "{0} ukryte — panel jest za wąski", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} natrafiło na konflikty. Rozwiąż je, a potem kontynuuj albo przerwij.", "{0} in Theirs": "{0} w Ich", "{0} in Yours": "{0} w Twoich", diff --git a/l10n/pt-br.json b/l10n/pt-br.json index f8fc6f89..5e92e9be 100644 --- a/l10n/pt-br.json +++ b/l10n/pt-br.json @@ -5268,6 +5268,7 @@ "no model set": "nenhum modelo definido", "no one": "ninguém", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "nenhum remoto deste repositório ({0}) é um endereço do GitHub, GitLab ou Bitbucket.", + "no room": "sem espaço", "no sha": "nenhum sha", "not a pull request number: {0}": "não é um número de pull request: {0}", "not a worktree": "não é um worktree", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} tem {1} que {2} não tem, e {3} tem {4} que {5} não tem — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} têm alterações que não estão em stage. Coloque-as em stage ou guarde-as no stash primeiro — o git não continua um rebase com alterações fora do stage.", "{0} hidden · drag header edges to resize": "{0} ocultos · arraste as bordas do cabeçalho para redimensionar", + "{0} hidden — panel too narrow": "{0} ocultos — painel estreito demais", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} encontrou conflitos. Resolva-os, depois continue ou aborte.", "{0} in Theirs": "{0} em Deles", "{0} in Yours": "{0} em Seu", diff --git a/l10n/ru.json b/l10n/ru.json index 556dffdc..0a5f6206 100644 --- a/l10n/ru.json +++ b/l10n/ru.json @@ -5268,6 +5268,7 @@ "no model set": "модель не задана", "no one": "никто", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "ни один удалённый репозиторий этого репозитория ({0}) не является адресом GitHub, GitLab или Bitbucket.", + "no room": "нет места", "no sha": "нет sha", "not a pull request number: {0}": "не номер pull request: {0}", "not a worktree": "не рабочий каталог", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "В {0} есть {1}, которых нет в {2}, а в {3} есть {4}, которых нет в {5} — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "В {0} есть изменения, не добавленные в индекс. Сначала добавьте их в индекс или спрячьте — git не продолжит перебазирование с неиндексированными изменениями.", "{0} hidden · drag header edges to resize": "{0} скрыто · перетащите края заголовка для изменения размера", + "{0} hidden — panel too narrow": "{0} скрыто — панель слишком узкая", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} привело к конфликтам. Разрешите их, затем продолжите или прервите.", "{0} in Theirs": "{0} в «Их»", "{0} in Yours": "{0} в «Ваши»", diff --git a/l10n/tr.json b/l10n/tr.json index f5a1b3a8..518429eb 100644 --- a/l10n/tr.json +++ b/l10n/tr.json @@ -5268,6 +5268,7 @@ "no model set": "model ayarlanmadı", "no one": "hiç kimse", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "bu deponun hiçbir uzak konumu ({0}) bir GitHub, GitLab veya Bitbucket adresi değil.", + "no room": "yer yok", "no sha": "sha yok", "not a pull request number: {0}": "bir çekme isteği numarası değil: {0}", "not a worktree": "bir çalışma alanı değil", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0}'da {2}'de olmayan {1} var ve {3}'de {5}'de olmayan {4} var — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0}'da hazırlanmamış değişiklikler var. Önce hazırlayın veya zulalayın — git hazırlanmamış değişikliklerle bir yeniden temellendirmeyi sürdürmez.", "{0} hidden · drag header edges to resize": "{0} gizli · boyutlandırmak için başlık kenarlarını sürükleyin", + "{0} hidden — panel too narrow": "{0} gizli — panel çok dar", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} çakışmalara çarptı. Çözün, sonra sürdürün veya iptal edin.", "{0} in Theirs": "Onlarınki'nde {0}", "{0} in Yours": "Sizinki'nde {0}", diff --git a/l10n/zh-cn.json b/l10n/zh-cn.json index f439357d..eab95f38 100644 --- a/l10n/zh-cn.json +++ b/l10n/zh-cn.json @@ -5268,6 +5268,7 @@ "no model set": "未设置模型", "no one": "无人", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "此仓库的所有远程仓库({0})都不是 GitHub、GitLab 或 Bitbucket 地址。", + "no room": "空间不足", "no sha": "无 SHA", "not a pull request number: {0}": "不是拉取请求编号:{0}", "not a worktree": "不是工作树", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} 有 {1} 是 {2} 没有的,而 {3} 有 {4} 是 {5} 没有的 — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} 有未暂存的更改。请先暂存或贮藏它们 — git 不会带着未暂存的更改继续变基。", "{0} hidden · drag header edges to resize": "已隐藏 {0} · 拖动表头边缘可调整大小", + "{0} hidden — panel too narrow": "已隐藏 {0} — 面板太窄", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} 遇到冲突。请解决它们,然后继续或中止。", "{0} in Theirs": "{0} 在“他们的”中", "{0} in Yours": "{0} 在“你的”中", diff --git a/l10n/zh-tw.json b/l10n/zh-tw.json index cfd36aed..b7b27067 100644 --- a/l10n/zh-tw.json +++ b/l10n/zh-tw.json @@ -5268,6 +5268,7 @@ "no model set": "未設定模型", "no one": "無人", "no remote of this repository ({0}) is a GitHub, GitLab or Bitbucket address.": "此儲存庫的所有遠端儲存庫({0})都不是 GitHub、GitLab 或 Bitbucket 地址。", + "no room": "空間不足", "no sha": "無 SHA", "not a pull request number: {0}": "不是拉取請求編號:{0}", "not a worktree": "不是工作樹", @@ -5734,6 +5735,7 @@ "{0} has {1} that {2} doesn't, and {3} has {4} that {5} doesn't — ": "{0} 有 {1} 是 {2} 沒有的,而 {3} 有 {4} 是 {5} 沒有的 — ", "{0} have changes that aren't staged. Stage or stash them first — git won't continue a rebase with unstaged changes.": "{0} 有未暫存的更改。請先暫存或儲藏它們 — git 不會帶著未暫存的更改繼續變基。", "{0} hidden · drag header edges to resize": "已隱藏 {0} · 拖動表頭邊緣可調整大小", + "{0} hidden — panel too narrow": "已隱藏 {0} — 面板太窄", "{0} hit conflicts. Resolve them, then continue or abort.": "{0} 遇到衝突。請解決它們,然後繼續或中止。", "{0} in Theirs": "{0} 在“他們的”中", "{0} in Yours": "{0} 在“你的”中", diff --git a/packages/webview-ui/src/graph/commit-graph.ts b/packages/webview-ui/src/graph/commit-graph.ts index 96aa991f..3bbb8cf6 100644 --- a/packages/webview-ui/src/graph/commit-graph.ts +++ b/packages/webview-ui/src/graph/commit-graph.ts @@ -103,6 +103,12 @@ const SUBJECT_MIN_WIDTH = 220; * fixed width: the user's own dragged width still wins above it. */ const REFS_MIN_READABLE = 150; +/** The Branch/Tag track's cap at and below COLUMN_DROP_TAIL_AT (the CSS tier). */ +const REFS_CAP_NARROW = 300; +/** …and in the narrow table tier, at and below COLUMN_DROP_TAIL_AT - 200. */ +const REFS_CAP_TIGHT = 240; +/** The message's floor in that narrow table tier. */ +const SUBJECT_MIN_TIGHT = Math.round(SUBJECT_MIN_WIDTH * 0.5); /** * The width at which a commit message stops feeling cramped. Above the hard * SUBJECT_MIN_WIDTH floor: the Branch/Tag track auto-fits only with whatever is @@ -121,21 +127,39 @@ const COMPACT_DROP_DATE_AT = 580; const COMPACT_DROP_AUTHOR_AT = 430; const SUBJECT_MIN_COMPACT_MID = 150; const SUBJECT_MIN_COMPACT_TIGHT = 120; +/** Compact's own floor: below this it is a one-line list with no header. */ +const COMPACT_LIST_AT = 330; +/** Compact's default track widths — narrower than the editor tab's (`def`). */ +const COMPACT_DEF = { changes: 84, author: 112, date: 64, sha: 66 } as const; /** - * Below this host width, column mode drops its Date and SHA tracks. + * Date and SHA stay on screen for as long as they FIT (issue #124). * - * The threshold is set by what the REFS column needs when the tail comes back, - * not by when the tail itself starts to feel tight. At 760 the tail returned - * ~36px too early: crossing it (a 1296px window) collapsed the branch/tag track - * from 168px to 87px and rendered zero readable characters in it, so WIDENING - * the window made a column narrower and emptied it. That put the dead band over - * exactly the maximised-laptop widths, and nothing on screen said the column had - * been starved — it just looked empty. + * They used to go at a fixed breakpoint — below an 860px host in the editor + * tab, and always in the bottom panel, which had no SHA track at all — whether + * or not there was room, while the Columns menu went on showing them ticked. + * "The SHA column is enabled and not shown" is what a person sees then, and + * nothing on screen says why. * - * Date and SHA are the right things to give up for it: both are still on the - * row's hover tooltip and in the details dock, and both can be turned back on - * from the Columns menu. A branch name has nowhere else to be. + * Now the message gives way first, down to its floor, and the Branch/Tag + * track keeps the width at which a ref name is still readable — the reason the + * breakpoint sat as high as it did: at 760 the tail came back ~36px too early, + * collapsed the branch/tag track from 168px to 87px and rendered zero readable + * characters in it. Only what is left over is offered to the tail, SHA first: + * it is the narrowest column and the one that names the commit. Date goes + * first; both are still on the row's tooltip and in the details pane, and a + * column that has no room says so in the Columns menu. See fitTail. */ +const TAIL_FIT_ORDER: readonly ColumnSpec["id"][] = ["sha", "date"]; +/** + * Compact fits Author too, between the two. Its ladder drops Author at 430px + * anyway; without this, the band just above that had no room for SHA and hid + * it, and narrowing the panel by ten more pixels brought it BACK — a column + * that blinks out and in as you drag. Taking Author first keeps it one way. + */ +const TAIL_FIT_ORDER_COMPACT: readonly ColumnSpec["id"][] = ["sha", "author", "date"]; +/** The row's own horizontal chrome: the 2px spacer border + padding-right. */ +const ROW_CHROME = 2 + 12; +const ROW_CHROME_COMPACT = 2 + 10; /** `:host([compact]) .content .refs { max-width }` — a share of the MESSAGE track. */ const COMPACT_REFS_SHARE = 0.44; @@ -590,6 +614,15 @@ export class CommitGraph extends LitElement { } .gh-menuitem[aria-checked="true"] .codicon-check { opacity: 1; } .gh-menuitem .lbl { flex: 1 1 auto; } + /* "no room": a ticked column this width cannot hold (issue #124). Muted, + like the footer that says the same at more length. */ + .gh-menu-note { + flex: 0 0 auto; + font-size: 10.5px; + color: var(--gs-menu-muted); + } + .gh-menuitem:hover .gh-menu-note, + .gh-menuitem:focus-visible .gh-menu-note { color: inherit; opacity: 0.8; } .gh-menuitem[disabled] { opacity: 0.5; cursor: default; @@ -822,29 +855,31 @@ export class CommitGraph extends LitElement { A short, wide surface. Two things wasted space here: a fixed Branch/Tag track that sat empty on most rows, and a wide gap between the message and the trailing metadata. So in compact the refs flow INLINE just before the - message (a ref-less commit uses the full width), the SHA track goes away - (it is right there in the details pane), and what is left — changes / - author / date — forms one quiet cluster on the right. The message leads; - everything else recedes. */ + message (a ref-less commit uses the full width), and what is left — + changes / author / date / sha — forms one quiet cluster on the right. + The message leads; everything else recedes. + The SHA track is a real one. It used to be left out here ("it is right + there in the details pane") while the Columns menu went on offering SHA, + ticked, with nothing behind it (issue #124). It is on when the user has + it on and there is room — see fitTail. */ :host([compact]) { --gs-grid: var(--gs-gutter-w, ${MIN_GUTTER_WIDTH}px) minmax(${SUBJECT_MIN_WIDTH}px, 1fr) - minmax(0, var(--col-changes-w, 84px)) - minmax(0, var(--col-author-w, 112px)) - minmax(0, var(--col-date-w, 64px)); + minmax(0, var(--col-changes-w, ${COMPACT_DEF.changes}px)) + minmax(0, var(--col-author-w, ${COMPACT_DEF.author}px)) + minmax(0, var(--col-date-w, ${COMPACT_DEF.date}px)) + minmax(0, var(--col-sha-w, ${COMPACT_DEF.sha}px)); } - :host([compact]) .colhead .ch-refs, - :host([compact]) .colhead .ch-sha, - :host([compact]) .row .sha { display: none; } + :host([compact]) .colhead .ch-refs { display: none; } /* Compact's tracks are graph | message | changes | author | date, so four of the six grips land on a real boundary and stay draggable. (The claim they "would sit on the wrong boundaries" only held for the refs grip, whose cell is hidden here anyway — and a short panel is precisely where width is scarce and re-balancing matters most.) */ :host([compact]) .col-resize[data-col="refs"] { display: none; } - /* Date is compact's last track: its right-edge grip divides nothing. */ - :host([compact]) .col-resize[data-col="date"] { display: none; } + /* Date's grip divides Date | SHA; with SHA off it divides nothing, and the + shared :host(.hide-sha) rule below takes it away. */ :host([compact]) .content { display: flex; align-items: center; gap: 7px; min-width: 0; } @@ -907,21 +942,16 @@ export class CommitGraph extends LitElement { :host(:not([compact])) .row { --gs-grid: var(--gs-gutter-w, ${MIN_GUTTER_WIDTH}px) - minmax(0, clamp(0px, var(--col-refs-w, ${col("refs")}px), 300px)) + minmax(0, clamp(0px, var(--col-refs-w, ${col("refs")}px), ${REFS_CAP_NARROW}px)) minmax(${SUBJECT_MIN_WIDTH}px, 1fr) minmax(0, var(--col-changes-w, ${col("changes")}px)) - minmax(0, var(--col-author-w, ${col("author")}px)); + minmax(0, var(--col-author-w, ${col("author")}px)) + minmax(0, var(--col-date-w, ${col("date")}px)) + minmax(0, var(--col-sha-w, ${col("sha")}px)); } - :host(:not([compact])) .colhead .ch-date, - :host(:not([compact])) .colhead .ch-sha, - :host(:not([compact])) .row .date, - :host(:not([compact])) .row .sha { display: none; } - /* The cells are gone, but their grips are absolutely positioned inside - them and survived as 0x0 hit targets — a handle you can see the cursor - change on but can never drag. Author becomes the last visible column - here, so it must not keep a trailing grip either. */ - :host(:not([compact])) .colhead .col-resize[data-col="date"], - :host(:not([compact])) .colhead .col-resize[data-col="author"] { display: none; } + /* Date and SHA no longer go here by breakpoint: they stay while they fit + and fitTail hides them (the .hide-* classes, with their grips) when + they do not — issue #124. */ } /* ── Still a table, just a narrower one ───────────────────────────────── Between the inline floor and the tail drop, the two things that identify @@ -935,15 +965,24 @@ export class CommitGraph extends LitElement { @container (max-width: ${COLUMN_DROP_TAIL_AT - 200}px) { :host(:not([compact])) .colhead, :host(:not([compact])) .row { + /* SHA stays (issue #124): ~66px that names the commit, where a + desktop window with the details pane open usually lands. Seven + tracks, the dropped ones at 0, because every cell is pinned. */ --gs-grid: var(--gs-gutter-w, ${MIN_GUTTER_WIDTH}px) - minmax(0, clamp(${REFS_MIN_READABLE}px, var(--col-refs-w, ${col("refs")}px), 240px)) - minmax(${Math.round(SUBJECT_MIN_WIDTH * 0.5)}px, 1fr); + minmax(0, clamp(${REFS_MIN_READABLE}px, var(--col-refs-w, ${col("refs")}px), ${REFS_CAP_TIGHT}px)) + minmax(${SUBJECT_MIN_TIGHT}px, 1fr) + 0px + 0px + 0px + minmax(0, var(--col-sha-w, ${col("sha")}px)); } :host(:not([compact])) .colhead .ch-changes, :host(:not([compact])) .colhead .ch-author, + :host(:not([compact])) .colhead .ch-date, :host(:not([compact])) .row .changes, - :host(:not([compact])) .row .author { display: none; } + :host(:not([compact])) .row .author, + :host(:not([compact])) .row .date { display: none; } /* Their grips would survive as 0x0 hit targets otherwise. */ :host(:not([compact])) .colhead .col-resize[data-col="changes"], :host(:not([compact])) .colhead .col-resize[data-col="refs"][data-invert="0"] { display: none; } @@ -953,18 +992,23 @@ export class CommitGraph extends LitElement { so the message keeps the width. Mirrors the column-mode ladder above without ever reintroducing a Branch/Tag track (refs flow inline here). */ @container (max-width: ${COMPACT_DROP_DATE_AT}px) { + /* Six tracks still, the dropped one at 0: every cell is pinned to its + track (see "Every cell is PINNED"), so removing a track would move + the ones after it. */ :host([compact]) .colhead, :host([compact]) .row { --gs-grid: var(--gs-gutter-w, ${MIN_GUTTER_WIDTH}px) minmax(${SUBJECT_MIN_COMPACT_MID}px, 1fr) - minmax(0, var(--col-changes-w, 84px)) - minmax(0, var(--col-author-w, 112px)); + minmax(0, var(--col-changes-w, ${COMPACT_DEF.changes}px)) + minmax(0, var(--col-author-w, ${COMPACT_DEF.author}px)) + 0px + minmax(0, var(--col-sha-w, ${COMPACT_DEF.sha}px)); } :host([compact]) .colhead .ch-date, :host([compact]) .row .date { display: none; } - /* Author is last now, so its grip divides nothing. */ - :host([compact]) .col-resize[data-col="author"] { display: none; } + /* Without SHA, Author is last, so its grip divides nothing. */ + :host([compact].hide-sha) .col-resize[data-col="author"] { display: none; } } @container (max-width: ${COMPACT_DROP_AUTHOR_AT}px) { :host([compact]) .colhead, @@ -972,11 +1016,16 @@ export class CommitGraph extends LitElement { --gs-grid: var(--gs-gutter-w, ${MIN_GUTTER_WIDTH}px) minmax(${SUBJECT_MIN_COMPACT_TIGHT}px, 1fr) - minmax(0, var(--col-changes-w, 84px)); + minmax(0, var(--col-changes-w, ${COMPACT_DEF.changes}px)) + 0px + 0px + minmax(0, var(--col-sha-w, ${COMPACT_DEF.sha}px)); } :host([compact]) .colhead .ch-author, :host([compact]) .row .author { display: none; } - :host([compact]) .col-resize[data-col="changes"][data-invert="0"] { display: none; } + :host([compact].hide-sha) .col-resize[data-col="changes"][data-invert="0"] { display: none; } + /* Author's grip went with its cell; with SHA on, the Changes | SHA + boundary keeps Changes' own. */ } /* ── Sidebar (inline) mode ────────────────────────────────────────────── @@ -1006,7 +1055,8 @@ export class CommitGraph extends LitElement { the two tracks that still exist and says what they are. */ :host(:not([compact])) .colhead .ch-refs, :host(:not([compact])) .colhead .ch-changes, - :host(:not([compact])) .colhead .ch-author { display: none; } + :host(:not([compact])) .colhead .ch-author, + :host(:not([compact])) .colhead .ch-sha { display: none; } :host(:not([compact])) .col-resize[data-col="refs"], :host(:not([compact])) .col-resize[data-col="changes"], :host(:not([compact])) .col-resize[data-col="author"] { display: none; } @@ -1027,13 +1077,14 @@ export class CommitGraph extends LitElement { } /* Compact's own floor: below this even three columns are too many, so it becomes the same clean one-line list the sidebar uses. */ - @container (max-width: 330px) { + @container (max-width: ${COMPACT_LIST_AT}px) { :host([compact]) .colhead { display: none; } :host([compact]) .col-resize { display: none; } :host([compact]) .colhead, :host([compact]) .row { --gs-grid: var(--gs-gutter-w, ${MIN_GUTTER_WIDTH}px) minmax(0, 1fr); } - :host([compact]) .row .changes { display: none; } + :host([compact]) .row .changes, + :host([compact]) .row .sha { display: none; } } /* ── Column header row (aligned to the row grid) ──────────────────── */ @@ -1151,7 +1202,7 @@ export class CommitGraph extends LitElement { Columns menu still showed SHA as checked, which is a menu lying about what is on screen. With an explicit grid-column, removing a cell moves nothing. Compact - mode lays .content out as flex and is unaffected. */ + lays .content out as flex, but its tracks are pinned too (below). */ :host(:not([compact])) .row > .gutter, :host(:not([compact])) .colhead .ch-graph { grid-column: 1; } :host(:not([compact])) .row .refs, @@ -1166,6 +1217,21 @@ export class CommitGraph extends LitElement { :host(:not([compact])) .colhead .ch-date { grid-column: 6; } :host(:not([compact])) .row .meta.sha, :host(:not([compact])) .colhead .ch-sha { grid-column: 7; } + /* Compact pins its own six tracks the same way. It did not need to while + SHA had no track there; now a user who turns Date off (issue #124's + reporter had) would see SHA slide into Date's 0px track and vanish. */ + :host([compact]) .row > .gutter, + :host([compact]) .colhead .ch-graph { grid-column: 1; } + :host([compact]) .row > .content, + :host([compact]) .colhead .ch-subject { grid-column: 2; } + :host([compact]) .row .changes, + :host([compact]) .colhead .ch-changes { grid-column: 3; } + :host([compact]) .row .meta.author, + :host([compact]) .colhead .ch-author { grid-column: 4; } + :host([compact]) .row .meta.date, + :host([compact]) .colhead .ch-date { grid-column: 5; } + :host([compact]) .row .meta.sha, + :host([compact]) .colhead .ch-sha { grid-column: 6; } /* ── Hidden columns: hide the cells/header (the track is collapsed to 0 on the inline :host style by applyColumnStyles, which outranks any saved @@ -1937,11 +2003,19 @@ export class CommitGraph extends LitElement { } | undefined; - /** Memoised auto-fit for the refs track, keyed on row count + host width. */ - private autoRefs = { n: -1, host: -1, w: 0 }; + /** Memoised auto-fit for the refs track, keyed on row count + host width + + * what the other tracks take (a column turned on or off moves the budget). */ + private autoRefs = { n: -1, host: -1, non: -1, w: 0 }; private resizeObs: ResizeObserver | undefined; /** Hidden column ids; persisted to localStorage. */ private hiddenCols = new Set(); + /** + * Columns the user has ON that this width has no room for (issue #124) — + * never persisted, recomputed on every update and resize. See fitTail. + */ + private fitHidden = new Set(); + /** Memo for fitTail: its inputs, joined, and the answer they gave. */ + private fitMemo = { key: "", out: new Set() }; /** Live column-drag bookkeeping (null when not dragging). */ private drag: { id: ColumnSpec["id"]; @@ -2059,11 +2133,15 @@ export class CommitGraph extends LitElement { // responsive behaviour never call back into JS. Without this the track // keeps whatever width the last Lit update computed, so a plain window // resize leaves it stale until something else happens to re-render. + // + // Date and SHA are fitted to the width as well (fitTail), so this runs for + // a user-set refs width too. And the Columns menu says which ticked + // columns have no room, which a resize changes while it is open. this.resizeObs = new ResizeObserver(() => { - if (this.colWidths.refs !== undefined) return; // user-set: nothing to fit - const before = this.autoRefs.w; + const before = `${this.autoRefs.w}|${[...this.fitHidden].join()}`; this.applyColumnStyles(); - if (this.autoRefs.w !== before) this.renderRows(); // re-fold the chips + if (`${this.autoRefs.w}|${[...this.fitHidden].join()}` !== before) this.renderRows(); // re-fold the chips + if (this.columnsOpen) this.requestUpdate(); }); this.resizeObs.observe(this); // A click in another editor, the Explorer or the terminal never reaches @@ -2423,26 +2501,27 @@ export class CommitGraph extends LitElement { } /** - * Which column tracks are actually on screen — the user's hidden set AND the + * Which column tracks are actually on screen — the user's hidden set, the * responsive ladder, which drops trailing columns via container queries that - * never call back into JS. + * never call back into JS, and (unless `fitted` is false) the columns + * fitTail found no room for. */ - private visibleTrackIds(): ColumnSpec["id"][] { + private visibleTrackIds(fitted = true): ColumnSpec["id"][] { const host = this.clientWidth; const compact = this.hasAttribute("compact"); const out: ColumnSpec["id"][] = []; for (const spec of COLUMN_SPECS) { if (this.hiddenCols.has(spec.id)) continue; + if (fitted && this.fitHidden.has(spec.id)) continue; if (compact) { - // Compact has no Branch/Tag track (chips flow inline) and no SHA track. - if (spec.id === "refs" || spec.id === "sha") continue; + // Compact has no Branch/Tag track: its chips flow inline. + if (spec.id === "refs") continue; if (host > 0 && host <= COMPACT_DROP_DATE_AT && spec.id === "date") continue; if (host > 0 && host <= COMPACT_DROP_AUTHOR_AT && spec.id === "author") continue; - } else if ( - host > 0 && - host <= COLUMN_DROP_TAIL_AT && - (spec.id === "date" || spec.id === "sha") - ) { + if (host > 0 && host <= COMPACT_LIST_AT && spec.id === "sha") continue; + } else if (host > 0 && host <= COLUMN_DROP_TAIL_AT - 200 && spec.id === "date") { + continue; + } else if (host > 0 && host <= INLINE_LIST_BELOW && spec.id === "sha") { continue; } out.push(spec.id); @@ -2450,6 +2529,127 @@ export class CommitGraph extends LitElement { return out; } + /** + * Is a column the user has ON missing from the screen for want of room? + * What the Columns menu says beside it (issue #124), so it mirrors every + * rung of the CSS ladder — including Changes and Author, which the narrow + * table tier and compact's floor drop — and not only the tracks that + * visibleTrackIds budgets for. Branch/Tag never is: where it is not a track + * its chips flow inline before the message. + */ + private noRoomFor(id: ColumnSpec["id"]): boolean { + if (id === "refs" || id === "graph" || this.hiddenCols.has(id)) return false; + return this.fitHidden.has(id) || this.ladderDrops(id); + } + + /** Does the CSS ladder (the container queries) drop this column here? */ + private ladderDrops(id: ColumnSpec["id"]): boolean { + const host = this.clientWidth; + if (host <= 0 || id === "graph" || id === "refs") return false; + if (this.hasAttribute("compact")) { + if (host <= COMPACT_LIST_AT) return true; + if (host <= COMPACT_DROP_AUTHOR_AT) return id === "author" || id === "date"; + if (host <= COMPACT_DROP_DATE_AT) return id === "date"; + return false; + } + if (host <= INLINE_LIST_BELOW) return true; + if (host <= COLUMN_DROP_TAIL_AT - 200) return id !== "sha"; + return false; + } + + /** + * Which of Date and SHA — those the user has on and the ladder still lays + * out — this width has no room for. The rule is in TAIL_FIT_ORDER's comment: + * every other track at its own width, the message at its floor and the + * Branch/Tag track at a readable width come first; SHA, then Date, take + * what is left, and whatever does not fit is hidden and named in the + * Columns menu. + * + * Memoised: it runs on every Lit update, and the refs reserve is O(rows). + */ + private fitTail(): Set { + const host = this.clientWidth; + const compact = this.hasAttribute("compact"); + const tracks = host > 0 ? this.visibleTrackIds(false) : []; + const key = [ + host, + compact ? 1 : 0, + this.rows.length, + tracks.join(), + JSON.stringify(this.colWidths), + this.colWidths.graph ?? this.gutterWidth(), + ].join("|"); + if (key === this.fitMemo.key) return this.fitMemo.out; + + const out = new Set(); + const order = compact ? TAIL_FIT_ORDER_COMPACT : TAIL_FIT_ORDER; + const tail = order.filter((id) => tracks.includes(id)); + if (tail.length > 0) { + const tight = !compact && host <= COLUMN_DROP_TAIL_AT - 200; + let room = + host - (compact ? ROW_CHROME_COMPACT : ROW_CHROME) - (tight ? SUBJECT_MIN_TIGHT : this.subjectFloor()); + for (const id of tracks) { + // visibleTrackIds budgets the refs track and keeps Changes and Author + // in the narrow tier; the CSS has them at 0px there, so they cost + // nothing here. + if (tail.includes(id) || this.ladderDrops(id)) continue; + room -= this.fitNeed(id, compact); + } + for (const id of tail) { + const need = this.fitNeed(id, compact); + if (need <= room) room -= need; + else out.add(id); + } + } + this.fitMemo = { key, out }; + return out; + } + + /** + * The width fitTail charges a track. In compact, Changes and Author may + * narrow to their own minimum to make room: they are minmax(0, …) tracks, + * and the grid takes a deficit from the widest track first, so SHA keeps its + * width and the author's name ellipsizes. Not in the editor tab, where the + * Branch/Tag auto-fit budgets against their FULL widths and would be the + * track starved instead. + */ + private fitNeed(id: ColumnSpec["id"], compact: boolean): number { + const need = this.trackNeed(id); + return compact && (id === "changes" || id === "author") + ? Math.min(need, COLUMN_BY_ID.get(id)!.min) + : need; + } + + /** The width a track takes when it is on screen, for fitTail. */ + private trackNeed(id: ColumnSpec["id"]): number { + if (id === "graph") return this.colWidths.graph ?? this.gutterWidth(); + if (id === "refs") return this.refsReserve(); + const own = this.colWidths[id]; + if (own !== undefined) return own; + const compactDef = (COMPACT_DEF as Partial>)[id]; + return (this.hasAttribute("compact") ? compactDef : undefined) ?? COLUMN_BY_ID.get(id)!.def; + } + + /** + * What the Branch/Tag track must keep before Date and SHA get any room: the + * user's own width, or the auto-fit's floor — the width at which the + * busiest ref name is still readable (fitRefsWidth's `legible`), never more + * than the refs want. Capped as the CSS caps the track. + */ + private refsReserve(): number { + const spec = COLUMN_BY_ID.get("refs")!; + const host = this.clientWidth; + // The narrow table tier clamps the track to [REFS_MIN_READABLE, 240]. + const tight = host <= COLUMN_DROP_TAIL_AT - 200; + const cap = tight ? REFS_CAP_TIGHT : host <= COLUMN_DROP_TAIL_AT ? REFS_CAP_NARROW : spec.max; + const floor = tight ? REFS_MIN_READABLE : 0; + const own = this.colWidths.refs; + if (own !== undefined) return Math.max(floor, Math.min(cap, own)); + const wanted = wantedRefsWidth(this.rows, spec.max, spec.min); + const auto = Math.max(spec.min, Math.min(wanted, legibleRefsWidth(this.rows))); + return Math.max(floor, Math.min(cap, auto)); + } + /** The floor the message track is entitled to at this width — matches the CSS. */ private subjectFloor(): number { const host = this.clientWidth; @@ -2465,10 +2665,14 @@ export class CommitGraph extends LitElement { * outranks the `:host(.hide-*)` stylesheet rule, so we must zero it here or a * previously-resized-then-hidden column would leave a ghost gap. */ private applyColumnStyles(): void { + // First: the refs auto-fit below budgets against the tracks on screen. + this.fitHidden = this.fitTail(); for (const spec of COLUMN_SPECS) { // The graph track is owned by applyGutterWidth (auto-size + override). if (spec.id === "graph") continue; - const hidden = this.hiddenCols.has(spec.id); + // A column with no room collapses exactly as an unticked one does — + // track at 0, cells and grip gone — but stays ticked in the menu. + const hidden = this.hiddenCols.has(spec.id) || this.fitHidden.has(spec.id); // refs falls back to its auto-fit rather than to the CSS literal, so the // track, the chip cap and the fold all read the same number. const w = @@ -2672,14 +2876,19 @@ export class CommitGraph extends LitElement { // (row count, host width): the ref set cannot change without the rows // changing, and the budget cannot change without a resize. const host = this.clientWidth; - if (this.autoRefs.n === this.rows.length && this.autoRefs.host === host) { + const nonRefs = this.nonRefsWidth(); + if ( + this.autoRefs.n === this.rows.length && + this.autoRefs.host === host && + this.autoRefs.non === nonRefs + ) { return this.autoRefs.w; } const fitted = fitRefsWidth({ wanted: wantedRefsWidth(this.rows, spec.max, spec.min), host, - nonRefs: this.nonRefsWidth(), + nonRefs, // A flat 420px comfort floor is most of a narrow host, which starved the // refs track to its minimum on any window under ~1000px. Scale it: the // message still leads, but it stops claiming the entire surface. @@ -2693,7 +2902,7 @@ export class CommitGraph extends LitElement { subjectFloor: this.subjectFloor(), legible: legibleRefsWidth(this.rows), }); - this.autoRefs = { n: this.rows.length, host, w: fitted }; + this.autoRefs = { n: this.rows.length, host, non: nonRefs, w: fitted }; return fitted; } @@ -4591,6 +4800,13 @@ export class CommitGraph extends LitElement { /** The "Columns" button + show/hide popover. */ private columnsControlHtml() { const hiddenCount = this.hiddenCols.size; + // Ticked columns this width has no room for (issue #124): the menu used to + // count only the unticked ones, so "1 hidden" meant Date while SHA was + // ticked and nowhere to be seen. Each is named, beside its row and below. + const noRoom = COLUMN_SPECS.filter((s) => s.hideable !== false && this.noRoomFor(s.id)); + const noRoomHint = noRoom.length + ? l10n.t("{0} hidden — panel too narrow", noRoom.map((s) => s.label).join(", ")) + : ""; return html` `; })}
@@ -4636,9 +4857,11 @@ export class CommitGraph extends LitElement {
- ${hiddenCount === 0 - ? l10n.t("Graph & message are always shown") - : l10n.t("{0} hidden · drag header edges to resize", hiddenCount)} + ${noRoomHint + ? noRoomHint + : hiddenCount === 0 + ? l10n.t("Graph & message are always shown") + : l10n.t("{0} hidden · drag header edges to resize", hiddenCount)}
` : nothing} diff --git a/packages/webview-ui/src/graph/refLayout.ts b/packages/webview-ui/src/graph/refLayout.ts index fa2609d6..15ebe532 100644 --- a/packages/webview-ui/src/graph/refLayout.ts +++ b/packages/webview-ui/src/graph/refLayout.ts @@ -167,6 +167,14 @@ const LEGIBLE_CHIP_CAP = 150; * a chip is 16px of icon + 14px of gap + the name + an optional 14px remote * tail, and the track adds REFS_PADDING around it. A floor short of that draws * the chip's furniture and none of its name. + * + * Plus one REF_CHIP_GAP of slack, the same trailing gap `wanted` carries for + * every chip. The estimate is an estimate: the current HEAD's chip is set at + * weight 650 against the 550 it is calibrated for, and "main" measured 57px + * against 55 estimated — so a track at the bare floor read "m…". It used to + * land there only in an 8px band above 860px; once Date and SHA stayed on + * screen below that (issue #124), it was every width down to 660. With the + * slack a one-chip row's floor equals its `wanted`, which never cut it. */ export function legibleRefsWidth(rows: readonly { refs?: WireRef[] }[]): number { let widest = 0; @@ -176,7 +184,7 @@ export function legibleRefsWidth(rows: readonly { refs?: WireRef[] }[]): number widest = Math.max(widest, estimateChipWidth(entry, LEGIBLE_CHIP_CAP)); } } - return widest === 0 ? 0 : REFS_PADDING + widest; + return widest === 0 ? 0 : REFS_PADDING + widest + REF_CHIP_GAP; } export function fitRefsWidth(opts: { diff --git a/packages/webview-ui/test/graphColumnFit.test.ts b/packages/webview-ui/test/graphColumnFit.test.ts new file mode 100644 index 00000000..7e08cf67 --- /dev/null +++ b/packages/webview-ui/test/graphColumnFit.test.ts @@ -0,0 +1,235 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { fileURLToPath } from "node:url"; +import { findChrome, runInChrome } from "./headless"; + +/** + * A column the user has on is on screen, or the Columns menu says why not + * (issue #124). + * + * The report: the Columns menu showed SHA ticked and the graph had no SHA + * column. Two things did that. The bottom panel's compact layout had no SHA + * track at all, whatever the menu said; and the editor tab dropped Date and + * SHA below an 860px host whether or not they would have fitted — a + * maximised laptop window with the details pane open is under that. The menu + * counted only the columns the user had unticked, so it said "1 hidden" about + * Date and nothing about SHA. + * + * Driven through the real webview entry in headless Chrome: what is on screen + * is grid tracks, container queries and shadow DOM. Widths are changed in the + * page and the graph is asked to update, because a ResizeObserver never runs + * under the headless shell's virtual time; the observer calls the same + * applyColumnStyles an update does. + */ +const ENTRY = fileURLToPath(new URL("../src/graph/main.ts", import.meta.url)); +const CHROME = findChrome(); +const skip = !CHROME && "no Chrome on this machine"; + +const prelude = (hidden: string[] = []) => ` + window.acquireVsCodeApi = () => ({ postMessage: () => {}, getState: () => undefined, setState: () => {} }); + try { + localStorage.removeItem("gitstudio.graph.cols.widths"); + localStorage.setItem("gitstudio.graph.cols.hidden", ${JSON.stringify(JSON.stringify(hidden))}); + } catch {} +`; + +const MOUNT = ` + const sha = (i) => (i + 1).toString(16).padStart(4, "0").repeat(10); + const row = (i, refs) => ({ + sha: sha(i), shortSha: sha(i).slice(0, 7), column: 0, color: 0, isMerge: false, + segments: [{ fromColumn: 0, toColumn: 0, color: 0 }], + subject: "fix(shots): site shots splice page code through jsLiteral " + i, + author: "Anton Arnaudov", authorEmail: "a@example.com", + authorDate: 1700000000 - i * 3600, refs: refs || [], + }); + const rows = [row(0, [{ name: "main", fullName: "refs/heads/main", kind: "currentHead" }])]; + for (let i = 1; i < 30; i++) rows.push(row(i)); + const root = document.getElementById("root"); + const graph = () => document.querySelector("gitstudio-graph"); + const sr = () => graph().shadowRoot; + // A poll for a condition, not a fixed wait: it returns as soon as it holds. + const until = async (probe, ms = 4000) => { + const t0 = Date.now(); + while (!probe() && Date.now() - t0 < ms) await new Promise((r) => setTimeout(r, 10)); + return probe(); + }; + window.postMessage({ type: "graphInit", rows, head: sha(0), totalColumns: 1, hasMore: false, refFilter: null }, "*"); + await until(() => graph() && sr() && sr().querySelector('.row[data-sha="' + sha(0) + '"]')); + const settle = async () => { + window.dispatchEvent(new Event("resize")); + graph().requestUpdate(); + await graph().updateComplete; + // A second pass: the first may have moved the fit, which re-renders. + graph().requestUpdate(); + await graph().updateComplete; + }; + const resize = async (w) => { root.style.width = w + "px"; await settle(); }; + const CELL = { refs: ".refs", changes: ".changes", author: ".meta.author", date: ".meta.date", sha: ".meta.sha" }; + const HEAD = { refs: ".ch-refs", changes: ".ch-changes", author: ".ch-author", date: ".ch-date", sha: ".ch-sha" }; + const firstRow = () => sr().querySelector('.row[data-sha="' + sha(0) + '"]'); + const box = (el) => { + if (!el) return null; + const cs = getComputedStyle(el); + if (cs.display === "none" || cs.visibility === "hidden") return null; + const r = el.getBoundingClientRect(); + return r.width >= 1 ? r : null; + }; + /** Is this column's cell on screen in the first row? */ + const cellBox = (id) => box(firstRow().querySelector(CELL[id])); + /** The sha text's own extent, so a cell that clips its text is caught. */ + const shaTextFits = () => { + const cell = firstRow().querySelector(CELL.sha); + const r = box(cell); + if (!r) return false; + const text = [...cell.childNodes].find((n) => n.nodeType === 3); + const range = document.createRange(); + range.selectNodeContents(text); + const t = range.getBoundingClientRect(); + return t.width > 20 && t.right <= r.right + 0.5 && t.left >= r.left - 0.5; + }; + const openMenu = async () => { + if (!sr().querySelector(".gh-pop[role=menu]")) sr().querySelector(".gh-columns-btn").click(); + await graph().updateComplete; + return sr().querySelector(".gh-pop[role=menu]"); + }; + /** What the Columns menu claims about each column. */ + const menuState = async () => { + const pop = await openMenu(); + const items = [...pop.querySelectorAll("[role=menuitemcheckbox]")]; + return { + items: items.map((it) => ({ + label: it.querySelector(".lbl").textContent.trim(), + on: it.getAttribute("aria-checked") === "true", + squeezed: !!it.querySelector(".gh-menu-note"), + })), + hint: (pop.querySelector(".gh-pop-hint")?.textContent || "").replace(/\\s+/g, " ").trim(), + }; + }; + /** The current branch's chip shows its whole name, not "m…". */ + const chipWhole = () => { + const nm = firstRow().querySelector(".chip .nm"); + return !!nm && nm.scrollWidth <= nm.clientWidth; + }; + const LABEL = { refs: "Branch / Tag", changes: "Changes", author: "Author", date: "Date", sha: "SHA" }; +`; + +const run = (script: string, o: { layout: "side" | "dock"; width: number; hidden?: string[] }) => + runInChrome(CHROME!, ENTRY, MOUNT + script, { + css: `#root{height:640px;width:${o.width}px}`, + prelude: prelude(o.hidden), + rootAttrs: o.layout === "side" ? 'data-layout="side"' : "", + width: 1600, + height: 720, + }); + +test("the bottom panel shows an SHA column the user left on — with Date off, as reported", { skip }, async () => { + const v = await run(` + for (const w of [1170, 900, 700]) { + await resize(w); + const shaBox = cellBox("sha"); + expect(!!shaBox, w + "px: the SHA cell is on screen"); + if (!shaBox) continue; + expect(shaTextFits(), w + "px: the whole short sha shows, not clipped"); + const author = cellBox("author"); + expect(!author || shaBox.left >= author.right - 1, w + "px: SHA sits in its own track, right of Author (" + (author && author.right) + " / " + shaBox.left + ")"); + const head = box(sr().querySelector(HEAD.sha)); + expect(!!head && Math.abs(head.left - shaBox.left) <= 2, w + "px: the SHA header sits over the SHA cells (" + (head && head.left) + " / " + shaBox.left + ")"); + expect(!cellBox("date"), w + "px: Date stays off, as the user set it"); + } + `, { layout: "side", width: 1170, hidden: ["date"] }); + assert.deepEqual(v.fails, [], v.fails.join("\n")); +}); + +test("the bottom panel keeps both Date and SHA when both are on and there is room", { skip }, async () => { + const v = await run(` + await resize(1170); + const dateBox = cellBox("date"), shaBox = cellBox("sha"); + expect(!!dateBox && !!shaBox, "both on screen (date " + !!dateBox + ", sha " + !!shaBox + ")"); + expect(!!dateBox && !!shaBox && shaBox.left >= dateBox.right - 1, "SHA follows Date"); + expect(shaTextFits(), "the whole short sha shows"); + `, { layout: "side", width: 1170 }); + assert.deepEqual(v.fails, [], v.fails.join("\n")); +}); + +test("the editor tab keeps Date and SHA under 860px while they fit, and gives up Date before SHA", { skip }, async () => { + const v = await run(` + for (const w of [840, 780]) { + await resize(w); + expect(!!cellBox("sha") && !!cellBox("date"), w + "px: Date and SHA on screen (date " + !!cellBox("date") + ", sha " + !!cellBox("sha") + ")"); + const subject = box(firstRow().querySelector(".subject")); + expect(!!subject && subject.width >= 200, w + "px: the message keeps its floor (" + (subject && subject.width) + ")"); + expect(chipWhole(), w + "px: the branch chip still reads main, whole"); + const last = cellBox("sha"); + expect(!!last && last.right <= firstRow().getBoundingClientRect().right + 0.5, w + "px: nothing runs off the row"); + } + // Narrower: there is room for one of them, and it is SHA. + await resize(690); + expect(!!cellBox("sha"), "690px: SHA on screen"); + expect(shaTextFits(), "690px: the whole short sha shows"); + expect(!cellBox("date"), "690px: Date has given way"); + const m = await menuState(); + const date = m.items.find((i) => i.label === "Date"); + expect(!!date && date.on && date.squeezed, "690px: the menu keeps Date ticked and says it has no room (" + JSON.stringify(date) + ")"); + expect(/Date/.test(m.hint), "690px: the menu's footer names Date (" + m.hint + ")"); + `, { layout: "dock", width: 840 }); + assert.deepEqual(v.fails, [], v.fails.join("\n")); +}); + +/** + * The state table: every width, both layouts, with and without a column the + * user unticked. A ticked column is on screen, or its menu row says it has no + * room — never both, never neither. An unticked one is neither. And the + * footer names every column that has no room. + */ +for (const layout of ["dock", "side"] as const) { + for (const hidden of [[], ["date"]]) { + test(`the Columns menu never claims a column that is not on screen — ${layout}, hidden ${JSON.stringify(hidden)}`, { skip }, async () => { + const v = await run(` + const seen = []; + // Where each column went while the pane narrowed: a column that has + // gone must not come back at a NARROWER width — one that blinks out + // and in as you drag reads as a bug, whatever the reason. + const goneAt = {}; + for (let w = 1400; w >= 300; w -= 10) { + await resize(w); + const host = graph().clientWidth; + const m = await menuState(); + const squeezedLabels = []; + for (const [id, label] of Object.entries(LABEL)) { + const item = m.items.find((i) => i.label === label); + if (!item) { expect(false, host + "px: no menu row for " + label); continue; } + const shown = !!cellBox(id); + // Where both are drawn, the header sits over its own cells. + const hb = box(sr().querySelector(".colhead " + HEAD[id])), cb = cellBox(id); + if (hb && cb && id !== "refs") expect(Math.abs(hb.left - cb.left) <= 2, host + "px: the " + label + " header sits over its cells (" + Math.round(hb.left) + " / " + Math.round(cb.left) + ")"); + if (!shown && item.on && goneAt[id] === undefined) goneAt[id] = host; + if (shown && goneAt[id] !== undefined) expect(false, label + " went at " + goneAt[id] + "px and came back at " + host + "px"); + if (!item.on) { + expect(!shown, host + "px: " + label + " is unticked yet on screen"); + expect(!item.squeezed, host + "px: " + label + " is unticked, so it is not 'no room'"); + } else { + expect(shown !== item.squeezed, host + "px: " + label + " ticked, on screen " + shown + ", menu says no room " + item.squeezed); + if (item.squeezed) squeezedLabels.push(label); + } + } + for (const label of squeezedLabels) { + expect(m.hint.includes(label), host + "px: the footer names " + label + " (" + m.hint + ")"); + } + seen.push(host + ":" + squeezedLabels.join("+")); + } + notes.seen = seen; + notes.goneAt = goneAt; + // SHA is the narrowest column and the one that names a commit: it + // stays wherever the layout is still a table of columns. + const floor = ${layout === "dock" ? 470 : 350}; + for (let w = 1400; w >= floor; w -= 10) { + await resize(w); + expect(!!cellBox("sha"), graph().clientWidth + "px: SHA on screen"); + // ...and not at the cost of the branch name it sits beside. + expect(chipWhole(), graph().clientWidth + "px: the branch chip reads main, whole"); + } + `, { layout, width: 1400, hidden }); + assert.deepEqual(v.fails, [], v.fails.join("\n")); + }); + } +} diff --git a/packages/webview-ui/test/refFilter.cov.test.ts b/packages/webview-ui/test/refFilter.cov.test.ts index 6d48d29c..bf400c5f 100644 --- a/packages/webview-ui/test/refFilter.cov.test.ts +++ b/packages/webview-ui/test/refFilter.cov.test.ts @@ -2,7 +2,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import type { GraphRefEntry, WireRef, WireRow } from "@gitstudio/host-bridge/graphProtocol"; import { presetUnavailable, refFilterHint } from "../src/graph/refFilter"; -import { REFS_PADDING, estimateChipWidth, foldRefs, legibleRefsWidth } from "../src/graph/refLayout"; +import { REFS_PADDING, REF_CHIP_GAP, estimateChipWidth, foldRefs, legibleRefsWidth } from "../src/graph/refLayout"; import { rowMatches } from "../src/graph/search"; // The Branches picker's footnote and excuses, the refs column's legibility @@ -49,13 +49,14 @@ test("the refs column's floor is one readable chip of the busiest row, or nothin ]; const widest = foldRefs(rows[1].refs).map((e) => estimateChipWidth(e, 150)); assert.equal(widest.length, 1, "the remote twin folds into its local chip"); - assert.equal(legibleRefsWidth(rows), REFS_PADDING + widest[0]); + // The chip, the track's padding, and one chip gap of slack for the estimate. + assert.equal(legibleRefsWidth(rows), REFS_PADDING + widest[0] + REF_CHIP_GAP); assert.ok(legibleRefsWidth(rows) > legibleRefsWidth([rows[0]]), "the busier chip sets the floor"); }); test("a very long branch name cannot make the floor demand half the window", () => { const long = [{ refs: [ref(`refs/heads/${"x".repeat(200)}`, "head")] }]; - assert.equal(legibleRefsWidth(long), REFS_PADDING + 150); + assert.equal(legibleRefsWidth(long), REFS_PADDING + 150 + REF_CHIP_GAP); }); test("the 'refs' search scope matches a ref's name and nothing else", () => {