Accessibility update

This commit is contained in:
Christien Rioux 2025-05-25 23:40:52 -04:00
parent be8014c97a
commit 3b1cb53b8a
55 changed files with 1089 additions and 807 deletions

View file

@ -2,21 +2,27 @@ import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../theme/theme.dart';
class DefaultAppBar extends AppBar {
DefaultAppBar(
{super.title,
{required BuildContext context,
super.title,
super.flexibleSpace,
super.key,
Widget? leading,
super.actions})
: super(
toolbarHeight: 40.scaled(context),
leadingWidth: 40.scaled(context),
leading: leading ??
Container(
margin: const EdgeInsets.all(4),
margin: const EdgeInsets.all(4).scaled(context),
decoration: BoxDecoration(
color: Colors.black.withAlpha(32),
shape: BoxShape.circle),
child:
SvgPicture.asset('assets/images/vlogo.svg', height: 24)
.paddingAll(4)));
child: SvgPicture.asset('assets/images/vlogo.svg',
width: 24.scaled(context),
height: 24.scaled(context))
.paddingAll(4.scaled(context))));
}

View file

@ -95,19 +95,15 @@ class _DrawerMenuState extends State<DrawerMenu> {
activeBorder = scale.primary;
}
final avatar = AvatarWidget(
final avatar = StyledAvatar(
name: name,
size: 34,
borderColor: border,
foregroundColor: loggedIn ? scale.primaryText : scale.subtleText,
backgroundColor: loggedIn ? scale.primary : scale.elementBackground,
scaleConfig: scaleConfig,
textStyle: theme.textTheme.titleLarge!,
size: 34.scaled(context),
);
return AnimatedPadding(
padding: EdgeInsets.fromLTRB(selected ? 0 : 8, selected ? 0 : 2,
selected ? 0 : 8, selected ? 0 : 2),
selected ? 0 : 8, selected ? 0 : 2)
.scaled(context),
duration: const Duration(milliseconds: 50),
child: MenuItemWidget(
title: name,
@ -144,7 +140,7 @@ class _DrawerMenuState extends State<DrawerMenu> {
(scaleConfig.preferBorders || scaleConfig.useVisualIndicators)
? null
: activeBorder,
minHeight: 48,
minHeight: 48.scaled(context),
));
}
@ -196,7 +192,8 @@ class _DrawerMenuState extends State<DrawerMenu> {
color: scaleScheme.errorScale.subtleBorder,
borderRadius: 12 * scaleConfig.borderRadiusScale),
);
loggedInAccounts.add(loggedInAccount.paddingLTRB(0, 0, 0, 8));
loggedInAccounts
.add(loggedInAccount.paddingLTRB(0, 0, 0, 8.scaled(context)));
} else {
// Account is not logged in
final scale = theme.extension<ScaleScheme>()!.grayScale;
@ -246,8 +243,8 @@ class _DrawerMenuState extends State<DrawerMenu> {
}
return IconButton(
icon: icon,
padding: const EdgeInsets.all(12),
color: border,
constraints: const BoxConstraints.expand(height: 48, width: 48),
style: ButtonStyle(
backgroundColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.hovered)) {
@ -286,7 +283,10 @@ class _DrawerMenuState extends State<DrawerMenu> {
final scale = scaleScheme.scale(_scaleKind);
final settingsButton = _getButton(
icon: const Icon(Icons.settings),
icon: const Icon(
Icons.settings,
applyTextScaling: true,
),
tooltip: translate('menu.settings_tooltip'),
scale: scale,
scaleConfig: scaleConfig,
@ -295,7 +295,10 @@ class _DrawerMenuState extends State<DrawerMenu> {
}).paddingLTRB(0, 0, 16, 0);
final addButton = _getButton(
icon: const Icon(Icons.add),
icon: const Icon(
Icons.add,
applyTextScaling: true,
),
tooltip: translate('menu.add_account_tooltip'),
scale: scale,
scaleConfig: scaleConfig,
@ -364,7 +367,7 @@ class _DrawerMenuState extends State<DrawerMenu> {
// : null)
// .paddingLTRB(0, 0, 16, 0),
GestureDetector(
onLongPress: () async {
onLongPress: () {
context
.findAncestorWidgetOfExactType<KeyboardShortcuts>()!
.reloadTheme(context);

View file

@ -2,6 +2,8 @@ import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import '../../../theme/views/preferences/preferences.dart';
class MenuItemWidget extends StatelessWidget {
const MenuItemWidget({
required this.title,
@ -81,7 +83,7 @@ class MenuItemWidget extends StatelessWidget {
hoverColor: footerButtonIconHoverColor,
icon: Icon(
footerButtonIcon,
size: 24,
size: 24.scaled(context),
),
onPressed: footerCallback),
],

View file

@ -28,73 +28,81 @@ class _HomeAccountReadyState extends State<HomeAccountReady> {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final scaleConfig = theme.extension<ScaleConfig>()!;
return IconButton(
icon: const Icon(Icons.menu),
color: scaleConfig.preferBorders
? scale.primaryScale.border
: scale.primaryScale.borderText,
constraints: const BoxConstraints.expand(height: 40, width: 40),
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(
scaleConfig.preferBorders
? scale.primaryScale.hoverElementBackground
: scale.primaryScale.hoverBorder),
shape: WidgetStateProperty.all(
RoundedRectangleBorder(
side: !scaleConfig.useVisualIndicators
? BorderSide.none
: BorderSide(
strokeAlign: BorderSide.strokeAlignCenter,
color: scaleConfig.preferBorders
? scale.primaryScale.border
: scale.primaryScale.borderText,
width: 2),
borderRadius: BorderRadius.all(
Radius.circular(8 * scaleConfig.borderRadiusScale))),
)),
tooltip: translate('menu.accounts_menu_tooltip'),
onPressed: () async {
final ctrl = context.read<ZoomDrawerController>();
await ctrl.toggle?.call();
});
return AspectRatio(
aspectRatio: 1,
child: IconButton(
icon: const Icon(
Icons.menu,
applyTextScaling: true,
),
color: scaleConfig.preferBorders
? scale.primaryScale.border
: scale.primaryScale.borderText,
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(
scaleConfig.preferBorders
? scale.primaryScale.hoverElementBackground
: scale.primaryScale.hoverBorder),
shape: WidgetStateProperty.all(
RoundedRectangleBorder(
side: !scaleConfig.useVisualIndicators
? BorderSide.none
: BorderSide(
strokeAlign: BorderSide.strokeAlignCenter,
color: scaleConfig.preferBorders
? scale.primaryScale.border
: scale.primaryScale.borderText,
width: 2),
borderRadius: BorderRadius.all(Radius.circular(
8 * scaleConfig.borderRadiusScale))),
)),
tooltip: translate('menu.accounts_menu_tooltip'),
onPressed: () async {
final ctrl = context.read<ZoomDrawerController>();
await ctrl.toggle?.call();
}));
});
Widget buildContactsButton() => Builder(builder: (context) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final scaleConfig = theme.extension<ScaleConfig>()!;
return IconButton(
icon: const Icon(Icons.contacts),
color: scaleConfig.preferBorders
? scale.primaryScale.border
: scale.primaryScale.borderText,
constraints: const BoxConstraints.expand(height: 40, width: 40),
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(
scaleConfig.preferBorders
? scale.primaryScale.hoverElementBackground
: scale.primaryScale.hoverBorder),
shape: WidgetStateProperty.all(
RoundedRectangleBorder(
side: !scaleConfig.useVisualIndicators
? BorderSide.none
: BorderSide(
strokeAlign: BorderSide.strokeAlignCenter,
color: scaleConfig.preferBorders
? scale.primaryScale.border
: scale.primaryScale.borderText,
width: 2),
borderRadius: BorderRadius.all(
Radius.circular(8 * scaleConfig.borderRadiusScale))),
)),
tooltip: translate('menu.contacts_tooltip'),
onPressed: () async {
await Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) => const ContactsPage(),
return AspectRatio(
aspectRatio: 1,
child: IconButton(
icon: const Icon(
Icons.contacts,
applyTextScaling: true,
),
);
});
color: scaleConfig.preferBorders
? scale.primaryScale.border
: scale.primaryScale.borderText,
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(
scaleConfig.preferBorders
? scale.primaryScale.hoverElementBackground
: scale.primaryScale.hoverBorder),
shape: WidgetStateProperty.all(
RoundedRectangleBorder(
side: !scaleConfig.useVisualIndicators
? BorderSide.none
: BorderSide(
strokeAlign: BorderSide.strokeAlignCenter,
color: scaleConfig.preferBorders
? scale.primaryScale.border
: scale.primaryScale.borderText,
width: 2),
borderRadius: BorderRadius.all(Radius.circular(
8 * scaleConfig.borderRadiusScale))),
)),
tooltip: translate('menu.contacts_tooltip'),
onPressed: () async {
await Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) => const ContactsPage(),
),
);
}));
});
Widget buildLeftPane(BuildContext context) => Builder(
@ -112,14 +120,17 @@ class _HomeAccountReadyState extends State<HomeAccountReady> {
? scale.primaryScale.subtleBackground
: scale.primaryScale.subtleBorder,
child: Column(children: <Widget>[
Row(children: [
buildMenuButton().paddingLTRB(0, 0, 8, 0),
ProfileWidget(
profile: profile,
showPronouns: false,
).expanded(),
buildContactsButton().paddingLTRB(8, 0, 0, 0),
]).paddingAll(8),
IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
buildMenuButton().paddingLTRB(0, 0, 8, 0),
ProfileWidget(
profile: profile,
showPronouns: false,
).expanded(),
buildContactsButton().paddingLTRB(8, 0, 0, 0),
])).paddingAll(8),
const ChatListWidget().expanded()
]));
})));

