lists: show unassigned mail in every For me lane
For me only listed unassigned messages in Inbox, so an unassigned
message in Do, Wait, or Watch showed up on nobody's landing page.
Unassigned means everyone's whatever the state, so the filter drops
the Inbox condition.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
diff --git a/docs/DESIGN.md b/docs/DESIGN.md
index f2471b3..d181ef8 100644
--- a/docs/DESIGN.md
+++ b/docs/DESIGN.md
@@ -83,7 +83,7 @@ Per-person read tracking lives in the database — `$seen` is shared across clie
Each message has zero or more assignees (me, them, or both). It's a soft signal, never a lock, and its meaning is the same in every state: these people should deal with this message.
-- Unassigned is normal. An unassigned Inbox message is everyone's.
+- Unassigned is normal. An unassigned message is everyone's.
- Assigning someone else is a handoff; add a comment to say why.
- Assignees come off by unassigning themselves. Opening a message doesn't unassign.
- New messages arrive unassigned.
@@ -105,7 +105,7 @@ There is no toolbar and no thread-level action. Each message's state, folder, an
## Core flows
-- **Landing — For me**: individual messages assigned to me (any state) plus unassigned Inbox messages, grouped by state, then by thread. A thread group lists only its messages in that state; the rest of the thread is omitted.
+- **Landing — For me**: individual messages assigned to me or unassigned (any state), grouped by state, then by thread. A thread group lists only its messages in that state; the rest of the thread is omitted.
- **Triage**: from the list or the thread view. Click the value to change it. No modals; an undo toast after each change.
- **Thread view**: received messages, sent messages, and comments in time order, as ruled rows of equal weight. Each row has the sender (and cc/bcc when present) and body on the left; a right gutter holds the date and, for received messages, state, folder, and assignees in fixed positions so they line up down the thread. Sent messages show the recipient after the sender and no values. Comments sit on a filled row. Events ("Sam moved to Do", "filed via another client"). Older messages collapse; their values stay clickable.
- **Lane views**: one list component showing individual messages, grouped by thread (only messages in that lane):
diff --git a/src/lists.rs b/src/lists.rs
index 3330235..1ab4a2e 100644
--- a/src/lists.rs
+++ b/src/lists.rs
@@ -179,7 +179,13 @@ mod tests {
// Alex's own Inbox messages share the section with unassigned ones.
let alex = summary(&store, ALEX, &View::ForMe);
- assert_eq!(heads(&store, ALEX, &View::ForMe), ["INBOX", "WAIT"]);
+ assert_eq!(
+ heads(&store, ALEX, &View::ForMe),
+ ["INBOX", "DO", "WAIT", "WATCH"]
+ );
+ // Unassigned is everyone's in every state, not just Inbox.
+ assert_eq!(alex[1].1, [vec![fixtures::id(13)]]);
+ assert_eq!(alex[3].1, [vec![fixtures::id(14)]]);
assert_eq!(
alex[0].1,
[
@@ -197,7 +203,7 @@ mod tests {
fn sidebar_count() {
let store = fixtures::store().unwrap();
let sam = store.user(SAM).unwrap().unwrap();
- assert_eq!(count(&store, &sam, &View::ForMe).unwrap(), 7);
+ assert_eq!(count(&store, &sam, &View::ForMe).unwrap(), 9);
// Counts come from SQL, so pin them to the rows each view lists.
for login in [SAM, ALEX] {
diff --git a/src/store.rs b/src/store.rs
index e9a6705..0e4924d 100644
--- a/src/store.rs
+++ b/src/store.rs
@@ -60,7 +60,7 @@ pub enum Filter<'a> {
/// Received messages in a state.
State(State),
/// Received messages in a state that are the user's: assigned to them,
- /// or unassigned in Inbox.
+ /// or unassigned.
ForMe { user: &'a str, state: State },
/// Messages whose subject, sender, or body contains the text. Case is
/// ignored for ASCII letters only, as SQLite's LIKE does.
@@ -80,7 +80,7 @@ impl Filter<'_> {
Filter::ForMe { user, state } => (
"m.kind = 'received' AND m.state = ?1 AND (
EXISTS (SELECT 1 FROM assignees a WHERE a.message = m.id AND a.user = ?2)
- OR (?1 = 'inbox' AND NOT EXISTS (SELECT 1 FROM assignees a WHERE a.message = m.id))
+ OR NOT EXISTS (SELECT 1 FROM assignees a WHERE a.message = m.id)
)",
vec![Text(state.slug().to_owned()), Text(user.to_owned())],
),