Commit b39ffaec3a

b39ffaec3ad4cef999a54fc271efff1bd47db3dc

parent: 2737992a54

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-28 06:46 UTC

notifications list: name --all when the empty inbox is just read items

Closes #265

Layout: unified · split

internal/control/notifications.go +8
@@ -418,6 +418,14 @@ func runNotificationsList(c *Ctx, args []string) int {
418 for _, n := range notices { 418 for _, n := range notices {
419 ds = append(ds, out{n.ID, n.RepoPath, n.Kind, n.Actor, n.Summary, n.Path, n.CreatedAt, n.ReadAt}) 419 ds = append(ds, out{n.ID, n.RepoPath, n.Kind, n.Actor, n.Summary, n.Path, n.CreatedAt, n.ReadAt})
420 } 420 }
421 if !c.JSON && !p.active && len(ds) == 0 {
422 msg := "nothing to list"
423 if !all {
424 msg = "no unread notifications (--all for read ones)"
425 }
426 fmt.Fprintln(c.Stderr, msg)
427 return protocol.ExitOK
428 }
421 return c.emitPage(p, ds, next, func(w io.Writer) { 429 return c.emitPage(p, ds, next, func(w io.Writer) {
422 tb := c.table(w, "ID", "WHEN", "REPO", "EVENT", "PATH") 430 tb := c.table(w, "ID", "WHEN", "REPO", "EVENT", "PATH")
423 for _, d := range ds { 431 for _, d := range ds {
internal/control/notifications_test.go +31
@@ -267,3 +267,34 @@ func TestNotificationsSettingsShowsPush(t *testing.T) {
267 t.Fatalf("no push key: %s", out.String()) 267 t.Fatalf("no push key: %s", out.String())
268 } 268 }
269} 269}
270
271func TestNotificationsListEmptyUnreadSaysHowToSeeRead(t *testing.T) {
272 c, repo, bob := testRepoWithWatcher(t)
273 // Give bob one notice (acting as alice, so bob isn't filtered out as
274 // the actor), then mark it read as bob, so his inbox has rows but no
275 // unread ones.
276 notify(c, []int64{bob}, notice{repo: repo, kind: "issue", subject: "s", action: "a", path: "x"})
277 c.User = store.User{ID: bob, Username: "bob"}
278 if code := runNotificationsRead(c, []string{"--all"}); code != protocol.ExitOK {
279 t.Fatalf("mark read: exit %d", code)
280 }
281 var out, errOut bytes.Buffer
282 c.Stdout, c.Stderr = &out, &errOut
283 if code := runNotificationsList(c, nil); code != protocol.ExitOK {
284 t.Fatalf("exit %d: %s", code, errOut.String())
285 }
286 if got := errOut.String(); got != "no unread notifications (--all for read ones)\n" {
287 t.Errorf("stderr = %q", got)
288 }
289 // --all sees it and stays the generic message when that too is empty.
290 out.Reset()
291 errOut.Reset()
292 if code := runNotificationsList(c, []string{"--all"}); code != protocol.ExitOK {
293 t.Fatalf("exit %d: %s", code, errOut.String())
294 }
295 // The inbox row's summary is the notice's action ("a"), not its mail
296 // subject ("s"); check the path instead, which is unique to this row.
297 if !strings.Contains(out.String(), "x") {
298 t.Errorf("--all did not show the read notice: %q", out.String())
299 }
300}