From 579bc3fa123dfba8a553693dbd3196336aa03ad5 Mon Sep 17 00:00:00 2001 From: Justin Do Date: Fri, 22 Mar 2024 01:58:17 +0700 Subject: [PATCH] Update UI for start page and fix bugs (#486) * update start page * update editor for password modal --- ui/cryptomaterial/editor.go | 10 +++ ui/cryptomaterial/slider.go | 21 ++++-- ui/modal/create_password_modal.go | 1 + ui/page/start_page.go | 121 +++++++++++------------------- ui/values/localizable/en.go | 2 +- 5 files changed, 73 insertions(+), 82 deletions(-) diff --git a/ui/cryptomaterial/editor.go b/ui/cryptomaterial/editor.go index 464d8e6cd..32cb0429b 100644 --- a/ui/cryptomaterial/editor.go +++ b/ui/cryptomaterial/editor.go @@ -71,6 +71,9 @@ type Editor struct { eventKey int isShowMenu bool isDisableMenu bool + + // add space for error lable if it is true + isSpaceError bool } func (t *Theme) EditorPassword(editor *widget.Editor, hint string) Editor { @@ -254,6 +257,9 @@ func (e *Editor) layout(gtx C) D { } return inset.Layout(gtx, e.errorLabel.Layout) } + if e.isSpaceError { + return layout.Spacer{Height: values.MarginPadding18}.Layout(gtx) + } return D{} }), ) @@ -490,3 +496,7 @@ func (e *Editor) ClearError() { func (e *Editor) IsDirty() bool { return e.errorLabel.Text == "" } + +func (e *Editor) AllowSpaceError(allow bool) { + e.isSpaceError = allow +} diff --git a/ui/cryptomaterial/slider.go b/ui/cryptomaterial/slider.go index 58ded658a..4f354def9 100644 --- a/ui/cryptomaterial/slider.go +++ b/ui/cryptomaterial/slider.go @@ -36,6 +36,8 @@ type Slider struct { slideAction *SlideAction clicker gesture.Click clicked bool + disableButtonDirection bool + ControlInset layout.Inset } var m4 = values.MarginPadding4 @@ -53,6 +55,12 @@ func (t *Theme) Slider() *Slider { slideAction: NewSlideAction(), } + sl.ControlInset = layout.Inset{ + Right: values.MarginPadding16, + Left: values.MarginPadding16, + Bottom: values.MarginPadding16, + } + sl.card = sl.t.Card() sl.card.Radius = Radius(8) @@ -69,6 +77,10 @@ func (s *Slider) GetSelectedIndex() int { return s.selected } +func (s *Slider) SetDisableDirectionBtn(disable bool) { + s.disableButtonDirection = disable +} + func (s *Slider) sliderItems(items []layout.Widget) []*sliderItem { slideItems := make([]*sliderItem, 0) for _, item := range items { @@ -106,16 +118,15 @@ func (s *Slider) Layout(gtx C, items []layout.Widget) D { if len(s.slideItems) == 1 { return D{} } - return layout.Inset{ - Right: values.MarginPadding16, - Left: values.MarginPadding16, - Bottom: values.MarginPadding16, - }.Layout(gtx, func(gtx C) D { + return s.ControlInset.Layout(gtx, func(gtx C) D { return layout.Flex{ Axis: layout.Horizontal, }.Layout(gtx, layout.Rigid(s.selectedItemIndicatorLayout), layout.Flexed(1, func(gtx C) D { + if s.disableButtonDirection { + return D{} + } return layout.E.Layout(gtx, s.buttonLayout) }), ) diff --git a/ui/modal/create_password_modal.go b/ui/modal/create_password_modal.go index 45a3a5c0b..f6d4d17c2 100644 --- a/ui/modal/create_password_modal.go +++ b/ui/modal/create_password_modal.go @@ -76,6 +76,7 @@ func NewCreatePasswordModal(l *load.Load) *CreatePasswordModal { cm.confirmPasswordEditor = l.Theme.EditorPassword(new(widget.Editor), values.String(values.StrConfirmSpendingPassword)) cm.confirmPasswordEditor.Editor.SingleLine, cm.confirmPasswordEditor.Editor.Submit = true, true + cm.confirmPasswordEditor.AllowSpaceError(true) // Set the default click functions cm.negativeButtonClicked = func() {} diff --git a/ui/page/start_page.go b/ui/page/start_page.go index 5d0303150..776a22c0e 100644 --- a/ui/page/start_page.go +++ b/ui/page/start_page.go @@ -29,7 +29,7 @@ import ( const ( StartPageID = "start_page" // startupSettingsPageIndex is the index of the settings setup page. - startupSettingsPageIndex = 3 + startupSettingsPageIndex = 1 // advancedSettingsOptionIndex is the index of the advanced settings option. advancedSettingsOptionIndex = 1 ) @@ -55,8 +55,7 @@ type onBoardingScreen struct { title string subTitle string - image *cryptomaterial.Image // optional - indicatorBtn *cryptomaterial.Clickable // optional + image *cryptomaterial.Image } type startPage struct { @@ -84,6 +83,8 @@ type startPage struct { currentPageIndex int selectedSettingsOptionIndex int + + introductionSlider *cryptomaterial.Slider } func NewStartPage(ctx context.Context, l *load.Load, isShuttingDown ...bool) app.Page { @@ -98,6 +99,15 @@ func NewStartPage(ctx context.Context, l *load.Load, isShuttingDown ...bool) app nextButton: l.Theme.Button(values.String(values.StrNext)), backButton: l.Theme.NewClickable(true), networkSwitchButton: l.Theme.NewClickable(true), + introductionSlider: l.Theme.Slider(), + } + + sp.introductionSlider.IndicatorBackgroundColor = values.TransparentColor(values.TransparentWhite, 1) + sp.introductionSlider.SelectedIndicatorColor = sp.Theme.Color.Primary + sp.introductionSlider.SetDisableDirectionBtn(true) + sp.introductionSlider.ControlInset = layout.Inset{ + Right: values.MarginPadding16, + Left: values.MarginPadding16, } if len(isShuttingDown) > 0 { @@ -155,26 +165,19 @@ func (sp *startPage) initPage() { sp.onBoardingScreens = []onBoardingScreen{ { - title: values.String(values.StrMultiWalletSupport), - subTitle: values.String(values.StrMultiWalletSupportSubtext), - image: sp.Theme.Icons.MultiWalletIcon, - indicatorBtn: sp.Theme.NewClickable(false), - }, - { - title: values.String(values.StrCrossPlatform), - subTitle: values.String(values.StrCrossPlatformSubtext), - image: sp.Theme.Icons.CrossPlatformIcon, - indicatorBtn: sp.Theme.NewClickable(false), + title: values.String(values.StrMultiWalletSupport), + subTitle: values.String(values.StrMultiWalletSupportSubtext), + image: sp.Theme.Icons.MultiWalletIcon, }, { - title: values.String(values.StrIntegratedExchangeFunctionality), - subTitle: values.String(values.StrIntegratedExchangeSubtext), - image: sp.Theme.Icons.IntegratedExchangeIcon, - indicatorBtn: sp.Theme.NewClickable(false), + title: values.String(values.StrCrossPlatform), + subTitle: values.String(values.StrCrossPlatformSubtext), + image: sp.Theme.Icons.CrossPlatformIcon, }, { - title: values.String(values.StrChooseSetupType), - subTitle: values.String(values.StrLanguage), + title: values.String(values.StrIntegratedExchangeFunctionality), + subTitle: values.String(values.StrIntegratedExchangeSubtext), + image: sp.Theme.Icons.IntegratedExchangeIcon, }, } @@ -256,12 +259,11 @@ func (sp *startPage) HandleUserInteractions() { } for sp.nextButton.Clicked() { - if sp.currentPageIndex == len(sp.onBoardingScreens)-1 { // index starts at 0 - // save user setting when reached the last sceen - sp.updateSettings() - sp.currentPageIndex = -1 // we have reached the last screen. - } else { + if sp.currentPageIndex < startupSettingsPageIndex { sp.currentPageIndex++ + } else { + sp.updateSettings() + sp.currentPageIndex = -1 } } @@ -298,14 +300,6 @@ func (sp *startPage) HandleUserInteractions() { sp.currentPageIndex-- } - for i, onBoardingScreen := range sp.onBoardingScreens { - if i < startupSettingsPageIndex { - if onBoardingScreen.indicatorBtn.Clicked() { - sp.currentPageIndex = i - } - } - } - if sp.displayStartPage { time.AfterFunc(time.Second*2, func() { sp.displayStartPage = false @@ -430,6 +424,22 @@ func (sp *startPage) loadingSection(gtx C) D { }) } +func (sp *startPage) introScreenLayout(gtx C) D { + sliderWidget := make([]layout.Widget, 0) + for i := range sp.onBoardingScreens { + onBoardingScreen := sp.onBoardingScreens[i] + dims := func(gtx C) D { + return layout.Inset{ + Bottom: values.MarginPadding40, + }.Layout(gtx, func(gtx C) D { + return sp.pageSections(gtx, onBoardingScreen) + }) + } + sliderWidget = append(sliderWidget, dims) + } + return sp.introductionSlider.Layout(gtx, sliderWidget) +} + func (sp *startPage) onBoardingScreensLayout(gtx C) D { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { @@ -449,12 +459,10 @@ func (sp *startPage) onBoardingScreensLayout(gtx C) D { Alignment: layout.Middle, Axis: layout.Vertical, }.Layout(gtx, - layout.Rigid(sp.onBoardingScreenLayout), layout.Rigid(func(gtx C) D { return layout.Inset{ - Top: values.MarginPadding30, Bottom: values.MarginPadding30, - }.Layout(gtx, sp.currentPageIndicatorLayout) + }.Layout(gtx, sp.introScreenLayout) }), layout.Rigid(func(gtx C) D { gtx.Constraints.Min.X = gtx.Dp(values.MarginPaddingTransform(sp.IsMobileView(), values.MarginPadding420)) @@ -495,7 +503,7 @@ func (sp *startPage) onBoardingScreensLayout(gtx C) D { return layout.Inset{Top: values.MarginPaddingMinus200}.Layout(gtx, func(gtx C) D { return layout.Flex{Axis: layout.Vertical, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(func(gtx C) D { - titleLabel := sp.Theme.Label(values.TextSize16, sp.onBoardingScreens[sp.currentPageIndex].title) + titleLabel := sp.Theme.Label(values.TextSize16, values.String(values.StrChooseSetupType)) titleLabel.Font.Weight = font.Bold return layout.Inset{Bottom: values.MarginPadding40}.Layout(gtx, titleLabel.Layout) }), @@ -524,16 +532,6 @@ func (sp *startPage) onBoardingScreensLayout(gtx C) D { ) } -func (sp *startPage) onBoardingScreenLayout(gtx C) D { - list := layout.List{Axis: layout.Horizontal} - return list.Layout(gtx, len(sp.onBoardingScreens), func(gtx C, i int) D { - if i != sp.currentPageIndex { - return D{} - } - return sp.pageSections(gtx, sp.onBoardingScreens[sp.currentPageIndex]) - }) -} - func (sp *startPage) settingsOptionsLayout(gtx C) D { padding := values.MarginPadding16 optionWidth := (settingsOptionPageWidth - padding) / unit.Dp(len(sp.settingsOptions)) @@ -610,7 +608,7 @@ func (sp *startPage) settingsOptionsLayout(gtx C) D { ) } -func (sp *startPage) pageHeaderLayout(gtx C) layout.Dimensions { +func (sp *startPage) pageHeaderLayout(gtx C) D { return cryptomaterial.LinearLayout{ Width: cryptomaterial.MatchParent, Height: cryptomaterial.WrapContent, @@ -653,35 +651,6 @@ func (sp *startPage) pageSections(gtx C, onBoardingScreen onBoardingScreen) D { ) } -func (sp *startPage) currentPageIndicatorLayout(gtx C) D { - if sp.currentPageIndex < 0 { - return D{} - } - - list := &layout.List{Axis: layout.Horizontal} - return list.Layout(gtx, len(sp.onBoardingScreens), func(gtx C, i int) D { - return layout.Inset{Top: values.MarginPadding35, Bottom: values.MarginPadding35}.Layout(gtx, func(gtx C) D { - if i > startupSettingsPageIndex-1 { - return D{} - } - - ic := cryptomaterial.NewIcon(sp.Theme.Icons.DotIcon) - ic.Color = values.TransparentColor(values.TransparentBlack, 0.2) - if i == sp.currentPageIndex { - ic.Color = sp.Theme.Color.Primary - } - return layout.Inset{ - Right: values.MarginPadding4, - Left: values.MarginPadding4, - }.Layout(gtx, func(gtx C) D { - return sp.onBoardingScreens[i].indicatorBtn.Layout(gtx, func(gtx C) D { - return ic.Layout(gtx, values.MarginPadding12) - }) - }) - }) - }) -} - func (sp *startPage) setLanguagePref(useExistingUserPreference bool) { var lang string if useExistingUserPreference { diff --git a/ui/values/localizable/en.go b/ui/values/localizable/en.go index 3330e3968..a813a9084 100644 --- a/ui/values/localizable/en.go +++ b/ui/values/localizable/en.go @@ -427,7 +427,7 @@ const EN = ` "owned" = "Valid address owned by you." "pageWarningNotSync" = "Page cannot be accessed because the wallet is not synced, please sync your wallet and try again" "pageWarningSync" = "Page cannot be accessed because the wallet sync is in progress, please wait for the sync to complete" -"passwordNotMatch" = "Passwords do not match" +"passwordNotMatch" = "Passwords do not match." "pasteSeedWords" = "Paste Seed Words" "peer" = "Peer" "peers" = "peers"