mirror of
https://github.com/mjl-/mox.git
synced 2024-12-27 08:53:48 +03:00
webmail: when open the first unread message of a thread by default when opening a mailbox with threading enabled and the most recent message is in a thread
This commit is contained in:
parent
fc6e61e9a5
commit
20f11409b6
1 changed files with 24 additions and 4 deletions
|
@ -842,7 +842,7 @@ func serveEvents(ctx context.Context, log *mlog.Log, w http.ResponseWriter, r *h
|
||||||
if !thread && req.Query.Threading != ThreadOff {
|
if !thread && req.Query.Threading != ThreadOff {
|
||||||
err := ensureTx()
|
err := ensureTx()
|
||||||
xcheckf(ctx, err, "transaction")
|
xcheckf(ctx, err, "transaction")
|
||||||
more, _, err := gatherThread(log, xtx, acc, v, m, 0)
|
more, _, err := gatherThread(log, xtx, acc, v, m, 0, false)
|
||||||
xcheckf(ctx, err, "gathering thread messages for id %d, thread %d", m.ID, m.ThreadID)
|
xcheckf(ctx, err, "gathering thread messages for id %d, thread %d", m.ID, m.ThreadID)
|
||||||
mil = append(mil, more...)
|
mil = append(mil, more...)
|
||||||
v.threadIDs[m.ThreadID] = struct{}{}
|
v.threadIDs[m.ThreadID] = struct{}{}
|
||||||
|
@ -1458,6 +1458,10 @@ func queryMessages(ctx context.Context, log *mlog.Log, acc *store.Account, tx *b
|
||||||
|
|
||||||
var pm *ParsedMessage
|
var pm *ParsedMessage
|
||||||
if m.ID == page.DestMessageID || page.DestMessageID == 0 && have == 0 && page.AnchorMessageID == 0 {
|
if m.ID == page.DestMessageID || page.DestMessageID == 0 && have == 0 && page.AnchorMessageID == 0 {
|
||||||
|
// For threads, if there was not DestMessageID, we may be getting the newest
|
||||||
|
// message. For an initial view, this isn't necessarily the first the user is
|
||||||
|
// expected to read first, that would be the first unread, which we'll get below
|
||||||
|
// when gathering the thread.
|
||||||
found = true
|
found = true
|
||||||
xpm, err := parsedMessage(log, m, &state, true, false)
|
xpm, err := parsedMessage(log, m, &state, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1472,7 +1476,7 @@ func queryMessages(ctx context.Context, log *mlog.Log, acc *store.Account, tx *b
|
||||||
}
|
}
|
||||||
mil := []MessageItem{mi}
|
mil := []MessageItem{mi}
|
||||||
if query.Threading != ThreadOff {
|
if query.Threading != ThreadOff {
|
||||||
more, xpm, err := gatherThread(log, tx, acc, v, m, page.DestMessageID)
|
more, xpm, err := gatherThread(log, tx, acc, v, m, page.DestMessageID, have == 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("gathering thread messages for id %d, thread %d: %v", m.ID, m.ThreadID, err)
|
return fmt.Errorf("gathering thread messages for id %d, thread %d: %v", m.ID, m.ThreadID, err)
|
||||||
}
|
}
|
||||||
|
@ -1535,7 +1539,7 @@ func queryMessages(ctx context.Context, log *mlog.Log, acc *store.Account, tx *b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func gatherThread(log *mlog.Log, tx *bstore.Tx, acc *store.Account, v view, m store.Message, destMessageID int64) ([]MessageItem, *ParsedMessage, error) {
|
func gatherThread(log *mlog.Log, tx *bstore.Tx, acc *store.Account, v view, m store.Message, destMessageID int64, first bool) ([]MessageItem, *ParsedMessage, error) {
|
||||||
if m.ThreadID == 0 {
|
if m.ThreadID == 0 {
|
||||||
// If we would continue, FilterNonzero would fail because there are no non-zero fields.
|
// If we would continue, FilterNonzero would fail because there are no non-zero fields.
|
||||||
return nil, nil, fmt.Errorf("message has threadid 0, account is probably still being upgraded, try turning threading off until the upgrade is done")
|
return nil, nil, fmt.Errorf("message has threadid 0, account is probably still being upgraded, try turning threading off until the upgrade is done")
|
||||||
|
@ -1546,6 +1550,7 @@ func gatherThread(log *mlog.Log, tx *bstore.Tx, acc *store.Account, v view, m st
|
||||||
qt.FilterNonzero(store.Message{ThreadID: m.ThreadID})
|
qt.FilterNonzero(store.Message{ThreadID: m.ThreadID})
|
||||||
qt.FilterEqual("Expunged", false)
|
qt.FilterEqual("Expunged", false)
|
||||||
qt.FilterNotEqual("ID", m.ID)
|
qt.FilterNotEqual("ID", m.ID)
|
||||||
|
qt.SortAsc("ID")
|
||||||
tml, err := qt.List()
|
tml, err := qt.List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("listing other messages in thread for message %d, thread %d: %v", m.ID, m.ThreadID, err)
|
return nil, nil, fmt.Errorf("listing other messages in thread for message %d, thread %d: %v", m.ID, m.ThreadID, err)
|
||||||
|
@ -1553,6 +1558,7 @@ func gatherThread(log *mlog.Log, tx *bstore.Tx, acc *store.Account, v view, m st
|
||||||
|
|
||||||
var mil []MessageItem
|
var mil []MessageItem
|
||||||
var pm *ParsedMessage
|
var pm *ParsedMessage
|
||||||
|
var firstUnread bool
|
||||||
for _, tm := range tml {
|
for _, tm := range tml {
|
||||||
err := func() error {
|
err := func() error {
|
||||||
xstate := msgState{acc: acc}
|
xstate := msgState{acc: acc}
|
||||||
|
@ -1570,7 +1576,8 @@ func gatherThread(log *mlog.Log, tx *bstore.Tx, acc *store.Account, v view, m st
|
||||||
}
|
}
|
||||||
mil = append(mil, mi)
|
mil = append(mil, mi)
|
||||||
|
|
||||||
if tm.ID == destMessageID {
|
if tm.ID == destMessageID || destMessageID == 0 && first && (pm == nil || !firstUnread && !tm.Seen) {
|
||||||
|
firstUnread = !tm.Seen
|
||||||
xpm, err := parsedMessage(log, tm, &xstate, true, false)
|
xpm, err := parsedMessage(log, tm, &xstate, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("parsing thread message %d: %v", tm.ID, err)
|
return fmt.Errorf("parsing thread message %d: %v", tm.ID, err)
|
||||||
|
@ -1583,6 +1590,19 @@ func gatherThread(log *mlog.Log, tx *bstore.Tx, acc *store.Account, v view, m st
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally, the message that caused us to gather this thread (which is likely the
|
||||||
|
// most recent message in the thread) could be the only unread message.
|
||||||
|
if destMessageID == 0 && first && !m.Seen && !firstUnread {
|
||||||
|
xstate := msgState{acc: acc}
|
||||||
|
defer xstate.clear()
|
||||||
|
xpm, err := parsedMessage(log, m, &xstate, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("parsing thread message %d: %v", m.ID, err)
|
||||||
|
}
|
||||||
|
pm = &xpm
|
||||||
|
}
|
||||||
|
|
||||||
return mil, pm, nil
|
return mil, pm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue