dev
dart 244 lines 9.36 KB
Raw
1 import 'dart:io';
2
3 import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
4 import 'package:cake_wallet/src/widgets/scrollable_with_bottom_section.dart';
5 import 'package:flutter/gestures.dart';
6 import 'package:flutter/material.dart';
7 import 'package:cake_wallet/routes.dart';
8 import 'package:cake_wallet/src/widgets/primary_button.dart';
9 import 'package:cake_wallet/src/screens/base_page.dart';
10 import 'package:cake_wallet/generated/i18n.dart';
11 import 'package:cake_wallet/wallet_type_utils.dart';
12 import '../../widgets/gradient_background.dart';
13 import '../../widgets/animated_typing_text.dart';
14
15 class CreatePinWelcomePage extends BasePage {
16 CreatePinWelcomePage(this.isWalletPasswordDirectInput);
17
18 final bool isWalletPasswordDirectInput;
19
20 static const imageAspectRatio = 1.25;
21 static const imageMaxWidth = 600.0;
22 final welcomeImageLight = 'assets/images/welcome_light_theme.svg';
23 final welcomeImageDark = 'assets/images/welcome_dark_theme.svg';
24 final cakeLogoLight = 'assets/images/cake_logo_light.svg';
25 final cakeLogoDark = 'assets/images/cake_logo_dark.svg';
26
27 String appTitle(BuildContext context) {
28 if (isMoneroOnly) {
29 return S.of(context).monero_com;
30 }
31
32 return S.of(context).cake_wallet;
33 }
34
35 String appDescription(BuildContext context) {
36 if (isMoneroOnly) {
37 return S.of(context).monero_com_wallet_text;
38 }
39
40 return S.of(context).payment_made_easy;
41 }
42
43 @override
44 bool get gradientBackground => true;
45
46 @override
47 Widget Function(BuildContext, Widget) get rootWrapper =>
48 (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
49
50 @override
51 Widget build(BuildContext context) {
52 return Scaffold(
53 backgroundColor: Theme.of(context).colorScheme.surface,
54 resizeToAvoidBottomInset: false,
55 body: Builder(
56 builder: (BuildContext context) {
57 return Container(
58 decoration: BoxDecoration(
59 color: Theme.of(context).colorScheme.surface,
60 gradient: LinearGradient(
61 colors: [
62 Theme.of(context).colorScheme.surface,
63 currentTheme.customColors.backgroundGradientColor,
64 ],
65 begin: Alignment.topCenter,
66 end: Alignment.bottomCenter,
67 ),
68 ),
69 child: body(context),
70 );
71 },
72 ),
73 );
74 }
75
76 @override
77 Widget body(BuildContext context) {
78 String welcomeImage;
79 String cakeLogoThemed;
80
81 if (currentTheme.isDark) {
82 welcomeImage = welcomeImageDark;
83 cakeLogoThemed = cakeLogoDark;
84 } else {
85 welcomeImage = welcomeImageLight;
86 cakeLogoThemed = cakeLogoLight;
87 }
88
89 return PopScope(
90 canPop: false,
91 child: SafeArea(
92 top: false,
93 bottom: Platform.isAndroid,
94 child: ScrollableWithBottomSection(
95 contentPadding: EdgeInsets.zero,
96 content: Container(
97 alignment: Alignment.center,
98 child: ConstrainedBox(
99 constraints: BoxConstraints(maxWidth: imageMaxWidth),
100 child: Stack(
101 alignment: Alignment.center,
102 clipBehavior: Clip.none,
103 children: <Widget>[
104 AspectRatio(
105 aspectRatio: imageAspectRatio,
106 child: FittedBox(
107 child: CakeImageWidget(
108 imageUrl: welcomeImage,
109 fit: BoxFit.contain,
110 ),
111 fit: BoxFit.contain,
112 ),
113 ),
114 Positioned(
115 top: (imageMaxWidth / imageAspectRatio) * 0.57,
116 child: Column(
117 children: <Widget>[
118 Text(
119 S.current.welcome,
120 style: Theme.of(context).textTheme.displayLarge?.copyWith(
121 fontWeight: FontWeight.w700,
122 fontSize: 60,
123 letterSpacing: 2.5,
124 color: Theme.of(context).colorScheme.primary,
125 ),
126 textAlign: TextAlign.center,
127 ),
128 SizedBox(height: 16),
129 Row(
130 mainAxisAlignment: MainAxisAlignment.center,
131 children: [
132 Text(
133 S.current.to.toLowerCase(),
134 style: Theme.of(context).textTheme.titleMedium,
135 textAlign: TextAlign.center,
136 ),
137 SizedBox(width: 8),
138 if (!isMoneroOnly) ...[
139 SizedBox(width: 8),
140 CakeImageWidget(
141 height: 40,
142 imageUrl: cakeLogoThemed,
143 fit: BoxFit.contain,
144 ),
145 SizedBox(width: 8),
146 ],
147 Text(
148 appTitle(context),
149 style: Theme.of(context).textTheme.titleLarge?.copyWith(
150 fontWeight: FontWeight.w600,
151 ),
152 textAlign: TextAlign.center,
153 ),
154 ],
155 ),
156 SizedBox(height: 48),
157 if (isMoneroOnly)
158 Text(
159 appDescription(context),
160 style: Theme.of(context)
161 .textTheme
162 .bodyLarge
163 ?.copyWith(fontWeight: FontWeight.w500),
164 textAlign: TextAlign.center,
165 ),
166 if (!isMoneroOnly)
167 Row(
168 mainAxisAlignment: MainAxisAlignment.center,
169 mainAxisSize: MainAxisSize.min,
170 children: [
171 AnimatedTypingText(
172 words: [S.current.payments, S.current.privacy, S.current.security],
173 style: Theme.of(context).textTheme.titleLarge?.copyWith(
174 fontWeight: FontWeight.w600,
175 color: Theme.of(context).colorScheme.primary,
176 ),
177 cursorColor: Theme.of(context).colorScheme.primary,
178 cursorHeight: 28,
179 cursorWidth: 4,
180 ),
181 SizedBox(width: 4),
182 Text(
183 S.current.made_easy,
184 style: Theme.of(context).textTheme.titleLarge?.copyWith(
185 fontWeight: FontWeight.w600,
186 ),
187 ),
188 ],
189 ),
190 ],
191 ),
192 ),
193 ],
194 ),
195 ),
196 ),
197 bottomSection: Column(
198 children: [
199 RichText(
200 textAlign: TextAlign.center,
201 text: TextSpan(
202 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
203 color: Theme.of(context).colorScheme.onSurfaceVariant,
204 ),
205 children: [
206 TextSpan(
207 text: 'By continuing, you agree to our ',
208 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
209 color: Theme.of(context).colorScheme.onSurfaceVariant,
210 fontWeight: FontWeight.w500,
211 ),
212 ),
213 TextSpan(
214 text: 'Terms of Service',
215 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
216 color: Theme.of(context).colorScheme.onSurfaceVariant,
217 decoration: TextDecoration.underline,
218 fontWeight: FontWeight.w700,
219 ),
220 recognizer: TapGestureRecognizer()
221 ..onTap = () => Navigator.pushNamed(context, Routes.readDisclaimer),
222 ),
223 ],
224 ),
225 ),
226 Padding(
227 padding: EdgeInsets.only(top: 24),
228 child: PrimaryButton(
229 key: ValueKey('create_pin_welcome_page_create_a_pin_button_key'),
230 onPressed: () => Navigator.pushNamed(context, Routes.welcomeWallet),
231 text:
232 isWalletPasswordDirectInput ? S.current.set_up_a_wallet : S.current.set_a_pin,
233 color: Theme.of(context).colorScheme.primary,
234 textColor: Theme.of(context).colorScheme.onPrimary,
235 ),
236 ),
237 SizedBox(height: 16),
238 ],
239 ),
240 ),
241 ),
242 );
243 }
244 }