From 5cd2af292e69d057cd6a190af04048cc0dda6132 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Thu, 1 Dec 2022 16:44:11 +0100 Subject: [PATCH 1/4] draft solution to implement queue announcement --- Libraries/Text/Text.js | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index eba66e2027793f..87a96e37efa2f4 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -231,6 +231,52 @@ const Text: React.AbstractComponent< const _hasOnPressOrOnLongPress = props.onPress != null || props.onLongPress != null; + // 1) trigger the announcement and add to the queue + // 2) failure -> if first item in queue equal to the that failed + // f --> edcb --> a + // 3) pop first item and trigger again announcement + // 4) when failure triggers, add it to the queue + const announcementQueue = []; + // the event listener detects if VoiceOver announcement fails + AccessibilityInfo.addEventListener( + 'announcementFinished', + ({announcement, success}) => { + const firstItem = announcementQueue[0]; + if (announcementQueue.length > 3) { + console.log('max queue of 3 reached, announcement skipped'); + return; + } + if (announcement === firstItem) { + AccessibilityInfo.announceForAccessibility(announcement); + const deletedItem = announcementQueue.shift(); + console.log('deleting first item in queue'); + console.log('deletedItem:', deletedItem); + } else { + announcementQueue.push(announcement); + console.log('adding item to queue'); + console.log('announcementQueue:', announcementQueue); + } + }, + ); + + // trigger voiceover announcement when text changes + if (Platform.OS === 'ios') { + React.useEffect(() => { + if ( + restProps.accessibilityLiveRegion != null && + restProps.accessibilityLiveRegion != 'none' && + typeof restProps.children === 'string' + ) { + const queue = restProps.accessibilityLiveRegion === 'polite'; + announcementQueue.push(restProps.children); + AccessibilityInfo.announceForAccessibilityWithOptions( + restProps.children, + {queue}, + ); + } + }, [restProps.children]); + } + return hasTextAncestor ? ( Date: Thu, 1 Dec 2022 16:54:14 +0100 Subject: [PATCH 2/4] retry last announcement --- Libraries/Text/Text.js | 33 ++++++++++--------- .../Text/RCTParagraphComponentView.mm | 3 +- .../View/RCTViewComponentView.mm | 2 +- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 87a96e37efa2f4..a10894ff3856ec 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -236,25 +236,29 @@ const Text: React.AbstractComponent< // f --> edcb --> a // 3) pop first item and trigger again announcement // 4) when failure triggers, add it to the queue - const announcementQueue = []; + let retryAnnouncement; // the event listener detects if VoiceOver announcement fails AccessibilityInfo.addEventListener( 'announcementFinished', ({announcement, success}) => { - const firstItem = announcementQueue[0]; - if (announcementQueue.length > 3) { - console.log('max queue of 3 reached, announcement skipped'); - return; - } - if (announcement === firstItem) { + if (!success && retryAnnouncement == null) { + retryAnnouncement = announcement; + console.log('retry announcement'); + console.log('announcement:', announcement); AccessibilityInfo.announceForAccessibility(announcement); - const deletedItem = announcementQueue.shift(); - console.log('deleting first item in queue'); - console.log('deletedItem:', deletedItem); - } else { - announcementQueue.push(announcement); - console.log('adding item to queue'); - console.log('announcementQueue:', announcementQueue); + } + if (success && retryAnnouncement === announcement) { + console.log('announcement succed, clear retryAnnouncement'); + console.log('announcement:', announcement); + retryAnnouncement = null; + } + + if (!success && retryAnnouncement != announcement) { + console.log( + 'skip retry announcement for ' + + announcement + + 'as another announcement failed and we try only 1 per time', + ); } }, ); @@ -268,7 +272,6 @@ const Text: React.AbstractComponent< typeof restProps.children === 'string' ) { const queue = restProps.accessibilityLiveRegion === 'polite'; - announcementQueue.push(restProps.children); AccessibilityInfo.announceForAccessibilityWithOptions( restProps.children, {queue}, diff --git a/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm b/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm index 42ce353888a9be..f390c1e4986d3f 100644 --- a/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm @@ -113,9 +113,10 @@ - (void)updateState:(State::Shared const &)state oldState:(State::Shared const & attrsDictionary[UIAccessibilitySpeechAttributeQueueAnnouncement] = @(accessibilityProps.accessibilityLiveRegion == AccessibilityLiveRegion::Polite ? YES : NO); NSAttributedString *announcementWithAttrs = [[NSAttributedString alloc] initWithString: self.accessibilityLabel attributes:attrsDictionary]; + dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 0.5); dispatch_after(delay, dispatch_get_main_queue(), ^(void){ - UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, announcementWithAttrs); + // UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, announcementWithAttrs); }); } } diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 8178a1be7fc6fd..32648b19cbc5fb 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -398,7 +398,7 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 0.5); dispatch_after(delay, dispatch_get_main_queue(), ^(void){ - UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, announcementWithAttrs); + // UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, announcementWithAttrs); }); } } From db6f1de0331dd646d15d0875176fd8cf8b3056de Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Thu, 1 Dec 2022 17:01:20 +0100 Subject: [PATCH 3/4] remove comments --- Libraries/Text/Text.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index a10894ff3856ec..b730e111c57271 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -231,11 +231,6 @@ const Text: React.AbstractComponent< const _hasOnPressOrOnLongPress = props.onPress != null || props.onLongPress != null; - // 1) trigger the announcement and add to the queue - // 2) failure -> if first item in queue equal to the that failed - // f --> edcb --> a - // 3) pop first item and trigger again announcement - // 4) when failure triggers, add it to the queue let retryAnnouncement; // the event listener detects if VoiceOver announcement fails AccessibilityInfo.addEventListener( From bccce1d0538761f2025fa6e6d5eb0f3454abec88 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Thu, 1 Dec 2022 17:04:28 +0100 Subject: [PATCH 4/4] minor changes --- Libraries/Text/Text.js | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index b730e111c57271..29d9510077081a 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -248,7 +248,7 @@ const Text: React.AbstractComponent< retryAnnouncement = null; } - if (!success && retryAnnouncement != announcement) { + if (!success && retryAnnouncement !== announcement) { console.log( 'skip retry announcement for ' + announcement + @@ -259,21 +259,20 @@ const Text: React.AbstractComponent< ); // trigger voiceover announcement when text changes - if (Platform.OS === 'ios') { - React.useEffect(() => { - if ( - restProps.accessibilityLiveRegion != null && - restProps.accessibilityLiveRegion != 'none' && - typeof restProps.children === 'string' - ) { - const queue = restProps.accessibilityLiveRegion === 'polite'; - AccessibilityInfo.announceForAccessibilityWithOptions( - restProps.children, - {queue}, - ); - } - }, [restProps.children]); - } + React.useEffect(() => { + if ( + Platform.OS === 'ios' && + restProps.accessibilityLiveRegion != null && + restProps.accessibilityLiveRegion !== 'none' && + typeof restProps.children === 'string' + ) { + const queue = restProps.accessibilityLiveRegion === 'polite'; + AccessibilityInfo.announceForAccessibilityWithOptions( + restProps.children, + {queue}, + ); + } + }, [restProps.children]); return hasTextAncestor ? (