mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 03:59:23 +00:00
Cw 304 enhance talkback (#887)
* fix(#536): add talkback support to missing main and common elements * fix(#564): add talkback support for slidable node items & addresses page * fix: add missing delete button from add pin widget
This commit is contained in:
parent
9e7009f339
commit
5ad67b62a5
8 changed files with 230 additions and 226 deletions
|
@ -58,19 +58,24 @@ abstract class BasePage extends StatelessWidget {
|
||||||
|
|
||||||
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context);
|
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context);
|
||||||
|
|
||||||
return SizedBox(
|
return MergeSemantics(
|
||||||
height: isMobileView ? 37 : 45,
|
child: SizedBox(
|
||||||
width: isMobileView ? 37 : 45,
|
height: isMobileView ? 37 : 45,
|
||||||
child: ButtonTheme(
|
width: isMobileView ? 37 : 45,
|
||||||
minWidth: double.minPositive,
|
child: ButtonTheme(
|
||||||
child: TextButton(
|
minWidth: double.minPositive,
|
||||||
style: ButtonStyle(
|
child: Semantics(
|
||||||
overlayColor: MaterialStateColor.resolveWith((states) => Colors.transparent),
|
label: canUseCloseIcon && !isMobileView ? 'Close' : 'Back',
|
||||||
|
child: TextButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
overlayColor: MaterialStateColor.resolveWith(
|
||||||
|
(states) => Colors.transparent),
|
||||||
|
),
|
||||||
|
onPressed: () => onClose(context),
|
||||||
|
child:
|
||||||
|
canUseCloseIcon && !isMobileView ? _closeButton : _backButton,
|
||||||
),
|
),
|
||||||
onPressed: () => onClose(context),
|
),
|
||||||
child: canUseCloseIcon && !isMobileView
|
|
||||||
? _closeButton
|
|
||||||
: _backButton,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -104,7 +104,7 @@ class _DashboardPageView extends BasePage {
|
||||||
//splashColor: Colors.transparent,
|
//splashColor: Colors.transparent,
|
||||||
//padding: EdgeInsets.all(0),
|
//padding: EdgeInsets.all(0),
|
||||||
onPressed: () => onOpenEndDrawer(),
|
onPressed: () => onOpenEndDrawer(),
|
||||||
child: menuButton));
|
child: Semantics(label: 'Menu', child: menuButton)));
|
||||||
}
|
}
|
||||||
|
|
||||||
final DashboardViewModel dashboardViewModel;
|
final DashboardViewModel dashboardViewModel;
|
||||||
|
@ -149,17 +149,21 @@ class _DashboardPageView extends BasePage {
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(bottom: 24, top: 10),
|
padding: EdgeInsets.only(bottom: 24, top: 10),
|
||||||
child: Observer(builder: (context) {
|
child: Observer(builder: (context) {
|
||||||
return SmoothPageIndicator(
|
return ExcludeSemantics(
|
||||||
controller: controller,
|
child: SmoothPageIndicator(
|
||||||
count: pages.length,
|
controller: controller,
|
||||||
effect: ColorTransitionEffect(
|
count: pages.length,
|
||||||
spacing: 6.0,
|
effect: ColorTransitionEffect(
|
||||||
radius: 6.0,
|
spacing: 6.0,
|
||||||
dotWidth: 6.0,
|
radius: 6.0,
|
||||||
dotHeight: 6.0,
|
dotWidth: 6.0,
|
||||||
dotColor: Theme.of(context).indicatorColor,
|
dotHeight: 6.0,
|
||||||
activeDotColor:
|
dotColor: Theme.of(context).indicatorColor,
|
||||||
Theme.of(context).accentTextTheme!.headline4!.backgroundColor!),
|
activeDotColor: Theme.of(context)
|
||||||
|
.accentTextTheme!
|
||||||
|
.headline4!
|
||||||
|
.backgroundColor!),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
)),
|
)),
|
||||||
|
@ -184,27 +188,38 @@ class _DashboardPageView extends BasePage {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: MainActions.all
|
children: MainActions.all
|
||||||
.where((element) => element.canShow?.call(dashboardViewModel) ?? true)
|
.where((element) => element.canShow?.call(dashboardViewModel) ?? true)
|
||||||
.map((action) => ActionButton(
|
.map((action) => Semantics(
|
||||||
image: Image.asset(action.image,
|
button: true,
|
||||||
height: 24,
|
enabled: (action.isEnabled
|
||||||
width: 24,
|
?.call(dashboardViewModel) ??
|
||||||
color: action.isEnabled?.call(dashboardViewModel) ?? true
|
true),
|
||||||
? Theme.of(context)
|
child: ActionButton(
|
||||||
.accentTextTheme
|
image: Image.asset(action.image,
|
||||||
.headline2!
|
height: 24,
|
||||||
.backgroundColor!
|
width: 24,
|
||||||
: Theme.of(context)
|
color: action.isEnabled?.call(
|
||||||
.accentTextTheme
|
dashboardViewModel) ??
|
||||||
.headline3!
|
true
|
||||||
.backgroundColor!),
|
? Theme.of(context)
|
||||||
title: action.name(context),
|
.accentTextTheme
|
||||||
onClick: () async => await action.onTap(context, dashboardViewModel),
|
.headline2!
|
||||||
textColor: action.isEnabled?.call(dashboardViewModel) ?? true
|
.backgroundColor!
|
||||||
? null
|
: Theme.of(context)
|
||||||
: Theme.of(context)
|
.accentTextTheme
|
||||||
.accentTextTheme
|
.headline3!
|
||||||
.headline3!
|
.backgroundColor!),
|
||||||
.backgroundColor!,
|
title: action.name(context),
|
||||||
|
onClick: () async => await action.onTap(
|
||||||
|
context, dashboardViewModel),
|
||||||
|
textColor: action.isEnabled
|
||||||
|
?.call(dashboardViewModel) ??
|
||||||
|
true
|
||||||
|
? null
|
||||||
|
: Theme.of(context)
|
||||||
|
.accentTextTheme
|
||||||
|
.headline3!
|
||||||
|
.backgroundColor!,
|
||||||
|
),
|
||||||
))
|
))
|
||||||
.toList(),
|
.toList(),
|
||||||
),
|
),
|
||||||
|
@ -222,10 +237,14 @@ class _DashboardPageView extends BasePage {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (dashboardViewModel.shouldShowMarketPlaceInDashboard) {
|
if (dashboardViewModel.shouldShowMarketPlaceInDashboard) {
|
||||||
pages.add(MarketPlacePage(dashboardViewModel: dashboardViewModel));
|
pages.add(Semantics(
|
||||||
|
label: 'Marketplace Page',
|
||||||
|
child: MarketPlacePage(dashboardViewModel: dashboardViewModel)));
|
||||||
}
|
}
|
||||||
pages.add(balancePage);
|
pages.add(Semantics(label: 'Balance Page', child: balancePage));
|
||||||
pages.add(TransactionsPage(dashboardViewModel: dashboardViewModel));
|
pages.add(Semantics(
|
||||||
|
label: 'Transactions Page',
|
||||||
|
child: TransactionsPage(dashboardViewModel: dashboardViewModel)));
|
||||||
_isEffectsInstalled = true;
|
_isEffectsInstalled = true;
|
||||||
|
|
||||||
autorun((_) async {
|
autorun((_) async {
|
||||||
|
|
|
@ -139,32 +139,35 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||||
.decorationColor!,
|
.decorationColor!,
|
||||||
width: 1.0),
|
width: 1.0),
|
||||||
),
|
),
|
||||||
suffixIcon: IconButton(
|
suffixIcon: Semantics(
|
||||||
onPressed: () async {
|
label: 'Generate Name',
|
||||||
final rName = await generateName();
|
child: IconButton(
|
||||||
FocusManager.instance.primaryFocus?.unfocus();
|
onPressed: () async {
|
||||||
|
final rName = await generateName();
|
||||||
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_controller.text = rName;
|
_controller.text = rName;
|
||||||
_walletNewVM.name = rName;
|
_walletNewVM.name = rName;
|
||||||
_controller.selection = TextSelection.fromPosition(
|
_controller.selection = TextSelection.fromPosition(
|
||||||
TextPosition(offset: _controller.text.length));
|
TextPosition(offset: _controller.text.length));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
icon: Container(
|
icon: Container(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(6.0),
|
borderRadius: BorderRadius.circular(6.0),
|
||||||
color: Theme.of(context).hintColor,
|
color: Theme.of(context).hintColor,
|
||||||
),
|
),
|
||||||
width: 34,
|
width: 34,
|
||||||
height: 34,
|
height: 34,
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
'assets/images/refresh_icon.png',
|
'assets/images/refresh_icon.png',
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.primaryTextTheme!
|
.primaryTextTheme!
|
||||||
.headline4!
|
.headline4!
|
||||||
.decorationColor!,
|
.decorationColor!,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -208,58 +208,29 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
|
||||||
const double marginLeft = 15;
|
const double marginLeft = 15;
|
||||||
|
|
||||||
if (index == 9) {
|
if (index == 9) {
|
||||||
|
// Empty container
|
||||||
return Container(
|
return Container(
|
||||||
margin: EdgeInsets.only(left: marginLeft, right: marginRight),
|
margin: EdgeInsets.only(left: marginLeft, right: marginRight),
|
||||||
child: TextButton(
|
|
||||||
onPressed: () => null,
|
|
||||||
// (widget.hasLengthSwitcher ||
|
|
||||||
// !settingsStore
|
|
||||||
// .allowBiometricalAuthentication)
|
|
||||||
// ? null
|
|
||||||
// : () {
|
|
||||||
// FIXME
|
|
||||||
// if (authStore != null) {
|
|
||||||
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
// final biometricAuth = BiometricAuth();
|
|
||||||
// biometricAuth.isAuthenticated().then(
|
|
||||||
// (isAuth) {
|
|
||||||
// if (isAuth) {
|
|
||||||
// authStore.biometricAuth();
|
|
||||||
// _key.currentState.showSnackBar(
|
|
||||||
// SnackBar(
|
|
||||||
// content: Text(S.of(context).authenticated),
|
|
||||||
// backgroundColor: Colors.green,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// FIX-ME: Style
|
|
||||||
//color: Theme.of(context).backgroundColor,
|
|
||||||
//shape: CircleBorder(),
|
|
||||||
child: Container()
|
|
||||||
// (widget.hasLengthSwitcher ||
|
|
||||||
// !settingsStore
|
|
||||||
// .allowBiometricalAuthentication)
|
|
||||||
// ? Offstage()
|
|
||||||
// : faceImage,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
} else if (index == 10) {
|
} else if (index == 10) {
|
||||||
index = 0;
|
index = 0;
|
||||||
} else if (index == 11) {
|
} else if (index == 11) {
|
||||||
return Container(
|
return MergeSemantics(
|
||||||
margin: EdgeInsets.only(left: marginLeft, right: marginRight),
|
child: Container(
|
||||||
child: TextButton(
|
margin: EdgeInsets.only(left: marginLeft, right: marginRight),
|
||||||
onPressed: () => _pop(),
|
child: Semantics(
|
||||||
style: TextButton.styleFrom(
|
label: 'Delete',
|
||||||
backgroundColor: Theme.of(context).backgroundColor,
|
button: true,
|
||||||
shape: CircleBorder(),
|
onTap: () => _pop(),
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () => _pop(),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
backgroundColor: Theme.of(context).backgroundColor,
|
||||||
|
shape: CircleBorder(),
|
||||||
|
),
|
||||||
|
child: deleteIconImage,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: deleteIconImage,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -41,26 +41,7 @@ class ReceivePage extends BasePage {
|
||||||
final FocusNode _cryptoAmountFocus;
|
final FocusNode _cryptoAmountFocus;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget leading(BuildContext context) {
|
Color get titleColor => Colors.white;
|
||||||
final _backButton = Icon(Icons.arrow_back_ios,
|
|
||||||
color: Theme.of(context).accentTextTheme!.headline2!.backgroundColor!,
|
|
||||||
size: 16,);
|
|
||||||
|
|
||||||
return SizedBox(
|
|
||||||
height: 37,
|
|
||||||
width: 37,
|
|
||||||
child: ButtonTheme(
|
|
||||||
minWidth: double.minPositive,
|
|
||||||
child: TextButton(
|
|
||||||
// FIX-ME: Style
|
|
||||||
//highlightColor: Colors.transparent,
|
|
||||||
//splashColor: Colors.transparent,
|
|
||||||
//padding: EdgeInsets.all(0),
|
|
||||||
onPressed: () => onClose(context),
|
|
||||||
child: _backButton),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget middle(BuildContext context) {
|
Widget middle(BuildContext context) {
|
||||||
|
@ -93,19 +74,22 @@ class ReceivePage extends BasePage {
|
||||||
|
|
||||||
return Material(
|
return Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: IconButton(
|
child: Semantics(
|
||||||
padding: EdgeInsets.zero,
|
label: 'Share',
|
||||||
constraints: BoxConstraints(),
|
child: IconButton(
|
||||||
highlightColor: Colors.transparent,
|
padding: EdgeInsets.zero,
|
||||||
splashColor: Colors.transparent,
|
constraints: BoxConstraints(),
|
||||||
iconSize: 25,
|
highlightColor: Colors.transparent,
|
||||||
onPressed: () {
|
splashColor: Colors.transparent,
|
||||||
ShareUtil.share(
|
iconSize: 25,
|
||||||
text: addressListViewModel.address.address,
|
onPressed: () {
|
||||||
context: context,
|
ShareUtil.share(
|
||||||
);
|
text: addressListViewModel.address.address,
|
||||||
},
|
context: context,
|
||||||
icon: shareImage
|
);
|
||||||
|
},
|
||||||
|
icon: shareImage
|
||||||
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,11 +70,16 @@ class AddressCell extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
return Slidable(
|
return Semantics(
|
||||||
key: Key(address),
|
label: 'Slidable',
|
||||||
startActionPane: _actionPane(context),
|
selected: isCurrent,
|
||||||
endActionPane: _actionPane(context),
|
enabled: !isCurrent,
|
||||||
child: cell,
|
child: Slidable(
|
||||||
|
key: Key(address),
|
||||||
|
startActionPane: _actionPane(context),
|
||||||
|
endActionPane: _actionPane(context),
|
||||||
|
child: cell,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,13 @@ class ConnectionSyncPage extends BasePage {
|
||||||
handler: (context) => Navigator.of(context).pushNamed(Routes.rescan),
|
handler: (context) => Navigator.of(context).pushNamed(Routes.rescan),
|
||||||
),
|
),
|
||||||
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||||
NodeHeaderListRow(
|
Semantics(
|
||||||
title: S.of(context).add_new_node,
|
button: true,
|
||||||
onTap: (_) async => await Navigator.of(context).pushNamed(Routes.newNode),
|
child: NodeHeaderListRow(
|
||||||
|
title: S.of(context).add_new_node,
|
||||||
|
onTap: (_) async =>
|
||||||
|
await Navigator.of(context).pushNamed(Routes.newNode),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||||
SizedBox(height: 100),
|
SizedBox(height: 100),
|
||||||
|
@ -60,31 +64,39 @@ class ConnectionSyncPage extends BasePage {
|
||||||
itemBuilder: (_, sectionIndex, index) {
|
itemBuilder: (_, sectionIndex, index) {
|
||||||
final node = nodeListViewModel.nodes[index];
|
final node = nodeListViewModel.nodes[index];
|
||||||
final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex;
|
final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex;
|
||||||
final nodeListRow = NodeListRow(
|
final nodeListRow = Semantics(
|
||||||
title: node.uriRaw,
|
label: 'Slidable',
|
||||||
isSelected: isSelected,
|
selected: isSelected,
|
||||||
isAlive: node.requestNode(),
|
enabled: !isSelected,
|
||||||
onTap: (_) async {
|
child: NodeListRow(
|
||||||
if (isSelected) {
|
title: node.uriRaw,
|
||||||
return;
|
isSelected: isSelected,
|
||||||
}
|
isAlive: node.requestNode(),
|
||||||
|
onTap: (_) async {
|
||||||
|
if (isSelected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await showPopUp<void>(
|
await showPopUp<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertWithTwoActions(
|
return AlertWithTwoActions(
|
||||||
alertTitle: S.of(context).change_current_node_title,
|
alertTitle:
|
||||||
alertContent: nodeListViewModel.getAlertContent(node.uriRaw),
|
S.of(context).change_current_node_title,
|
||||||
leftButtonText: S.of(context).cancel,
|
alertContent: nodeListViewModel
|
||||||
rightButtonText: S.of(context).change,
|
.getAlertContent(node.uriRaw),
|
||||||
actionLeftButton: () => Navigator.of(context).pop(),
|
leftButtonText: S.of(context).cancel,
|
||||||
actionRightButton: () async {
|
rightButtonText: S.of(context).change,
|
||||||
await nodeListViewModel.setAsCurrent(node);
|
actionLeftButton: () =>
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop(),
|
||||||
},
|
actionRightButton: () async {
|
||||||
);
|
await nodeListViewModel.setAsCurrent(node);
|
||||||
});
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final dismissibleRow = Slidable(
|
final dismissibleRow = Slidable(
|
||||||
|
|
|
@ -33,54 +33,59 @@ class IntroducingCard extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Padding(
|
child: MergeSemantics(
|
||||||
padding: const EdgeInsets.all(24),
|
child: Padding(
|
||||||
child: Column(
|
padding: const EdgeInsets.all(24),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
AutoSizeText(title ?? '',
|
children: [
|
||||||
style: TextStyle(
|
AutoSizeText(title ?? '',
|
||||||
fontSize: 24,
|
style: TextStyle(
|
||||||
fontFamily: 'Lato',
|
fontSize: 24,
|
||||||
fontWeight: FontWeight.bold,
|
fontFamily: 'Lato',
|
||||||
color: Theme.of(context)
|
fontWeight: FontWeight.bold,
|
||||||
.accentTextTheme!
|
color: Theme.of(context)
|
||||||
.headline2!
|
.accentTextTheme!
|
||||||
.backgroundColor!,
|
.headline2!
|
||||||
height: 1),
|
.backgroundColor!,
|
||||||
maxLines: 1,
|
height: 1),
|
||||||
textAlign: TextAlign.center),
|
maxLines: 1,
|
||||||
SizedBox(height: 14),
|
textAlign: TextAlign.center),
|
||||||
Text(subTitle ?? '',
|
SizedBox(height: 14),
|
||||||
textAlign: TextAlign.left,
|
Text(subTitle ?? '',
|
||||||
style: TextStyle(
|
textAlign: TextAlign.left,
|
||||||
fontSize: 12,
|
style: TextStyle(
|
||||||
fontFamily: 'Lato',
|
fontSize: 12,
|
||||||
color: Theme.of(context)
|
fontFamily: 'Lato',
|
||||||
.accentTextTheme!
|
color: Theme.of(context)
|
||||||
.headline2!
|
.accentTextTheme!
|
||||||
.backgroundColor!,
|
.headline2!
|
||||||
height: 1)),
|
.backgroundColor!,
|
||||||
],
|
height: 1)),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(0,16,16,0),
|
padding: const EdgeInsets.fromLTRB(0,16,16,0),
|
||||||
child: GestureDetector(
|
child: Semantics(
|
||||||
onTap: closeCard,
|
label: 'Close',
|
||||||
child: Container(
|
child: GestureDetector(
|
||||||
height: 23,
|
onTap: closeCard,
|
||||||
width: 23,
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
height: 23,
|
||||||
color: Colors.white, shape: BoxShape.circle),
|
width: 23,
|
||||||
child: Center(
|
decoration: BoxDecoration(
|
||||||
child: Image.asset(
|
color: Colors.white, shape: BoxShape.circle),
|
||||||
'assets/images/x.png',
|
child: Center(
|
||||||
color: Palette.darkBlueCraiola,
|
child: Image.asset(
|
||||||
height: 15,
|
'assets/images/x.png',
|
||||||
width: 15,
|
color: Palette.darkBlueCraiola,
|
||||||
)),
|
height: 15,
|
||||||
|
width: 15,
|
||||||
|
)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue