package ui import ( "errors" "fmt" "gioui.org/layout" "gioui.org/widget" "gioui.org/widget/material" "git.wxccs.org/iceking2nd/winauth-go/internal/config" "git.wxccs.org/iceking2nd/winauth-go/internal/global" "git.wxccs.org/iceking2nd/winauth-go/internal/i18n" ) // restoreBackupDialog loads an encrypted .winauth.bak file produced by the // export dialog. The user supplies the path and the backup's password; on // success the loaded entries are handed back to the caller for merging. type restoreBackupDialog struct { pathEd widget.Editor pwEd widget.Editor restoreB widget.Clickable cancelB widget.Clickable errorMsg string } func newRestoreBackupDialog() *restoreBackupDialog { d := &restoreBackupDialog{} d.pathEd.SingleLine = true d.pwEd.SingleLine = true d.pwEd.Mask = '*' return d } // restoreBackupResult carries the outcome of the dialog. type restoreBackupResult struct { cfg *config.Config cancel bool } func (d *restoreBackupDialog) Layout( gtx layout.Context, th *material.Theme, onDone func(restoreBackupResult), ) layout.Dimensions { if d.cancelB.Clicked(gtx) { d.wipe() onDone(restoreBackupResult{cancel: true}) return layout.Dimensions{Size: gtx.Constraints.Max} } if d.restoreB.Clicked(gtx) { path := d.pathEd.Text() if path == "" { d.errorMsg = i18n.T("msg_empty_backup_path") } else { pw := []byte(d.pwEd.Text()) cfg, err := config.LoadYAML(path, pw) for i := range pw { pw[i] = 0 } switch { case errors.Is(err, config.ErrPasswordRequired): d.errorMsg = i18n.T("msg_password_required") case errors.Is(err, config.ErrPasswordWrong): d.errorMsg = i18n.T("msg_password_wrong") case err != nil: d.errorMsg = fmt.Sprintf(i18n.T("msg_restore_failed"), err.Error()) global.Log.WithField("func", "internal.ui.restoreBackupDialog.Layout"). WithError(err).Warn("restore backup failed") default: d.wipe() onDone(restoreBackupResult{cfg: cfg}) return layout.Dimensions{Size: gtx.Constraints.Max} } } } body := func(gtx layout.Context) layout.Dimensions { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(material.Body2(th, i18n.T("restore_backup_intro")).Layout), layout.Rigid(layout.Spacer{Height: 8}.Layout), layout.Rigid(labeledEditor(th, i18n.T("label_backup_path"), &d.pathEd, "backup.winauth.bak")), layout.Rigid(labeledEditor(th, i18n.T("label_password"), &d.pwEd, "")), layout.Rigid(errorLabel(th, d.errorMsg)), ) } return modalCard(gtx, th, i18n.T("dialog_restore_backup_title"), i18n.T("btn_restore"), i18n.T("btn_cancel"), &d.restoreB, &d.cancelB, body) } func (d *restoreBackupDialog) wipe() { d.pwEd.SetText("") }