~sircmpwn/aerc

0abafa60e159f87595148c0d0fc4f5f46be2d400 — Drew DeVault 2 years ago 95875b1
Make message viewer real, part two
4 files changed, 38 insertions(+), 23 deletions(-)

M lib/msgstore.go
M widgets/account.go
M widgets/msgviewer.go
M worker/imap/fetch.go
M lib/msgstore.go => lib/msgstore.go +1 -1
@@ 157,7 157,7 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
			}
		}
		update = true
	case *types.MessageBody:
	case *types.FullMessage:
		if _, ok := store.pendingBodies[msg.Uid]; ok {
			delete(store.pendingBodies, msg.Uid)
			if cbs, ok := store.bodyCallbacks[msg.Uid]; ok {

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

M widgets/msgviewer.go => widgets/msgviewer.go +22 -10
@@ 16,10 16,11 @@ import (
)

type MessageViewer struct {
	mail io.Reader
	pipe io.Writer
	grid *ui.Grid
	term *Terminal
	cmd    *exec.Cmd
	source io.Reader
	sink   io.WriteCloser
	grid   *ui.Grid
	term   *Terminal
}

func formatAddresses(addrs []*imap.Address) string {


@@ 92,22 93,33 @@ func NewMessageViewer(store *lib.MessageStore,
	grid.AddChild(body).At(1, 0)

	viewer := &MessageViewer{
		pipe: pipe,
		cmd:  cmd,
		sink: pipe,
		grid: grid,
		term: term,
	}

	store.FetchBodyPart(msg.Uid, 0, func(reader io.Reader) {
		viewer.mail = reader
		go func() {
			io.Copy(pipe, reader)
			pipe.Close()
		}()
		viewer.source = reader
		viewer.attemptCopy()
	})

	term.OnStart = func() {
		viewer.attemptCopy()
	}

	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) {
	mv.grid.Draw(ctx)
}

M worker/imap/fetch.go => worker/imap/fetch.go +14 -11
@@ 18,7 18,7 @@ func (imapw *IMAPWorker) handleFetchMessageHeaders(
		imap.FetchUid,
	}

	imapw.handleFetchMessages(msg, &msg.Uids, items)
	imapw.handleFetchMessages(msg, &msg.Uids, items, nil)
}

func (imapw *IMAPWorker) handleFetchMessageBodyPart(


@@ 26,11 26,11 @@ func (imapw *IMAPWorker) handleFetchMessageBodyPart(

	imapw.worker.Logger.Printf("Fetching message part")
	section := &imap.BodySectionName{}
	section.Path = []int{msg.Part}
	section.Path = []int{msg.Part + 1}
	items := []imap.FetchItem{section.FetchItem()}
	uids := imap.SeqSet{}
	uids.AddNum(msg.Uid)
	imapw.handleFetchMessages(msg, &uids, items)
	imapw.handleFetchMessages(msg, &uids, items, section)
}

func (imapw *IMAPWorker) handleFetchFullMessages(


@@ 39,11 39,12 @@ func (imapw *IMAPWorker) handleFetchFullMessages(
	imapw.worker.Logger.Printf("Fetching full messages")
	section := &imap.BodySectionName{}
	items := []imap.FetchItem{section.FetchItem()}
	imapw.handleFetchMessages(msg, &msg.Uids, items)
	imapw.handleFetchMessages(msg, &msg.Uids, items, section)
}

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() {
		messages := make(chan *imap.Message)


@@ 52,12 53,12 @@ func (imapw *IMAPWorker) handleFetchMessages(
			done <- imapw.client.UidFetch(uids, items, messages)
		}()
		go func() {
			section := &imap.BodySectionName{}
			for _msg := range messages {
				imapw.seqMap[_msg.SeqNum-1] = _msg.Uid
				switch msg.(type) {
				case *types.FetchMessageHeaders:
					imapw.worker.PostMessage(&types.MessageInfo{
						Message:       types.RespondTo(msg),
						BodyStructure: _msg.BodyStructure,
						Envelope:      _msg.Envelope,
						Flags:         _msg.Flags,


@@ 66,15 67,17 @@ func (imapw *IMAPWorker) handleFetchMessages(
					}, nil)
				case *types.FetchFullMessages:
					reader := _msg.GetBody(section)
					imapw.worker.PostMessage(&types.MessageBody{
						Reader: reader,
						Uid:    _msg.Uid,
					imapw.worker.PostMessage(&types.FullMessage{
						Message: types.RespondTo(msg),
						Reader:  reader,
						Uid:     _msg.Uid,
					}, nil)
				case *types.FetchMessageBodyPart:
					reader := _msg.GetBody(section)
					imapw.worker.PostMessage(&types.MessageBodyPart{
						Reader: reader,
						Uid:    _msg.Uid,
						Message: types.RespondTo(msg),
						Reader:  reader,
						Uid:     _msg.Uid,
					}, nil)
				}
			}