Cw 765 onboarding flow improvements (#1817)

* update onboarding flow

* update welcome subtitle

* update wallet title

* add create restore wallet subtitles

* info button

* minor fix [skip ci]

* Update text and iconbutton

* Cleanup

---------

Co-authored-by: tuxpizza <tuxsudo@tux.pizza>
This commit is contained in:
Serhii
2024-11-27 23:05:04 +02:00
committed by GitHub
co-authored by tuxpizza
parent 13c4fbd225
commit 5ca1c0c56e
35 changed files with 478 additions and 226 deletions
@@ -85,9 +85,7 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
key: ValueKey('restore_options_from_seeds_or_keys_button_key'),
onPressed: () => Navigator.pushNamed(
context,
Routes.restoreWalletFromSeedKeys,
arguments: widget.isNewInstall,
),
Routes.restoreWalletFromSeedKeys),
image: imageSeedKeys,
title: S.of(context).restore_title_from_seed_keys,
description: S.of(context).restore_description_from_seed_keys,
@@ -109,8 +107,7 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
child: OptionTile(
key: ValueKey('restore_options_from_hardware_wallet_button_key'),
onPressed: () => Navigator.pushNamed(
context, Routes.restoreWalletFromHardwareWallet,
arguments: widget.isNewInstall),
context, Routes.restoreWalletFromHardwareWallet),
image: imageLedger,
title: S.of(context).restore_title_from_hardware_wallet,
description: S.of(context).restore_description_from_hardware_wallet,
@@ -158,15 +155,6 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
await PermissionHandler.checkPermission(Permission.camera, context);
if (!isCameraPermissionGranted) return;
bool isPinSet = false;
if (widget.isNewInstall) {
await Navigator.pushNamed(context, Routes.setupPin,
arguments: (PinCodeState<PinCodeWidget> setupPinContext, String _) {
setupPinContext.close();
isPinSet = true;
});
}
if (!widget.isNewInstall || isPinSet) {
try {
if (isRestoring) {
return;
@@ -188,5 +176,4 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
_onWalletCreateFailure(context, e.toString());
}
}
}
}
@@ -0,0 +1,138 @@
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/wallet_type_utils.dart';
import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart';
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
class CreatePinWelcomePage extends BasePage {
static const aspectRatioImage = 1.25;
final welcomeImageLight = Image.asset('assets/images/welcome_light.png');
final welcomeImageDark = Image.asset('assets/images/welcome.png');
String appTitle(BuildContext context) {
if (isMoneroOnly) {
return S.of(context).monero_com;
}
if (isHaven) {
return S.of(context).haven_app;
}
return S.of(context).cake_wallet;
}
String appDescription(BuildContext context) {
if (isMoneroOnly) {
return S.of(context).monero_com_wallet_text;
}
if (isHaven) {
return S.of(context).haven_app_wallet_text;
}
return S.of(context).new_first_wallet_text;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.background,
resizeToAvoidBottomInset: false,
body: body(context));
}
@override
Widget body(BuildContext context) {
final welcomeImage = currentTheme.type == ThemeType.dark ? welcomeImageDark : welcomeImageLight;
final newWalletImage = Image.asset('assets/images/new_wallet.png',
height: 12,
width: 12,
color: Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor);
return PopScope(
canPop: false,
child: ScrollableWithBottomSection(
content: Container(
alignment: Alignment.center,
child: ConstrainedBox(
constraints:
BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: <Widget>[
SizedBox(height: 70),
AspectRatio(
aspectRatio: aspectRatioImage,
child: FittedBox(child: welcomeImage, fit: BoxFit.contain),
),
SizedBox(height: 50),
Padding(
padding: EdgeInsets.only(top: 24),
child: Text(
S.of(context).welcome,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor,
),
textAlign: TextAlign.center,
),
),
Padding(
padding: EdgeInsets.only(top: 5),
child: Text(
appTitle(context),
style: TextStyle(
fontSize: 36,
fontWeight: FontWeight.bold,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
),
textAlign: TextAlign.center,
),
),
Padding(
padding: EdgeInsets.only(top: 5),
child: Text(
appDescription(context),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor,
),
textAlign: TextAlign.center,
),
),
],
),
],
),
),
),
bottomSection: Padding(
padding: EdgeInsets.only(top: 24),
child: PrimaryImageButton(
key: ValueKey('create_pin_welcome_page_create_a_pin_button_key'),
onPressed: () => Navigator.pushNamed(context, Routes.welcomeWallet),
image: newWalletImage,
text: S.current.set_a_pin,
color: Theme.of(context)
.extension<WalletListTheme>()!
.createNewWalletButtonBackgroundColor,
textColor:
Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor,
),
),
),
);
}
}
@@ -1,4 +0,0 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/screens/welcome/welcome_page.dart';
Widget createWelcomePage() => WelcomePage();
+142 -126
View File
@@ -10,42 +10,28 @@ import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/wallet_type_utils.dart';
import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart';
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
import 'package:url_launcher/url_launcher.dart';
class WelcomePage extends BasePage {
static const aspectRatioImage = 1.25;
final welcomeImageLight = Image.asset('assets/images/welcome_light.png');
final welcomeImageDark = Image.asset('assets/images/welcome.png');
String appTitle(BuildContext context) {
if (isMoneroOnly) {
return S.of(context).monero_com;
}
if (isHaven) {
return S.of(context).haven_app;
}
return S.of(context).cake_wallet;
}
String appDescription(BuildContext context) {
if (isMoneroOnly) {
return S.of(context).monero_com_wallet_text;
}
if (isHaven) {
return S.of(context).haven_app_wallet_text;
}
return S.of(context).new_first_wallet_text;
}
final welcomeImageLight = Image.asset('assets/images/wallet_type_light.png');
final welcomeImageDark = Image.asset('assets/images/wallet_type.png');
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.background,
resizeToAvoidBottomInset: false,
body: body(context));
String? get title => S.current.wallet;
@override
bool get resizeToAvoidBottomInset => false;
@override
Widget trailing(BuildContext context) {
final Uri _url = Uri.parse('https://guides.cakewallet.com/docs/basic-features/basic-features/');
return IconButton(
icon: Icon(Icons.info_outline),
onPressed: () async {
await launchUrl(_url);
},
);
}
@override
@@ -59,106 +45,136 @@ class WelcomePage extends BasePage {
final restoreWalletImage = Image.asset('assets/images/restore_wallet.png',
height: 12, width: 12, color: Theme.of(context).extension<CakeTextTheme>()!.titleColor);
return WillPopScope(
onWillPop: () async => false,
child: ScrollableWithBottomSection(
content: Container(
alignment: Alignment.center,
padding: EdgeInsets.only(top: 64, bottom: 24, left: 24, right: 24),
child: ConstrainedBox(
constraints:
BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: <Widget>[
AspectRatio(
aspectRatio: aspectRatioImage,
child: FittedBox(child: welcomeImage, fit: BoxFit.contain),
),
Padding(
padding: EdgeInsets.only(top: 24),
child: Text(
S.of(context).welcome,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor,
),
textAlign: TextAlign.center,
),
),
Padding(
return ScrollableWithBottomSection(
content: Container(
alignment: Alignment.center,
padding: EdgeInsets.only(top: 64, bottom: 24, left: 24, right: 24),
child: ConstrainedBox(
constraints:
BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: <Widget>[
AspectRatio(
aspectRatio: aspectRatioImage,
child: FittedBox(child: welcomeImage, fit: BoxFit.contain),
),
Padding(
padding: EdgeInsets.only(top: 20),
child: highlightText(context, S.of(context).welcome_subtitle_new_wallet,
S.of(context).create_new)),
SizedBox(height: 10),
Padding(
padding: EdgeInsets.only(top: 5),
child: Text(
appTitle(context),
style: TextStyle(
fontSize: 36,
fontWeight: FontWeight.bold,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
),
textAlign: TextAlign.center,
),
),
Padding(
padding: EdgeInsets.only(top: 5),
child: Text(
appDescription(context),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor,
),
textAlign: TextAlign.center,
),
),
],
),
],
),
child: highlightText(context, S.of(context).welcome_subtitle_restore_wallet,
S.of(context).restore_existing_wallet)),
],
),
],
),
),
bottomSection: Column(
children: <Widget>[
Text(
S.of(context).please_make_selection,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.normal,
color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor,
),
textAlign: TextAlign.center,
),
Padding(
padding: EdgeInsets.only(top: 24),
child: PrimaryImageButton(
key: ValueKey('welcome_page_create_new_wallet_button_key'),
onPressed: () => Navigator.pushNamed(context, Routes.newWalletFromWelcome),
image: newWalletImage,
text: S.of(context).create_new,
color: Theme.of(context)
.extension<WalletListTheme>()!
.createNewWalletButtonBackgroundColor,
textColor:
Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor,
),
),
Padding(
padding: EdgeInsets.only(top: 10),
child: PrimaryImageButton(
),
bottomSection: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 24),
child: PrimaryImageButton(
key: ValueKey('welcome_page_restore_wallet_button_key'),
onPressed: () {
Navigator.pushNamed(context, Routes.restoreOptions, arguments: true);
},
image: restoreWalletImage,
text: S.of(context).restore_wallet,
color: Theme.of(context).cardColor,
textColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
)
],
),
onPressed: () {
Navigator.pushNamed(context, Routes.restoreOptions, arguments: true);
},
image: restoreWalletImage,
text: S.of(context).restore_existing_wallet,
color: Theme.of(context).cardColor,
textColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
),
Padding(
padding: EdgeInsets.only(top: 10),
child: PrimaryImageButton(
key: ValueKey('welcome_page_create_new_wallet_button_key'),
onPressed: () => Navigator.pushNamed(context, Routes.newWalletFromWelcome),
image: newWalletImage,
text: S.of(context).create_new,
color: Theme.of(context)
.extension<WalletListTheme>()!
.createNewWalletButtonBackgroundColor,
textColor:
Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor,
),
),
],
),
);
}
RichText highlightText(BuildContext context, String text, String highlightWord) {
final regex = RegExp(highlightWord, caseSensitive: false);
final matches = regex.allMatches(text);
if (matches.isEmpty) {
return RichText(
textAlign: TextAlign.center,
text: TextSpan(
text: text,
style: TextStyle(
fontSize: 16,
height: 1.5,
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
),
),
);
}
List<InlineSpan> spans = [];
int lastMatchEnd = 0;
for (final match in matches) {
final start = match.start;
final end = match.end;
if (start > lastMatchEnd) {
spans.add(TextSpan(
text: text.substring(lastMatchEnd, start),
style: TextStyle(
fontSize: 16,
height: 1.5,
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
),
));
}
spans.add(TextSpan(
text: text.substring(start, end),
style: TextStyle(
fontSize: 16,
height: 1.5,
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
fontWeight: FontWeight.bold,
),
));
lastMatchEnd = end;
}
if (lastMatchEnd < text.length) {
spans.add(TextSpan(
text: text.substring(lastMatchEnd),
style: TextStyle(
fontSize: 16,
height: 1.5,
fontWeight: FontWeight.w400,
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
),
));
}
return RichText(
textAlign: TextAlign.center,
text: TextSpan(children: spans),
);
}
}