composer: restructure to implement account switching

Extract some functionality of the composer constructor into a
account-specific setup function that can be used to implement account
switching.

Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
Koni Marti 2022-08-15 21:58:42 +02:00 committed by Robin Jarry
parent b31bb1876b
commit ee4f2ea49d
2 changed files with 106 additions and 30 deletions

View file

@ -375,6 +375,21 @@ func (aerc *Aerc) SelectedAccount() *AccountView {
return aerc.account(aerc.SelectedTabContent()) return aerc.account(aerc.SelectedTabContent())
} }
func (aerc *Aerc) Account(name string) (*AccountView, error) {
if acct, ok := aerc.accounts[name]; ok {
return acct, nil
}
return nil, fmt.Errorf("account <%s> not found", name)
}
func (aerc *Aerc) AccountNames() []string {
results := make([]string, 0)
for name := range aerc.accounts {
results = append(results, name)
}
return results
}
func (aerc *Aerc) account(d ui.Drawable) *AccountView { func (aerc *Aerc) account(d ui.Drawable) *AccountView {
switch tab := d.(type) { switch tab := d.(type) {
case *AccountView: case *AccountView:

View file

@ -69,27 +69,6 @@ func NewComposer(aerc *Aerc, acct *AccountView, conf *config.AercConfig,
if h == nil { if h == nil {
h = new(mail.Header) h = new(mail.Header)
} }
if fl, err := h.AddressList("from"); err != nil || fl == nil {
fl, err = mail.ParseAddressList(acctConfig.From)
// realistically this blows up way before us during the config loading
if err != nil {
return nil, err
}
if fl != nil {
h.SetAddressList("from", fl)
}
}
templateData := templates.ParseTemplateData(h, orig)
cmd := acctConfig.AddressBookCmd
if cmd == "" {
cmd = conf.Compose.AddressBookCmd
}
cmpl := completer.New(cmd, func(err error) {
aerc.PushError(
fmt.Sprintf("could not complete header: %v", err))
logging.Errorf("could not complete header: %v", err)
})
email, err := os.CreateTemp("", "aerc-compose-*.eml") email, err := os.CreateTemp("", "aerc-compose-*.eml")
if err != nil { if err != nil {
@ -108,31 +87,113 @@ func NewComposer(aerc *Aerc, acct *AccountView, conf *config.AercConfig,
worker: worker, worker: worker,
// You have to backtab to get to "From", since you usually don't edit it // You have to backtab to get to "From", since you usually don't edit it
focused: 1, focused: 1,
completer: cmpl, completer: nil,
} }
templateData := templates.ParseTemplateData(h, orig)
if err := c.AddTemplate(template, templateData); err != nil { if err := c.AddTemplate(template, templateData); err != nil {
return nil, err return nil, err
} }
c.buildComposeHeader(aerc, cmpl)
c.AddSignature() c.AddSignature()
c.updateGrid() if err := c.setupFor(acct); err != nil {
err = c.updateCrypto() return nil, err
if err != nil {
logging.Warnf("failed to update crypto: %v", err)
} }
c.ShowTerminal() c.ShowTerminal()
return c, nil
}
func (c *Composer) SwitchAccount(newAcct *AccountView) error {
if c.acct == newAcct {
logging.Infof("same accounts: no switch")
return nil
}
// sync the header with the editors
for _, editor := range c.editors {
editor.storeValue()
}
// ensure that from header is updated, so remove it
c.header.Del("from")
// update entire composer with new the account
if err := c.setupFor(newAcct); err != nil {
return err
}
// sync the header with the editors
for _, editor := range c.editors {
editor.loadValue()
}
c.Invalidate()
c.aerc.Invalidate()
logging.Infof("account sucessfully switched")
return nil
}
func (c *Composer) setupFor(acct *AccountView) error {
// set new account and accountConfig
c.acct = acct
c.acctConfig = acct.AccountConfig()
c.worker = acct.Worker()
// Set from header if not already in header
if fl, err := c.header.AddressList("from"); err != nil || fl == nil {
fl, err = mail.ParseAddressList(c.acctConfig.From)
if err != nil {
return err
}
if fl != nil {
c.header.SetAddressList("from", fl)
}
}
// update completer
cmd := c.acctConfig.AddressBookCmd
if cmd == "" {
cmd = c.config.Compose.AddressBookCmd
}
cmpl := completer.New(cmd, func(err error) {
c.aerc.PushError(
fmt.Sprintf("could not complete header: %v", err))
logging.Errorf("could not complete header: %v", err)
})
c.completer = cmpl
// if editor already exists, we have to get it from the focusable slice
// because this will be rebuild during buildComposeHeader()
var focusEditor ui.MouseableDrawableInteractive
if c.editor != nil && len(c.focusable) > 0 {
focusEditor = c.focusable[len(c.focusable)-1]
}
// rebuild editors and focusable slice
c.buildComposeHeader(c.aerc, cmpl)
// restore the editor in the focusable list
if focusEditor != nil {
c.focusable = append(c.focusable, focusEditor)
}
// redraw the grid
c.updateGrid()
// update the crypto parts
c.crypto = nil
c.sign = false
if c.acctConfig.PgpAutoSign { if c.acctConfig.PgpAutoSign {
err = c.SetSign(true) err := c.SetSign(true)
logging.Warnf("failed to enable message signing: %v", err) logging.Warnf("failed to enable message signing: %v", err)
} }
c.encrypt = false
if c.acctConfig.PgpOpportunisticEncrypt { if c.acctConfig.PgpOpportunisticEncrypt {
c.SetEncrypt(true) c.SetEncrypt(true)
} }
err := c.updateCrypto()
if err != nil {
logging.Warnf("failed to update crypto: %v", err)
}
return c, nil return nil
} }
func (c *Composer) buildComposeHeader(aerc *Aerc, cmpl *completer.Completer) { func (c *Composer) buildComposeHeader(aerc *Aerc, cmpl *completer.Completer) {