Fix mailbox UI sorting and target layout

This commit is contained in:
DonVoo 2026-07-15 00:14:54 +02:00
parent 8e8c651eaa
commit e63a513cff
6 changed files with 196 additions and 46 deletions

View file

@ -51,6 +51,7 @@ type SourceMailbox interface {
Folders() ([]Folder, error) // rekursiver Ordnerbaum
Count(folder string) (int, error)
Headers(folder string, limit, offset int) ([]MessageHeader, error)
AllHeaders(folder string) ([]MessageHeader, error)
FetchOne(folder string, uid uint32) (RawMessage, error)
Fetch(folder string, fn func(RawMessage) error) error // BODY[] FLAGS INTERNALDATE
Close() error
@ -102,6 +103,10 @@ func (s *imapSource) Headers(folder string, limit, offset int) ([]MessageHeader,
return s.mailbox.fetchHeaders(folder, limit, offset)
}
func (s *imapSource) AllHeaders(folder string) ([]MessageHeader, error) {
return s.mailbox.fetchAllHeadersByUID(folder)
}
func (s *imapSource) FetchOne(folder string, uid uint32) (RawMessage, error) {
return s.mailbox.fetchOne(folder, uid)
}
@ -208,56 +213,25 @@ func (m *imapClientMailbox) count(folder string) (int, error) {
}
func (m *imapClientMailbox) fetchHeaders(folder string, limit, offset int) ([]MessageHeader, error) {
selected, err := m.c.Select(folder, &imap.SelectOptions{ReadOnly: true}).Wait()
if err != nil {
return nil, err
}
if selected.NumMessages == 0 {
return nil, nil
}
if limit <= 0 || limit > 200 {
limit = 200
}
if offset < 0 {
offset = 0
}
stop := int(selected.NumMessages) - offset
if stop <= 0 {
headers, err := m.fetchAllHeadersByUID(folder)
if err != nil {
return nil, err
}
sortMessageHeadersByDateDesc(headers)
if offset >= len(headers) {
return nil, nil
}
start := stop - limit + 1
if start < 1 {
start = 1
end := offset + limit
if end > len(headers) {
end = len(headers)
}
seqSet := imap.SeqSet{}
seqSet.AddRange(uint32(start), uint32(stop))
cmd := m.c.Fetch(seqSet, &imap.FetchOptions{
Envelope: true,
Flags: true,
InternalDate: true,
RFC822Size: true,
UID: true,
})
defer cmd.Close()
var out []MessageHeader
for {
data := cmd.Next()
if data == nil {
break
}
buf, err := data.Collect()
if err != nil {
return out, err
}
out = append(out, messageHeaderFromFetch(buf))
}
if err := cmd.Close(); err != nil {
return out, err
}
reverseHeaders(out)
return out, nil
return headers[offset:end], nil
}
func (m *imapClientMailbox) fetchAllHeadersByUID(folder string) ([]MessageHeader, error) {
@ -463,6 +437,24 @@ func sortMessageHeadersByUID(headers []MessageHeader) {
})
}
func sortMessageHeadersByDateDesc(headers []MessageHeader) {
sort.SliceStable(headers, func(i, j int) bool {
di := headerSortDate(headers[i])
dj := headerSortDate(headers[j])
if !di.Equal(dj) {
return di.After(dj)
}
return headers[i].UID > headers[j].UID
})
}
func headerSortDate(h MessageHeader) time.Time {
if !h.Date.IsZero() {
return h.Date
}
return h.InternalDate
}
func messageIDFromFetch(buf *imapclient.FetchMessageBuffer, body []byte) string {
if buf != nil && buf.Envelope != nil && strings.TrimSpace(buf.Envelope.MessageID) != "" {
return normalizeMessageID(buf.Envelope.MessageID)