diff options
author | Robin Jarry <robin@jarry.cc> | 2022-12-20 18:37:16 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-01-04 22:57:31 +0100 |
commit | d758441fe0c4da6bc3486d0643436ad7ac290a56 (patch) | |
tree | 8d8fe289a4612c2dd5b8043028cf5a813502b0f6 /lib/templates/data.go | |
parent | ae675b491d2b55a06588e8ab4ce8205aaae796c8 (diff) | |
download | aerc-d758441fe0c4da6bc3486d0643436ad7ac290a56.tar.gz |
templates: add more fields and functions
Add functions and fields in preparation for more than only message
templates. The idea is to reuse the same symbols for the message list
format and other parts of the UI.
Update the man page accordingly.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
Diffstat (limited to 'lib/templates/data.go')
-rw-r--r-- | lib/templates/data.go | 321 |
1 files changed, 304 insertions, 17 deletions
diff --git a/lib/templates/data.go b/lib/templates/data.go index 8637aa7f..dab698d5 100644 --- a/lib/templates/data.go +++ b/lib/templates/data.go @@ -1,59 +1,289 @@ package templates import ( + "fmt" + "strings" "time" "git.sr.ht/~rjarry/aerc/models" + sortthread "github.com/emersion/go-imap-sortthread" "github.com/emersion/go-message/mail" ) type TemplateData struct { - msg *mail.Header - // Only available when replying with a quote + // only available when composing/replying/forwarding + headers *mail.Header + // only available when replying with a quote parent *models.OriginalMail + // only available for the message list + info *models.MessageInfo + marked bool + msgNum int + + // account config + myAddresses map[string]bool + account string + folder string // selected folder name + + // ui config + timeFmt string + thisDayTimeFmt string + thisWeekTimeFmt string + thisYearTimeFmt string + iconAttachment string } func NewTemplateData( - msg *mail.Header, parent *models.OriginalMail, + from *mail.Address, + aliases []*mail.Address, + account string, + folder string, + timeFmt string, + thisDayTimeFmt string, + thisWeekTimeFmt string, + thisYearTimeFmt string, + iconAttachment string, ) *TemplateData { + myAddresses := map[string]bool{from.Address: true} + for _, addr := range aliases { + myAddresses[addr.Address] = true + } return &TemplateData{ - msg: msg, - parent: parent, + myAddresses: myAddresses, + account: account, + folder: folder, + timeFmt: timeFmt, + thisDayTimeFmt: thisDayTimeFmt, + thisWeekTimeFmt: thisWeekTimeFmt, + thisYearTimeFmt: thisYearTimeFmt, + iconAttachment: iconAttachment, } } +// only used for compose/reply/forward +func (d *TemplateData) SetHeaders(h *mail.Header, o *models.OriginalMail) { + d.headers = h + d.parent = o +} + +// only used for message list templates +func (d *TemplateData) SetInfo(info *models.MessageInfo, num int, marked bool) { + d.info = info + d.msgNum = num + d.marked = marked +} + +func (d *TemplateData) Account() string { + return d.account +} + +func (d *TemplateData) Folder() string { + return d.folder +} + func (d *TemplateData) To() []*mail.Address { - to, _ := d.msg.AddressList("to") + var to []*mail.Address + switch { + case d.info != nil && d.info.Envelope != nil: + to = d.info.Envelope.To + case d.headers != nil: + to, _ = d.headers.AddressList("to") + } return to } func (d *TemplateData) Cc() []*mail.Address { - to, _ := d.msg.AddressList("cc") - return to + var cc []*mail.Address + switch { + case d.info != nil && d.info.Envelope != nil: + cc = d.info.Envelope.Cc + case d.headers != nil: + cc, _ = d.headers.AddressList("cc") + } + return cc } func (d *TemplateData) Bcc() []*mail.Address { - to, _ := d.msg.AddressList("bcc") - return to + var bcc []*mail.Address + switch { + case d.info != nil && d.info.Envelope != nil: + bcc = d.info.Envelope.Bcc + case d.headers != nil: + bcc, _ = d.headers.AddressList("bcc") + } + return bcc } func (d *TemplateData) From() []*mail.Address { - to, _ := d.msg.AddressList("from") - return to + var from []*mail.Address + switch { + case d.info != nil && d.info.Envelope != nil: + from = d.info.Envelope.From + case d.headers != nil: + from, _ = d.headers.AddressList("from") + } + return from +} + +func (d *TemplateData) Peer() []*mail.Address { + var from, to []*mail.Address + switch { + case d.info != nil && d.info.Envelope != nil: + from = d.info.Envelope.From + to = d.info.Envelope.To + case d.headers != nil: + from, _ = d.headers.AddressList("from") + to, _ = d.headers.AddressList("to") + } + for _, addr := range from { + if d.myAddresses[addr.Address] { + return to + } + } + return from +} + +func (d *TemplateData) ReplyTo() []*mail.Address { + var replyTo []*mail.Address + switch { + case d.info != nil && d.info.Envelope != nil: + replyTo = d.info.Envelope.ReplyTo + case d.headers != nil: + replyTo, _ = d.headers.AddressList("reply-to") + } + return replyTo } func (d *TemplateData) Date() time.Time { - return time.Now() + var date time.Time + switch { + case d.info != nil && d.info.Envelope != nil: + date = d.info.Envelope.Date + case d.info != nil: + date = d.info.InternalDate + default: + date = time.Now() + } + return date } -func (d *TemplateData) Subject() string { - subject, err := d.msg.Text("subject") +func (d *TemplateData) DateAutoFormat(date time.Time) string { + if date.IsZero() { + return "" + } + year := date.Year() + day := date.YearDay() + now := time.Now() + thisYear := now.Year() + thisDay := now.YearDay() + fmt := d.timeFmt + if year == thisYear { + switch { + case day == thisDay && d.thisDayTimeFmt != "": + fmt = d.thisDayTimeFmt + case day > thisDay-7 && d.thisWeekTimeFmt != "": + fmt = d.thisDayTimeFmt + case d.thisYearTimeFmt != "": + fmt = d.thisYearTimeFmt + } + } + return date.Format(fmt) +} + +func (d *TemplateData) Header(name string) string { + var h *mail.Header + switch { + case d.headers != nil: + h = d.headers + case d.info != nil && d.info.RFC822Headers != nil: + h = d.info.RFC822Headers + default: + return "" + } + text, err := h.Text(name) if err != nil { - subject = d.msg.Get("subject") + text = h.Get(name) + } + return text +} + +func (d *TemplateData) Subject() string { + var subject string + switch { + case d.info != nil && d.info.Envelope != nil: + subject = d.info.Envelope.Subject + case d.headers != nil: + subject = d.Header("subject") } return subject } +func (d *TemplateData) SubjectBase() string { + base, _ := sortthread.GetBaseSubject(d.Subject()) + return base +} + +func (d *TemplateData) Number() string { + return fmt.Sprintf("%d", d.msgNum) +} + +func (d *TemplateData) Labels() []string { + if d.info == nil { + return nil + } + return d.info.Labels +} + +func (d *TemplateData) Flags() []string { + var flags []string + if d.info == nil { + return flags + } + + switch { + case d.info.Flags.Has(models.SeenFlag | models.AnsweredFlag): + flags = append(flags, "r") // message has been replied to + case d.info.Flags.Has(models.SeenFlag): + break + case d.info.Flags.Has(models.RecentFlag): + flags = append(flags, "N") // message is new + default: + flags = append(flags, "O") // message is old + } + if d.info.Flags.Has(models.DeletedFlag) { + flags = append(flags, "D") + } + if d.info.BodyStructure != nil { + for _, bS := range d.info.BodyStructure.Parts { + if strings.ToLower(bS.Disposition) == "attachment" { + flags = append(flags, d.iconAttachment) + break + } + } + } + if d.info.Flags.Has(models.FlaggedFlag) { + flags = append(flags, "!") + } + if d.marked { + flags = append(flags, "*") + } + return flags +} + +func (d *TemplateData) MessageId() string { + if d.info == nil || d.info.Envelope == nil { + return "" + } + return d.info.Envelope.MessageId +} + +func (d *TemplateData) Size() uint32 { + if d.info == nil || d.info.Envelope == nil { + return 0 + } + return d.info.Size +} + func (d *TemplateData) OriginalText() string { if d.parent == nil { return "" @@ -83,6 +313,17 @@ func (d *TemplateData) OriginalMIMEType() string { return d.parent.MIMEType } +func (d *TemplateData) OriginalHeader(name string) string { + if d.parent == nil || d.parent.RFC822Headers == nil { + return "" + } + text, err := d.parent.RFC822Headers.Text(name) + if err != nil { + text = d.parent.RFC822Headers.Get(name) + } + return text +} + // DummyData provides dummy data to test template validity func DummyData() *TemplateData { from := &mail.Address{ @@ -108,5 +349,51 @@ func DummyData() *TemplateData { MIMEType: "text/plain", RFC822Headers: oh, } - return NewTemplateData(h, &original) + data := NewTemplateData( + to, + nil, + "account", + "folder", + "2006 Jan 02, 15:04 GMT-0700", + "15:04", + "Monday 15:04", + "Jan 02", + "a", + ) + data.SetHeaders(h, &original) + + info := &models.MessageInfo{ + BodyStructure: &models.BodyStructure{ + MIMEType: "text", + MIMESubType: "plain", + Params: make(map[string]string), + Description: "", + Encoding: "", + Parts: []*models.BodyStructure{}, + Disposition: "", + DispositionParams: make(map[string]string), + }, + Envelope: &models.Envelope{ + Date: time.Date(1981, 6, 23, 16, 52, 0, 0, time.UTC), + Subject: "[PATCH aerc 2/3] foo: baz bar buz", + From: []*mail.Address{from}, + ReplyTo: []*mail.Address{}, + To: []*mail.Address{to}, + Cc: []*mail.Address{}, + Bcc: []*mail.Address{}, + MessageId: "", + InReplyTo: "", + }, + Flags: models.FlaggedFlag, + Labels: []string{"inbox", "patch"}, + InternalDate: time.Now(), + RFC822Headers: nil, + Refs: []string{}, + Size: 65512, + Uid: 12345, + Error: nil, + } + data.SetInfo(info, 42, true) + + return data } |