CWA-220 | changed menu widget; changed primary account to primary subaddress in subaddress list; applied short address if the label of a subaddress is empty; applied full address when long press on subaddress tile without label; applied biometrical authentication button when the authentication switch is on; changed dismissible icon in the node list page

Oleksandr Sobol committed Jun 5, 2020 at 12:34 UTC 289d8dca428626d40d428c7d53df99d1fa57bb9c
7 files changed +357 -308
lib/src/screens/auth/auth_page.dart
+10 -2
@@ -8,6 +8,8 @@ import 'package:cake_wallet/src/stores/auth/auth_store.dart';
8 import 'package:cake_wallet/src/screens/pin_code/pin_code.dart';
9 import 'package:cake_wallet/src/stores/settings/settings_store.dart';
10 import 'package:cake_wallet/src/domain/common/biometric_auth.dart';
11 +import 'package:cake_wallet/themes.dart';
12 +import 'package:cake_wallet/theme_changer.dart';
13
14 typedef OnAuthenticationFinished = void Function(bool, AuthPageState);
15
@@ -26,6 +28,7 @@ class AuthPageState extends State<AuthPage> {
28 final _pinCodeKey = GlobalKey<PinCodeState>();
29 final _backArrowImageDarkTheme =
30 Image.asset('assets/images/back_arrow_dark_theme.png');
31 + final _backArrowImage = Image.asset('assets/images/back_arrow.png');
32
33 void changeProcessText(String text) {
34 _key.currentState.showSnackBar(
@@ -39,6 +42,10 @@ class AuthPageState extends State<AuthPage> {
42 final authStore = Provider.of<AuthStore>(context);
43 final settingsStore = Provider.of<SettingsStore>(context);
44
45 + final _themeChanger = Provider.of<ThemeChanger>(context);
46 + final _backButton = _themeChanger.getTheme() == Themes.darkTheme
47 + ? _backArrowImageDarkTheme : _backArrowImage;
48 +
49 if (settingsStore.allowBiometricalAuthentication) {
50 WidgetsBinding.instance.addPostFrameCallback((_) {
51 final biometricAuth = BiometricAuth();
@@ -134,7 +141,7 @@ class AuthPageState extends State<AuthPage> {
141 splashColor: Colors.transparent,
142 padding: EdgeInsets.all(0),
143 onPressed: () => Navigator.of(context).pop(),
137 - child: _backArrowImageDarkTheme),
144 + child: _backButton),
145 ),
146 )
147 : Container(),
@@ -146,6 +153,7 @@ class AuthPageState extends State<AuthPage> {
153 (pin, _) => authStore.auth(
154 password: pin.fold('', (ac, val) => ac + '$val')),
155 false,
149 - _pinCodeKey));
156 + _pinCodeKey,
157 + authStore: authStore,));
158 }
159 }
lib/src/screens/dashboard/dashboard_page.dart
+11 -11
@@ -28,6 +28,7 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
28
29 return SafeArea(
30 child: Scaffold(
31 + endDrawer: MenuWidget(),
32 body: Container(
33 decoration: BoxDecoration(
34 gradient: LinearGradient(
@@ -49,17 +50,16 @@ class DashboardPageBodyState extends State<DashboardPageBody> {
50 width: 44,
51 child: ButtonTheme(
52 minWidth: double.minPositive,
52 - child: FlatButton(
53 - highlightColor: Colors.transparent,
54 - splashColor: Colors.transparent,
55 - padding: EdgeInsets.all(0),
56 - onPressed: () async {
57 - await showDialog<void>(
58 - builder: (_) => MenuWidget(),
59 - context: context
60 - );
61 - },
62 - child: menuButton),
53 + child: Builder(
54 + builder: (context) {
55 + return FlatButton(
56 + highlightColor: Colors.transparent,
57 + splashColor: Colors.transparent,
58 + padding: EdgeInsets.all(0),
59 + onPressed: () => Scaffold.of(context).openEndDrawer(),
60 + child: menuButton);
61 + }
62 + ),
63 ),
64 ),
65 ),
lib/src/screens/dashboard/widgets/menu_widget.dart
+164 -192
@@ -1,7 +1,5 @@
1 -import 'dart:async';
1 import 'dart:ui';
2 import 'package:flutter/material.dart';
4 -import 'package:cake_wallet/palette.dart';
3 import 'package:cake_wallet/src/screens/dashboard/wallet_menu.dart';
4 import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
5 import 'package:provider/provider.dart';
@@ -19,7 +17,6 @@ class MenuWidgetState extends State<MenuWidget> {
17 double screenWidth;
18 double screenHeight;
19 double opacity;
22 - bool isDraw;
20
21 double headerHeight;
22 double tileHeight;
@@ -32,7 +29,6 @@ class MenuWidgetState extends State<MenuWidget> {
29 screenWidth = 0;
30 screenHeight = 0;
31 opacity = 0;
35 - isDraw = false;
32
33 headerHeight = 120;
34 tileHeight = 75;
@@ -59,10 +55,6 @@ class MenuWidgetState extends State<MenuWidget> {
55 fromBottomEdge *= scale;
56 }
57 });
62 -
63 - Timer(Duration(milliseconds: 350), () =>
64 - setState(() => isDraw = true)
65 - );
58 }
59
60 @override
@@ -71,194 +63,174 @@ class MenuWidgetState extends State<MenuWidget> {
63 final walletStore = Provider.of<WalletStore>(context);
64 final itemCount = walletMenu.items.length;
65
74 - return GestureDetector(
75 - onTap: () => Navigator.of(context).pop(),
76 - child: Container(
77 - color: Colors.transparent,
78 - child: BackdropFilter(
79 - filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0),
66 + return Row(
67 + mainAxisSize: MainAxisSize.max,
68 + crossAxisAlignment: CrossAxisAlignment.center,
69 + children: <Widget>[
70 + Padding(
71 + padding: EdgeInsets.only(left: 24),
72 child: Container(
81 - decoration: BoxDecoration(color: PaletteDark.darkNightBlue.withOpacity(0.75)),
82 - child: Row(
83 - mainAxisSize: MainAxisSize.max,
84 - crossAxisAlignment: CrossAxisAlignment.center,
85 - children: <Widget>[
86 - Padding(
87 - padding: EdgeInsets.only(left: 24),
88 - child: isDraw
89 - ? Container(
90 - height: 60,
91 - width: 4,
92 - decoration: BoxDecoration(
93 - borderRadius: BorderRadius.all(Radius.circular(2)),
94 - color: Theme.of(context).hintColor //
95 - ),
96 - )
97 - : Container(
98 - height: 60,
99 - width: 4,
100 - )
73 + height: 60,
74 + width: 4,
75 + decoration: BoxDecoration(
76 + borderRadius: BorderRadius.all(Radius.circular(2)),
77 + color: Theme.of(context).hintColor
78 + ),
79 + )
80 + ),
81 + SizedBox(width: 12),
82 + Expanded(
83 + child: GestureDetector(
84 + onTap: () => null,
85 + child: Container(
86 + width: menuWidth,
87 + height: double.infinity,
88 + decoration: BoxDecoration(
89 + borderRadius: BorderRadius.only(
90 + topLeft: Radius.circular(24),
91 + bottomLeft: Radius.circular(24)),
92 + color: Theme.of(context).primaryTextTheme.display1.color
93 ),
102 - SizedBox(width: 12),
103 - Expanded(
104 - child: GestureDetector(
105 - onTap: () => null,
106 - child: Container(
107 - width: double.infinity,
108 - height: double.infinity,
109 - alignment: Alignment.centerRight,
110 - child: AnimatedContainer(
111 - alignment: Alignment.centerLeft,
112 - width: menuWidth,
113 - height: double.infinity,
114 - duration: Duration(milliseconds: 500),
115 - curve: Curves.fastOutSlowIn,
116 - decoration: BoxDecoration(
117 - borderRadius: BorderRadius.only(topLeft: Radius.circular(24), bottomLeft: Radius.circular(24)),
118 - color: Theme.of(context).primaryTextTheme.display1.color.withOpacity(opacity)
94 + child: ClipRRect(
95 + borderRadius: BorderRadius.only(
96 + topLeft: Radius.circular(24),
97 + bottomLeft: Radius.circular(24)),
98 + child: ListView.separated(
99 + itemBuilder: (_, index) {
100 +
101 + if (index == 0) {
102 + return Container(
103 + height: headerHeight,
104 + padding: EdgeInsets.only(
105 + left: 24,
106 + top: fromTopEdge,
107 + right: 24,
108 + bottom: fromBottomEdge),
109 + decoration: BoxDecoration(
110 + borderRadius: BorderRadius.only(topLeft: Radius.circular(24)),
111 + color: Theme.of(context).primaryTextTheme.display2.color
112 + ),
113 + child: Row(
114 + mainAxisAlignment: MainAxisAlignment.start,
115 + children: <Widget>[
116 + moneroIcon,
117 + SizedBox(width: 16),
118 + Expanded(
119 + child: Container(
120 + height: 40,
121 + child: Column(
122 + crossAxisAlignment: CrossAxisAlignment.start,
123 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
124 + children: <Widget>[
125 + Text(
126 + walletStore.name,
127 + style: TextStyle(
128 + color: Theme.of(context).primaryTextTheme.title.color,
129 + decoration: TextDecoration.none,
130 + fontFamily: 'Lato',
131 + fontSize: 20,
132 + fontWeight: FontWeight.bold
133 + ),
134 + ),
135 + Text(
136 + walletStore.account.label,
137 + style: TextStyle(
138 + color: Theme.of(context).primaryTextTheme.caption.color,
139 + decoration: TextDecoration.none,
140 + fontFamily: 'Lato',
141 + fontSize: 12
142 + ),
143 + )
144 + ],
145 + ),
146 + )
147 + )
148 + ],
149 + ),
150 + );
151 + }
152 +
153 + index -= 1;
154 + final item = walletMenu.items[index];
155 + final image = walletMenu.images[index] ?? Offstage();
156 +
157 + return GestureDetector(
158 + onTap: () {
159 + Navigator.of(context).pop();
160 + walletMenu.action(index);
161 + },
162 + child: index == itemCount - 1
163 + ? Container(
164 + height: headerHeight,
165 + padding: EdgeInsets.only(
166 + left: 24,
167 + right: 24,
168 + top: fromBottomEdge,
169 + bottom: fromTopEdge),
170 + alignment: Alignment.topLeft,
171 + decoration: BoxDecoration(
172 + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(24)),
173 + color: Theme.of(context).primaryTextTheme.display1.color,
174 + ),
175 + child: Row(
176 + mainAxisAlignment: MainAxisAlignment.start,
177 + crossAxisAlignment: CrossAxisAlignment.center,
178 + children: <Widget>[
179 + image,
180 + SizedBox(width: 16),
181 + Expanded(
182 + child: Text(
183 + item,
184 + style: TextStyle(
185 + decoration: TextDecoration.none,
186 + color: Theme.of(context).primaryTextTheme.title.color,
187 + fontFamily: 'Lato',
188 + fontSize: 20,
189 + fontWeight: FontWeight.bold
190 + ),
191 + )
192 + )
193 + ],
194 + ),
195 + )
196 + : Container(
197 + height: tileHeight,
198 + padding: EdgeInsets.only(left: 24, right: 24),
199 + color: Theme.of(context).primaryTextTheme.display1.color,
200 + child: Row(
201 + mainAxisAlignment: MainAxisAlignment.start,
202 + crossAxisAlignment: CrossAxisAlignment.center,
203 + children: <Widget>[
204 + image,
205 + SizedBox(width: 16),
206 + Expanded(
207 + child: Text(
208 + item,
209 + style: TextStyle(
210 + decoration: TextDecoration.none,
211 + color: Theme.of(context).primaryTextTheme.title.color,
212 + fontFamily: 'Lato',
213 + fontSize: 20,
214 + fontWeight: FontWeight.bold
215 + ),
216 + )
217 + )
218 + ],
219 + ),
220 ),
120 - child: isDraw
121 - ? ListView.separated(
122 - itemBuilder: (_, index) {
123 -
124 - if (index == 0) {
125 - return Container(
126 - height: headerHeight,
127 - padding: EdgeInsets.only(
128 - left: 24,
129 - top: fromTopEdge,
130 - right: 24,
131 - bottom: fromBottomEdge),
132 - decoration: BoxDecoration(
133 - borderRadius: BorderRadius.only(topLeft: Radius.circular(24)),
134 - color: Theme.of(context).primaryTextTheme.display2.color
135 - ),
136 - child: Row(
137 - mainAxisAlignment: MainAxisAlignment.start,
138 - children: <Widget>[
139 - moneroIcon,
140 - SizedBox(width: 16),
141 - Expanded(
142 - child: Container(
143 - height: 40,
144 - child: Column(
145 - crossAxisAlignment: CrossAxisAlignment.start,
146 - mainAxisAlignment: MainAxisAlignment.spaceBetween,
147 - children: <Widget>[
148 - Text(
149 - walletStore.name,
150 - style: TextStyle(
151 - color: Theme.of(context).primaryTextTheme.title.color,
152 - decoration: TextDecoration.none,
153 - fontFamily: 'Lato',
154 - fontSize: 20,
155 - fontWeight: FontWeight.bold
156 - ),
157 - ),
158 - Text(
159 - walletStore.account.label,
160 - style: TextStyle(
161 - color: Theme.of(context).primaryTextTheme.caption.color,
162 - decoration: TextDecoration.none,
163 - fontFamily: 'Lato',
164 - fontSize: 12
165 - ),
166 - )
167 - ],
168 - ),
169 - )
170 - )
171 - ],
172 - ),
173 - );
174 - }
175 -
176 - index -= 1;
177 - final item = walletMenu.items[index];
178 - final image = walletMenu.images[index] ?? Offstage();
179 -
180 - return GestureDetector(
181 - onTap: () {
182 - Navigator.of(context).pop();
183 - walletMenu.action(index);
184 - },
185 - child: index == itemCount - 1
186 - ? Container(
187 - height: headerHeight,
188 - padding: EdgeInsets.only(
189 - left: 24,
190 - right: 24,
191 - top: fromBottomEdge,
192 - bottom: fromTopEdge),
193 - alignment: Alignment.topLeft,
194 - decoration: BoxDecoration(
195 - borderRadius: BorderRadius.only(bottomLeft: Radius.circular(24)),
196 - color: Theme.of(context).primaryTextTheme.display1.color,
197 - ),
198 - child: Row(
199 - mainAxisAlignment: MainAxisAlignment.start,
200 - crossAxisAlignment: CrossAxisAlignment.center,
201 - children: <Widget>[
202 - image,
203 - SizedBox(width: 16),
204 - Expanded(
205 - child: Text(
206 - item,
207 - style: TextStyle(
208 - decoration: TextDecoration.none,
209 - color: Theme.of(context).primaryTextTheme.title.color,
210 - fontFamily: 'Lato',
211 - fontSize: 20,
212 - fontWeight: FontWeight.bold
213 - ),
214 - )
215 - )
216 - ],
217 - ),
218 - )
219 - : Container(
220 - height: tileHeight,
221 - padding: EdgeInsets.only(left: 24, right: 24),
222 - color: Theme.of(context).primaryTextTheme.display1.color,
223 - child: Row(
224 - mainAxisAlignment: MainAxisAlignment.start,
225 - crossAxisAlignment: CrossAxisAlignment.center,
226 - children: <Widget>[
227 - image,
228 - SizedBox(width: 16),
229 - Expanded(
230 - child: Text(
231 - item,
232 - style: TextStyle(
233 - decoration: TextDecoration.none,
234 - color: Theme.of(context).primaryTextTheme.title.color,
235 - fontFamily: 'Lato',
236 - fontSize: 20,
237 - fontWeight: FontWeight.bold
238 - ),
239 - )
240 - )
241 - ],
242 - ),
243 - ),
244 - );
245 - },
246 - separatorBuilder: (_, index) =>
247 - Container(
248 - height: 1,
249 - color: Theme.of(context).dividerColor,
250 - ),
251 - itemCount: itemCount + 1)
252 - : Offstage()
253 - ),
254 - ),
255 - )
256 - )
257 - ],
221 + );
222 + },
223 + separatorBuilder: (_, index) =>
224 + Container(
225 + height: 1,
226 + color: Theme.of(context).dividerColor,
227 + ),
228 + itemCount: itemCount + 1),
229 + ),
230 + ),
231 )
259 - ),
260 - ),
261 - ),
232 + )
233 + ],
234 );
235 }
236 }
\ No newline at end of file
lib/src/screens/nodes/nodes_list_page.dart
+6 -4
@@ -77,8 +77,6 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
77 final nodeList = Provider.of<NodeListStore>(context);
78 final settings = Provider.of<SettingsStore>(context);
79
80 - final trashImage = Image.asset('assets/images/trash.png', height: 32, width: 32, color: Colors.white);
81 -
80 final currentColor = Theme.of(context).accentTextTheme.subtitle.decorationColor;
81 final notCurrentColor = Theme.of(context).accentTextTheme.title.backgroundColor;
82
@@ -194,12 +192,16 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
192 await nodeList.remove(node: node),
193 direction: DismissDirection.endToStart,
194 background: Container(
197 - padding: EdgeInsets.only(right: 10.0, top: 2),
195 + padding: EdgeInsets.only(right: 10.0),
196 alignment: AlignmentDirectional.centerEnd,
197 color: Palette.red,
198 child: Column(
199 + mainAxisAlignment: MainAxisAlignment.spaceEvenly,
200 children: <Widget>[
202 - trashImage,
201 + const Icon(
202 + CupertinoIcons.delete,
203 + color: Colors.white,
204 + ),
205 Text(
206 S.of(context).delete,
207 style: TextStyle(color: Colors.white),
lib/src/screens/pin_code/pin_code.dart
+39 -5
@@ -3,6 +3,8 @@ import 'package:flutter/material.dart';
3 import 'package:flutter/cupertino.dart';
4 import 'package:cake_wallet/src/stores/settings/settings_store.dart';
5 import 'package:cake_wallet/generated/i18n.dart';
6 +import 'package:cake_wallet/src/stores/auth/auth_store.dart';
7 +import 'package:cake_wallet/src/domain/common/biometric_auth.dart';
8
9 abstract class PinCodeWidget extends StatefulWidget {
10 PinCodeWidget({Key key, this.onPinCodeEntered, this.hasLengthSwitcher})
@@ -14,21 +16,26 @@ abstract class PinCodeWidget extends StatefulWidget {
16
17 class PinCode extends PinCodeWidget {
18 PinCode(Function(List<int> pin, PinCodeState state) onPinCodeEntered,
17 - bool hasLengthSwitcher, Key key)
19 + bool hasLengthSwitcher, Key key, {this.authStore})
20 : super(
21 key: key,
22 onPinCodeEntered: onPinCodeEntered,
23 hasLengthSwitcher: hasLengthSwitcher);
24
25 + final AuthStore authStore;
26 +
27 @override
24 - PinCodeState createState() => PinCodeState();
28 + PinCodeState createState() => PinCodeState(authStore: authStore);
29 }
30
31 class PinCodeState<T extends PinCodeWidget> extends State<T> {
32 + PinCodeState({this.authStore});
33 static const defaultPinLength = 4;
34 static const sixPinLength = 6;
35 static const fourPinLength = 4;
36 final _gridViewKey = GlobalKey();
37 + final AuthStore authStore;
38 + final _key = GlobalKey<ScaffoldState>();
39
40 int pinLength = defaultPinLength;
41 List<int> pin = List<int>.filled(defaultPinLength, null);
@@ -83,9 +90,11 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
90 }
91
92 @override
86 - Widget build(BuildContext context) => Scaffold(body: body(context));
93 + Widget build(BuildContext context) => Scaffold(key: _key, body: body(context));
94
95 Widget body(BuildContext context) {
96 + final settingsStore = Provider.of<SettingsStore>(context);
97 +
98 final deleteIconImage = Image.asset(
99 'assets/images/delete_icon.png',
100 color: Theme.of(context).primaryTextTheme.title.color,
@@ -161,10 +170,35 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
170 margin: EdgeInsets.only(
171 left: marginLeft, right: marginRight),
172 child: FlatButton(
164 - onPressed: () {},
173 + onPressed: (widget.hasLengthSwitcher ||
174 + !settingsStore.allowBiometricalAuthentication)
175 + ? null
176 + : () {
177 + if (authStore != null) {
178 + WidgetsBinding.instance.addPostFrameCallback((_) {
179 + final biometricAuth = BiometricAuth();
180 + biometricAuth.isAuthenticated().then(
181 + (isAuth) {
182 + if (isAuth) {
183 + authStore.biometricAuth();
184 + _key.currentState.showSnackBar(
185 + SnackBar(
186 + content: Text(S.of(context).authenticated),
187 + backgroundColor: Colors.green,
188 + ),
189 + );
190 + }
191 + }
192 + );
193 + });
194 + }
195 + },
196 color: Theme.of(context).backgroundColor,
197 shape: CircleBorder(),
167 - child: faceImage,
198 + child: (widget.hasLengthSwitcher ||
199 + !settingsStore.allowBiometricalAuthentication)
200 + ? Offstage()
201 + : faceImage,
202 ),
203 );
204 } else if (index == 10) {
lib/src/screens/receive/receive_page.dart
+114 -94
@@ -245,110 +245,130 @@ class ReceivePageState extends State<ReceivePage> {
245 ),
246 ),
247 Observer(
248 - builder: (_) => ListView.separated(
249 - separatorBuilder: (context, index) => Divider(
250 - height: 1,
251 - color: Theme.of(context).dividerColor,
252 - ),
253 - shrinkWrap: true,
254 - physics: NeverScrollableScrollPhysics(),
255 - itemCount: subaddressListStore.subaddresses.length + 2,
256 - itemBuilder: (context, index) {
248 + builder: (_) {
249 + subaddressListStore.updateShortAddressShow();
250
258 - if (index == 0) {
259 - return ClipRRect(
260 - borderRadius: BorderRadius.only(
261 - topLeft: Radius.circular(24),
262 - topRight: Radius.circular(24)
263 - ),
264 - child: HeaderTile(
265 - onTap: () async {
266 - await showDialog<void>(
267 - context: context,
268 - builder: (BuildContext context) {
269 - return AccountListPage(accountListStore: accountListStore);
270 - }
271 - );
272 - },
273 - title: walletStore.account.label,
251 + return ListView.separated(
252 + separatorBuilder: (context, index) => Divider(
253 + height: 1,
254 + color: Theme.of(context).dividerColor,
255 + ),
256 + shrinkWrap: true,
257 + physics: NeverScrollableScrollPhysics(),
258 + itemCount: subaddressListStore.subaddresses.length + 2,
259 + itemBuilder: (context, index) {
260 +
261 + if (index == 0) {
262 + return ClipRRect(
263 + borderRadius: BorderRadius.only(
264 + topLeft: Radius.circular(24),
265 + topRight: Radius.circular(24)
266 + ),
267 + child: HeaderTile(
268 + onTap: () async {
269 + await showDialog<void>(
270 + context: context,
271 + builder: (BuildContext context) {
272 + return AccountListPage(accountListStore: accountListStore);
273 + }
274 + );
275 + },
276 + title: walletStore.account.label,
277 + icon: Icon(
278 + Icons.arrow_forward_ios,
279 + size: 14,
280 + color: Theme.of(context).primaryTextTheme.title.color,
281 + )
282 + ),
283 + );
284 + }
285 +
286 + if (index == 1) {
287 + return HeaderTile(
288 + onTap: () => Navigator.of(context)
289 + .pushNamed(Routes.newSubaddress),
290 + title: S.of(context).subaddresses,
291 icon: Icon(
275 - Icons.arrow_forward_ios,
276 - size: 14,
292 + Icons.add,
293 + size: 20,
294 color: Theme.of(context).primaryTextTheme.title.color,
295 )
279 - ),
280 - );
281 - }
296 + );
297 + }
298
283 - if (index == 1) {
284 - return HeaderTile(
285 - onTap: () => Navigator.of(context)
286 - .pushNamed(Routes.newSubaddress),
287 - title: S.of(context).subaddresses,
288 - icon: Icon(
289 - Icons.add,
290 - size: 20,
291 - color: Theme.of(context).primaryTextTheme.title.color,
292 - )
293 - );
294 - }
299 + index -= 2;
300
296 - index -= 2;
301 + return Observer(
302 + builder: (_) {
303 + final subaddress = subaddressListStore.subaddresses[index];
304 + final isCurrent =
305 + walletStore.subaddress.address == subaddress.address;
306
298 - return Observer(
299 - builder: (_) {
300 - final subaddress = subaddressListStore.subaddresses[index];
301 - final isCurrent =
302 - walletStore.subaddress.address == subaddress.address;
307 + String shortAddress = subaddress.address;
308 + shortAddress = shortAddress.replaceRange(8, shortAddress.length - 8, '...');
309
304 - final label = subaddress.label.isNotEmpty
305 - ? subaddress.label
306 - : subaddress.address;
310 + final content = Observer(
311 + builder: (_) {
312 + final isShortAddressShow = subaddressListStore.isShortAddressShow[index];
313
308 - final content = InkWell(
309 - onTap: () => walletStore.setSubaddress(subaddress),
310 - child: Container(
311 - color: isCurrent ? currentColor : notCurrentColor,
312 - padding: EdgeInsets.only(
313 - left: 24,
314 - right: 24,
315 - top: 28,
316 - bottom: 28
317 - ),
318 - child: Text(
319 - label,
320 - style: TextStyle(
321 - fontSize: subaddress.label.isNotEmpty
322 - ? 18 : 10,
323 - fontWeight: FontWeight.bold,
324 - color: isCurrent
325 - ? currentTextColor
326 - : notCurrentTextColor,
327 - ),
328 - ),
329 - ),
330 - );
314 + final label = index == 0
315 + ? 'Primary subaddress'
316 + : subaddress.label.isNotEmpty
317 + ? subaddress.label
318 + : isShortAddressShow ? shortAddress : subaddress.address;
319 +
320 + return InkWell(
321 + onTap: () => walletStore.setSubaddress(subaddress),
322 + onLongPress: () {
323 + if (subaddress.label.isNotEmpty) {
324 + return;
325 + }
326 + subaddressListStore.setShortAddressShow(index, !isShortAddressShow);
327 + },
328 + child: Container(
329 + color: isCurrent ? currentColor : notCurrentColor,
330 + padding: EdgeInsets.only(
331 + left: 24,
332 + right: 24,
333 + top: 28,
334 + bottom: 28
335 + ),
336 + child: Text(
337 + label,
338 + style: TextStyle(
339 + fontSize: 18,
340 + fontWeight: FontWeight.bold,
341 + color: isCurrent
342 + ? currentTextColor
343 + : notCurrentTextColor,
344 + ),
345 + ),
346 + ),
347 + );
348 + }
349 + );
350
332 - return isCurrent
333 - ? content
334 - : Slidable(
335 - key: Key(subaddress.address),
336 - actionPane: SlidableDrawerActionPane(),
337 - child: content,
338 - secondaryActions: <Widget>[
339 - IconSlideAction(
340 - caption: S.of(context).edit,
341 - color: Theme.of(context).primaryTextTheme.overline.color,
342 - icon: Icons.edit,
343 - onTap: () => Navigator.of(context)
344 - .pushNamed(Routes.newSubaddress, arguments: subaddress),
345 - )
346 - ]
347 - );
348 - }
349 - );
350 - }
351 - )
351 + return isCurrent || index == 0
352 + ? content
353 + : Slidable(
354 + key: Key(subaddress.address),
355 + actionPane: SlidableDrawerActionPane(),
356 + child: content,
357 + secondaryActions: <Widget>[
358 + IconSlideAction(
359 + caption: S.of(context).edit,
360 + color: Theme.of(context).primaryTextTheme.overline.color,
361 + icon: Icons.edit,
362 + onTap: () => Navigator.of(context)
363 + .pushNamed(Routes.newSubaddress, arguments: subaddress),
364 + )
365 + ]
366 + );
367 + }
368 + );
369 + }
370 + );
371 + }
372 ),
373 ],
374 ),
lib/src/stores/subaddress_list/subaddress_list_store.dart
+13
@@ -15,6 +15,7 @@ class SubaddressListStore = SubaddressListStoreBase with _$SubaddressListStore;
15 abstract class SubaddressListStoreBase with Store {
16 SubaddressListStoreBase({@required WalletService walletService}) {
17 subaddresses = ObservableList<Subaddress>();
18 + isShortAddressShow = ObservableList<bool>();
19
20 if (walletService.currentWallet != null) {
21 _onWalletChanged(walletService.currentWallet);
@@ -27,12 +28,20 @@ abstract class SubaddressListStoreBase with Store {
28 @observable
29 ObservableList<Subaddress> subaddresses;
30
31 + @observable
32 + ObservableList<bool> isShortAddressShow;
33 +
34 SubaddressList _subaddressList;
35 StreamSubscription<Wallet> _onWalletChangeSubscription;
36 StreamSubscription<List<Subaddress>> _onSubaddressesChangeSubscription;
37 StreamSubscription<Account> _onAccountChangeSubscription;
38 Account _account;
39
40 + @action
41 + void setShortAddressShow(int index, bool isShow) {
42 + isShortAddressShow[index] = isShow;
43 + }
44 +
45 @override
46 void dispose() {
47 if (_onSubaddressesChangeSubscription != null) {
@@ -47,6 +56,10 @@ abstract class SubaddressListStoreBase with Store {
56 super.dispose();
57 }
58
59 + void updateShortAddressShow() {
60 + isShortAddressShow = ObservableList.of(List.generate(subaddresses.length, (i) => true));
61 + }
62 +
63 Future<void> _updateSubaddressList({int accountIndex}) async {
64 await _subaddressList.refresh(accountIndex: accountIndex);
65 subaddresses = ObservableList.of(_subaddressList.getAll());