Make message viewer real, part two

This commit is contained in:
Drew DeVault 2019-03-31 12:35:51 -04:00
parent 95875b13f8
commit 0abafa60e1
4 changed files with 38 additions and 23 deletions

View file

@ -157,7 +157,7 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
} }
} }
update = true update = true
case *types.MessageBody: case *types.FullMessage:
if _, ok := store.pendingBodies[msg.Uid]; ok { if _, ok := store.pendingBodies[msg.Uid]; ok {
delete(store.pendingBodies, msg.Uid) delete(store.pendingBodies, msg.Uid)
if cbs, ok := store.bodyCallbacks[msg.Uid]; ok { if cbs, ok := store.bodyCallbacks[msg.Uid]; ok {

View file

@ -173,7 +173,7 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
case *types.DirectoryContents: case *types.DirectoryContents:
store := acct.msgStores[acct.dirlist.selected] store := acct.msgStores[acct.dirlist.selected]
store.Update(msg) store.Update(msg)
case *types.MessageBody: case *types.FullMessage:
store := acct.msgStores[acct.dirlist.selected] store := acct.msgStores[acct.dirlist.selected]
store.Update(msg) store.Update(msg)
case *types.MessageInfo: case *types.MessageInfo:

View file

@ -16,10 +16,11 @@ import (
) )
type MessageViewer struct { type MessageViewer struct {
mail io.Reader cmd *exec.Cmd
pipe io.Writer source io.Reader
grid *ui.Grid sink io.WriteCloser
term *Terminal grid *ui.Grid
term *Terminal
} }
func formatAddresses(addrs []*imap.Address) string { func formatAddresses(addrs []*imap.Address) string {
@ -92,22 +93,33 @@ func NewMessageViewer(store *lib.MessageStore,
grid.AddChild(body).At(1, 0) grid.AddChild(body).At(1, 0)
viewer := &MessageViewer{ viewer := &MessageViewer{
pipe: pipe, cmd: cmd,
sink: pipe,
grid: grid, grid: grid,
term: term, term: term,
} }
store.FetchBodyPart(msg.Uid, 0, func(reader io.Reader) { store.FetchBodyPart(msg.Uid, 0, func(reader io.Reader) {
viewer.mail = reader viewer.source = reader
go func() { viewer.attemptCopy()
io.Copy(pipe, reader)
pipe.Close()
}()
}) })
term.OnStart = func() {
viewer.attemptCopy()
}
return viewer return viewer
} }
func (mv *MessageViewer) attemptCopy() {
if mv.source != nil && mv.cmd.Process != nil {
go func() {
io.Copy(mv.sink, mv.source)
mv.sink.Close()
}()
}
}
func (mv *MessageViewer) Draw(ctx *ui.Context) { func (mv *MessageViewer) Draw(ctx *ui.Context) {
mv.grid.Draw(ctx) mv.grid.Draw(ctx)
} }

View file

@ -18,7 +18,7 @@ func (imapw *IMAPWorker) handleFetchMessageHeaders(
imap.FetchUid, imap.FetchUid,
} }
imapw.handleFetchMessages(msg, &msg.Uids, items) imapw.handleFetchMessages(msg, &msg.Uids, items, nil)
} }
func (imapw *IMAPWorker) handleFetchMessageBodyPart( func (imapw *IMAPWorker) handleFetchMessageBodyPart(
@ -26,11 +26,11 @@ func (imapw *IMAPWorker) handleFetchMessageBodyPart(
imapw.worker.Logger.Printf("Fetching message part") imapw.worker.Logger.Printf("Fetching message part")
section := &imap.BodySectionName{} section := &imap.BodySectionName{}
section.Path = []int{msg.Part} section.Path = []int{msg.Part + 1}
items := []imap.FetchItem{section.FetchItem()} items := []imap.FetchItem{section.FetchItem()}
uids := imap.SeqSet{} uids := imap.SeqSet{}
uids.AddNum(msg.Uid) uids.AddNum(msg.Uid)
imapw.handleFetchMessages(msg, &uids, items) imapw.handleFetchMessages(msg, &uids, items, section)
} }
func (imapw *IMAPWorker) handleFetchFullMessages( func (imapw *IMAPWorker) handleFetchFullMessages(
@ -39,11 +39,12 @@ func (imapw *IMAPWorker) handleFetchFullMessages(
imapw.worker.Logger.Printf("Fetching full messages") imapw.worker.Logger.Printf("Fetching full messages")
section := &imap.BodySectionName{} section := &imap.BodySectionName{}
items := []imap.FetchItem{section.FetchItem()} items := []imap.FetchItem{section.FetchItem()}
imapw.handleFetchMessages(msg, &msg.Uids, items) imapw.handleFetchMessages(msg, &msg.Uids, items, section)
} }
func (imapw *IMAPWorker) handleFetchMessages( func (imapw *IMAPWorker) handleFetchMessages(
msg types.WorkerMessage, uids *imap.SeqSet, items []imap.FetchItem) { msg types.WorkerMessage, uids *imap.SeqSet, items []imap.FetchItem,
section *imap.BodySectionName) {
go func() { go func() {
messages := make(chan *imap.Message) messages := make(chan *imap.Message)
@ -52,12 +53,12 @@ func (imapw *IMAPWorker) handleFetchMessages(
done <- imapw.client.UidFetch(uids, items, messages) done <- imapw.client.UidFetch(uids, items, messages)
}() }()
go func() { go func() {
section := &imap.BodySectionName{}
for _msg := range messages { for _msg := range messages {
imapw.seqMap[_msg.SeqNum-1] = _msg.Uid imapw.seqMap[_msg.SeqNum-1] = _msg.Uid
switch msg.(type) { switch msg.(type) {
case *types.FetchMessageHeaders: case *types.FetchMessageHeaders:
imapw.worker.PostMessage(&types.MessageInfo{ imapw.worker.PostMessage(&types.MessageInfo{
Message: types.RespondTo(msg),
BodyStructure: _msg.BodyStructure, BodyStructure: _msg.BodyStructure,
Envelope: _msg.Envelope, Envelope: _msg.Envelope,
Flags: _msg.Flags, Flags: _msg.Flags,
@ -66,15 +67,17 @@ func (imapw *IMAPWorker) handleFetchMessages(
}, nil) }, nil)
case *types.FetchFullMessages: case *types.FetchFullMessages:
reader := _msg.GetBody(section) reader := _msg.GetBody(section)
imapw.worker.PostMessage(&types.MessageBody{ imapw.worker.PostMessage(&types.FullMessage{
Reader: reader, Message: types.RespondTo(msg),
Uid: _msg.Uid, Reader: reader,
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{
Reader: reader, Message: types.RespondTo(msg),
Uid: _msg.Uid, Reader: reader,
Uid: _msg.Uid,
}, nil) }, nil)
} }
} }