Factor UI models out of the worker message package
Before, the information needed to display different parts of the UI was tightly coupled to the specific messages being sent back and forth to the backend worker. Separating out a models package allows us to be more specific about exactly what a backend is able to and required to provide for the UI.
This commit is contained in:
parent
c79577d376
commit
cce7cb4808
12 changed files with 145 additions and 85 deletions
|
@ -9,11 +9,11 @@ import (
|
||||||
"github.com/emersion/go-imap"
|
"github.com/emersion/go-imap"
|
||||||
|
|
||||||
"git.sr.ht/~sircmpwn/aerc/config"
|
"git.sr.ht/~sircmpwn/aerc/config"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseIndexFormat(conf *config.AercConfig, number int,
|
func ParseIndexFormat(conf *config.AercConfig, number int,
|
||||||
msg *types.MessageInfo) (string, []interface{}, error) {
|
msg *models.MessageInfo) (string, []interface{}, error) {
|
||||||
|
|
||||||
format := conf.Ui.IndexFormat
|
format := conf.Ui.IndexFormat
|
||||||
retval := make([]byte, 0, len(format))
|
retval := make([]byte, 0, len(format))
|
||||||
|
|
|
@ -6,14 +6,15 @@ import (
|
||||||
|
|
||||||
"github.com/emersion/go-imap"
|
"github.com/emersion/go-imap"
|
||||||
|
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Accesses to fields must be guarded by MessageStore.Lock/Unlock
|
// Accesses to fields must be guarded by MessageStore.Lock/Unlock
|
||||||
type MessageStore struct {
|
type MessageStore struct {
|
||||||
Deleted map[uint32]interface{}
|
Deleted map[uint32]interface{}
|
||||||
DirInfo types.DirectoryInfo
|
DirInfo models.DirectoryInfo
|
||||||
Messages map[uint32]*types.MessageInfo
|
Messages map[uint32]*models.MessageInfo
|
||||||
// Ordered list of known UIDs
|
// Ordered list of known UIDs
|
||||||
Uids []uint32
|
Uids []uint32
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ type MessageStore struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMessageStore(worker *types.Worker,
|
func NewMessageStore(worker *types.Worker,
|
||||||
dirInfo *types.DirectoryInfo) *MessageStore {
|
dirInfo *models.DirectoryInfo) *MessageStore {
|
||||||
|
|
||||||
return &MessageStore{
|
return &MessageStore{
|
||||||
Deleted: make(map[uint32]interface{}),
|
Deleted: make(map[uint32]interface{}),
|
||||||
|
@ -106,11 +107,11 @@ func (store *MessageStore) FetchBodyPart(
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cb(msg.Reader)
|
cb(msg.Part.Reader)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func merge(to *types.MessageInfo, from *types.MessageInfo) {
|
func merge(to *models.MessageInfo, from *models.MessageInfo) {
|
||||||
if from.BodyStructure != nil {
|
if from.BodyStructure != nil {
|
||||||
to.BodyStructure = from.BodyStructure
|
to.BodyStructure = from.BodyStructure
|
||||||
}
|
}
|
||||||
|
@ -131,11 +132,11 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
|
||||||
update := false
|
update := false
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case *types.DirectoryInfo:
|
case *types.DirectoryInfo:
|
||||||
store.DirInfo = *msg
|
store.DirInfo = *msg.Info
|
||||||
store.worker.PostAction(&types.FetchDirectoryContents{}, nil)
|
store.worker.PostAction(&types.FetchDirectoryContents{}, nil)
|
||||||
update = true
|
update = true
|
||||||
case *types.DirectoryContents:
|
case *types.DirectoryContents:
|
||||||
newMap := make(map[uint32]*types.MessageInfo)
|
newMap := make(map[uint32]*models.MessageInfo)
|
||||||
for _, uid := range msg.Uids {
|
for _, uid := range msg.Uids {
|
||||||
if msg, ok := store.Messages[uid]; ok {
|
if msg, ok := store.Messages[uid]; ok {
|
||||||
newMap[uid] = msg
|
newMap[uid] = msg
|
||||||
|
@ -147,14 +148,14 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
|
||||||
store.Uids = msg.Uids
|
store.Uids = msg.Uids
|
||||||
update = true
|
update = true
|
||||||
case *types.MessageInfo:
|
case *types.MessageInfo:
|
||||||
if existing, ok := store.Messages[msg.Uid]; ok && existing != nil {
|
if existing, ok := store.Messages[msg.Info.Uid]; ok && existing != nil {
|
||||||
merge(existing, msg)
|
merge(existing, msg.Info)
|
||||||
} else {
|
} else {
|
||||||
store.Messages[msg.Uid] = msg
|
store.Messages[msg.Info.Uid] = msg.Info
|
||||||
}
|
}
|
||||||
if _, ok := store.pendingHeaders[msg.Uid]; msg.Envelope != nil && ok {
|
if _, ok := store.pendingHeaders[msg.Info.Uid]; msg.Info.Envelope != nil && ok {
|
||||||
delete(store.pendingHeaders, msg.Uid)
|
delete(store.pendingHeaders, msg.Info.Uid)
|
||||||
if cbs, ok := store.headerCallbacks[msg.Uid]; ok {
|
if cbs, ok := store.headerCallbacks[msg.Info.Uid]; ok {
|
||||||
for _, cb := range cbs {
|
for _, cb := range cbs {
|
||||||
cb(msg)
|
cb(msg)
|
||||||
}
|
}
|
||||||
|
@ -162,11 +163,11 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
|
||||||
}
|
}
|
||||||
update = true
|
update = true
|
||||||
case *types.FullMessage:
|
case *types.FullMessage:
|
||||||
if _, ok := store.pendingBodies[msg.Uid]; ok {
|
if _, ok := store.pendingBodies[msg.Content.Uid]; ok {
|
||||||
delete(store.pendingBodies, msg.Uid)
|
delete(store.pendingBodies, msg.Content.Uid)
|
||||||
if cbs, ok := store.bodyCallbacks[msg.Uid]; ok {
|
if cbs, ok := store.bodyCallbacks[msg.Content.Uid]; ok {
|
||||||
for _, cb := range cbs {
|
for _, cb := range cbs {
|
||||||
cb(msg.Reader)
|
cb(msg.Content.Reader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,7 +284,7 @@ func (store *MessageStore) Read(uids []uint32, read bool,
|
||||||
}, cb)
|
}, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *MessageStore) Selected() *types.MessageInfo {
|
func (store *MessageStore) Selected() *models.MessageInfo {
|
||||||
return store.Messages[store.Uids[len(store.Uids)-store.selected-1]]
|
return store.Messages[store.Uids[len(store.Uids)-store.selected-1]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
52
models/models.go
Normal file
52
models/models.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/emersion/go-imap"
|
||||||
|
"github.com/emersion/go-message/mail"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Directory struct {
|
||||||
|
Name string
|
||||||
|
Attributes []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type DirectoryInfo struct {
|
||||||
|
Name string
|
||||||
|
Flags []string
|
||||||
|
ReadOnly bool
|
||||||
|
|
||||||
|
// The total number of messages in this mailbox.
|
||||||
|
Exists int
|
||||||
|
|
||||||
|
// The number of messages not seen since the last time the mailbox was opened.
|
||||||
|
Recent int
|
||||||
|
|
||||||
|
// The number of unread messages
|
||||||
|
Unseen int
|
||||||
|
}
|
||||||
|
|
||||||
|
// A MessageInfo holds information about the structure of a message
|
||||||
|
type MessageInfo struct {
|
||||||
|
BodyStructure *imap.BodyStructure
|
||||||
|
Envelope *imap.Envelope
|
||||||
|
Flags []string
|
||||||
|
InternalDate time.Time
|
||||||
|
RFC822Headers *mail.Header
|
||||||
|
Size uint32
|
||||||
|
Uid uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// A MessageBodyPart can be displayed in the message viewer
|
||||||
|
type MessageBodyPart struct {
|
||||||
|
Reader io.Reader
|
||||||
|
Uid uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// A FullMessage is the entire message
|
||||||
|
type FullMessage struct {
|
||||||
|
Reader io.Reader
|
||||||
|
Uid uint32
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"git.sr.ht/~sircmpwn/aerc/config"
|
"git.sr.ht/~sircmpwn/aerc/config"
|
||||||
"git.sr.ht/~sircmpwn/aerc/lib"
|
"git.sr.ht/~sircmpwn/aerc/lib"
|
||||||
"git.sr.ht/~sircmpwn/aerc/lib/ui"
|
"git.sr.ht/~sircmpwn/aerc/lib/ui"
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker"
|
"git.sr.ht/~sircmpwn/aerc/worker"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
||||||
)
|
)
|
||||||
|
@ -169,7 +170,7 @@ func (acct *AccountView) SelectedAccount() *AccountView {
|
||||||
return acct
|
return acct
|
||||||
}
|
}
|
||||||
|
|
||||||
func (acct *AccountView) SelectedMessage() *types.MessageInfo {
|
func (acct *AccountView) SelectedMessage() *models.MessageInfo {
|
||||||
return acct.msglist.Selected()
|
return acct.msglist.Selected()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,11 +196,11 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
|
||||||
acct.dirlist.UpdateList(nil)
|
acct.dirlist.UpdateList(nil)
|
||||||
}
|
}
|
||||||
case *types.DirectoryInfo:
|
case *types.DirectoryInfo:
|
||||||
if store, ok := acct.msgStores[msg.Name]; ok {
|
if store, ok := acct.msgStores[msg.Info.Name]; ok {
|
||||||
store.Update(msg)
|
store.Update(msg)
|
||||||
} else {
|
} else {
|
||||||
store = lib.NewMessageStore(acct.worker, msg)
|
store = lib.NewMessageStore(acct.worker, msg.Info)
|
||||||
acct.msgStores[msg.Name] = store
|
acct.msgStores[msg.Info.Name] = store
|
||||||
store.OnUpdate(func(_ *lib.MessageStore) {
|
store.OnUpdate(func(_ *lib.MessageStore) {
|
||||||
store.OnUpdate(nil)
|
store.OnUpdate(nil)
|
||||||
acct.msglist.SetStore(store)
|
acct.msglist.SetStore(store)
|
||||||
|
|
|
@ -55,7 +55,7 @@ func (dirlist *DirectoryList) UpdateList(done func(dirs []string)) {
|
||||||
|
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case *types.Directory:
|
case *types.Directory:
|
||||||
dirs = append(dirs, msg.Name)
|
dirs = append(dirs, msg.Dir.Name)
|
||||||
case *types.Done:
|
case *types.Done:
|
||||||
sort.Strings(dirs)
|
sort.Strings(dirs)
|
||||||
dirlist.store.Update(dirs)
|
dirlist.store.Update(dirs)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"git.sr.ht/~sircmpwn/aerc/config"
|
"git.sr.ht/~sircmpwn/aerc/config"
|
||||||
"git.sr.ht/~sircmpwn/aerc/lib"
|
"git.sr.ht/~sircmpwn/aerc/lib"
|
||||||
"git.sr.ht/~sircmpwn/aerc/lib/ui"
|
"git.sr.ht/~sircmpwn/aerc/lib/ui"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MessageList struct {
|
type MessageList struct {
|
||||||
|
@ -176,7 +176,7 @@ func (ml *MessageList) Empty() bool {
|
||||||
return store == nil || len(store.Uids) == 0
|
return store == nil || len(store.Uids) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ml *MessageList) Selected() *types.MessageInfo {
|
func (ml *MessageList) Selected() *models.MessageInfo {
|
||||||
store := ml.Store()
|
store := ml.Store()
|
||||||
return store.Messages[store.Uids[len(store.Uids)-ml.store.SelectedIndex()-1]]
|
return store.Messages[store.Uids[len(store.Uids)-ml.store.SelectedIndex()-1]]
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"git.sr.ht/~sircmpwn/aerc/config"
|
"git.sr.ht/~sircmpwn/aerc/config"
|
||||||
"git.sr.ht/~sircmpwn/aerc/lib"
|
"git.sr.ht/~sircmpwn/aerc/lib"
|
||||||
"git.sr.ht/~sircmpwn/aerc/lib/ui"
|
"git.sr.ht/~sircmpwn/aerc/lib/ui"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ansi = regexp.MustCompile("^\x1B\\[[0-?]*[ -/]*[@-~]")
|
var ansi = regexp.MustCompile("^\x1B\\[[0-?]*[ -/]*[@-~]")
|
||||||
|
@ -31,7 +31,7 @@ type MessageViewer struct {
|
||||||
conf *config.AercConfig
|
conf *config.AercConfig
|
||||||
err error
|
err error
|
||||||
grid *ui.Grid
|
grid *ui.Grid
|
||||||
msg *types.MessageInfo
|
msg *models.MessageInfo
|
||||||
switcher *PartSwitcher
|
switcher *PartSwitcher
|
||||||
store *lib.MessageStore
|
store *lib.MessageStore
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ type PartSwitcher struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMessageViewer(acct *AccountView, conf *config.AercConfig,
|
func NewMessageViewer(acct *AccountView, conf *config.AercConfig,
|
||||||
store *lib.MessageStore, msg *types.MessageInfo) *MessageViewer {
|
store *lib.MessageStore, msg *models.MessageInfo) *MessageViewer {
|
||||||
|
|
||||||
grid := ui.NewGrid().Rows([]ui.GridSpec{
|
grid := ui.NewGrid().Rows([]ui.GridSpec{
|
||||||
{ui.SIZE_EXACT, 4}, // TODO: Based on number of header rows
|
{ui.SIZE_EXACT, 4}, // TODO: Based on number of header rows
|
||||||
|
@ -112,7 +112,7 @@ handle_error:
|
||||||
}
|
}
|
||||||
|
|
||||||
func enumerateParts(conf *config.AercConfig, store *lib.MessageStore,
|
func enumerateParts(conf *config.AercConfig, store *lib.MessageStore,
|
||||||
msg *types.MessageInfo, body *imap.BodyStructure,
|
msg *models.MessageInfo, body *imap.BodyStructure,
|
||||||
showHeaders bool, index []int) ([]*PartViewer, error) {
|
showHeaders bool, index []int) ([]*PartViewer, error) {
|
||||||
|
|
||||||
var parts []*PartViewer
|
var parts []*PartViewer
|
||||||
|
@ -140,7 +140,7 @@ func enumerateParts(conf *config.AercConfig, store *lib.MessageStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSwitcher(switcher *PartSwitcher, conf *config.AercConfig,
|
func createSwitcher(switcher *PartSwitcher, conf *config.AercConfig,
|
||||||
store *lib.MessageStore, msg *types.MessageInfo, showHeaders bool) error {
|
store *lib.MessageStore, msg *models.MessageInfo, showHeaders bool) error {
|
||||||
var err error
|
var err error
|
||||||
switcher.showHeaders = showHeaders
|
switcher.showHeaders = showHeaders
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ func (mv *MessageViewer) SelectedAccount() *AccountView {
|
||||||
return mv.acct
|
return mv.acct
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mv *MessageViewer) SelectedMessage() *types.MessageInfo {
|
func (mv *MessageViewer) SelectedMessage() *models.MessageInfo {
|
||||||
return mv.msg
|
return mv.msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ type PartViewer struct {
|
||||||
fetched bool
|
fetched bool
|
||||||
filter *exec.Cmd
|
filter *exec.Cmd
|
||||||
index []int
|
index []int
|
||||||
msg *types.MessageInfo
|
msg *models.MessageInfo
|
||||||
pager *exec.Cmd
|
pager *exec.Cmd
|
||||||
pagerin io.WriteCloser
|
pagerin io.WriteCloser
|
||||||
part *imap.BodyStructure
|
part *imap.BodyStructure
|
||||||
|
@ -333,7 +333,7 @@ type PartViewer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPartViewer(conf *config.AercConfig,
|
func NewPartViewer(conf *config.AercConfig,
|
||||||
store *lib.MessageStore, msg *types.MessageInfo,
|
store *lib.MessageStore, msg *models.MessageInfo,
|
||||||
part *imap.BodyStructure, showHeaders bool,
|
part *imap.BodyStructure, showHeaders bool,
|
||||||
index []int) (*PartViewer, error) {
|
index []int) (*PartViewer, error) {
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
|
|
||||||
"git.sr.ht/~sircmpwn/aerc/lib"
|
"git.sr.ht/~sircmpwn/aerc/lib"
|
||||||
"git.sr.ht/~sircmpwn/aerc/lib/ui"
|
"git.sr.ht/~sircmpwn/aerc/lib/ui"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PartInfo struct {
|
type PartInfo struct {
|
||||||
|
@ -19,6 +19,6 @@ type ProvidesMessage interface {
|
||||||
ui.Drawable
|
ui.Drawable
|
||||||
Store() *lib.MessageStore
|
Store() *lib.MessageStore
|
||||||
SelectedAccount() *AccountView
|
SelectedAccount() *AccountView
|
||||||
SelectedMessage() *types.MessageInfo
|
SelectedMessage() *models.MessageInfo
|
||||||
SelectedMessagePart() *PartInfo
|
SelectedMessagePart() *PartInfo
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/emersion/go-message/mail"
|
"github.com/emersion/go-message/mail"
|
||||||
"github.com/emersion/go-message/textproto"
|
"github.com/emersion/go-message/textproto"
|
||||||
|
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -83,38 +84,48 @@ func (imapw *IMAPWorker) handleFetchMessages(
|
||||||
}
|
}
|
||||||
imapw.worker.PostMessage(&types.MessageInfo{
|
imapw.worker.PostMessage(&types.MessageInfo{
|
||||||
Message: types.RespondTo(msg),
|
Message: types.RespondTo(msg),
|
||||||
|
Info: &models.MessageInfo{
|
||||||
BodyStructure: _msg.BodyStructure,
|
BodyStructure: _msg.BodyStructure,
|
||||||
Envelope: _msg.Envelope,
|
Envelope: _msg.Envelope,
|
||||||
Flags: _msg.Flags,
|
Flags: _msg.Flags,
|
||||||
InternalDate: _msg.InternalDate,
|
InternalDate: _msg.InternalDate,
|
||||||
RFC822Headers: header,
|
RFC822Headers: header,
|
||||||
Uid: _msg.Uid,
|
Uid: _msg.Uid,
|
||||||
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
case *types.FetchFullMessages:
|
case *types.FetchFullMessages:
|
||||||
reader := _msg.GetBody(section)
|
reader := _msg.GetBody(section)
|
||||||
imapw.worker.PostMessage(&types.FullMessage{
|
imapw.worker.PostMessage(&types.FullMessage{
|
||||||
Message: types.RespondTo(msg),
|
Message: types.RespondTo(msg),
|
||||||
|
Content: &models.FullMessage{
|
||||||
Reader: reader,
|
Reader: reader,
|
||||||
Uid: _msg.Uid,
|
Uid: _msg.Uid,
|
||||||
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
// Update flags (to mark message as read)
|
// Update flags (to mark message as read)
|
||||||
imapw.worker.PostMessage(&types.MessageInfo{
|
imapw.worker.PostMessage(&types.MessageInfo{
|
||||||
Message: types.RespondTo(msg),
|
Message: types.RespondTo(msg),
|
||||||
|
Info: &models.MessageInfo{
|
||||||
Flags: _msg.Flags,
|
Flags: _msg.Flags,
|
||||||
Uid: _msg.Uid,
|
Uid: _msg.Uid,
|
||||||
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
case *types.FetchMessageBodyPart:
|
case *types.FetchMessageBodyPart:
|
||||||
reader := _msg.GetBody(section)
|
reader := _msg.GetBody(section)
|
||||||
imapw.worker.PostMessage(&types.MessageBodyPart{
|
imapw.worker.PostMessage(&types.MessageBodyPart{
|
||||||
Message: types.RespondTo(msg),
|
Message: types.RespondTo(msg),
|
||||||
|
Part: &models.MessageBodyPart{
|
||||||
Reader: reader,
|
Reader: reader,
|
||||||
Uid: _msg.Uid,
|
Uid: _msg.Uid,
|
||||||
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
// Update flags (to mark message as read)
|
// Update flags (to mark message as read)
|
||||||
imapw.worker.PostMessage(&types.MessageInfo{
|
imapw.worker.PostMessage(&types.MessageInfo{
|
||||||
Message: types.RespondTo(msg),
|
Message: types.RespondTo(msg),
|
||||||
|
Info: &models.MessageInfo{
|
||||||
Flags: _msg.Flags,
|
Flags: _msg.Flags,
|
||||||
Uid: _msg.Uid,
|
Uid: _msg.Uid,
|
||||||
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package imap
|
||||||
import (
|
import (
|
||||||
"github.com/emersion/go-imap"
|
"github.com/emersion/go-imap"
|
||||||
|
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,8 +20,10 @@ func (imapw *IMAPWorker) handleListDirectories(msg *types.ListDirectories) {
|
||||||
}
|
}
|
||||||
imapw.worker.PostMessage(&types.Directory{
|
imapw.worker.PostMessage(&types.Directory{
|
||||||
Message: types.RespondTo(msg),
|
Message: types.RespondTo(msg),
|
||||||
|
Dir: &models.Directory{
|
||||||
Name: mbox.Name,
|
Name: mbox.Name,
|
||||||
Attributes: mbox.Attributes,
|
Attributes: mbox.Attributes,
|
||||||
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
}
|
}
|
||||||
done <- nil
|
done <- nil
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
idle "github.com/emersion/go-imap-idle"
|
idle "github.com/emersion/go-imap-idle"
|
||||||
"github.com/emersion/go-imap/client"
|
"github.com/emersion/go-imap/client"
|
||||||
|
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -169,6 +170,7 @@ func (w *IMAPWorker) handleImapUpdate(update client.Update) {
|
||||||
w.selected = *status
|
w.selected = *status
|
||||||
}
|
}
|
||||||
w.worker.PostMessage(&types.DirectoryInfo{
|
w.worker.PostMessage(&types.DirectoryInfo{
|
||||||
|
Info: &models.DirectoryInfo{
|
||||||
Flags: status.Flags,
|
Flags: status.Flags,
|
||||||
Name: status.Name,
|
Name: status.Name,
|
||||||
ReadOnly: status.ReadOnly,
|
ReadOnly: status.ReadOnly,
|
||||||
|
@ -176,6 +178,7 @@ func (w *IMAPWorker) handleImapUpdate(update client.Update) {
|
||||||
Exists: int(status.Messages),
|
Exists: int(status.Messages),
|
||||||
Recent: int(status.Recent),
|
Recent: int(status.Recent),
|
||||||
Unseen: int(status.Unseen),
|
Unseen: int(status.Unseen),
|
||||||
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
case *client.MessageUpdate:
|
case *client.MessageUpdate:
|
||||||
msg := update.Message
|
msg := update.Message
|
||||||
|
@ -183,11 +186,13 @@ func (w *IMAPWorker) handleImapUpdate(update client.Update) {
|
||||||
msg.Uid = w.seqMap[msg.SeqNum-1]
|
msg.Uid = w.seqMap[msg.SeqNum-1]
|
||||||
}
|
}
|
||||||
w.worker.PostMessage(&types.MessageInfo{
|
w.worker.PostMessage(&types.MessageInfo{
|
||||||
|
Info: &models.MessageInfo{
|
||||||
BodyStructure: msg.BodyStructure,
|
BodyStructure: msg.BodyStructure,
|
||||||
Envelope: msg.Envelope,
|
Envelope: msg.Envelope,
|
||||||
Flags: msg.Flags,
|
Flags: msg.Flags,
|
||||||
InternalDate: msg.InternalDate,
|
InternalDate: msg.InternalDate,
|
||||||
Uid: msg.Uid,
|
Uid: msg.Uid,
|
||||||
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
case *client.ExpungeUpdate:
|
case *client.ExpungeUpdate:
|
||||||
i := update.SeqNum - 1
|
i := update.SeqNum - 1
|
||||||
|
|
|
@ -5,9 +5,9 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/emersion/go-imap"
|
"github.com/emersion/go-imap"
|
||||||
"github.com/emersion/go-message/mail"
|
|
||||||
|
|
||||||
"git.sr.ht/~sircmpwn/aerc/config"
|
"git.sr.ht/~sircmpwn/aerc/config"
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WorkerMessage interface {
|
type WorkerMessage interface {
|
||||||
|
@ -139,17 +139,12 @@ type AppendMessage struct {
|
||||||
|
|
||||||
type Directory struct {
|
type Directory struct {
|
||||||
Message
|
Message
|
||||||
Attributes []string
|
Dir *models.Directory
|
||||||
Name string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DirectoryInfo struct {
|
type DirectoryInfo struct {
|
||||||
Message
|
Message
|
||||||
Flags []string
|
Info *models.DirectoryInfo
|
||||||
Name string
|
|
||||||
ReadOnly bool
|
|
||||||
|
|
||||||
Exists, Recent, Unseen int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DirectoryContents struct {
|
type DirectoryContents struct {
|
||||||
|
@ -164,25 +159,17 @@ type SearchResults struct {
|
||||||
|
|
||||||
type MessageInfo struct {
|
type MessageInfo struct {
|
||||||
Message
|
Message
|
||||||
BodyStructure *imap.BodyStructure
|
Info *models.MessageInfo
|
||||||
Envelope *imap.Envelope
|
|
||||||
Flags []string
|
|
||||||
InternalDate time.Time
|
|
||||||
RFC822Headers *mail.Header
|
|
||||||
Size uint32
|
|
||||||
Uid uint32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type FullMessage struct {
|
type FullMessage struct {
|
||||||
Message
|
Message
|
||||||
Reader io.Reader
|
Content *models.FullMessage
|
||||||
Uid uint32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessageBodyPart struct {
|
type MessageBodyPart struct {
|
||||||
Message
|
Message
|
||||||
Reader io.Reader
|
Part *models.MessageBodyPart
|
||||||
Uid uint32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessagesDeleted struct {
|
type MessagesDeleted struct {
|
||||||
|
|
Loading…
Reference in a new issue