diff options
| -rw-r--r-- | commands/new-account.go | 2 | ||||
| -rw-r--r-- | widgets/account-wizard.go | 146 | 
2 files changed, 140 insertions, 8 deletions
diff --git a/commands/new-account.go b/commands/new-account.go index 6a64eb2..3d6551f 100644 --- a/commands/new-account.go +++ b/commands/new-account.go @@ -14,7 +14,7 @@ func CommandNewAccount(aerc *widgets.Aerc, args []string) error {  	if len(args) != 1 {  		return errors.New("Usage: new-account")  	} -	wizard := widgets.NewAccountWizard() +	wizard := widgets.NewAccountWizard(aerc.Config(), aerc)  	aerc.NewTab(wizard, "New account")  	return nil  } diff --git a/widgets/account-wizard.go b/widgets/account-wizard.go index 8e20900..7ed9a62 100644 --- a/widgets/account-wizard.go +++ b/widgets/account-wizard.go @@ -1,11 +1,19 @@  package widgets  import ( +	"errors" +	"fmt"  	"net/url" +	"os" +	"path"  	"strings" +	"time"  	"github.com/gdamore/tcell" +	"github.com/go-ini/ini" +	"github.com/kyoh86/xdg" +	"git.sr.ht/~sircmpwn/aerc/config"  	"git.sr.ht/~sircmpwn/aerc/lib/ui"  ) @@ -30,6 +38,8 @@ const (  type AccountWizard struct {  	ui.Invalidatable +	aerc    *Aerc +	conf    *config.AercConfig  	step    int  	steps   []*ui.Grid  	focus   int @@ -60,20 +70,22 @@ type AccountWizard struct {  	complete []ui.Interactive  } -func NewAccountWizard() *AccountWizard { +func NewAccountWizard(conf *config.AercConfig, aerc *Aerc) *AccountWizard {  	wizard := &AccountWizard{  		accountName:  ui.NewTextInput("").Prompt("> "), +		aerc:         aerc, +		conf:         conf, +		copySent:     true,  		email:        ui.NewTextInput("").Prompt("> "),  		fullName:     ui.NewTextInput("").Prompt("> "), -		imapUsername: ui.NewTextInput("").Prompt("> "),  		imapPassword: ui.NewTextInput("").Prompt("] ").Password(true),  		imapServer:   ui.NewTextInput("").Prompt("> "),  		imapStr:      ui.NewText("imaps://"), -		smtpUsername: ui.NewTextInput("").Prompt("> "), +		imapUsername: ui.NewTextInput("").Prompt("> "),  		smtpPassword: ui.NewTextInput("").Prompt("] ").Password(true),  		smtpServer:   ui.NewTextInput("").Prompt("> "),  		smtpStr:      ui.NewText("smtps://"), -		copySent:     true, +		smtpUsername: ui.NewTextInput("").Prompt("> "),  	}  	// Autofill some stuff for the user @@ -350,10 +362,9 @@ func NewAccountWizard() *AccountWizard {  		case "Previous":  			wizard.advance("Previous")  		case "Finish & open tutorial": -			// TODO -			fallthrough +			wizard.finish(true)  		case "Finish": -			// TODO +			wizard.finish(false)  		}  	})  	complete.AddChild(selecter).At(1, 0) @@ -366,6 +377,127 @@ func NewAccountWizard() *AccountWizard {  	return wizard  } +func (wizard *AccountWizard) errorFor(d ui.Interactive, err error) { +	if d == nil { +		wizard.aerc.PushStatus(" "+err.Error(), 10*time.Second). +			Color(tcell.ColorDefault, tcell.ColorRed) +		wizard.Invalidate() +		return +	} +	for step, interactives := range [][]ui.Interactive{ +		wizard.basics, +		wizard.incoming, +		wizard.outgoing, +	} { +		for focus, item := range interactives { +			if item == d { +				wizard.Focus(false) +				wizard.step = step +				wizard.focus = focus +				wizard.Focus(true) +				wizard.aerc.PushStatus(" "+err.Error(), 10*time.Second). +					Color(tcell.ColorDefault, tcell.ColorRed) +				wizard.Invalidate() +				return +			} +		} +	} +} + +func (wizard *AccountWizard) finish(tutorial bool) { +	accountsConf := path.Join(xdg.ConfigHome(), "aerc", "accounts.conf") + +	// Validation +	if wizard.accountName.String() == "" { +		wizard.errorFor(wizard.accountName, +			errors.New("Account name is required")) +		return +	} +	if wizard.email.String() == "" { +		wizard.errorFor(wizard.email, +			errors.New("Email address is required")) +		return +	} +	if wizard.fullName.String() == "" { +		wizard.errorFor(wizard.fullName, +			errors.New("Full name is required")) +		return +	} +	if wizard.imapServer.String() == "" { +		wizard.errorFor(wizard.imapServer, +			errors.New("IMAP server is required")) +		return +	} +	if wizard.imapServer.String() == "" { +		wizard.errorFor(wizard.smtpServer, +			errors.New("SMTP server is required")) +		return +	} + +	file, err := ini.Load(accountsConf) +	if err == os.ErrNotExist { +		file = ini.Empty() +	} else if err != nil { +		wizard.errorFor(nil, err) +		return +	} + +	var sec *ini.Section +	if sec, _ = file.GetSection(wizard.accountName.String()); sec != nil { +		wizard.errorFor(wizard.accountName, +			errors.New("An account by this name already exists")) +		return +	} +	sec, _ = file.NewSection(wizard.accountName.String()) +	sec.NewKey("source", wizard.imapUrl.String()) +	sec.NewKey("outgoing", wizard.smtpUrl.String()) +	if wizard.smtpMode == SMTP_STARTTLS { +		sec.NewKey("smtp-starttls", "yes") +	} +	sec.NewKey("from", fmt.Sprintf("%s <%s>", +		wizard.fullName.String(), wizard.email.String())) +	if wizard.copySent { +		sec.NewKey("copy-to", "Sent") +	} + +	f, err := os.OpenFile(accountsConf, os.O_WRONLY|os.O_CREATE, 0600) +	if err != nil { +		wizard.errorFor(nil, err) +		return +	} +	if _, err = file.WriteTo(f); err != nil { +		wizard.errorFor(nil, err) +		return +	} + +	account := config.AccountConfig{ +		Name:     sec.Name(), +		From:     sec.Key("from").String(), +		Source:   sec.Key("source").String(), +		Outgoing: sec.Key("outgoing").String(), +	} +	if wizard.smtpMode == SMTP_STARTTLS { +		account.Params = map[string]string{ +			"smtp-starttls": "yes", +		} +	} +	if wizard.copySent { +		account.CopyTo = "Sent" +	} +	wizard.conf.Accounts = append(wizard.conf.Accounts, account) + +	view := NewAccountView(wizard.conf, &account, +		wizard.aerc.logger, wizard.aerc) +	wizard.aerc.accounts[account.Name] = view +	wizard.aerc.NewTab(view, account.Name) + +	if tutorial { +		// TODO: Open tutorial +	} + +	wizard.aerc.RemoveTab(wizard) +} +  func (wizard *AccountWizard) imapUri() url.URL {  	host := wizard.imapServer.String()  	user := wizard.imapUsername.String()  | 
