thunderbird-patch-review

Easy-to-use patch review interface for Thunderbird

Contribute: ~marcc/thunderbird-review-plugin@lists.sr.ht

git clone git://mccd.space/thunderbird-patch-review

commit bce9576f90902b376174f9d4bbadce2299cd401c
parent ddb4bee763b8210aa161971f35336a06b771988f
Author: Pi Agent <agent@pi.local>
Date:   Sat, 18 Jul 2026 22:30:39 +0200

review: restore the bold top-left title; pills stay under the top bar

Return "Reviewing patch N" / "Reviewing cover" to a bold #series-title\nelement in the top bar (top left, as it was), driven by a new\nrenderSeriesTitle() called on init and on patch switch. The pills remain\nwhere the last change put them — in #content above the subject — and the\nin-nav title span is removed.

Diffstat:
Mextension/review/review.css | 6+++---
Mextension/review/review.html | 1+
Mextension/review/review.js | 29+++++++++++++++++------------
3 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/extension/review/review.css b/extension/review/review.css
@@ -64,11 +64,11 @@ body {
   margin: 0.6rem 0;
 }
 
-#series-nav .series-title {
+#series-title {
   font-weight: 600;
+  overflow: hidden;
+  text-overflow: ellipsis;
   white-space: nowrap;
-  margin-bottom: 0.2rem;
-  flex: 1 0 100%;
 }
 
 #actions {
diff --git a/extension/review/review.html b/extension/review/review.html
@@ -7,6 +7,7 @@
 </head>
 <body>
   <header id="topbar">
+    <div id="series-title">Review</div>
     <div id="actions">
       <div class="cluster" id="repo-cluster">
         <button id="repo-path" type="button" title="Click to choose the repository directory">no repository chosen</button>
diff --git a/extension/review/review.js b/extension/review/review.js
@@ -47,6 +47,7 @@ async function init() {
   document.title = `Review: ${anchor.title}`;
   state.navEl = $("#series-nav");
   renderNav();
+  renderSeriesTitle();
   refreshRepoDisplay(state.repo);
   state.slug =
     anchor.title.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60) ||
@@ -71,23 +72,24 @@ async function init() {
 // ---------------------------------------------------------------------------
 // Rendering
 
+// The top-left title is static-colored but reflects the currently viewed
+// patch of the series ("Reviewing cover", "Reviewing patch N").
+function renderSeriesTitle() {
+  const current = state.series[state.current];
+  let text = "Review";
+  if (current) {
+    if (current.isCover) text = "Reviewing cover";
+    else if (current.n !== null && current.m) text = `Reviewing patch ${current.n}`;
+    else text = "Reviewing patch";
+  }
+  $("#series-title").textContent = text;
+}
+
 function renderNav() {
   const nav = state.navEl;
   if (!nav) return;
   nav.textContent = "";
 
-  const current = state.series[state.current];
-  const title = document.createElement("span");
-  title.className = "series-title";
-  title.textContent = current
-    ? current.isCover
-      ? "Reviewing cover"
-      : current.n !== null && current.m
-        ? `Reviewing patch ${current.n}`
-        : "Reviewing patch"
-    : "Review";
-  nav.appendChild(title);
-
   state.series.forEach((patch, i) => {
     const pill = document.createElement("span");
     pill.className = "pill" + (i === state.current ? " active" : "");
@@ -107,6 +109,7 @@ function renderNav() {
     pill.addEventListener("click", () => {
       state.current = i;
       renderNav();
+      renderSeriesTitle();
       renderPatch();
     });
     nav.appendChild(pill);
@@ -761,6 +764,8 @@ $("#btn-status-close").addEventListener("click", hideStatus);
 
 init().catch((e) => {
   document.title = "Review: error";
+  const titleEl = $("#series-title");
+  if (titleEl) titleEl.textContent = "Error";
   if (state.navEl) state.navEl.textContent = "";
   showStatus(e.message || String(e), { error: true });
 });