mirror of
https://github.com/mjl-/mox.git
synced 2025-07-14 08:14:37 +03:00
webmail: fix js error rerendering additional headers after updated keywords
i've seen the error a few times: msgheaderElem.children[(msgheaderElem.children.length - 1)] is undefined i've seen it happen after sending a reply (with the "answered" flag added). the updateKeywords callback would render the message again, but the code for rendering the "additional headers" table rows again was making invalid assumptions. the approach is now changed. the backend now just immediately sends the additional headers to the frontend. before, the frontend would first render the base message, then render again once the headers came in for the parsed message. this also prevents a reflow for the (quite common) case that one of the additional headers are present in the message.
This commit is contained in:
@ -172,8 +172,9 @@ type MessageItem struct {
|
||||
Attachments []Attachment
|
||||
IsSigned bool
|
||||
IsEncrypted bool
|
||||
FirstLine string // Of message body, for showing as preview.
|
||||
MatchQuery bool // If message does not match query, it can still be included because of threading.
|
||||
FirstLine string // Of message body, for showing as preview.
|
||||
MatchQuery bool // If message does not match query, it can still be included because of threading.
|
||||
MoreHeaders [][2]string // All headers from store.Settings.ShowHeaders that are present.
|
||||
}
|
||||
|
||||
// ParsedMessage has more parsed/derived information about a message, intended
|
||||
@ -488,6 +489,23 @@ type ioErr struct {
|
||||
err error
|
||||
}
|
||||
|
||||
// ensure we have a non-nil moreHeaders, taking it from Settings.
|
||||
func ensureMoreHeaders(tx *bstore.Tx, moreHeaders []string) ([]string, error) {
|
||||
if moreHeaders != nil {
|
||||
return moreHeaders, nil
|
||||
}
|
||||
|
||||
s := store.Settings{ID: 1}
|
||||
if err := tx.Get(&s); err != nil {
|
||||
return nil, fmt.Errorf("get settings: %v", err)
|
||||
}
|
||||
moreHeaders = s.ShowHeaders
|
||||
if moreHeaders == nil {
|
||||
moreHeaders = []string{} // Ensure we won't get Settings again next call.
|
||||
}
|
||||
return moreHeaders, nil
|
||||
}
|
||||
|
||||
// serveEvents serves an SSE connection. Authentication is done through a query
|
||||
// string parameter "singleUseToken", a one-time-use token returned by the Token
|
||||
// API call.
|
||||
@ -824,6 +842,17 @@ func serveEvents(ctx context.Context, log mlog.Log, accountPath string, w http.R
|
||||
return bstore.QueryTx[store.Message](xtx).FilterEqual("Expunged", false).FilterNonzero(store.Message{MailboxID: mailboxID, UID: uid}).Get()
|
||||
}
|
||||
|
||||
// Additional headers from settings to add to MessageItems.
|
||||
var moreHeaders []string
|
||||
xmoreHeaders := func() []string {
|
||||
err := ensureTx()
|
||||
xcheckf(ctx, err, "transaction")
|
||||
|
||||
moreHeaders, err = ensureMoreHeaders(xtx, moreHeaders)
|
||||
xcheckf(ctx, err, "ensuring more headers")
|
||||
return moreHeaders
|
||||
}
|
||||
|
||||
// Return uids that are within range in view. Because the end has been reached, or
|
||||
// because the UID is not after the last message.
|
||||
xchangedUIDs := func(mailboxID int64, uids []store.UID, isRemove bool) (changedUIDs []store.UID) {
|
||||
@ -860,8 +889,9 @@ func serveEvents(ctx context.Context, log mlog.Log, accountPath string, w http.R
|
||||
if !ok && !thread {
|
||||
continue
|
||||
}
|
||||
|
||||
state := msgState{acc: acc}
|
||||
mi, err := messageItem(log, m, &state)
|
||||
mi, err := messageItem(log, m, &state, xmoreHeaders())
|
||||
state.clear()
|
||||
xcheckf(ctx, err, "make messageitem")
|
||||
mi.MatchQuery = ok
|
||||
@ -870,7 +900,7 @@ func serveEvents(ctx context.Context, log mlog.Log, accountPath string, w http.R
|
||||
if !thread && req.Query.Threading != ThreadOff {
|
||||
err := ensureTx()
|
||||
xcheckf(ctx, err, "transaction")
|
||||
more, _, err := gatherThread(log, xtx, acc, v, m, 0, false)
|
||||
more, _, err := gatherThread(log, xtx, acc, v, m, 0, false, xmoreHeaders())
|
||||
xcheckf(ctx, err, "gathering thread messages for id %d, thread %d", m.ID, m.ThreadID)
|
||||
mil = append(mil, more...)
|
||||
v.threadIDs[m.ThreadID] = struct{}{}
|
||||
@ -1460,6 +1490,8 @@ func queryMessages(ctx context.Context, log mlog.Log, acc *store.Account, tx *bs
|
||||
q.FilterFn(wordsFilter)
|
||||
}
|
||||
|
||||
var moreHeaders []string // From store.Settings.ShowHeaders
|
||||
|
||||
if query.OrderAsc {
|
||||
q.SortAsc("Received")
|
||||
} else {
|
||||
@ -1501,13 +1533,19 @@ func queryMessages(ctx context.Context, log mlog.Log, acc *store.Account, tx *bs
|
||||
}
|
||||
}
|
||||
|
||||
mi, err := messageItem(log, m, &state)
|
||||
var err error
|
||||
moreHeaders, err = ensureMoreHeaders(tx, moreHeaders)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ensuring more headers: %v", err)
|
||||
}
|
||||
|
||||
mi, err := messageItem(log, m, &state, moreHeaders)
|
||||
if err != nil {
|
||||
return fmt.Errorf("making messageitem for message %d: %v", m.ID, err)
|
||||
}
|
||||
mil := []MessageItem{mi}
|
||||
if query.Threading != ThreadOff {
|
||||
more, xpm, err := gatherThread(log, tx, acc, v, m, page.DestMessageID, page.AnchorMessageID == 0 && have == 0)
|
||||
more, xpm, err := gatherThread(log, tx, acc, v, m, page.DestMessageID, page.AnchorMessageID == 0 && have == 0, moreHeaders)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gathering thread messages for id %d, thread %d: %v", m.ID, m.ThreadID, err)
|
||||
}
|
||||
@ -1576,7 +1614,7 @@ func queryMessages(ctx context.Context, log mlog.Log, acc *store.Account, tx *bs
|
||||
}
|
||||
}
|
||||
|
||||
func gatherThread(log mlog.Log, tx *bstore.Tx, acc *store.Account, v view, m store.Message, destMessageID int64, first bool) ([]MessageItem, *ParsedMessage, error) {
|
||||
func gatherThread(log mlog.Log, tx *bstore.Tx, acc *store.Account, v view, m store.Message, destMessageID int64, first bool, moreHeaders []string) ([]MessageItem, *ParsedMessage, error) {
|
||||
if m.ThreadID == 0 {
|
||||
// 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")
|
||||
@ -1601,7 +1639,7 @@ func gatherThread(log mlog.Log, tx *bstore.Tx, acc *store.Account, v view, m sto
|
||||
xstate := msgState{acc: acc}
|
||||
defer xstate.clear()
|
||||
|
||||
mi, err := messageItem(log, tm, &xstate)
|
||||
mi, err := messageItem(log, tm, &xstate, moreHeaders)
|
||||
if err != nil {
|
||||
return fmt.Errorf("making messageitem for message %d, for thread %d: %v", tm.ID, m.ThreadID, err)
|
||||
}
|
||||
|
Reference in New Issue
Block a user