View file

@ -71,8 +71,9 @@ class HomeScreenState extends State<HomeScreen>
context: context,
title: translate('splash.beta_title'),
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
const Icon(Icons.warning, size: 64),
Icon(Icons.warning, size: 64.scaled(context)),
RichText(
textScaler: MediaQuery.of(context).textScaler,
textAlign: TextAlign.center,
text: TextSpan(
children: <TextSpan>[
@ -206,34 +207,36 @@ class HomeScreenState extends State<HomeScreen>
.indexWhere((x) => x.superIdentity.recordKey == activeLocalAccount);
final canClose = activeIndex != -1;
final drawer = ZoomDrawer(
controller: _zoomDrawerController,
menuScreen: Builder(builder: (context) {
final zoomDrawer = ZoomDrawer.of(context);
zoomDrawer!.stateNotifier.addListener(() {
if (zoomDrawer.isOpen()) {
FocusManager.instance.primaryFocus?.unfocus();
}
});
return const DrawerMenu();
}),
mainScreen: Provider<ZoomDrawerController>.value(
value: _zoomDrawerController,
child: Builder(builder: _buildAccountPageView)),
borderRadius: 0,
angle: 0,
openCurve: Curves.fastEaseInToSlowEaseOut,
closeCurve: Curves.fastEaseInToSlowEaseOut,
menuScreenTapClose: canClose,
mainScreenTapClose: canClose,
disableDragGesture: !canClose,
mainScreenScale: .25,
slideWidth: min(360, MediaQuery.of(context).size.width * 0.9),
);
final drawerWithAvoider =
isWeb ? drawer : KeyboardAvoider(curve: Curves.ease, child: drawer);
return DefaultTextStyle(
style: theme.textTheme.bodySmall!,
child: KeyboardAvoider(
curve: Curves.ease,
child: ZoomDrawer(
controller: _zoomDrawerController,
menuScreen: Builder(builder: (context) {
final zoomDrawer = ZoomDrawer.of(context);
zoomDrawer!.stateNotifier.addListener(() {
if (zoomDrawer.isOpen()) {
FocusManager.instance.primaryFocus?.unfocus();
}
});
return const DrawerMenu();
}),
mainScreen: Provider<ZoomDrawerController>.value(
value: _zoomDrawerController,
child: Builder(builder: _buildAccountPageView)),
borderRadius: 0,
angle: 0,
openCurve: Curves.fastEaseInToSlowEaseOut,
closeCurve: Curves.fastEaseInToSlowEaseOut,
menuScreenTapClose: canClose,
mainScreenTapClose: canClose,
disableDragGesture: !canClose,
mainScreenScale: .25,
slideWidth: min(360, MediaQuery.of(context).size.width * 0.9),
)));
style: theme.textTheme.bodySmall!, child: drawerWithAvoider);
}
////////////////////////////////////////////////////////////////////////////