dev
dart 185 lines 5.91 KB
Raw
1 import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
2 import 'package:cake_wallet/src/widgets/scrollable_with_bottom_section.dart';
3 import 'package:cake_wallet/utils/responsive_layout_util.dart';
4 import 'package:flutter/material.dart';
5 import 'package:cake_wallet/routes.dart';
6 import 'package:cake_wallet/src/widgets/primary_button.dart';
7 import 'package:cake_wallet/src/screens/base_page.dart';
8 import 'package:cake_wallet/generated/i18n.dart';
9 import 'package:url_launcher/url_launcher.dart';
10 import 'package:cake_wallet/src/widgets/gradient_background.dart';
11
12 class WelcomePage extends BasePage {
13 static const aspectRatioImage = 1.5;
14 final welcomeImageLight = 'assets/new-ui/hero/welcome_wallet_light.svg';
15 final welcomeImageDark = 'assets/new-ui/hero/welcome_wallet_dark.svg';
16
17 @override
18 String? get title => S.current.wallet;
19
20 @override
21 bool get gradientBackground => true;
22
23 @override
24 Widget Function(BuildContext, Widget) get rootWrapper =>
25 (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
26
27 @override
28 bool get resizeToAvoidBottomInset => false;
29
30 @override
31 Widget trailing(BuildContext context) {
32 final Uri _url = Uri.parse('https://docs.cakewallet.com/get-started/setup/');
33 return IconButton(
34 icon: Icon(
35 Icons.info_outline,
36 size: 26,
37 ),
38 onPressed: () async {
39 await launchUrl(_url);
40 },
41 );
42 }
43
44 @override
45 Widget body(BuildContext context) {
46 final welcomeImage = currentTheme.isDark ? welcomeImageDark : welcomeImageLight;
47
48 return ScrollableWithBottomSection(
49 content: Container(
50 alignment: Alignment.center,
51 padding: EdgeInsets.only(top: 64, bottom: 24, left: 24, right: 24),
52 child: ConstrainedBox(
53 constraints:
54 BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
55 child: Column(
56 mainAxisAlignment: MainAxisAlignment.spaceBetween,
57 children: <Widget>[
58 Column(
59 children: <Widget>[
60 AspectRatio(
61 aspectRatio: aspectRatioImage,
62 child: FittedBox(
63 fit: BoxFit.contain,
64 child: CakeImageWidget(imageUrl: welcomeImage),
65 ),
66 ),
67 Padding(
68 padding: EdgeInsets.only(top: 48),
69 child: highlightText(
70 context,
71 S.of(context).welcome_subtitle_new_wallet,
72 S.of(context).create_new,
73 ),
74 ),
75 SizedBox(height: 10),
76 Padding(
77 padding: EdgeInsets.only(top: 5),
78 child: highlightText(
79 context,
80 S.of(context).welcome_subtitle_restore_wallet,
81 S.of(context).restore_existing_wallet,
82 ),
83 ),
84 ],
85 ),
86 ],
87 ),
88 ),
89 ),
90 bottomSection: Column(
91 children: <Widget>[
92 Text(
93 'Please make selection below \nto create or recover your wallet.',
94 style: Theme.of(context).textTheme.bodySmall?.copyWith(
95 fontWeight: FontWeight.w500,
96 color: Theme.of(context).colorScheme.onSurfaceVariant,
97 ),
98 textAlign: TextAlign.center,
99 ),
100 Padding(
101 padding: EdgeInsets.only(top: 24),
102 child: PrimaryButton(
103 key: ValueKey('welcome_page_restore_wallet_button_key'),
104 onPressed: () {
105 Navigator.pushNamed(context, Routes.restoreOptions, arguments: true);
106 },
107 text: S.of(context).restore_restore_wallet,
108 color: Theme.of(context).colorScheme.surfaceContainer,
109 textColor: Theme.of(context).colorScheme.onSecondaryContainer,
110 ),
111 ),
112 Padding(
113 padding: EdgeInsets.only(top: 12),
114 child: PrimaryButton(
115 key: ValueKey('welcome_page_create_new_wallet_button_key'),
116 onPressed: () => Navigator.pushNamed(context, Routes.newWalletFromWelcome),
117 text: S.of(context).create_new,
118 color: Theme.of(context).colorScheme.primary,
119 textColor: Theme.of(context).colorScheme.onPrimary,
120 ),
121 ),
122 SizedBox(height: 16),
123 ],
124 ),
125 );
126 }
127
128 RichText highlightText(BuildContext context, String text, String highlightWord) {
129 final regex = RegExp(highlightWord, caseSensitive: false);
130 final matches = regex.allMatches(text);
131
132 if (matches.isEmpty) {
133 return RichText(
134 textAlign: TextAlign.center,
135 text: TextSpan(
136 text: text,
137 style: Theme.of(context).textTheme.bodyLarge?.copyWith(height: 1.5),
138 ),
139 );
140 }
141
142 List<InlineSpan> spans = [];
143 int lastMatchEnd = 0;
144
145 for (final match in matches) {
146 final start = match.start;
147 final end = match.end;
148
149 if (start > lastMatchEnd) {
150 spans.add(
151 TextSpan(
152 text: text.substring(lastMatchEnd, start),
153 style: Theme.of(context).textTheme.bodyLarge?.copyWith(height: 1.5),
154 ),
155 );
156 }
157
158 spans.add(
159 TextSpan(
160 text: text.substring(start, end),
161 style: Theme.of(context).textTheme.bodyLarge?.copyWith(
162 height: 1.5,
163 fontWeight: FontWeight.w700,
164 ),
165 ),
166 );
167
168 lastMatchEnd = end;
169 }
170
171 if (lastMatchEnd < text.length) {
172 spans.add(
173 TextSpan(
174 text: text.substring(lastMatchEnd),
175 style: Theme.of(context).textTheme.bodyLarge?.copyWith(height: 1.5),
176 ),
177 );
178 }
179
180 return RichText(
181 textAlign: TextAlign.center,
182 text: TextSpan(children: spans),
183 );
184 }
185 }