Unverified Commit 74ea7132 authored by nbayati's avatar nbayati Committed by GitHub

Add optional flag to determine assertiveness level in aria announcement for flutter web (#107568)

parent e5055293
......@@ -8,6 +8,21 @@ import 'package:flutter/painting.dart';
export 'dart:ui' show TextDirection;
/// Determines the assertiveness level of the accessibility announcement.
///
/// It is used by [AnnounceSemanticsEvent] to determine the priority with which
/// assistive technology should treat announcements.
enum Assertiveness {
/// The assistive technology will speak changes whenever the user is idle.
polite,
/// The assistive technology will interrupt any announcement that it is
/// currently making to notify the user about the change.
///
/// It should only be used for time-sensitive/critical notifications.
assertive,
}
/// An event sent by the application to notify interested listeners that
/// something happened to the user interface (e.g. a view scrolled).
///
......@@ -71,7 +86,7 @@ abstract class SemanticsEvent {
class AnnounceSemanticsEvent extends SemanticsEvent {
/// Constructs an event that triggers an announcement by the platform.
const AnnounceSemanticsEvent(this.message, this.textDirection)
const AnnounceSemanticsEvent(this.message, this.textDirection, {this.assertiveness = Assertiveness.polite})
: assert(message != null),
assert(textDirection != null),
super('announce');
......@@ -86,11 +101,20 @@ class AnnounceSemanticsEvent extends SemanticsEvent {
/// This property must not be null.
final TextDirection textDirection;
/// Determines whether the announcement should interrupt any existing announcement,
/// or queue after it.
///
/// On the web this option uses the aria-live level to set the assertiveness
/// of the announcement. On iOS, Android, Windows, Linux, macOS, and Fuchsia
/// this option currently has no effect.
final Assertiveness assertiveness;
@override
Map<String, dynamic> getDataMap() {
return <String, dynamic>{
'message': message,
'textDirection': textDirection.index,
'assertiveness': assertiveness.index,
};
}
}
......
......@@ -6,7 +6,7 @@ import 'dart:ui' show TextDirection;
import 'package:flutter/services.dart' show SystemChannels;
import 'semantics_event.dart' show AnnounceSemanticsEvent, TooltipSemanticsEvent;
import 'semantics_event.dart' show AnnounceSemanticsEvent, Assertiveness, TooltipSemanticsEvent;
export 'dart:ui' show TextDirection;
......@@ -29,8 +29,12 @@ class SemanticsService {
///
/// For example a camera application can use this method to make accessibility
/// announcements regarding objects in the viewfinder.
static Future<void> announce(String message, TextDirection textDirection) async {
final AnnounceSemanticsEvent event = AnnounceSemanticsEvent(message, textDirection);
///
/// The assertiveness level of the announcement is determined by [assertiveness].
/// Currently, this is only supported by the web engine and has no effect on
/// other platforms. The default mode is [Assertiveness.polite].
static Future<void> announce(String message, TextDirection textDirection, {Assertiveness assertiveness = Assertiveness.polite}) async {
final AnnounceSemanticsEvent event = AnnounceSemanticsEvent(message, textDirection, assertiveness: assertiveness);
await SystemChannels.accessibility.send(event.toMap());
}
......
......@@ -20,11 +20,10 @@ void main() {
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, handleMessage);
await SemanticsService.announce('announcement 1', TextDirection.ltr);
await SemanticsService.announce('announcement 2', TextDirection.rtl);
await SemanticsService.announce('announcement 2', TextDirection.rtl, assertiveness: Assertiveness.assertive);
expect(log, equals(<Map<String, dynamic>>[
<String, dynamic>{'type': 'announce', 'data': <String, dynamic>{'message': 'announcement 1', 'textDirection': 1}},
<String, dynamic>{'type': 'announce', 'data': <String, dynamic>{'message': 'announcement 2', 'textDirection': 0}},
<String, dynamic>{'type': 'announce', 'data': <String, dynamic>{'message': 'announcement 1', 'textDirection': 1, 'assertiveness': 0}},
<String, dynamic>{'type': 'announce', 'data': <String, dynamic>{'message': 'announcement 2', 'textDirection': 0, 'assertiveness': 1}},
]));
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment