diff options
Diffstat (limited to 'widgets/compose.go')
-rw-r--r-- | widgets/compose.go | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/widgets/compose.go b/widgets/compose.go index 5dab4294..49627fca 100644 --- a/widgets/compose.go +++ b/widgets/compose.go @@ -198,8 +198,21 @@ func (c *Composer) Sign() bool { } func (c *Composer) SetEncrypt(encrypt bool) *Composer { - c.encrypt = encrypt - c.updateCrypto() + if !encrypt { + c.encrypt = encrypt + c.updateCrypto() + return c + } + // Check on any attempt to encrypt, and any lost focus of "to", "cc", or + // "bcc" field. Use OnFocusLost instead of OnChange to limit keyring checks + c.encrypt = c.checkEncryptionKeys("") + if c.crypto.setEncOneShot { + // Prevent registering a lot of callbacks + c.OnFocusLost("to", c.checkEncryptionKeys) + c.OnFocusLost("cc", c.checkEncryptionKeys) + c.OnFocusLost("bcc", c.checkEncryptionKeys) + c.crypto.setEncOneShot = false + } return c } @@ -365,6 +378,15 @@ func (c *Composer) OnHeaderChange(header string, fn func(subject string)) { } } +// OnFocusLost registers an OnFocusLost callback for the specified header. +func (c *Composer) OnFocusLost(header string, fn func(input string) bool) { + if editor, ok := c.editors[strings.ToLower(header)]; ok { + editor.OnFocusLost(func() { + fn(editor.input.String()) + }) + } +} + func (c *Composer) OnClose(fn func(composer *Composer)) { c.onClose = append(c.onClose, fn) } @@ -984,6 +1006,12 @@ func (he *headerEditor) OnChange(fn func()) { }) } +func (he *headerEditor) OnFocusLost(fn func()) { + he.input.OnFocusLost(func(_ *ui.TextInput) { + fn() + }) +} + type reviewMessage struct { composer *Composer grid *ui.Grid @@ -1090,18 +1118,21 @@ func (rm *reviewMessage) Draw(ctx *ui.Context) { } type cryptoStatus struct { - title string - status *ui.Text - uiConfig *config.UIConfig - signKey string + title string + status *ui.Text + uiConfig *config.UIConfig + signKey string + setEncOneShot bool } func newCryptoStatus(uiConfig *config.UIConfig) *cryptoStatus { defaultStyle := uiConfig.GetStyle(config.STYLE_DEFAULT) return &cryptoStatus{ - title: "Security", - status: ui.NewText("", defaultStyle), - uiConfig: uiConfig, + title: "Security", + status: ui.NewText("", defaultStyle), + uiConfig: uiConfig, + signKey: "", + setEncOneShot: true, } } @@ -1124,3 +1155,33 @@ func (cs *cryptoStatus) OnInvalidate(fn func(ui.Drawable)) { fn(cs) }) } + +func (c *Composer) checkEncryptionKeys(_ string) bool { + rcpts, err := getRecipientsEmail(c) + if err != nil { + // checkEncryptionKeys gets registered as a callback and must + // explicitly call c.SetEncrypt(false) when encryption is not possible + c.SetEncrypt(false) + st := fmt.Sprintf("Cannot encrypt: %v", err) + c.aerc.statusline.PushError(st) + return false + } + var mk []string + for _, rcpt := range rcpts { + key, err := c.aerc.Crypto.GetKeyId(rcpt) + if err != nil || key == "" { + mk = append(mk, rcpt) + } + } + if len(mk) > 0 { + c.SetEncrypt(false) + st := fmt.Sprintf("Cannot encrypt, missing keys: %s", strings.Join(mk, ", ")) + c.aerc.statusline.PushError(st) + return false + } + // If callbacks were registered, encrypt will be set when user removes + // recipients with missing keys + c.encrypt = true + c.updateCrypto() + return true +} |