From 709c4bf04e445a01a041cc8d131fe15ae2290c8e Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Sat, 2 Oct 2021 14:04:40 +0200 Subject: [PATCH] fix: refactor to only use accessibility when actually used --- .../core/accessibility/accessibility-types.ts | 116 +++++++++--------- packages/core/accessibility/index.android.ts | 21 +++- packages/core/accessibility/index.ios.ts | 37 +++--- packages/core/application/index.android.ts | 5 - packages/core/application/index.ios.ts | 5 - packages/core/ui/core/view/index.android.ts | 8 +- packages/core/ui/core/view/index.ios.ts | 19 +-- packages/core/ui/core/view/view-common.ts | 6 +- packages/core/ui/page/index.android.ts | 5 +- 9 files changed, 112 insertions(+), 110 deletions(-) diff --git a/packages/core/accessibility/accessibility-types.ts b/packages/core/accessibility/accessibility-types.ts index 48e3cac44..824b54aa3 100644 --- a/packages/core/accessibility/accessibility-types.ts +++ b/packages/core/accessibility/accessibility-types.ts @@ -4,264 +4,264 @@ export enum AccessibilityTrait { /** * The element allows direct touch interaction for VoiceOver users. */ - AllowsDirectInteraction = 'allowsDirectInteraction', + AllowsDirectInteraction, /** * The element should cause an automatic page turn when VoiceOver finishes reading the text within it. * Note: Requires custom view with accessibilityScroll(...) */ - CausesPageTurn = 'pageTurn', + CausesPageTurn, /** * The element is not enabled and does not respond to user interaction. */ - NotEnabled = 'disabled', + NotEnabled, /** * The element is currently selected. */ - Selected = 'selected', + Selected, /** * The element frequently updates its label or value. */ - UpdatesFrequently = 'frequentUpdates', + UpdatesFrequently, } export enum AccessibilityRole { /** * The element allows continuous adjustment through a range of values. */ - Adjustable = 'adjustable', + Adjustable, /** * The element should be treated as a button. */ - Button = 'button', + Button, /** * The element behaves like a Checkbox */ - Checkbox = 'checkbox', + Checkbox, /** * The element is a header that divides content into sections, such as the title of a navigation bar. */ - Header = 'header', + Header, /** * The element should be treated as an image. */ - Image = 'image', + Image, /** * The element should be treated as a image button. */ - ImageButton = 'imageButton', + ImageButton, /** * The element behaves as a keyboard key. */ - KeyboardKey = 'keyboardKey', + KeyboardKey, /** * The element should be treated as a link. */ - Link = 'link', + Link, /** * The element has no traits. */ - None = 'none', + None, /** * The element plays its own sound when activated. */ - PlaysSound = 'plays', + PlaysSound, /** * The element behaves like a ProgressBar */ - ProgressBar = 'progressBar', + ProgressBar, /** * The element behaves like a RadioButton */ - RadioButton = 'radioButton', + RadioButton, /** * The element should be treated as a search field. */ - Search = 'search', + Search, /** * The element behaves like a SpinButton */ - SpinButton = 'spinButton', + SpinButton, /** * The element starts a media session when it is activated. */ - StartsMediaSession = 'startsMedia', + StartsMediaSession, /** * The element should be treated as static text that cannot change. */ - StaticText = 'text', + StaticText, /** * The element provides summary information when the application starts. */ - Summary = 'summary', + Summary, /** * The element behaves like a switch */ - Switch = 'switch', + Switch, } export enum AccessibilityState { - Selected = 'selected', - Checked = 'checked', - Unchecked = 'unchecked', - Disabled = 'disabled', + Selected, + Checked, + Unchecked, + Disabled, } export enum AccessibilityLiveRegion { - None = 'none', - Polite = 'polite', - Assertive = 'assertive', + None, + Polite, + Assertive, } export enum IOSPostAccessibilityNotificationType { - Announcement = 'announcement', - Screen = 'screen', - Layout = 'layout', + Announcement, + Screen, + Layout, } export enum AndroidAccessibilityEvent { /** * Invalid selection/focus position. */ - INVALID_POSITION = 'invalid_position', + INVALID_POSITION, /** * Maximum length of the text fields. */ - MAX_TEXT_LENGTH = 'max_text_length', + MAX_TEXT_LENGTH, /** * Represents the event of clicking on a android.view.View like android.widget.Button, android.widget.CompoundButton, etc. */ - VIEW_CLICKED = 'view_clicked', + VIEW_CLICKED, /** * Represents the event of long clicking on a android.view.View like android.widget.Button, android.widget.CompoundButton, etc. */ - VIEW_LONG_CLICKED = 'view_long_clicked', + VIEW_LONG_CLICKED, /** * Represents the event of selecting an item usually in the context of an android.widget.AdapterView. */ - VIEW_SELECTED = 'view_selected', + VIEW_SELECTED, /** * Represents the event of setting input focus of a android.view.View. */ - VIEW_FOCUSED = 'view_focused', + VIEW_FOCUSED, /** * Represents the event of changing the text of an android.widget.EditText. */ - VIEW_TEXT_CHANGED = 'view_text_changed', + VIEW_TEXT_CHANGED, /** * Represents the event of opening a android.widget.PopupWindow, android.view.Menu, android.app.Dialog, etc. */ - WINDOW_STATE_CHANGED = 'window_state_changed', + WINDOW_STATE_CHANGED, /** * Represents the event showing a android.app.Notification. */ - NOTIFICATION_STATE_CHANGED = 'notification_state_changed', + NOTIFICATION_STATE_CHANGED, /** * Represents the event of a hover enter over a android.view.View. */ - VIEW_HOVER_ENTER = 'view_hover_enter', + VIEW_HOVER_ENTER, /** * Represents the event of a hover exit over a android.view.View. */ - VIEW_HOVER_EXIT = 'view_hover_exit', + VIEW_HOVER_EXIT, /** * Represents the event of starting a touch exploration gesture. */ - TOUCH_EXPLORATION_GESTURE_START = 'touch_exploration_gesture_start', + TOUCH_EXPLORATION_GESTURE_START, /** * Represents the event of ending a touch exploration gesture. */ - TOUCH_EXPLORATION_GESTURE_END = 'touch_exploration_gesture_end', + TOUCH_EXPLORATION_GESTURE_END, /** * Represents the event of changing the content of a window and more specifically the sub-tree rooted at the event's source. */ - WINDOW_CONTENT_CHANGED = 'window_content_changed', + WINDOW_CONTENT_CHANGED, /** * Represents the event of scrolling a view. */ - VIEW_SCROLLED = 'view_scrolled', + VIEW_SCROLLED, /** * Represents the event of changing the selection in an android.widget.EditText. */ - VIEW_TEXT_SELECTION_CHANGED = 'view_text_selection_changed', + VIEW_TEXT_SELECTION_CHANGED, /** * Represents the event of an application making an announcement. */ - ANNOUNCEMENT = 'announcement', + ANNOUNCEMENT, /** * Represents the event of gaining accessibility focus. */ - VIEW_ACCESSIBILITY_FOCUSED = 'view_accessibility_focused', + VIEW_ACCESSIBILITY_FOCUSED, /** * Represents the event of clearing accessibility focus. */ - VIEW_ACCESSIBILITY_FOCUS_CLEARED = 'view_accessibility_focus_cleared', + VIEW_ACCESSIBILITY_FOCUS_CLEARED, /** * Represents the event of traversing the text of a view at a given movement granularity. */ - VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 'view_text_traversed_at_movement_granularity', + VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY, /** * Represents the event of beginning gesture detection. */ - GESTURE_DETECTION_START = 'gesture_detection_start', + GESTURE_DETECTION_START, /** * Represents the event of ending gesture detection. */ - GESTURE_DETECTION_END = 'gesture_detection_end', + GESTURE_DETECTION_END, /** * Represents the event of the user starting to touch the screen. */ - TOUCH_INTERACTION_START = 'touch_interaction_start', + TOUCH_INTERACTION_START, /** * Represents the event of the user ending to touch the screen. */ - TOUCH_INTERACTION_END = 'touch_interaction_end', + TOUCH_INTERACTION_END, /** * Mask for AccessibilityEvent all types. */ - ALL_MASK = 'all', + ALL_MASK, } export interface AccessibilityEventPerformEscape extends EventData { diff --git a/packages/core/accessibility/index.android.ts b/packages/core/accessibility/index.android.ts index 0850510a0..e098c5bc5 100644 --- a/packages/core/accessibility/index.android.ts +++ b/packages/core/accessibility/index.android.ts @@ -1,8 +1,10 @@ +import { initAccessibilityFontScale } from 'accessibility'; import * as Application from '../application'; import { Trace } from '../trace'; import type { View } from '../ui/core/view'; import { GestureTypes } from '../ui/gestures'; import { notifyAccessibilityFocusState } from './accessibility-common'; +import { initAccessibilityCssHelper } from './accessibility-css-helper'; import { getAndroidAccessibilityManager } from './accessibility-service'; import { AccessibilityRole, AccessibilityState, AndroidAccessibilityEvent } from './accessibility-types'; @@ -10,7 +12,7 @@ export * from './accessibility-common'; export * from './accessibility-types'; export * from './font-scale'; -let clickableRolesMap = new Set(); +let clickableRolesMap = new Set(); let lastFocusedView: WeakRef>; function accessibilityEventHelper(view: Partial, eventType: number) { @@ -105,7 +107,7 @@ let TNSAccessibilityDelegate: android.view.View.androidviewViewAccessibilityDele const androidViewToTNSView = new WeakMap>>(); let accessibilityEventMap: Map; -let accessibilityEventTypeMap: Map; +let accessibilityEventTypeMap: Map; function ensureNativeClasses() { if (TNSAccessibilityDelegate) { @@ -130,7 +132,7 @@ function ensureNativeClasses() { [AccessibilityRole.ProgressBar, android.widget.ProgressBar.class.getName()], ]); - clickableRolesMap = new Set([AccessibilityRole.Button, AccessibilityRole.ImageButton]); + clickableRolesMap = new Set([AccessibilityRole.Button, AccessibilityRole.ImageButton]); const ignoreRoleTypesForTrace = new Set([AccessibilityRole.Header, AccessibilityRole.Link, AccessibilityRole.None, AccessibilityRole.Summary]); @@ -437,9 +439,9 @@ export function isAccessibilityServiceEnabled(): boolean { return accessibilityServiceEnabled; } -export function setupAccessibleView(view: Partial): void { - updateAccessibilityProperties(view); -} +// export function setupAccessibleView(view: Partial): void { +// updateAccessibilityProperties(view); +// } export function updateAccessibilityProperties(view: Partial): void { if (!view.nativeViewProtected) { @@ -537,10 +539,17 @@ export function updateContentDescription(view: View, forceUpdate?: boolean): str return applyContentDescription(view, forceUpdate); } + +let started = false; function setAccessibilityDelegate(view: Partial): void { if (!view.nativeViewProtected) { return; } + if (!started) { + started = true; + initAccessibilityCssHelper(); + initAccessibilityFontScale(); + } ensureNativeClasses(); diff --git a/packages/core/accessibility/index.ios.ts b/packages/core/accessibility/index.ios.ts index 74b1a4213..220ea276e 100644 --- a/packages/core/accessibility/index.ios.ts +++ b/packages/core/accessibility/index.ios.ts @@ -1,6 +1,8 @@ +import { initAccessibilityFontScale } from 'accessibility'; import * as Application from '../application'; import type { View } from '../ui/core/view'; import { notifyAccessibilityFocusState } from './accessibility-common'; +import { initAccessibilityCssHelper } from './accessibility-css-helper'; import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait } from './accessibility-types'; export * from './accessibility-common'; @@ -35,7 +37,7 @@ function inputArrayToBitMask(values: string | string[], map: Map ); } -let AccessibilityTraitsMap: Map; +let AccessibilityTraitsMap: Map; let RoleTypeMap: Map; let nativeFocusedNotificationObserver; @@ -120,27 +122,32 @@ function ensureNativeClasses() { }); } -export function setupAccessibleView(view: View): void { - const uiView = view.nativeViewProtected as UIView; - if (!uiView) { - return; - } +// export function setupAccessibleView(view: View): void { +// const uiView = view.nativeViewProtected as UIView; +// if (!uiView) { +// return; +// } - /** - * We need to map back from the UIView to the NativeScript View. - * - * We do that by setting the uiView's tag to the View's domId. - * This way we can do reverse lookup. - */ - uiView.tag = view._domId; -} +// /** +// * We need to map back from the UIView to the NativeScript View. +// * +// * We do that by setting the uiView's tag to the View's domId. +// * This way we can do reverse lookup. +// */ +// uiView.tag = view._domId; +// } +let started = false; export function updateAccessibilityProperties(view: View): void { const uiView = view.nativeViewProtected as UIView; if (!uiView) { return; } - + if (!started) { + started = true; + initAccessibilityCssHelper(); + initAccessibilityFontScale(); + } ensureNativeClasses(); const accessibilityRole = view.accessibilityRole; diff --git a/packages/core/application/index.android.ts b/packages/core/application/index.android.ts index b9ea5c926..7aeb305f6 100644 --- a/packages/core/application/index.android.ts +++ b/packages/core/application/index.android.ts @@ -14,8 +14,6 @@ import { NavigationEntry, AndroidActivityCallbacks } from '../ui/frame/frame-int import { Observable } from '../data/observable'; import { profile } from '../profiling'; -import { initAccessibilityCssHelper } from '../accessibility/accessibility-css-helper'; -import { initAccessibilityFontScale } from '../accessibility/font-scale'; const ActivityCreated = 'activityCreated'; const ActivityDestroyed = 'activityDestroyed'; @@ -177,9 +175,6 @@ export function run(entry?: NavigationEntry | string) { const nativeApp = getNativeApplication(); androidApp.init(nativeApp); } - - initAccessibilityCssHelper(); - initAccessibilityFontScale(); } export function addCss(cssText: string, attributeScoped?: boolean): void { diff --git a/packages/core/application/index.ios.ts b/packages/core/application/index.ios.ts index cf9e84751..232f3e284 100644 --- a/packages/core/application/index.ios.ts +++ b/packages/core/application/index.ios.ts @@ -18,8 +18,6 @@ import { IOSHelper } from '../ui/core/view/view-helper'; import { Device } from '../platform'; import { profile } from '../profiling'; import { iOSNativeHelper } from '../utils'; -import { initAccessibilityCssHelper } from '../accessibility/accessibility-css-helper'; -import { initAccessibilityFontScale } from '../accessibility/font-scale'; const IOS_PLATFORM = 'ios'; @@ -437,9 +435,6 @@ export function run(entry?: string | NavigationEntry) { } } } - - initAccessibilityCssHelper(); - initAccessibilityFontScale(); } export function addCss(cssText: string, attributeScoped?: boolean): void { diff --git a/packages/core/ui/core/view/index.android.ts b/packages/core/ui/core/view/index.android.ts index 113f5e990..710f682d8 100644 --- a/packages/core/ui/core/view/index.android.ts +++ b/packages/core/ui/core/view/index.android.ts @@ -22,7 +22,7 @@ import { AndroidActivityBackPressedEventData, android as androidApp } from '../. import { Device } from '../../../platform'; import lazy from '../../../utils/lazy'; import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty } from '../../../accessibility/accessibility-properties'; -import { AccessibilityLiveRegion, AccessibilityRole, AndroidAccessibilityEvent, setupAccessibleView, isAccessibilityServiceEnabled, sendAccessibilityEvent, updateAccessibilityProperties, updateContentDescription, AccessibilityState } from '../../../accessibility'; +import { AccessibilityLiveRegion, AccessibilityRole, AndroidAccessibilityEvent, isAccessibilityServiceEnabled, sendAccessibilityEvent, updateAccessibilityProperties, updateContentDescription, AccessibilityState } from '../../../accessibility'; import * as Utils from '../../../utils'; import { CSSShadow } from 'ui/styling/css-shadow'; @@ -324,12 +324,6 @@ export class View extends ViewCommon { nativeViewProtected: android.view.View; - constructor() { - super(); - - this.on(View.loadedEvent, () => setupAccessibleView(this)); - } - // TODO: Implement unobserve that detach the touchListener. _observe(type: GestureTypes, callback: (args: GestureEventData) => void, thisArg?: any): void { super._observe(type, callback, thisArg); diff --git a/packages/core/ui/core/view/index.ios.ts b/packages/core/ui/core/view/index.ios.ts index 7485818aa..a5c472944 100644 --- a/packages/core/ui/core/view/index.ios.ts +++ b/packages/core/ui/core/view/index.ios.ts @@ -11,7 +11,7 @@ import { ios as iosBackground, Background } from '../../styling/background'; import { perspectiveProperty, visibilityProperty, opacityProperty, rotateProperty, rotateXProperty, rotateYProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty, clipPathProperty } from '../../styling/style-properties'; import { profile } from '../../../profiling'; import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty, accessibilityIgnoresInvertColorsProperty } from '../../../accessibility/accessibility-properties'; -import { setupAccessibleView, IOSPostAccessibilityNotificationType, isAccessibilityServiceEnabled, updateAccessibilityProperties, AccessibilityEventOptions, AccessibilityRole, AccessibilityState } from '../../../accessibility'; +import { IOSPostAccessibilityNotificationType, isAccessibilityServiceEnabled, updateAccessibilityProperties, AccessibilityEventOptions, AccessibilityRole, AccessibilityState } from '../../../accessibility'; import { CoreTypes } from '../../../core-types'; export * from './view-common'; @@ -56,11 +56,16 @@ export class View extends ViewCommon implements ViewDefinition { get isLayoutRequested(): boolean { return (this._privateFlags & PFLAG_FORCE_LAYOUT) === PFLAG_FORCE_LAYOUT; } - - constructor() { - super(); - - this.once(View.loadedEvent, () => setupAccessibleView(this)); + initNativeView() { + super.initNativeView() + const nativeView = this.nativeViewProtected; + /** + * We need to map back from the UIView to the NativeScript View for accessibility. + * + * We do that by setting the uiView's tag to the View's domId. + * This way we can do reverse lookup. + */ + nativeView.tag = this._domId; } requestlayoutIfNeeded() { @@ -785,7 +790,7 @@ export class View extends ViewCommon implements ViewDefinition { args = msg; } - switch (options.iosNotificationType) { + switch (options.iosNotificationType as IOSPostAccessibilityNotificationType) { case IOSPostAccessibilityNotificationType.Announcement: { notification = UIAccessibilityAnnouncementNotification; break; diff --git a/packages/core/ui/core/view/view-common.ts b/packages/core/ui/core/view/view-common.ts index 0278c689b..cad170f80 100644 --- a/packages/core/ui/core/view/view-common.ts +++ b/packages/core/ui/core/view/view-common.ts @@ -24,7 +24,7 @@ import { LinearGradient } from '../../styling/linear-gradient'; import * as am from '../../animation'; import { AccessibilityEventOptions, AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait } from '../../../accessibility/accessibility-types'; import { accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityValueProperty, accessibilityIgnoresInvertColorsProperty } from '../../../accessibility/accessibility-properties'; -import { accessibilityBlurEvent, accessibilityFocusChangedEvent, accessibilityFocusEvent, accessibilityPerformEscapeEvent, getCurrentFontScale } from '../../../accessibility'; +import { getCurrentFontScale } from '../../../accessibility'; import { CSSShadow } from '../../styling/css-shadow'; // helpers (these are okay re-exported here) @@ -72,10 +72,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { public static shownModallyEvent = 'shownModally'; public static showingModallyEvent = 'showingModally'; public static closingModallyEvent = 'closingModally'; - public static accessibilityBlurEvent = accessibilityBlurEvent; - public static accessibilityFocusEvent = accessibilityFocusEvent; - public static accessibilityFocusChangedEvent = accessibilityFocusChangedEvent; - public static accessibilityPerformEscapeEvent = accessibilityPerformEscapeEvent; public accessibilityIdentifier: string; public accessibilityLabel: string; diff --git a/packages/core/ui/page/index.android.ts b/packages/core/ui/page/index.android.ts index 59a0d064d..e4a043658 100644 --- a/packages/core/ui/page/index.android.ts +++ b/packages/core/ui/page/index.android.ts @@ -150,7 +150,8 @@ export class Page extends PageBase { return; } - - this.actionBar.accessibilityScreenChanged(); + if (this.hasActionBar) { + this.actionBar.accessibilityScreenChanged(); + } } }