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); 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,
), ),
), ),
); );

View file

@ -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 {

View file

@ -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!,
),
), ),
), ),
), ),

View file

@ -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 {

View file

@ -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
),
) )
); );
} }

View file

@ -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,
),
); );
} }

View file

@ -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(

View file

@ -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,
)),
),
), ),
), ),
) )