Initial commit 🎉
fbshipit-source-id: b6fc29740c6875d2e78953b8a7123890a67930f2 Co-authored-by: Sebastian McKenzie <sebmck@fb.com> Co-authored-by: John Knox <jknox@fb.com> Co-authored-by: Emil Sjölander <emilsj@fb.com> Co-authored-by: Pritesh Nandgaonkar <prit91@fb.com>
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 2004-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "CKComponent+Sonar.h"
|
||||
|
||||
#import <ComponentKit/CKComponentAccessibility.h>
|
||||
#import <ComponentKit/CKComponentController.h>
|
||||
#import <ComponentKit/CKComponentInternal.h>
|
||||
#import <ComponentKit/CKComponentSubclass.h>
|
||||
#import <ComponentKit/CKComponentViewConfiguration.h>
|
||||
#import <SonarKitLayoutPlugin/SKNamed.h>
|
||||
#import <SonarKitLayoutPlugin/SKObject.h>
|
||||
|
||||
/** This protocol isn't actually adopted anywhere, it just lets us use the SEL below */
|
||||
@protocol SonarKitLayoutComponentKitOverrideInformalProtocol
|
||||
- (NSString *)sonar_componentNameOverride;
|
||||
- (NSString *)sonar_componentDecorationOverride;
|
||||
- (NSArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *)sonar_additionalDataOverride;
|
||||
@end
|
||||
|
||||
static BOOL AccessibilityContextIsDefault(CKComponentAccessibilityContext accessibilityContext) {
|
||||
return accessibilityContext == CKComponentAccessibilityContext();
|
||||
}
|
||||
|
||||
static NSDictionary<NSString *, NSObject *> *AccessibilityContextDict(CKComponentAccessibilityContext accessibilityContext) {
|
||||
NSMutableDictionary<NSString *, NSObject *> *accessibilityDict = [NSMutableDictionary new];
|
||||
if (accessibilityContext.isAccessibilityElement != nil) {
|
||||
accessibilityDict[@"isAccessibilityElement"] = SKObject(@([accessibilityContext.isAccessibilityElement boolValue]));
|
||||
}
|
||||
if (accessibilityContext.accessibilityLabel.hasText()) {
|
||||
accessibilityDict[@"accessibilityLabel"] = SKObject(accessibilityContext.accessibilityLabel.value());
|
||||
}
|
||||
if (accessibilityContext.accessibilityHint.hasText()) {
|
||||
accessibilityDict[@"accessibilityHint"] = SKObject(accessibilityContext.accessibilityHint.value());
|
||||
}
|
||||
if (accessibilityContext.accessibilityValue.hasText()) {
|
||||
accessibilityDict[@"accessibilityValue"] = SKObject(accessibilityContext.accessibilityValue.value());
|
||||
}
|
||||
if (accessibilityContext.accessibilityTraits != nil) {
|
||||
accessibilityDict[@"accessibilityTraits"] = SKObject(@([accessibilityContext.accessibilityTraits integerValue]));
|
||||
}
|
||||
if (accessibilityContext.accessibilityComponentAction) {
|
||||
accessibilityDict[@"accessibilityComponentAction.identifier"] = SKObject(@(accessibilityContext.accessibilityComponentAction.identifier().c_str()));
|
||||
}
|
||||
return accessibilityDict;
|
||||
}
|
||||
|
||||
FB_LINKABLE(CKComponent_Sonar)
|
||||
@implementation CKComponent (Sonar)
|
||||
|
||||
- (NSString *)sonar_getName
|
||||
{
|
||||
if ([self respondsToSelector:@selector(sonar_componentNameOverride)]) {
|
||||
return [(id)self sonar_componentNameOverride];
|
||||
}
|
||||
return NSStringFromClass([self class]);
|
||||
}
|
||||
|
||||
- (NSString *)sonar_getDecoration
|
||||
{
|
||||
if ([self respondsToSelector:@selector(sonar_componentDecorationOverride)]) {
|
||||
return [(id)self sonar_componentDecorationOverride];
|
||||
}
|
||||
return @"componentkit";
|
||||
}
|
||||
|
||||
- (NSArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *)sonar_getData
|
||||
{
|
||||
static NSDictionary<NSNumber *, NSString *> *UIControlEventsEnumMap = @{
|
||||
@(UIControlEventTouchDown): @"UIControlEventTouchDown",
|
||||
@(UIControlEventTouchDownRepeat): @"UIControlEventTouchDownRepeat",
|
||||
@(UIControlEventTouchDragInside): @"UIControlEventTouchDragInside",
|
||||
@(UIControlEventTouchDragOutside): @"UIControlEventTouchDragOutside",
|
||||
@(UIControlEventTouchDragEnter): @"UIControlEventTouchDragEnter",
|
||||
@(UIControlEventTouchDragExit): @"UIControlEventTouchDragExit",
|
||||
@(UIControlEventTouchUpInside): @"UIControlEventTouchUpInside",
|
||||
@(UIControlEventTouchUpOutside): @"UIControlEventTouchUpOutside",
|
||||
@(UIControlEventTouchCancel): @"UIControlEventTouchTouchCancel",
|
||||
|
||||
@(UIControlEventValueChanged): @"UIControlEventValueChanged",
|
||||
@(UIControlEventPrimaryActionTriggered): @"UIControlEventPrimaryActionTriggered",
|
||||
|
||||
@(UIControlEventEditingDidBegin): @"UIControlEventEditingDidBegin",
|
||||
@(UIControlEventEditingChanged): @"UIControlEventEditingChanged",
|
||||
@(UIControlEventEditingDidEnd): @"UIControlEventEditingDidEnd",
|
||||
@(UIControlEventEditingDidEndOnExit): @"UIControlEventEditingDidEndOnExit",
|
||||
};
|
||||
|
||||
|
||||
NSMutableArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *data = [NSMutableArray new];
|
||||
|
||||
[data addObject: [SKNamed newWithName: @"CKComponent"
|
||||
withValue: @{
|
||||
@"frame": SKObject(self.viewContext.frame),
|
||||
@"controller": SKObject(NSStringFromClass([self.controller class])),
|
||||
}]];
|
||||
|
||||
if (self.viewContext.view) {
|
||||
auto _actions = _CKComponentDebugControlActionsForComponent(self);
|
||||
if (_actions.size() > 0) {
|
||||
NSMutableDictionary<NSString *, NSObject *> *actions = [NSMutableDictionary new];
|
||||
|
||||
for (NSNumber *controlEvent : [UIControlEventsEnumMap allKeys]) {
|
||||
NSMutableArray<NSDictionary<NSString *, NSObject *> *> *responders = [NSMutableArray new];
|
||||
|
||||
for (const auto action : _actions) {
|
||||
if ((action.first & [controlEvent integerValue]) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto responder : action.second) {
|
||||
id initialTarget = _CKTypedComponentDebugInitialTarget(responder).get(self);
|
||||
const CKActionInfo actionInfo = CKActionFind(responder.selector(), initialTarget);
|
||||
[responders addObject: @{
|
||||
@"initialTarget": SKObject(NSStringFromClass([initialTarget class])),
|
||||
@"identifier": SKObject(@(responder.identifier().c_str())),
|
||||
@"handler": SKObject(NSStringFromClass([actionInfo.responder class])),
|
||||
@"selector": SKObject(NSStringFromSelector(responder.selector())),
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
if (responders.count > 0) {
|
||||
actions[UIControlEventsEnumMap[controlEvent]] = responders;
|
||||
}
|
||||
}
|
||||
|
||||
[data addObject: [SKNamed newWithName: @"Actions" withValue: actions]];
|
||||
}
|
||||
}
|
||||
|
||||
// Only add accessibility panel if accessibilityContext is not default
|
||||
CKComponentAccessibilityContext accessibilityContext = [self viewConfiguration].accessibilityContext();
|
||||
if (!AccessibilityContextIsDefault(accessibilityContext)) {
|
||||
[data addObject:
|
||||
[SKNamed newWithName: @"Accessibility"
|
||||
withValue: @{
|
||||
@"accessibilityContext": AccessibilityContextDict(accessibilityContext),
|
||||
@"accessibilityEnabled": SKMutableObject(@(CK::Component::Accessibility::IsAccessibilityEnabled())),
|
||||
}]];
|
||||
}
|
||||
|
||||
if ([self respondsToSelector:@selector(sonar_additionalDataOverride)]) {
|
||||
[data addObjectsFromArray:[(id)self sonar_additionalDataOverride]];
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, SKNodeUpdateData> *)sonar_getDataMutations {
|
||||
return @{
|
||||
@"CKComponentAccessibility.accessibilityEnabled": ^(NSNumber *value) {
|
||||
CK::Component::Accessibility::SetForceAccessibilityEnabled([value boolValue]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user