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:
Rafael Saes 2023-04-18 17:36:56 +00:00 committed by GitHub
parent 9e7009f339
commit 5ad67b62a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 230 additions and 226 deletions

View file

@ -58,19 +58,24 @@ abstract class BasePage extends StatelessWidget {
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context);
return SizedBox(
height: isMobileView ? 37 : 45,
width: isMobileView ? 37 : 45,
child: ButtonTheme(
minWidth: double.minPositive,
child: TextButton(
style: ButtonStyle(
overlayColor: MaterialStateColor.resolveWith((states) => Colors.transparent),
return MergeSemantics(
child: SizedBox(
height: isMobileView ? 37 : 45,
width: isMobileView ? 37 : 45,
child: ButtonTheme(
minWidth: double.minPositive,
child: Semantics(
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,
),
),
),
);

View file

@ -104,7 +104,7 @@ class _DashboardPageView extends BasePage {
//splashColor: Colors.transparent,
//padding: EdgeInsets.all(0),
onPressed: () => onOpenEndDrawer(),
child: menuButton));
child: Semantics(label: 'Menu', child: menuButton)));
}
final DashboardViewModel dashboardViewModel;
@ -149,17 +149,21 @@ class _DashboardPageView extends BasePage {
Padding(
padding: EdgeInsets.only(bottom: 24, top: 10),
child: Observer(builder: (context) {
return SmoothPageIndicator(
controller: controller,
count: pages.length,
effect: ColorTransitionEffect(
spacing: 6.0,
radius: 6.0,
dotWidth: 6.0,
dotHeight: 6.0,
dotColor: Theme.of(context).indicatorColor,
activeDotColor:
Theme.of(context).accentTextTheme!.headline4!.backgroundColor!),
return ExcludeSemantics(
child: SmoothPageIndicator(
controller: controller,
count: pages.length,
effect: ColorTransitionEffect(
spacing: 6.0,
radius: 6.0,
dotWidth: 6.0,
dotHeight: 6.0,
dotColor: Theme.of(context).indicatorColor,
activeDotColor: Theme.of(context)
.accentTextTheme!
.headline4!
.backgroundColor!),
),
);
}
)),
@ -184,27 +188,38 @@ class _DashboardPageView extends BasePage {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: MainActions.all
.where((element) => element.canShow?.call(dashboardViewModel) ?? true)
.map((action) => ActionButton(
image: Image.asset(action.image,
height: 24,
width: 24,
color: action.isEnabled?.call(dashboardViewModel) ?? true
? Theme.of(context)
.accentTextTheme
.headline2!
.backgroundColor!
: Theme.of(context)
.accentTextTheme
.headline3!
.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!,
.map((action) => Semantics(
button: true,
enabled: (action.isEnabled
?.call(dashboardViewModel) ??
true),
child: ActionButton(
image: Image.asset(action.image,
height: 24,
width: 24,
color: action.isEnabled?.call(
dashboardViewModel) ??
true
? Theme.of(context)
.accentTextTheme
.headline2!
.backgroundColor!
: Theme.of(context)
.accentTextTheme
.headline3!
.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(),
),
@ -222,10 +237,14 @@ class _DashboardPageView extends BasePage {
return;
}
if (dashboardViewModel.shouldShowMarketPlaceInDashboard) {
pages.add(MarketPlacePage(dashboardViewModel: dashboardViewModel));
pages.add(Semantics(
label: 'Marketplace Page',
child: MarketPlacePage(dashboardViewModel: dashboardViewModel)));
}
pages.add(balancePage);
pages.add(TransactionsPage(dashboardViewModel: dashboardViewModel));
pages.add(Semantics(label: 'Balance Page', child: balancePage));
pages.add(Semantics(
label: 'Transactions Page',
child: TransactionsPage(dashboardViewModel: dashboardViewModel)));
_isEffectsInstalled = true;
autorun((_) async {

View file

@ -139,32 +139,35 @@ class _WalletNameFormState extends State<WalletNameForm> {
.decorationColor!,
width: 1.0),
),
suffixIcon: IconButton(
onPressed: () async {
final rName = await generateName();
FocusManager.instance.primaryFocus?.unfocus();
suffixIcon: Semantics(
label: 'Generate Name',
child: IconButton(
onPressed: () async {
final rName = await generateName();
FocusManager.instance.primaryFocus?.unfocus();
setState(() {
_controller.text = rName;
_walletNewVM.name = rName;
_controller.selection = TextSelection.fromPosition(
TextPosition(offset: _controller.text.length));
});
},
icon: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.0),
color: Theme.of(context).hintColor,
),
width: 34,
height: 34,
child: Image.asset(
'assets/images/refresh_icon.png',
color: Theme.of(context)
.primaryTextTheme!
.headline4!
.decorationColor!,
setState(() {
_controller.text = rName;
_walletNewVM.name = rName;
_controller.selection = TextSelection.fromPosition(
TextPosition(offset: _controller.text.length));
});
},
icon: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.0),
color: Theme.of(context).hintColor,
),
width: 34,
height: 34,
child: Image.asset(
'assets/images/refresh_icon.png',
color: Theme.of(context)
.primaryTextTheme!
.headline4!
.decorationColor!,
),
),
),
),

View file

@ -208,58 +208,29 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
const double marginLeft = 15;
if (index == 9) {
// Empty container
return Container(
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) {
index = 0;
} else if (index == 11) {
return Container(
margin: EdgeInsets.only(left: marginLeft, right: marginRight),
child: TextButton(
onPressed: () => _pop(),
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).backgroundColor,
shape: CircleBorder(),
return MergeSemantics(
child: Container(
margin: EdgeInsets.only(left: marginLeft, right: marginRight),
child: Semantics(
label: 'Delete',
button: true,
onTap: () => _pop(),
child: TextButton(
onPressed: () => _pop(),
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).backgroundColor,
shape: CircleBorder(),
),
child: deleteIconImage,
),
),
child: deleteIconImage,
),
);
} else {

View file

@ -41,26 +41,7 @@ class ReceivePage extends BasePage {
final FocusNode _cryptoAmountFocus;
@override
Widget leading(BuildContext context) {
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),
),
);
}
Color get titleColor => Colors.white;
@override
Widget middle(BuildContext context) {
@ -93,19 +74,22 @@ class ReceivePage extends BasePage {
return Material(
color: Colors.transparent,
child: IconButton(
padding: EdgeInsets.zero,
constraints: BoxConstraints(),
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
iconSize: 25,
onPressed: () {
ShareUtil.share(
text: addressListViewModel.address.address,
context: context,
);
},
icon: shareImage
child: Semantics(
label: 'Share',
child: IconButton(
padding: EdgeInsets.zero,
constraints: BoxConstraints(),
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
iconSize: 25,
onPressed: () {
ShareUtil.share(
text: addressListViewModel.address.address,
context: context,
);
},
icon: shareImage
),
)
);
}

View file

@ -70,11 +70,16 @@ class AddressCell extends StatelessWidget {
),
),
));
return Slidable(
key: Key(address),
startActionPane: _actionPane(context),
endActionPane: _actionPane(context),
child: cell,
return Semantics(
label: 'Slidable',
selected: isCurrent,
enabled: !isCurrent,
child: Slidable(
key: Key(address),
startActionPane: _actionPane(context),
endActionPane: _actionPane(context),
child: cell,
),
);
}

View file

@ -41,9 +41,13 @@ class ConnectionSyncPage extends BasePage {
handler: (context) => Navigator.of(context).pushNamed(Routes.rescan),
),
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
NodeHeaderListRow(
title: S.of(context).add_new_node,
onTap: (_) async => await Navigator.of(context).pushNamed(Routes.newNode),
Semantics(
button: true,
child: NodeHeaderListRow(
title: S.of(context).add_new_node,
onTap: (_) async =>
await Navigator.of(context).pushNamed(Routes.newNode),
),
),
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
SizedBox(height: 100),
@ -60,31 +64,39 @@ class ConnectionSyncPage extends BasePage {
itemBuilder: (_, sectionIndex, index) {
final node = nodeListViewModel.nodes[index];
final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex;
final nodeListRow = NodeListRow(
title: node.uriRaw,
isSelected: isSelected,
isAlive: node.requestNode(),
onTap: (_) async {
if (isSelected) {
return;
}
final nodeListRow = Semantics(
label: 'Slidable',
selected: isSelected,
enabled: !isSelected,
child: NodeListRow(
title: node.uriRaw,
isSelected: isSelected,
isAlive: node.requestNode(),
onTap: (_) async {
if (isSelected) {
return;
}
await showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle: S.of(context).change_current_node_title,
alertContent: nodeListViewModel.getAlertContent(node.uriRaw),
leftButtonText: S.of(context).cancel,
rightButtonText: S.of(context).change,
actionLeftButton: () => Navigator.of(context).pop(),
actionRightButton: () async {
await nodeListViewModel.setAsCurrent(node);
Navigator.of(context).pop();
},
);
});
},
await showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle:
S.of(context).change_current_node_title,
alertContent: nodeListViewModel
.getAlertContent(node.uriRaw),
leftButtonText: S.of(context).cancel,
rightButtonText: S.of(context).change,
actionLeftButton: () =>
Navigator.of(context).pop(),
actionRightButton: () async {
await nodeListViewModel.setAsCurrent(node);
Navigator.of(context).pop();
},
);
});
},
),
);
final dismissibleRow = Slidable(

View file

@ -33,54 +33,59 @@ class IntroducingCard extends StatelessWidget {
children: [
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AutoSizeText(title ?? '',
style: TextStyle(
fontSize: 24,
fontFamily: 'Lato',
fontWeight: FontWeight.bold,
color: Theme.of(context)
.accentTextTheme!
.headline2!
.backgroundColor!,
height: 1),
maxLines: 1,
textAlign: TextAlign.center),
SizedBox(height: 14),
Text(subTitle ?? '',
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
color: Theme.of(context)
.accentTextTheme!
.headline2!
.backgroundColor!,
height: 1)),
],
child: MergeSemantics(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AutoSizeText(title ?? '',
style: TextStyle(
fontSize: 24,
fontFamily: 'Lato',
fontWeight: FontWeight.bold,
color: Theme.of(context)
.accentTextTheme!
.headline2!
.backgroundColor!,
height: 1),
maxLines: 1,
textAlign: TextAlign.center),
SizedBox(height: 14),
Text(subTitle ?? '',
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 12,
fontFamily: 'Lato',
color: Theme.of(context)
.accentTextTheme!
.headline2!
.backgroundColor!,
height: 1)),
],
),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0,16,16,0),
child: GestureDetector(
onTap: closeCard,
child: Container(
height: 23,
width: 23,
decoration: BoxDecoration(
color: Colors.white, shape: BoxShape.circle),
child: Center(
child: Image.asset(
'assets/images/x.png',
color: Palette.darkBlueCraiola,
height: 15,
width: 15,
)),
child: Semantics(
label: 'Close',
child: GestureDetector(
onTap: closeCard,
child: Container(
height: 23,
width: 23,
decoration: BoxDecoration(
color: Colors.white, shape: BoxShape.circle),
child: Center(
child: Image.asset(
'assets/images/x.png',
color: Palette.darkBlueCraiola,
height: 15,
width: 15,
)),
),
),
),
)