-
Notifications
You must be signed in to change notification settings - Fork 486
Expose setAccessibilityFocus from Native-Common AccessibilityUtil and expose setting accessibility focus on RX.TextInput. #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@eulphean, |
|
|
||
| export class AccessibilityUtil extends CommonAccessibilityUtil { | ||
| // Native platform specific instance for AccessibilityUtil. | ||
| private _instance: typeof AndroidAccessibilityUtil | typeof iOSAccessibilityUtil; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should both be the same type. You should define an interface (or abstract base class) that both iOS and Android need to implmenet
| break; | ||
|
|
||
| default: | ||
| assert(false, 'Unknown platform.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uwp isn't an unknown platform inside ReactXP
| }; | ||
|
|
||
| // Platform specific helpers exposed through Native-Common AccessibilityUtil. | ||
| export abstract class NativeHelpers { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider giving a more specific name to this class to be derived by each platform. Maybe someone like CommonNativeAccessibilityUtil which would be in line with the pattern used currently or NativeAccessibilityHelpers. NativeHelpers is very generic and makes it's difficult to the reader to understand what it's about on its own.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with Seb. NativeHelpers is too generic a name to export.
src/android/AccessibilityUtil.ts
Outdated
|
|
||
| import Accessibility from '../native-common/Accessibility'; | ||
| import { AccessibilityUtil as CommonAccessibilityUtil } from '../native-common/AccessibilityUtil'; | ||
| import { NativeHelpers } from '../native-common/AccessibilityUtil'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you have a potential circular dependency here. native-common/AccessibilityUtil -> android/AccessibilityUtil -> native-common/AccessibilityUtil
src/ios/AccessibilityUtil.ts
Outdated
| @@ -0,0 +1,22 @@ | |||
| /** | |||
| * iOSAccessibilityUtil.ts | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment should match the file name.
| import RN = require('react-native'); | ||
|
|
||
| import { AccessibilityUtil as CommonAccessibilityUtil } from '../common/AccessibilityUtil'; | ||
| import AndroidAccessibilityUtil from '../android/AccessibilityUtil'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you importing platform-specific files within a common file? This is an anti-pattern and will create dependency cycles. Platform-specific files should import native-common, not the other way around.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this is an anti-pattern, it's beneficial to us. The idea behind this is that pretty much every UI component needs to talk to AccessibilityUtils in some way, shape or form. That leaves a few options:
- Extend every UI component (that needs accessibility) for every platform so that it imports the platform specific AccessibiilityUtils and calls the function
- Provide some sort of override/shim at the RX platform creation (something AccessibilityUtils.setPlatformHelperFunctions that pipes to this._impl that's in this PR)
- Have native-common/AccessibilityUtils decide which impl to use on init and import platform specific implementations
#1 adds a bunch of extra code and another layer of abstract classes
#2 is somewhat obscure and non-obvious to someone working in the codebase
#3 isn't ideal but seems somewhat better than the other options. (Also can be done without cycles)
Do you have any alternative solutions?
| }; | ||
|
|
||
| // Platform specific helpers exposed through Native-Common AccessibilityUtil. | ||
| export abstract class NativeHelpers { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with Seb. NativeHelpers is too generic a name to export.
… components can leverage native-common instance directly to set focus on iOS and Android platforms.
4f32743 to
e904f2e
Compare
|
I have a new iteration addressing the comments. |
| @@ -1,5 +1,5 @@ | |||
| /** | |||
| * AccessibilityUtil.ts | |||
| * AndroidAccessibilityUtil.ts | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you rename this file to start with "Android"? It's already in the Android directory, so adding this is redundant. It's also inconsistent with all of the other code in ReactXP. I'd prefer if you went back to the previous name for consistency.
src/ios/iOSAccessibilityUtil.ts
Outdated
| @@ -0,0 +1,22 @@ | |||
| /** | |||
| * iOSAccessibilityUtil.ts | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once again, the file name shouldn't contain iOS since that's redundant. It's already in a folder called iOS. Same with the class name it exports.
| import RN = require('react-native'); | ||
|
|
||
| import { AccessibilityUtil as CommonAccessibilityUtil, PlatformAccessibilityHelpers } from '../common/AccessibilityUtil'; | ||
| import AndroidAccessibilityUtil from '../android/AndroidAccessibilityUtil'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still inverted. The "native common" implementation should not be importing the platform-specific implementations. It should be the other way around. The platform-specific implementations should be importing the common and overriding the parts that are necessary. Doing it the other way is inconsistent with all other parts of ReactXP and has the potential for creating dependency cycles.
| // Set AccessibilityUtil instance based on the platform. | ||
| switch (RN.Platform.OS) { | ||
| case 'android': | ||
| this._instance = AndroidAccessibilityUtil; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instantiation of platform-specific modules should happen only in the ReactXP.ts files that are specific to each platform. You shouldn't be doing it here in this native-common module. By doing so, you're pulling in all platform implementation on all platforms. The iOS version of ReactXP shouldn't contain any Android-specific code and vice versa. By instantiating the platform-specific code in ReactXP.ts, we are able to strip out the code for other platforms. By doing it here, you defeat that mechanism.
| @@ -0,0 +1,20 @@ | |||
| /** | |||
| * WindowsAccessibilityUtil.ts | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See note above. This file and its exported class shouldn't start with "Windows".
|
Thanks for the feedback, guys. I just pushed a latest iteration that should address the concerns around this. The problem with using a flat inheritance model how RX.Linking component does is that platform specific implementations need to be initialized inside Native-Common AccessibilityUtil in order for it to consume it. This brings up the concern of importing platform specific code into Native-Common instance that defeats the purpose of ReactXp's message. By letting initialization path in ReactXp poke the platform specific instance inside native-common AccessibilityUtil, we solve that problem. I used Seb's suggestion for naming the platform specific accessibility helper. Goal was to keep the suffix 'Util' to bear resemblance and use the term 'Native' to drive the difference between the two classes. |
|
Looking better. I realize this approach is still a bit convoluted, but I think it's much better than the previous approach. Once @berickson1 reviews and approves the change, he or I can merge it in. |
…ame AccessibilityNativeUtil to AccessibilityPlatformUtil as that is more in sync with all the comments in the codebase.
… expose setting accessibility focus on RX.TextInput. (microsoft#69) * Expose setAccessibilityFocus from Native-Common AccessibilityUtil, so components can leverage native-common instance directly to set focus on iOS and Android platforms. * Code review feedback. * PR feedback. * PR feedback. * Nit: Space * PR feedback. Rename platform specific files to AccessibilityUtil. Rename AccessibilityNativeUtil to AccessibilityPlatformUtil as that is more in sync with all the comments in the codebase.
This change exposes a way to set accessibility focus on RX.TextInput. This also changes the way we had AccessibilityUtil implementations individually for each platform. That becomes an overhead for each component that wants to leverage those platform helpers. We need to create a platform specific copy of each component and leverage the platform specific AccessibilityUtil.
With this change, we let Native-Common AccessibilityUtil do all the work for calling any platform specific methods.