Run CLANGFORMAT on plugins
Summary: This diff runs CLANGFORMAT lint on plugins. I have added CLANGFORMAT as the lint engined for objc files in xplat/sonar. Right now the iOS folder is not formatted according to CLANGFORMAT. Ran `arc lint -a --paths-cmd "find ./iOS/Plugins -type f" --verbose` Reviewed By: passy Differential Revision: D19942173 fbshipit-source-id: 8b975b0a344df073b02d69cd1f9ee5629af2799d
This commit is contained in:
committed by
Facebook Github Bot
parent
a19a430eee
commit
e8b20d5b15
@@ -7,13 +7,12 @@
|
|||||||
|
|
||||||
#if FB_SONARKIT_ENABLED
|
#if FB_SONARKIT_ENABLED
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#import <FlipperKit/FlipperPlugin.h>
|
#import <FlipperKit/FlipperPlugin.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface FlipperKitBloksPlugin : NSObject<FlipperPlugin>
|
@interface FlipperKitBloksPlugin : NSObject<FlipperPlugin>
|
||||||
|
|
||||||
- (void)logAction:(NSString *)action
|
- (void)logAction:(NSString*)action withData:(NSDictionary*)data;
|
||||||
withData:(NSDictionary *)data;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,7 @@
|
|||||||
#import <FlipperKit/FlipperResponder.h>
|
#import <FlipperKit/FlipperResponder.h>
|
||||||
#import "Plugins.h"
|
#import "Plugins.h"
|
||||||
|
|
||||||
@implementation FlipperKitBloksPlugin
|
@implementation FlipperKitBloksPlugin {
|
||||||
{
|
|
||||||
id<FlipperConnection> _connection;
|
id<FlipperConnection> _connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +24,7 @@
|
|||||||
_connection = nil;
|
_connection = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)identifier {
|
- (NSString*)identifier {
|
||||||
return @"flipper-plugin-bloks";
|
return @"flipper-plugin-bloks";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,15 +32,13 @@
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)logAction:(NSString *)action
|
- (void)logAction:(NSString*)action withData:(NSDictionary*)data {
|
||||||
withData:(NSDictionary *)data {
|
|
||||||
[_connection send:action withParams:data];
|
[_connection send:action withParams:data];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
void IGBloksFlipperPluginInit(FlipperClient *client)
|
void IGBloksFlipperPluginInit(FlipperClient* client) {
|
||||||
{
|
|
||||||
[client addPlugin:[FlipperKitBloksPlugin new]];
|
[client addPlugin:[FlipperKitBloksPlugin new]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,19 +5,20 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#import <FlipperKit/FlipperPlugin.h>
|
#import <FlipperKit/FlipperPlugin.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@protocol FlipperKitExampleCommunicationResponderDelegate
|
@protocol FlipperKitExampleCommunicationResponderDelegate
|
||||||
- (void)messageReceived:(NSString *)msg;
|
- (void)messageReceived:(NSString*)msg;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface FlipperKitExamplePlugin : NSObject<FlipperPlugin>
|
@interface FlipperKitExamplePlugin : NSObject<FlipperPlugin>
|
||||||
@property (weak, nonatomic) id<FlipperKitExampleCommunicationResponderDelegate> delegate;
|
@property(weak, nonatomic) id<FlipperKitExampleCommunicationResponderDelegate>
|
||||||
|
delegate;
|
||||||
|
|
||||||
- (instancetype)init NS_UNAVAILABLE;
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
- (void)sendMessage:(NSString *)msg;
|
- (void)sendMessage:(NSString*)msg;
|
||||||
- (void)triggerNotification;
|
- (void)triggerNotification;
|
||||||
+ (instancetype) sharedInstance;
|
+ (instancetype)sharedInstance;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
#import <FlipperKit/FlipperConnection.h>
|
#import <FlipperKit/FlipperConnection.h>
|
||||||
#import <FlipperKit/FlipperResponder.h>
|
#import <FlipperKit/FlipperResponder.h>
|
||||||
|
|
||||||
@interface FlipperKitExamplePlugin()
|
@interface FlipperKitExamplePlugin ()
|
||||||
@property (strong, nonatomic) id<FlipperConnection> connection;
|
@property(strong, nonatomic) id<FlipperConnection> connection;
|
||||||
@property (nonatomic) NSInteger triggerCount;
|
@property(nonatomic) NSInteger triggerCount;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)sharedInstance {
|
+ (instancetype)sharedInstance {
|
||||||
static FlipperKitExamplePlugin *sInstance = nil;
|
static FlipperKitExamplePlugin* sInstance = nil;
|
||||||
|
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
@@ -38,11 +38,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)didConnect:(id<FlipperConnection>)connection {
|
- (void)didConnect:(id<FlipperConnection>)connection {
|
||||||
__weak FlipperKitExamplePlugin *weakSelf = self;
|
__weak FlipperKitExamplePlugin* weakSelf = self;
|
||||||
self.connection = connection;
|
self.connection = connection;
|
||||||
[connection receive:@"displayMessage" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
|
[connection receive:@"displayMessage"
|
||||||
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
[weakSelf.delegate messageReceived:params[@"message"]];
|
[weakSelf.delegate messageReceived:params[@"message"]];
|
||||||
[responder success:@{@"greeting": @"Hello"}];
|
[responder success:@{@"greeting" : @"Hello"}];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@
|
|||||||
self.connection = nil;
|
self.connection = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)identifier {
|
- (NSString*)identifier {
|
||||||
return @"Example";
|
return @"Example";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,12 +59,13 @@
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)sendMessage:(NSString *)msg {
|
- (void)sendMessage:(NSString*)msg {
|
||||||
[self.connection send:@"displayMessage" withParams:@{@"msg": msg}];
|
[self.connection send:@"displayMessage" withParams:@{@"msg" : msg}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)triggerNotification {
|
- (void)triggerNotification {
|
||||||
[self.connection send:@"triggerNotification" withParams:@{@"id": @(self.triggerCount)}];
|
[self.connection send:@"triggerNotification"
|
||||||
|
withParams:@{@"id" : @(self.triggerCount)}];
|
||||||
self.triggerCount++;
|
self.triggerCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,17 +14,27 @@
|
|||||||
|
|
||||||
#import "CKComponent+Sonar.h"
|
#import "CKComponent+Sonar.h"
|
||||||
|
|
||||||
static NSDictionary<NSString *, NSObject *> *CKCenterLayoutComponentCenteringOptionsParser(CKCenterLayoutComponentCenteringOptions centeringOptions) {
|
static NSDictionary<NSString*, NSObject*>*
|
||||||
NSMutableDictionary<NSString *, NSObject *> *centeringDict = [NSMutableDictionary new];
|
CKCenterLayoutComponentCenteringOptionsParser(
|
||||||
centeringDict[@"centeringX"] = SKMutableObject(@((BOOL)(centeringOptions & CKCenterLayoutComponentCenteringX)));
|
CKCenterLayoutComponentCenteringOptions centeringOptions) {
|
||||||
centeringDict[@"centeringY"] = SKMutableObject(@((BOOL)(centeringOptions & CKCenterLayoutComponentCenteringY)));
|
NSMutableDictionary<NSString*, NSObject*>* centeringDict =
|
||||||
|
[NSMutableDictionary new];
|
||||||
|
centeringDict[@"centeringX"] = SKMutableObject(
|
||||||
|
@((BOOL)(centeringOptions & CKCenterLayoutComponentCenteringX)));
|
||||||
|
centeringDict[@"centeringY"] = SKMutableObject(
|
||||||
|
@((BOOL)(centeringOptions & CKCenterLayoutComponentCenteringY)));
|
||||||
return centeringDict;
|
return centeringDict;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSDictionary<NSString *, NSObject *> *CKCenterLayoutComponentSizingOptionsParser(CKCenterLayoutComponentSizingOptions sizingOptions) {
|
static NSDictionary<NSString*, NSObject*>*
|
||||||
NSMutableDictionary<NSString *, NSObject *> *centeringDict = [NSMutableDictionary new];
|
CKCenterLayoutComponentSizingOptionsParser(
|
||||||
centeringDict[@"sizingMinimumX"] = SKMutableObject(@((BOOL)(sizingOptions & CKCenterLayoutComponentSizingOptionMinimumX)));
|
CKCenterLayoutComponentSizingOptions sizingOptions) {
|
||||||
centeringDict[@"sizingMinimumY"] = SKMutableObject(@((BOOL)(sizingOptions & CKCenterLayoutComponentSizingOptionMinimumY)));
|
NSMutableDictionary<NSString*, NSObject*>* centeringDict =
|
||||||
|
[NSMutableDictionary new];
|
||||||
|
centeringDict[@"sizingMinimumX"] = SKMutableObject(
|
||||||
|
@((BOOL)(sizingOptions & CKCenterLayoutComponentSizingOptionMinimumX)));
|
||||||
|
centeringDict[@"sizingMinimumY"] = SKMutableObject(
|
||||||
|
@((BOOL)(sizingOptions & CKCenterLayoutComponentSizingOptionMinimumY)));
|
||||||
return centeringDict;
|
return centeringDict;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,12 +50,20 @@ struct CKCenterLayoutComponentOptionsStruct {
|
|||||||
FB_LINKABLE(CKCenterLayoutComponent_Sonar)
|
FB_LINKABLE(CKCenterLayoutComponent_Sonar)
|
||||||
@implementation CKCenterLayoutComponent (Sonar)
|
@implementation CKCenterLayoutComponent (Sonar)
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *)sonar_additionalDataOverride
|
- (NSArray<SKNamed<NSDictionary<NSString*, NSObject*>*>*>*)
|
||||||
{
|
sonar_additionalDataOverride {
|
||||||
return @[[SKNamed newWithName:@"CKCenterLayoutComponent" withValue:@{
|
return @[ [SKNamed
|
||||||
@"centeringOptions": SKMutableObject(CKCenterLayoutComponentCenteringOptionsParser((CKCenterLayoutComponentCenteringOptions)[[self valueForKey:@"_centeringOptions"] longValue])),
|
newWithName:@"CKCenterLayoutComponent"
|
||||||
@"sizingOptions": SKMutableObject(CKCenterLayoutComponentSizingOptionsParser((CKCenterLayoutComponentSizingOptions)[[self valueForKey:@"_sizingOptions"] longValue]))
|
withValue:@{
|
||||||
}]];
|
@"centeringOptions" :
|
||||||
|
SKMutableObject(CKCenterLayoutComponentCenteringOptionsParser(
|
||||||
|
(CKCenterLayoutComponentCenteringOptions)[
|
||||||
|
[self valueForKey:@"_centeringOptions"] longValue])),
|
||||||
|
@"sizingOptions" :
|
||||||
|
SKMutableObject(CKCenterLayoutComponentSizingOptionsParser(
|
||||||
|
(CKCenterLayoutComponentSizingOptions)[
|
||||||
|
[self valueForKey:@"_sizingOptions"] longValue]))
|
||||||
|
}] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setMutableData:(id)data {
|
- (void)setMutableData:(id)data {
|
||||||
@@ -55,15 +73,19 @@ FB_LINKABLE(CKCenterLayoutComponent_Sonar)
|
|||||||
[self setValue:@(value.sizingOptions) forKey:@"_sizingOptions"];
|
[self setValue:@(value.sizingOptions) forKey:@"_sizingOptions"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, SKNodeDataChanged> *)sonar_getDataMutationsChanged {
|
- (NSDictionary<NSString*, SKNodeDataChanged>*)sonar_getDataMutationsChanged {
|
||||||
__block CKCenterLayoutComponentOptionsStruct options;
|
__block CKCenterLayoutComponentOptionsStruct options;
|
||||||
options.centeringOptions = (CKCenterLayoutComponentCenteringOptions)[[self valueForKey:@"_centeringOptions"] longValue];
|
options.centeringOptions = (CKCenterLayoutComponentCenteringOptions)[
|
||||||
options.sizingOptions = (CKCenterLayoutComponentSizingOptions)[[self valueForKey:@"_sizingOptions"] longValue];
|
[self valueForKey:@"_centeringOptions"] longValue];
|
||||||
|
options.sizingOptions = (CKCenterLayoutComponentSizingOptions)[
|
||||||
|
[self valueForKey:@"_sizingOptions"] longValue];
|
||||||
return @{
|
return @{
|
||||||
@"CKCenterLayoutComponent.centeringOptions.centeringX": ^(NSNumber *value) {
|
@"CKCenterLayoutComponent.centeringOptions.centeringX" : ^(NSNumber* value){
|
||||||
options.centeringOptions ^= CKCenterLayoutComponentCenteringX;
|
options.centeringOptions ^= CKCenterLayoutComponentCenteringX;
|
||||||
return [NSValue value:&options withObjCType:@encode(CKCenterLayoutComponentOptionsStruct)];
|
return [NSValue value:&options
|
||||||
},
|
withObjCType:@encode(CKCenterLayoutComponentOptionsStruct)];
|
||||||
|
}
|
||||||
|
,
|
||||||
@"CKCenterLayoutComponent.centeringOptions.centeringY": ^(NSNumber *value) {
|
@"CKCenterLayoutComponent.centeringOptions.centeringY": ^(NSNumber *value) {
|
||||||
options.centeringOptions ^= CKCenterLayoutComponentCenteringY;
|
options.centeringOptions ^= CKCenterLayoutComponentCenteringY;
|
||||||
return [NSValue value:&options withObjCType:@encode(CKCenterLayoutComponentOptionsStruct)];
|
return [NSValue value:&options withObjCType:@encode(CKCenterLayoutComponentOptionsStruct)];
|
||||||
@@ -76,7 +98,8 @@ FB_LINKABLE(CKCenterLayoutComponent_Sonar)
|
|||||||
options.sizingOptions ^= CKCenterLayoutComponentSizingOptionMinimumY;
|
options.sizingOptions ^= CKCenterLayoutComponentSizingOptionMinimumY;
|
||||||
return [NSValue value:&options withObjCType:@encode(CKCenterLayoutComponentOptionsStruct)];
|
return [NSValue value:&options withObjCType:@encode(CKCenterLayoutComponentOptionsStruct)];
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ typedef id (^SKNodeDataChanged)(id value);
|
|||||||
|
|
||||||
FB_LINK_REQUIRE_CATEGORY(CKComponent_Sonar)
|
FB_LINK_REQUIRE_CATEGORY(CKComponent_Sonar)
|
||||||
@interface CKComponent (Sonar)
|
@interface CKComponent (Sonar)
|
||||||
@property (assign, nonatomic) NSUInteger flipper_canBeReusedCounter;
|
@property(assign, nonatomic) NSUInteger flipper_canBeReusedCounter;
|
||||||
|
|
||||||
- (void)setMutableData:(id)data;
|
- (void)setMutableData:(id)data;
|
||||||
- (NSDictionary<NSString *, SKNodeDataChanged> *)sonar_getDataMutationsChanged;
|
- (NSDictionary<NSString*, SKNodeDataChanged>*)sonar_getDataMutationsChanged;
|
||||||
- (NSArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *)sonar_getData;
|
- (NSArray<SKNamed<NSDictionary<NSString*, NSObject*>*>*>*)sonar_getData;
|
||||||
- (NSDictionary<NSString *, SKNodeUpdateData> *)sonar_getDataMutations;
|
- (NSDictionary<NSString*, SKNodeUpdateData>*)sonar_getDataMutations;
|
||||||
- (NSString *)sonar_getName;
|
- (NSString*)sonar_getName;
|
||||||
- (NSString *)sonar_getDecoration;
|
- (NSString*)sonar_getDecoration;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,54 +11,66 @@
|
|||||||
|
|
||||||
#import <ComponentKit/CKComponentAccessibility.h>
|
#import <ComponentKit/CKComponentAccessibility.h>
|
||||||
#import <ComponentKit/CKComponentController.h>
|
#import <ComponentKit/CKComponentController.h>
|
||||||
|
#import <ComponentKit/CKComponentDebugController.h>
|
||||||
#import <ComponentKit/CKComponentInternal.h>
|
#import <ComponentKit/CKComponentInternal.h>
|
||||||
#import <ComponentKit/CKComponentSubclass.h>
|
#import <ComponentKit/CKComponentSubclass.h>
|
||||||
#import <ComponentKit/CKComponentViewConfiguration.h>
|
#import <ComponentKit/CKComponentViewConfiguration.h>
|
||||||
#import <ComponentKit/CKComponentDebugController.h>
|
|
||||||
#import <ComponentKit/CKMutex.h>
|
#import <ComponentKit/CKMutex.h>
|
||||||
#import <FlipperKitLayoutPlugin/SKNamed.h>
|
#import <FlipperKitLayoutPlugin/SKNamed.h>
|
||||||
#import <FlipperKitLayoutPlugin/SKObject.h>
|
#import <FlipperKitLayoutPlugin/SKObject.h>
|
||||||
#import <objc/runtime.h>
|
|
||||||
#import <objc/message.h>
|
#import <objc/message.h>
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
#import "CKCenterLayoutComponent+Sonar.h"
|
#import "CKCenterLayoutComponent+Sonar.h"
|
||||||
#import "CKRatioLayoutComponent+Sonar.h"
|
|
||||||
#import "CKFlexboxComponent+Sonar.h"
|
#import "CKFlexboxComponent+Sonar.h"
|
||||||
#import "CKInsetComponent+Sonar.h"
|
#import "CKInsetComponent+Sonar.h"
|
||||||
|
#import "CKRatioLayoutComponent+Sonar.h"
|
||||||
#import "CKStatelessComponent+Sonar.h"
|
#import "CKStatelessComponent+Sonar.h"
|
||||||
#import "FKDataStorageForLiveEditing.h"
|
#import "FKDataStorageForLiveEditing.h"
|
||||||
#import "Utils.h"
|
#import "Utils.h"
|
||||||
|
|
||||||
/** This protocol isn't actually adopted anywhere, it just lets us use the SEL below */
|
/** This protocol isn't actually adopted anywhere, it just lets us use the SEL
|
||||||
|
* below */
|
||||||
@protocol SonarKitLayoutComponentKitOverrideInformalProtocol
|
@protocol SonarKitLayoutComponentKitOverrideInformalProtocol
|
||||||
- (NSString *)sonar_componentNameOverride;
|
- (NSString*)sonar_componentNameOverride;
|
||||||
- (NSString *)sonar_componentDecorationOverride;
|
- (NSString*)sonar_componentDecorationOverride;
|
||||||
- (NSArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *)sonar_additionalDataOverride;
|
- (NSArray<SKNamed<NSDictionary<NSString*, NSObject*>*>*>*)
|
||||||
|
sonar_additionalDataOverride;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
static BOOL AccessibilityContextIsDefault(CKComponentAccessibilityContext accessibilityContext) {
|
static BOOL AccessibilityContextIsDefault(
|
||||||
|
CKComponentAccessibilityContext accessibilityContext) {
|
||||||
return accessibilityContext == CKComponentAccessibilityContext();
|
return accessibilityContext == CKComponentAccessibilityContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSDictionary<NSString *, NSObject *> *AccessibilityContextDict(CKComponentAccessibilityContext accessibilityContext) {
|
static NSDictionary<NSString*, NSObject*>* AccessibilityContextDict(
|
||||||
NSMutableDictionary<NSString *, NSObject *> *accessibilityDict = [NSMutableDictionary new];
|
CKComponentAccessibilityContext accessibilityContext) {
|
||||||
|
NSMutableDictionary<NSString*, NSObject*>* accessibilityDict =
|
||||||
|
[NSMutableDictionary new];
|
||||||
if (accessibilityContext.isAccessibilityElement != nil) {
|
if (accessibilityContext.isAccessibilityElement != nil) {
|
||||||
accessibilityDict[@"isAccessibilityElement"] = SKObject(@([accessibilityContext.isAccessibilityElement boolValue]));
|
accessibilityDict[@"isAccessibilityElement"] =
|
||||||
|
SKObject(@([accessibilityContext.isAccessibilityElement boolValue]));
|
||||||
}
|
}
|
||||||
if (accessibilityContext.accessibilityLabel.hasText()) {
|
if (accessibilityContext.accessibilityLabel.hasText()) {
|
||||||
accessibilityDict[@"accessibilityLabel"] = SKObject(accessibilityContext.accessibilityLabel.value());
|
accessibilityDict[@"accessibilityLabel"] =
|
||||||
|
SKObject(accessibilityContext.accessibilityLabel.value());
|
||||||
}
|
}
|
||||||
if (accessibilityContext.accessibilityHint.hasText()) {
|
if (accessibilityContext.accessibilityHint.hasText()) {
|
||||||
accessibilityDict[@"accessibilityHint"] = SKObject(accessibilityContext.accessibilityHint.value());
|
accessibilityDict[@"accessibilityHint"] =
|
||||||
|
SKObject(accessibilityContext.accessibilityHint.value());
|
||||||
}
|
}
|
||||||
if (accessibilityContext.accessibilityValue.hasText()) {
|
if (accessibilityContext.accessibilityValue.hasText()) {
|
||||||
accessibilityDict[@"accessibilityValue"] = SKObject(accessibilityContext.accessibilityValue.value());
|
accessibilityDict[@"accessibilityValue"] =
|
||||||
|
SKObject(accessibilityContext.accessibilityValue.value());
|
||||||
}
|
}
|
||||||
if (accessibilityContext.accessibilityTraits != nil) {
|
if (accessibilityContext.accessibilityTraits != nil) {
|
||||||
accessibilityDict[@"accessibilityTraits"] = SKObject(@([accessibilityContext.accessibilityTraits integerValue]));
|
accessibilityDict[@"accessibilityTraits"] =
|
||||||
|
SKObject(@([accessibilityContext.accessibilityTraits integerValue]));
|
||||||
}
|
}
|
||||||
if (accessibilityContext.accessibilityComponentAction) {
|
if (accessibilityContext.accessibilityComponentAction) {
|
||||||
accessibilityDict[@"accessibilityComponentAction.identifier"] = SKObject(@(accessibilityContext.accessibilityComponentAction.identifier().c_str()));
|
accessibilityDict[@"accessibilityComponentAction.identifier"] = SKObject(
|
||||||
|
@(accessibilityContext.accessibilityComponentAction.identifier()
|
||||||
|
.c_str()));
|
||||||
}
|
}
|
||||||
return accessibilityDict;
|
return accessibilityDict;
|
||||||
}
|
}
|
||||||
@@ -66,22 +78,22 @@ static NSDictionary<NSString *, NSObject *> *AccessibilityContextDict(CKComponen
|
|||||||
FB_LINKABLE(CKComponent_Sonar)
|
FB_LINKABLE(CKComponent_Sonar)
|
||||||
@implementation CKComponent (Sonar)
|
@implementation CKComponent (Sonar)
|
||||||
|
|
||||||
static FKDataStorageForLiveEditing *_dataStorage;
|
static FKDataStorageForLiveEditing* _dataStorage;
|
||||||
static NSMutableSet<NSString *> *_swizzledClasses;
|
static NSMutableSet<NSString*>* _swizzledClasses;
|
||||||
static CK::StaticMutex _mutex = CK_MUTEX_INITIALIZER;
|
static CK::StaticMutex _mutex = CK_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
+ (void)swizzleOriginalSEL:(SEL)originalSEL to:(SEL)replacementSEL
|
+ (void)swizzleOriginalSEL:(SEL)originalSEL to:(SEL)replacementSEL {
|
||||||
{
|
|
||||||
Class targetClass = self;
|
Class targetClass = self;
|
||||||
Method original = class_getInstanceMethod(targetClass, originalSEL);
|
Method original = class_getInstanceMethod(targetClass, originalSEL);
|
||||||
Method replacement = class_getInstanceMethod(targetClass, replacementSEL);
|
Method replacement = class_getInstanceMethod(targetClass, replacementSEL);
|
||||||
BOOL didAddMethod =
|
BOOL didAddMethod = class_addMethod(
|
||||||
class_addMethod(targetClass,
|
targetClass,
|
||||||
originalSEL,
|
originalSEL,
|
||||||
method_getImplementation(replacement),
|
method_getImplementation(replacement),
|
||||||
method_getTypeEncoding(replacement));
|
method_getTypeEncoding(replacement));
|
||||||
if (didAddMethod) {
|
if (didAddMethod) {
|
||||||
class_replaceMethod(targetClass,
|
class_replaceMethod(
|
||||||
|
targetClass,
|
||||||
replacementSEL,
|
replacementSEL,
|
||||||
method_getImplementation(original),
|
method_getImplementation(original),
|
||||||
method_getTypeEncoding(original));
|
method_getTypeEncoding(original));
|
||||||
@@ -90,74 +102,80 @@ static CK::StaticMutex _mutex = CK_MUTEX_INITIALIZER;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)sonar_getName
|
- (NSString*)sonar_getName {
|
||||||
{
|
|
||||||
if ([self respondsToSelector:@selector(sonar_componentNameOverride)]) {
|
if ([self respondsToSelector:@selector(sonar_componentNameOverride)]) {
|
||||||
return [(id)self sonar_componentNameOverride];
|
return [(id)self sonar_componentNameOverride];
|
||||||
}
|
}
|
||||||
auto const canBeReusedCounter = self.flipper_canBeReusedCounter;
|
auto const canBeReusedCounter = self.flipper_canBeReusedCounter;
|
||||||
if (canBeReusedCounter > 0) {
|
if (canBeReusedCounter > 0) {
|
||||||
return [NSString stringWithFormat:@"%@ (Can be reused x%lu)", NSStringFromClass([self class]), (unsigned long)canBeReusedCounter];
|
return [NSString stringWithFormat:@"%@ (Can be reused x%lu)",
|
||||||
|
NSStringFromClass([self class]),
|
||||||
|
(unsigned long)canBeReusedCounter];
|
||||||
}
|
}
|
||||||
return NSStringFromClass([self class]);
|
return NSStringFromClass([self class]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)sonar_getDecoration
|
- (NSString*)sonar_getDecoration {
|
||||||
{
|
|
||||||
if ([self respondsToSelector:@selector(sonar_componentDecorationOverride)]) {
|
if ([self respondsToSelector:@selector(sonar_componentDecorationOverride)]) {
|
||||||
return [(id)self sonar_componentDecorationOverride];
|
return [(id)self sonar_componentDecorationOverride];
|
||||||
}
|
}
|
||||||
return @"componentkit";
|
return @"componentkit";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *)sonar_getData
|
- (NSArray<SKNamed<NSDictionary<NSString*, NSObject*>*>*>*)sonar_getData {
|
||||||
{
|
static NSDictionary<NSNumber*, NSString*>* UIControlEventsEnumMap = @{
|
||||||
static NSDictionary<NSNumber *, NSString *> *UIControlEventsEnumMap = @{
|
@(UIControlEventTouchDown) : @"UIControlEventTouchDown",
|
||||||
@(UIControlEventTouchDown): @"UIControlEventTouchDown",
|
@(UIControlEventTouchDownRepeat) : @"UIControlEventTouchDownRepeat",
|
||||||
@(UIControlEventTouchDownRepeat): @"UIControlEventTouchDownRepeat",
|
@(UIControlEventTouchDragInside) : @"UIControlEventTouchDragInside",
|
||||||
@(UIControlEventTouchDragInside): @"UIControlEventTouchDragInside",
|
@(UIControlEventTouchDragOutside) : @"UIControlEventTouchDragOutside",
|
||||||
@(UIControlEventTouchDragOutside): @"UIControlEventTouchDragOutside",
|
@(UIControlEventTouchDragEnter) : @"UIControlEventTouchDragEnter",
|
||||||
@(UIControlEventTouchDragEnter): @"UIControlEventTouchDragEnter",
|
@(UIControlEventTouchDragExit) : @"UIControlEventTouchDragExit",
|
||||||
@(UIControlEventTouchDragExit): @"UIControlEventTouchDragExit",
|
@(UIControlEventTouchUpInside) : @"UIControlEventTouchUpInside",
|
||||||
@(UIControlEventTouchUpInside): @"UIControlEventTouchUpInside",
|
@(UIControlEventTouchUpOutside) : @"UIControlEventTouchUpOutside",
|
||||||
@(UIControlEventTouchUpOutside): @"UIControlEventTouchUpOutside",
|
@(UIControlEventTouchCancel) : @"UIControlEventTouchTouchCancel",
|
||||||
@(UIControlEventTouchCancel): @"UIControlEventTouchTouchCancel",
|
|
||||||
|
|
||||||
@(UIControlEventValueChanged): @"UIControlEventValueChanged",
|
@(UIControlEventValueChanged) : @"UIControlEventValueChanged",
|
||||||
@(UIControlEventPrimaryActionTriggered): @"UIControlEventPrimaryActionTriggered",
|
@(UIControlEventPrimaryActionTriggered) :
|
||||||
|
@"UIControlEventPrimaryActionTriggered",
|
||||||
|
|
||||||
@(UIControlEventEditingDidBegin): @"UIControlEventEditingDidBegin",
|
@(UIControlEventEditingDidBegin) : @"UIControlEventEditingDidBegin",
|
||||||
@(UIControlEventEditingChanged): @"UIControlEventEditingChanged",
|
@(UIControlEventEditingChanged) : @"UIControlEventEditingChanged",
|
||||||
@(UIControlEventEditingDidEnd): @"UIControlEventEditingDidEnd",
|
@(UIControlEventEditingDidEnd) : @"UIControlEventEditingDidEnd",
|
||||||
@(UIControlEventEditingDidEndOnExit): @"UIControlEventEditingDidEndOnExit",
|
@(UIControlEventEditingDidEndOnExit) : @"UIControlEventEditingDidEndOnExit",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NSMutableArray<SKNamed<NSDictionary<NSString*, NSObject*>*>*>* data =
|
||||||
|
[NSMutableArray new];
|
||||||
|
|
||||||
NSMutableArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *data = [NSMutableArray new];
|
[data addObject:[SKNamed newWithName:@"CKComponent"
|
||||||
|
withValue:@{
|
||||||
[data addObject: [SKNamed newWithName: @"CKComponent"
|
@"frame" : SKObject(self.viewContext.frame),
|
||||||
withValue: @{
|
@"controller" : SKObject(
|
||||||
@"frame": SKObject(self.viewContext.frame),
|
NSStringFromClass([self.controller class])),
|
||||||
@"controller": SKObject(NSStringFromClass([self.controller class])),
|
@"size" : SKObject(ckcomponentSize([self size])),
|
||||||
@"size": SKObject(ckcomponentSize([self size])),
|
|
||||||
}]];
|
}]];
|
||||||
|
|
||||||
auto const canBeReusedCounter = self.flipper_canBeReusedCounter;
|
auto const canBeReusedCounter = self.flipper_canBeReusedCounter;
|
||||||
if (canBeReusedCounter > 0) {
|
if (canBeReusedCounter > 0) {
|
||||||
[data addObject: [SKNamed newWithName: @"Convert to CKRenderComponent"
|
[data addObject:[SKNamed
|
||||||
withValue: @{
|
newWithName:@"Convert to CKRenderComponent"
|
||||||
@"This component can be reused" :
|
withValue:@{
|
||||||
SKObject([NSString stringWithFormat:@"%lu times", (unsigned long)canBeReusedCounter])
|
@"This component can be reused" : SKObject([NSString
|
||||||
|
stringWithFormat:@"%lu times",
|
||||||
|
(unsigned long)
|
||||||
|
canBeReusedCounter])
|
||||||
}]];
|
}]];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.viewContext.view) {
|
if (self.viewContext.view) {
|
||||||
auto _actions = _CKComponentDebugControlActionsForComponent(self);
|
auto _actions = _CKComponentDebugControlActionsForComponent(self);
|
||||||
if (_actions.size() > 0) {
|
if (_actions.size() > 0) {
|
||||||
NSMutableDictionary<NSString *, NSObject *> *actions = [NSMutableDictionary new];
|
NSMutableDictionary<NSString*, NSObject*>* actions =
|
||||||
|
[NSMutableDictionary new];
|
||||||
|
|
||||||
for (NSNumber *controlEvent : [UIControlEventsEnumMap allKeys]) {
|
for (NSNumber* controlEvent : [UIControlEventsEnumMap allKeys]) {
|
||||||
NSMutableArray<NSDictionary<NSString *, NSObject *> *> *responders = [NSMutableArray new];
|
NSMutableArray<NSDictionary<NSString*, NSObject*>*>* responders =
|
||||||
|
[NSMutableArray new];
|
||||||
|
|
||||||
for (const auto action : _actions) {
|
for (const auto action : _actions) {
|
||||||
if ((action.first & [controlEvent integerValue]) == 0) {
|
if ((action.first & [controlEvent integerValue]) == 0) {
|
||||||
@@ -167,19 +185,24 @@ static CK::StaticMutex _mutex = CK_MUTEX_INITIALIZER;
|
|||||||
for (auto responder : action.second) {
|
for (auto responder : action.second) {
|
||||||
auto debugTarget = _CKTypedComponentDebugInitialTarget(responder);
|
auto debugTarget = _CKTypedComponentDebugInitialTarget(responder);
|
||||||
if (debugTarget.isBlockBaseAction()) {
|
if (debugTarget.isBlockBaseAction()) {
|
||||||
[responders addObject: @{
|
[responders addObject:@{
|
||||||
@"identifier": SKObject(@(responder.identifier().c_str())),
|
@"identifier" : SKObject(@(responder.identifier().c_str())),
|
||||||
@"selector": SKObject(NSStringFromSelector(responder.selector())),
|
@"selector" :
|
||||||
|
SKObject(NSStringFromSelector(responder.selector())),
|
||||||
}];
|
}];
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
id initialTarget = debugTarget.get(self);
|
id initialTarget = debugTarget.get(self);
|
||||||
const CKActionInfo actionInfo = CKActionFind(responder.selector(), initialTarget);
|
const CKActionInfo actionInfo =
|
||||||
[responders addObject: @{
|
CKActionFind(responder.selector(), initialTarget);
|
||||||
@"initialTarget": SKObject(NSStringFromClass([initialTarget class])),
|
[responders addObject:@{
|
||||||
@"identifier": SKObject(@(responder.identifier().c_str())),
|
@"initialTarget" :
|
||||||
@"handler": SKObject(NSStringFromClass([actionInfo.responder class])),
|
SKObject(NSStringFromClass([initialTarget class])),
|
||||||
@"selector": SKObject(NSStringFromSelector(responder.selector())),
|
@"identifier" : SKObject(@(responder.identifier().c_str())),
|
||||||
|
@"handler" :
|
||||||
|
SKObject(NSStringFromClass([actionInfo.responder class])),
|
||||||
|
@"selector" :
|
||||||
|
SKObject(NSStringFromSelector(responder.selector())),
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,18 +213,22 @@ static CK::StaticMutex _mutex = CK_MUTEX_INITIALIZER;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[data addObject: [SKNamed newWithName: @"Actions" withValue: actions]];
|
[data addObject:[SKNamed newWithName:@"Actions" withValue:actions]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only add accessibility panel if accessibilityContext is not default
|
// Only add accessibility panel if accessibilityContext is not default
|
||||||
CKComponentAccessibilityContext accessibilityContext = [self viewConfiguration].accessibilityContext();
|
CKComponentAccessibilityContext accessibilityContext =
|
||||||
|
[self viewConfiguration].accessibilityContext();
|
||||||
if (!AccessibilityContextIsDefault(accessibilityContext)) {
|
if (!AccessibilityContextIsDefault(accessibilityContext)) {
|
||||||
[data addObject:
|
[data addObject:[SKNamed
|
||||||
[SKNamed newWithName: @"Accessibility"
|
newWithName:@"Accessibility"
|
||||||
withValue: @{
|
withValue:@{
|
||||||
@"accessibilityContext": AccessibilityContextDict(accessibilityContext),
|
@"accessibilityContext" :
|
||||||
@"accessibilityEnabled": SKMutableObject(@(CK::Component::Accessibility::IsAccessibilityEnabled())),
|
AccessibilityContextDict(accessibilityContext),
|
||||||
|
@"accessibilityEnabled" : SKMutableObject(
|
||||||
|
@(CK::Component::Accessibility::
|
||||||
|
IsAccessibilityEnabled())),
|
||||||
}]];
|
}]];
|
||||||
}
|
}
|
||||||
if ([self respondsToSelector:@selector(sonar_additionalDataOverride)]) {
|
if ([self respondsToSelector:@selector(sonar_additionalDataOverride)]) {
|
||||||
@@ -212,10 +239,9 @@ static CK::StaticMutex _mutex = CK_MUTEX_INITIALIZER;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)setMutableData:(id)value {
|
- (void)setMutableData:(id)value {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setMutableDataFromStorage {
|
- (void)setMutableDataFromStorage {
|
||||||
const auto globalID = self.treeNode.nodeIdentifier;
|
const auto globalID = self.treeNode.nodeIdentifier;
|
||||||
id data = [_dataStorage dataForTreeNodeIdentifier:globalID];
|
id data = [_dataStorage dataForTreeNodeIdentifier:globalID];
|
||||||
if (data) {
|
if (data) {
|
||||||
@@ -223,32 +249,36 @@ static CK::StaticMutex _mutex = CK_MUTEX_INITIALIZER;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString *)swizzledMethodNameForRender {
|
+ (NSString*)swizzledMethodNameForRender {
|
||||||
return [NSString stringWithFormat:@"sonar_render_%@", NSStringFromClass(self)];
|
return
|
||||||
|
[NSString stringWithFormat:@"sonar_render_%@", NSStringFromClass(self)];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (SEL)registerNewImplementation:(SEL)selector {
|
+ (SEL)registerNewImplementation:(SEL)selector {
|
||||||
SEL resultSelector = sel_registerName([[self swizzledMethodNameForRender] UTF8String]);
|
SEL resultSelector =
|
||||||
|
sel_registerName([[self swizzledMethodNameForRender] UTF8String]);
|
||||||
Method method = class_getInstanceMethod(self, selector);
|
Method method = class_getInstanceMethod(self, selector);
|
||||||
class_addMethod(self,
|
class_addMethod(
|
||||||
|
self,
|
||||||
resultSelector,
|
resultSelector,
|
||||||
method_getImplementation(method),
|
method_getImplementation(method),
|
||||||
method_getTypeEncoding(method)
|
method_getTypeEncoding(method));
|
||||||
);
|
|
||||||
return resultSelector;
|
return resultSelector;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CKComponent *)sonar_render:(id)state {
|
- (CKComponent*)sonar_render:(id)state {
|
||||||
[self setMutableDataFromStorage];
|
[self setMutableDataFromStorage];
|
||||||
SEL resultSelector = NSSelectorFromString([[self class] swizzledMethodNameForRender]);
|
SEL resultSelector =
|
||||||
return ((CKComponent *(*)(CKComponent *, SEL, id))objc_msgSend)(self, resultSelector, state);
|
NSSelectorFromString([[self class] swizzledMethodNameForRender]);
|
||||||
|
return ((CKComponent * (*)(CKComponent*, SEL, id)) objc_msgSend)(
|
||||||
|
self, resultSelector, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, SKNodeDataChanged> *)sonar_getDataMutationsChanged {
|
- (NSDictionary<NSString*, SKNodeDataChanged>*)sonar_getDataMutationsChanged {
|
||||||
return @{};
|
return @{};
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, SKNodeUpdateData> *)sonar_getDataMutations {
|
- (NSDictionary<NSString*, SKNodeUpdateData>*)sonar_getDataMutations {
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
_dataStorage = [[FKDataStorageForLiveEditing alloc] init];
|
_dataStorage = [[FKDataStorageForLiveEditing alloc] init];
|
||||||
@@ -259,46 +289,55 @@ static CK::StaticMutex _mutex = CK_MUTEX_INITIALIZER;
|
|||||||
if (![_swizzledClasses containsObject:NSStringFromClass([self class])]) {
|
if (![_swizzledClasses containsObject:NSStringFromClass([self class])]) {
|
||||||
[_swizzledClasses addObject:NSStringFromClass([self class])];
|
[_swizzledClasses addObject:NSStringFromClass([self class])];
|
||||||
if ([self respondsToSelector:@selector(render:)]) {
|
if ([self respondsToSelector:@selector(render:)]) {
|
||||||
SEL replacement = [[self class] registerNewImplementation:@selector(sonar_render:)];
|
SEL replacement =
|
||||||
|
[[self class] registerNewImplementation:@selector(sonar_render:)];
|
||||||
[[self class] swizzleOriginalSEL:@selector(render:) to:replacement];
|
[[self class] swizzleOriginalSEL:@selector(render:) to:replacement];
|
||||||
} else {
|
} else {
|
||||||
CKAssert(NO, @"Only CKRenderLayoutComponent and CKRenderLayoutWithChildrenComponent children are now able to be live editable");
|
CKAssert(
|
||||||
|
NO,
|
||||||
|
@"Only CKRenderLayoutComponent and CKRenderLayoutWithChildrenComponent children are now able to be live editable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NSDictionary<NSString *, SKNodeDataChanged> *dataChanged = [self sonar_getDataMutationsChanged];
|
NSDictionary<NSString*, SKNodeDataChanged>* dataChanged =
|
||||||
NSMutableDictionary *dataMutation = [[NSMutableDictionary alloc] init];
|
[self sonar_getDataMutationsChanged];
|
||||||
|
NSMutableDictionary* dataMutation = [[NSMutableDictionary alloc] init];
|
||||||
[dataMutation addEntriesFromDictionary:@{
|
[dataMutation addEntriesFromDictionary:@{
|
||||||
@"Accessibility.accessibilityEnabled": ^(NSNumber *value) {
|
@"Accessibility.accessibilityEnabled": ^(NSNumber *value) {
|
||||||
CK::Component::Accessibility::SetForceAccessibilityEnabled([value boolValue]);
|
CK::Component::Accessibility::SetForceAccessibilityEnabled([value boolValue]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
const auto globalID = self.treeNode.nodeIdentifier;
|
const auto globalID = self.treeNode.nodeIdentifier;
|
||||||
for (NSString *key in dataChanged) {
|
for (NSString* key in dataChanged) {
|
||||||
const auto block = dataChanged[key];
|
const auto block = dataChanged[key];
|
||||||
[dataMutation setObject:^(id value) {
|
[dataMutation
|
||||||
|
setObject:^(id value) {
|
||||||
id data = block(value);
|
id data = block(value);
|
||||||
[_dataStorage setData:data forTreeNodeIdentifier:globalID];
|
[_dataStorage setData:data forTreeNodeIdentifier:globalID];
|
||||||
[CKComponentDebugController reflowComponentsWithTreeNodeIdentifier:globalID];
|
[CKComponentDebugController
|
||||||
|
reflowComponentsWithTreeNodeIdentifier:globalID];
|
||||||
}
|
}
|
||||||
forKey:key];
|
forKey:key];
|
||||||
}
|
}
|
||||||
return dataMutation;
|
return dataMutation;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char const kCanBeReusedKey = ' ';
|
static char const kCanBeReusedKey = ' ';
|
||||||
|
|
||||||
- (void)setFlipper_canBeReusedCounter:(NSUInteger)canBeReusedCounter
|
- (void)setFlipper_canBeReusedCounter:(NSUInteger)canBeReusedCounter {
|
||||||
{
|
objc_setAssociatedObject(
|
||||||
objc_setAssociatedObject(self, &kCanBeReusedKey, @(canBeReusedCounter), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
self,
|
||||||
}
|
&kCanBeReusedKey,
|
||||||
|
@(canBeReusedCounter),
|
||||||
|
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||||
|
}
|
||||||
|
|
||||||
- (NSUInteger)flipper_canBeReusedCounter
|
- (NSUInteger)flipper_canBeReusedCounter {
|
||||||
{
|
return [objc_getAssociatedObject(self, &kCanBeReusedKey)
|
||||||
return [objc_getAssociatedObject(self, &kCanBeReusedKey) unsignedIntegerValue];
|
unsignedIntegerValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,69 +18,72 @@
|
|||||||
FB_LINKABLE(CKFlexboxComponent_Sonar)
|
FB_LINKABLE(CKFlexboxComponent_Sonar)
|
||||||
@implementation CKFlexboxComponent (Sonar)
|
@implementation CKFlexboxComponent (Sonar)
|
||||||
|
|
||||||
static NSDictionary<NSNumber *, NSString *> *CKFlexboxDirectionEnumMap;
|
static NSDictionary<NSNumber*, NSString*>* CKFlexboxDirectionEnumMap;
|
||||||
|
|
||||||
static NSDictionary<NSNumber *, NSString *> *CKFlexboxJustifyContentEnumMap;
|
static NSDictionary<NSNumber*, NSString*>* CKFlexboxJustifyContentEnumMap;
|
||||||
|
|
||||||
static NSDictionary<NSNumber *, NSString *> *CKFlexboxAlignItemsEnumMap;
|
static NSDictionary<NSNumber*, NSString*>* CKFlexboxAlignItemsEnumMap;
|
||||||
|
|
||||||
static NSDictionary<NSNumber *, NSString *> *CKFlexboxAlignContentEnumMap;
|
static NSDictionary<NSNumber*, NSString*>* CKFlexboxAlignContentEnumMap;
|
||||||
|
|
||||||
static NSDictionary<NSNumber *, NSString *> *CKFlexboxWrapEnumMap;
|
static NSDictionary<NSNumber*, NSString*>* CKFlexboxWrapEnumMap;
|
||||||
|
|
||||||
+ (void)initialize
|
+ (void)initialize {
|
||||||
{
|
|
||||||
CKFlexboxDirectionEnumMap = @{
|
CKFlexboxDirectionEnumMap = @{
|
||||||
@(CKFlexboxDirectionColumn): @"column",
|
@(CKFlexboxDirectionColumn) : @"column",
|
||||||
@(CKFlexboxDirectionRow): @"row",
|
@(CKFlexboxDirectionRow) : @"row",
|
||||||
@(CKFlexboxDirectionColumnReverse): @"column-reverse",
|
@(CKFlexboxDirectionColumnReverse) : @"column-reverse",
|
||||||
@(CKFlexboxDirectionRowReverse): @"row-reverse",
|
@(CKFlexboxDirectionRowReverse) : @"row-reverse",
|
||||||
};
|
};
|
||||||
CKFlexboxJustifyContentEnumMap = @{
|
CKFlexboxJustifyContentEnumMap = @{
|
||||||
@(CKFlexboxJustifyContentStart): @"start",
|
@(CKFlexboxJustifyContentStart) : @"start",
|
||||||
@(CKFlexboxJustifyContentCenter): @"center",
|
@(CKFlexboxJustifyContentCenter) : @"center",
|
||||||
@(CKFlexboxJustifyContentEnd): @"end",
|
@(CKFlexboxJustifyContentEnd) : @"end",
|
||||||
@(CKFlexboxJustifyContentSpaceBetween): @"space-between",
|
@(CKFlexboxJustifyContentSpaceBetween) : @"space-between",
|
||||||
@(CKFlexboxJustifyContentSpaceAround): @"space-around",
|
@(CKFlexboxJustifyContentSpaceAround) : @"space-around",
|
||||||
};
|
};
|
||||||
CKFlexboxAlignItemsEnumMap = @{
|
CKFlexboxAlignItemsEnumMap = @{
|
||||||
@(CKFlexboxAlignItemsStart): @"start",
|
@(CKFlexboxAlignItemsStart) : @"start",
|
||||||
@(CKFlexboxAlignItemsEnd): @"end",
|
@(CKFlexboxAlignItemsEnd) : @"end",
|
||||||
@(CKFlexboxAlignItemsCenter): @"center",
|
@(CKFlexboxAlignItemsCenter) : @"center",
|
||||||
@(CKFlexboxAlignItemsBaseline): @"baseline",
|
@(CKFlexboxAlignItemsBaseline) : @"baseline",
|
||||||
@(CKFlexboxAlignItemsStretch): @"stretch",
|
@(CKFlexboxAlignItemsStretch) : @"stretch",
|
||||||
};
|
};
|
||||||
CKFlexboxAlignContentEnumMap = @{
|
CKFlexboxAlignContentEnumMap = @{
|
||||||
@(CKFlexboxAlignContentStart): @"start",
|
@(CKFlexboxAlignContentStart) : @"start",
|
||||||
@(CKFlexboxAlignContentEnd): @"end",
|
@(CKFlexboxAlignContentEnd) : @"end",
|
||||||
@(CKFlexboxAlignContentCenter): @"center",
|
@(CKFlexboxAlignContentCenter) : @"center",
|
||||||
@(CKFlexboxAlignContentSpaceBetween): @"space-between",
|
@(CKFlexboxAlignContentSpaceBetween) : @"space-between",
|
||||||
@(CKFlexboxAlignContentSpaceAround): @"space-around",
|
@(CKFlexboxAlignContentSpaceAround) : @"space-around",
|
||||||
@(CKFlexboxAlignContentStretch): @"stretch",
|
@(CKFlexboxAlignContentStretch) : @"stretch",
|
||||||
};
|
};
|
||||||
CKFlexboxWrapEnumMap = @{
|
CKFlexboxWrapEnumMap = @{
|
||||||
@(CKFlexboxWrapWrap): @"wrap",
|
@(CKFlexboxWrapWrap) : @"wrap",
|
||||||
@(CKFlexboxWrapNoWrap): @"no-wrap",
|
@(CKFlexboxWrapNoWrap) : @"no-wrap",
|
||||||
@(CKFlexboxWrapWrapReverse): @"wrap-reverse",
|
@(CKFlexboxWrapWrapReverse) : @"wrap-reverse",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *)sonar_additionalDataOverride
|
- (NSArray<SKNamed<NSDictionary<NSString*, NSObject*>*>*>*)
|
||||||
{
|
sonar_additionalDataOverride {
|
||||||
CKFlexboxComponentStyle style;
|
CKFlexboxComponentStyle style;
|
||||||
[[self valueForKey: @"_style"] getValue: &style];
|
[[self valueForKey:@"_style"] getValue:&style];
|
||||||
|
|
||||||
return @[[SKNamed
|
return @[ [SKNamed
|
||||||
newWithName:@"CKFlexboxComponent"
|
newWithName:@"CKFlexboxComponent"
|
||||||
withValue:@{
|
withValue:@{
|
||||||
@"spacing": SKMutableObject(@(style.spacing)),
|
@"spacing" : SKMutableObject(@(style.spacing)),
|
||||||
@"direction": SKMutableObject(CKFlexboxDirectionEnumMap[@(style.direction)]),
|
@"direction" :
|
||||||
@"justifyContent": SKMutableObject(CKFlexboxJustifyContentEnumMap[@(style.justifyContent)]),
|
SKMutableObject(CKFlexboxDirectionEnumMap[@(style.direction)]),
|
||||||
@"alignItems": SKMutableObject(CKFlexboxAlignItemsEnumMap[@(style.alignItems)]),
|
@"justifyContent" : SKMutableObject(
|
||||||
@"alignContent": SKMutableObject(CKFlexboxAlignContentEnumMap[@(style.alignContent)]),
|
CKFlexboxJustifyContentEnumMap[@(style.justifyContent)]),
|
||||||
@"wrap": SKMutableObject(CKFlexboxWrapEnumMap[@(style.wrap)]),
|
@"alignItems" :
|
||||||
@"padding": SKMutableObject(flexboxRect(style.padding)),
|
SKMutableObject(CKFlexboxAlignItemsEnumMap[@(style.alignItems)]),
|
||||||
}]];
|
@"alignContent" : SKMutableObject(
|
||||||
|
CKFlexboxAlignContentEnumMap[@(style.alignContent)]),
|
||||||
|
@"wrap" : SKMutableObject(CKFlexboxWrapEnumMap[@(style.wrap)]),
|
||||||
|
@"padding" : SKMutableObject(flexboxRect(style.padding)),
|
||||||
|
}] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setMutableData:(id)data {
|
- (void)setMutableData:(id)data {
|
||||||
@@ -89,14 +92,14 @@ static NSDictionary<NSNumber *, NSString *> *CKFlexboxWrapEnumMap;
|
|||||||
[self setValue:data forKey:@"_style"];
|
[self setValue:data forKey:@"_style"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, SKNodeDataChanged> *)sonar_getDataMutationsChanged {
|
- (NSDictionary<NSString*, SKNodeDataChanged>*)sonar_getDataMutationsChanged {
|
||||||
__block CKFlexboxComponentStyle style;
|
__block CKFlexboxComponentStyle style;
|
||||||
[[self valueForKey:@"_style"] getValue: &style];
|
[[self valueForKey:@"_style"] getValue:&style];
|
||||||
return @{
|
return @{@"CKFlexboxComponent.spacing" : ^(NSNumber* value){
|
||||||
@"CKFlexboxComponent.spacing": ^(NSNumber *value) {
|
|
||||||
style.spacing = value.floatValue;
|
style.spacing = value.floatValue;
|
||||||
return [NSValue value:&style withObjCType:@encode(CKFlexboxComponentStyle)];
|
return [NSValue value:&style withObjCType:@encode(CKFlexboxComponentStyle)];
|
||||||
},
|
}
|
||||||
|
,
|
||||||
@"CKFlexboxComponent.direction": ^(NSString *value) {
|
@"CKFlexboxComponent.direction": ^(NSString *value) {
|
||||||
for (NSNumber *key in CKFlexboxDirectionEnumMap) {
|
for (NSNumber *key in CKFlexboxDirectionEnumMap) {
|
||||||
if ([CKFlexboxDirectionEnumMap[key] isEqualToString:value]) {
|
if ([CKFlexboxDirectionEnumMap[key] isEqualToString:value]) {
|
||||||
@@ -158,7 +161,8 @@ static NSDictionary<NSNumber *, NSString *> *CKFlexboxWrapEnumMap;
|
|||||||
style.padding.start = relativeStructDimension(value);
|
style.padding.start = relativeStructDimension(value);
|
||||||
return [NSValue value:&style withObjCType:@encode(CKFlexboxComponentStyle)];
|
return [NSValue value:&style withObjCType:@encode(CKFlexboxComponentStyle)];
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -17,22 +17,27 @@
|
|||||||
FB_LINKABLE(CKInsetComponent_Sonar)
|
FB_LINKABLE(CKInsetComponent_Sonar)
|
||||||
@implementation CKInsetComponent (Sonar)
|
@implementation CKInsetComponent (Sonar)
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *)sonar_additionalDataOverride
|
- (NSArray<SKNamed<NSDictionary<NSString*, NSObject*>*>*>*)
|
||||||
{
|
sonar_additionalDataOverride {
|
||||||
return @[[SKNamed newWithName:@"CKInsetComponent" withValue:@{@"insets": SKMutableObject([[self valueForKey:@"_insets"] UIEdgeInsetsValue])}]];
|
return @[ [SKNamed newWithName:@"CKInsetComponent"
|
||||||
|
withValue:@{
|
||||||
|
@"insets" : SKMutableObject(
|
||||||
|
[[self valueForKey:@"_insets"] UIEdgeInsetsValue])
|
||||||
|
}] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setMutableData:(id)data {
|
- (void)setMutableData:(id)data {
|
||||||
[self setValue:data forKey:@"_insets"];
|
[self setValue:data forKey:@"_insets"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, SKNodeDataChanged> *)sonar_getDataMutationsChanged {
|
- (NSDictionary<NSString*, SKNodeDataChanged>*)sonar_getDataMutationsChanged {
|
||||||
__block UIEdgeInsets insets = [[self valueForKey:@"_insets"] UIEdgeInsetsValue];
|
__block UIEdgeInsets insets =
|
||||||
return @{
|
[[self valueForKey:@"_insets"] UIEdgeInsetsValue];
|
||||||
@"CKInsetComponent.insets.bottom": ^(NSNumber *value) {
|
return @{@"CKInsetComponent.insets.bottom" : ^(NSNumber* value){
|
||||||
insets.bottom = value.floatValue;
|
insets.bottom = value.floatValue;
|
||||||
return [NSValue valueWithUIEdgeInsets:insets];
|
return [NSValue valueWithUIEdgeInsets:insets];
|
||||||
},
|
}
|
||||||
|
,
|
||||||
@"CKInsetComponent.insets.left": ^(NSNumber *value) {
|
@"CKInsetComponent.insets.left": ^(NSNumber *value) {
|
||||||
insets.left = value.floatValue;
|
insets.left = value.floatValue;
|
||||||
return [NSValue valueWithUIEdgeInsets:insets];
|
return [NSValue valueWithUIEdgeInsets:insets];
|
||||||
@@ -45,7 +50,8 @@ FB_LINKABLE(CKInsetComponent_Sonar)
|
|||||||
insets.top = value.floatValue;
|
insets.top = value.floatValue;
|
||||||
return [NSValue valueWithUIEdgeInsets:insets];
|
return [NSValue valueWithUIEdgeInsets:insets];
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -12,4 +12,3 @@ FB_LINK_REQUIRE_CATEGORY(CKRatioLayoutComponent_Sonar)
|
|||||||
@interface CKRatioLayoutComponent (Sonar)
|
@interface CKRatioLayoutComponent (Sonar)
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -17,23 +17,28 @@
|
|||||||
FB_LINKABLE(CKRatioLayoutComponent_Sonar)
|
FB_LINKABLE(CKRatioLayoutComponent_Sonar)
|
||||||
@implementation CKRatioLayoutComponent (Sonar)
|
@implementation CKRatioLayoutComponent (Sonar)
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *)sonar_additionalDataOverride
|
- (NSArray<SKNamed<NSDictionary<NSString*, NSObject*>*>*>*)
|
||||||
{
|
sonar_additionalDataOverride {
|
||||||
return @[[SKNamed newWithName:@"CKRatioLayoutComponent" withValue:@{@"ratio": SKMutableObject((NSNumber *)[self valueForKey:@"_ratio"])}]];
|
return @[ [SKNamed
|
||||||
|
newWithName:@"CKRatioLayoutComponent"
|
||||||
|
withValue:@{
|
||||||
|
@"ratio" : SKMutableObject((NSNumber*)[self valueForKey:@"_ratio"])
|
||||||
|
}] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setMutableData:(id)data {
|
- (void)setMutableData:(id)data {
|
||||||
[self setValue:data forKey:@"_ratio"];
|
[self setValue:data forKey:@"_ratio"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, SKNodeDataChanged> *)sonar_getDataMutationsChanged {
|
- (NSDictionary<NSString*, SKNodeDataChanged>*)sonar_getDataMutationsChanged {
|
||||||
return @{
|
return @{@"CKRatioLayoutComponent.ratio" : ^(NSNumber* value){
|
||||||
@"CKRatioLayoutComponent.ratio": ^(NSNumber *value) {
|
CGFloat ratio = [(NSNumber*)[self valueForKey:@"_ratio"] floatValue];
|
||||||
CGFloat ratio = [(NSNumber *)[self valueForKey:@"_ratio"] floatValue];
|
|
||||||
ratio = value.floatValue;
|
ratio = value.floatValue;
|
||||||
return [NSNumber numberWithFloat:ratio];
|
return [NSNumber numberWithFloat:ratio];
|
||||||
},
|
}
|
||||||
};
|
,
|
||||||
|
}
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,6 +11,6 @@
|
|||||||
FB_LINK_REQUIRE_CATEGORY(CKStatelessComponent_Sonar)
|
FB_LINK_REQUIRE_CATEGORY(CKStatelessComponent_Sonar)
|
||||||
@interface CKStatelessComponent (Sonar)
|
@interface CKStatelessComponent (Sonar)
|
||||||
|
|
||||||
- (NSString *)sonar_componentNameOverride;
|
- (NSString*)sonar_componentNameOverride;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
FB_LINKABLE(CKStatelessComponent_Sonar)
|
FB_LINKABLE(CKStatelessComponent_Sonar)
|
||||||
@implementation CKStatelessComponent (Sonar)
|
@implementation CKStatelessComponent (Sonar)
|
||||||
|
|
||||||
- (NSString *)sonar_componentNameOverride
|
- (NSString*)sonar_componentNameOverride {
|
||||||
{
|
|
||||||
return [self description];
|
return [self description];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,12 @@
|
|||||||
|
|
||||||
#import <ComponentKit/CKTreeNodeTypes.h>
|
#import <ComponentKit/CKTreeNodeTypes.h>
|
||||||
|
|
||||||
/** DataStorage uses to map global IDs of nodes to data which we want to store
|
/** DataStorage uses to map global IDs of nodes to data which we want to store
|
||||||
to prodice live editing*/
|
to prodice live editing*/
|
||||||
@interface FKDataStorageForLiveEditing : NSObject
|
@interface FKDataStorageForLiveEditing : NSObject
|
||||||
|
|
||||||
- (id)dataForTreeNodeIdentifier:(CKTreeNodeIdentifier)treeNodeIdentifier;
|
- (id)dataForTreeNodeIdentifier:(CKTreeNodeIdentifier)treeNodeIdentifier;
|
||||||
- (void)setData:(id)value forTreeNodeIdentifier:(CKTreeNodeIdentifier)treeNodeIdentifier;
|
- (void)setData:(id)value
|
||||||
|
forTreeNodeIdentifier:(CKTreeNodeIdentifier)treeNodeIdentifier;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setData:(id)value forTreeNodeIdentifier:(CKTreeNodeIdentifier)treeNodeIdentifier {
|
- (void)setData:(id)value
|
||||||
|
forTreeNodeIdentifier:(CKTreeNodeIdentifier)treeNodeIdentifier {
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
_data[treeNodeIdentifier] = value;
|
_data[treeNodeIdentifier] = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
#import "SKSubDescriptor.h"
|
|
||||||
#import <FlipperKitLayoutPlugin/SKDescriptorMapper.h>
|
#import <FlipperKitLayoutPlugin/SKDescriptorMapper.h>
|
||||||
|
#import "SKSubDescriptor.h"
|
||||||
|
|
||||||
@interface FlipperKitLayoutComponentKitSupport : NSObject
|
@interface FlipperKitLayoutComponentKitSupport : NSObject
|
||||||
|
|
||||||
+ (void)setUpWithDescriptorMapper:(SKDescriptorMapper *)mapper;
|
+ (void)setUpWithDescriptorMapper:(SKDescriptorMapper*)mapper;
|
||||||
|
|
||||||
+ (void)setUpWithDescriptorMapper:(SKDescriptorMapper *)mapper
|
+ (void)setUpWithDescriptorMapper:(SKDescriptorMapper*)mapper
|
||||||
subDescriptors:(NSArray<SKSubDescriptor *>*)subDescriptors;
|
subDescriptors:(NSArray<SKSubDescriptor*>*)subDescriptors;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,42 +9,48 @@
|
|||||||
|
|
||||||
#import "FlipperKitLayoutComponentKitSupport.h"
|
#import "FlipperKitLayoutComponentKitSupport.h"
|
||||||
|
|
||||||
#import <ComponentKit/CKComponentRootView.h>
|
|
||||||
#import <ComponentKit/CKComponentHostingView.h>
|
#import <ComponentKit/CKComponentHostingView.h>
|
||||||
|
#import <ComponentKit/CKComponentRootView.h>
|
||||||
|
|
||||||
#import <FlipperKitLayoutPlugin/SKDescriptorMapper.h>
|
#import <FlipperKitLayoutPlugin/SKDescriptorMapper.h>
|
||||||
|
|
||||||
#import "SKComponentHostingViewDescriptor.h"
|
#import "SKComponentHostingViewDescriptor.h"
|
||||||
#import "SKComponentRootViewDescriptor.h"
|
|
||||||
#import "SKComponentLayoutDescriptor.h"
|
#import "SKComponentLayoutDescriptor.h"
|
||||||
#import "SKComponentLayoutWrapper.h"
|
#import "SKComponentLayoutWrapper.h"
|
||||||
|
#import "SKComponentRootViewDescriptor.h"
|
||||||
#import "SKSubDescriptor.h"
|
#import "SKSubDescriptor.h"
|
||||||
|
|
||||||
@implementation FlipperKitLayoutComponentKitSupport
|
@implementation FlipperKitLayoutComponentKitSupport
|
||||||
|
|
||||||
+ (void)setUpWithDescriptorMapper:(SKDescriptorMapper *)mapper
|
+ (void)setUpWithDescriptorMapper:(SKDescriptorMapper*)mapper
|
||||||
subDescriptors:(NSArray<SKSubDescriptor *>*)subDescriptors{
|
subDescriptors:(NSArray<SKSubDescriptor*>*)subDescriptors {
|
||||||
[mapper registerDescriptor: [[SKComponentHostingViewDescriptor alloc] initWithDescriptorMapper: mapper]
|
[mapper registerDescriptor:[[SKComponentHostingViewDescriptor alloc]
|
||||||
forClass: [CKComponentHostingView class]];
|
initWithDescriptorMapper:mapper]
|
||||||
[mapper registerDescriptor: [[SKComponentRootViewDescriptor alloc] initWithDescriptorMapper: mapper]
|
forClass:[CKComponentHostingView class]];
|
||||||
forClass: [CKComponentRootView class]];
|
[mapper registerDescriptor:[[SKComponentRootViewDescriptor alloc]
|
||||||
SKComponentLayoutDescriptor *layoutDescriptor = [[SKComponentLayoutDescriptor alloc] initWithDescriptorMapper:mapper];
|
initWithDescriptorMapper:mapper]
|
||||||
|
forClass:[CKComponentRootView class]];
|
||||||
|
SKComponentLayoutDescriptor* layoutDescriptor =
|
||||||
|
[[SKComponentLayoutDescriptor alloc] initWithDescriptorMapper:mapper];
|
||||||
[layoutDescriptor addSubDescriptors:subDescriptors];
|
[layoutDescriptor addSubDescriptors:subDescriptors];
|
||||||
[mapper registerDescriptor: layoutDescriptor
|
[mapper registerDescriptor:layoutDescriptor
|
||||||
forClass: [SKComponentLayoutWrapper class]];
|
forClass:[SKComponentLayoutWrapper class]];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)setUpWithDescriptorMapper:(SKDescriptorMapper *)mapper {
|
+ (void)setUpWithDescriptorMapper:(SKDescriptorMapper*)mapper {
|
||||||
// What we really want here is "forProtocol:@protocol(CKInspectableView)" but no such luck.
|
// What we really want here is "forProtocol:@protocol(CKInspectableView)" but
|
||||||
[mapper registerDescriptor: [[SKComponentHostingViewDescriptor alloc] initWithDescriptorMapper: mapper]
|
// no such luck.
|
||||||
forClass: [CKComponentHostingView class]];
|
[mapper registerDescriptor:[[SKComponentHostingViewDescriptor alloc]
|
||||||
[mapper registerDescriptor: [[SKComponentRootViewDescriptor alloc] initWithDescriptorMapper: mapper]
|
initWithDescriptorMapper:mapper]
|
||||||
forClass: [CKComponentRootView class]];
|
forClass:[CKComponentHostingView class]];
|
||||||
[mapper registerDescriptor: [[SKComponentLayoutDescriptor alloc] initWithDescriptorMapper: mapper]
|
[mapper registerDescriptor:[[SKComponentRootViewDescriptor alloc]
|
||||||
forClass: [SKComponentLayoutWrapper class]];
|
initWithDescriptorMapper:mapper]
|
||||||
|
forClass:[CKComponentRootView class]];
|
||||||
|
[mapper registerDescriptor:[[SKComponentLayoutDescriptor alloc]
|
||||||
|
initWithDescriptorMapper:mapper]
|
||||||
|
forClass:[SKComponentLayoutWrapper class]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
@class CKComponentHostingView;
|
@class CKComponentHostingView;
|
||||||
|
|
||||||
@interface SKComponentHostingViewDescriptor : SKNodeDescriptor<CKComponentHostingView *>
|
@interface SKComponentHostingViewDescriptor
|
||||||
|
: SKNodeDescriptor<CKComponentHostingView*>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#import <ComponentKit/CKComponentHostingView.h>
|
#import <ComponentKit/CKComponentHostingView.h>
|
||||||
#import <ComponentKit/CKComponentHostingViewInternal.h>
|
#import <ComponentKit/CKComponentHostingViewInternal.h>
|
||||||
#import <ComponentKit/CKComponentLayout.h>
|
#import <ComponentKit/CKComponentLayout.h>
|
||||||
#import <ComponentKit/CKComponentHostingViewInternal.h>
|
|
||||||
|
|
||||||
#import <FlipperKitLayoutPlugin/SKDescriptorMapper.h>
|
#import <FlipperKitLayoutPlugin/SKDescriptorMapper.h>
|
||||||
|
|
||||||
@@ -21,25 +20,25 @@
|
|||||||
|
|
||||||
@implementation SKComponentHostingViewDescriptor
|
@implementation SKComponentHostingViewDescriptor
|
||||||
|
|
||||||
- (NSString *)identifierForNode:(CKComponentHostingView *)node {
|
- (NSString*)identifierForNode:(CKComponentHostingView*)node {
|
||||||
return [NSString stringWithFormat: @"%p", node];
|
return [NSString stringWithFormat:@"%p", node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)childCountForNode:(CKComponentHostingView *)node {
|
- (NSUInteger)childCountForNode:(CKComponentHostingView*)node {
|
||||||
return node.mountedLayout.component ? 1 : 0;
|
return node.mountedLayout.component ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)childForNode:(CKComponentHostingView *)node atIndex:(NSUInteger)index {
|
- (id)childForNode:(CKComponentHostingView*)node atIndex:(NSUInteger)index {
|
||||||
return [SKComponentLayoutWrapper newFromRoot:node];
|
return [SKComponentLayoutWrapper newFromRoot:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted forNode:(CKComponentHostingView *)node {
|
- (void)setHighlighted:(BOOL)highlighted forNode:(CKComponentHostingView*)node {
|
||||||
SKNodeDescriptor *viewDescriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* viewDescriptor = [self descriptorForClass:[UIView class]];
|
||||||
[viewDescriptor setHighlighted: highlighted forNode: node];
|
[viewDescriptor setHighlighted:highlighted forNode:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)hitTest:(SKTouch *)touch forNode:(CKComponentHostingView *)node {
|
- (void)hitTest:(SKTouch*)touch forNode:(CKComponentHostingView*)node {
|
||||||
[touch continueWithChildIndex: 0 withOffset: (CGPoint){ 0, 0 }];
|
[touch continueWithChildIndex:0 withOffset:(CGPoint){0, 0}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,8 +11,9 @@
|
|||||||
|
|
||||||
@class SKComponentLayoutWrapper;
|
@class SKComponentLayoutWrapper;
|
||||||
|
|
||||||
@interface SKComponentLayoutDescriptor: SKNodeDescriptor<SKComponentLayoutWrapper *>
|
@interface SKComponentLayoutDescriptor
|
||||||
|
: SKNodeDescriptor<SKComponentLayoutWrapper*>
|
||||||
|
|
||||||
- (void)addSubDescriptors:(NSArray<SKSubDescriptor *>*)subDescriptors;
|
- (void)addSubDescriptors:(NSArray<SKSubDescriptor*>*)subDescriptors;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -10,30 +10,29 @@
|
|||||||
#import "SKComponentLayoutDescriptor.h"
|
#import "SKComponentLayoutDescriptor.h"
|
||||||
|
|
||||||
#import <ComponentKit/CKComponent.h>
|
#import <ComponentKit/CKComponent.h>
|
||||||
#import <ComponentKit/CKComponentInternal.h>
|
#import <ComponentKit/CKComponentAccessibility.h>
|
||||||
#import <ComponentKit/CKComponentActionInternal.h>
|
#import <ComponentKit/CKComponentActionInternal.h>
|
||||||
|
#import <ComponentKit/CKComponentDebugController.h>
|
||||||
|
#import <ComponentKit/CKComponentInternal.h>
|
||||||
#import <ComponentKit/CKComponentLayout.h>
|
#import <ComponentKit/CKComponentLayout.h>
|
||||||
#import <ComponentKit/CKComponentRootView.h>
|
#import <ComponentKit/CKComponentRootView.h>
|
||||||
#import <ComponentKit/CKComponentViewConfiguration.h>
|
#import <ComponentKit/CKComponentViewConfiguration.h>
|
||||||
#import <ComponentKit/CKComponentAccessibility.h>
|
|
||||||
#import <ComponentKit/CKComponentDebugController.h>
|
|
||||||
#import <ComponentKit/CKInsetComponent.h>
|
|
||||||
#import <ComponentKit/CKFlexboxComponent.h>
|
#import <ComponentKit/CKFlexboxComponent.h>
|
||||||
|
#import <ComponentKit/CKInsetComponent.h>
|
||||||
|
|
||||||
#import <FlipperKitHighlightOverlay/SKHighlightOverlay.h>
|
#import <FlipperKitHighlightOverlay/SKHighlightOverlay.h>
|
||||||
#import <FlipperKitLayoutPlugin/SKObject.h>
|
#import <FlipperKitLayoutPlugin/SKObject.h>
|
||||||
#import <FlipperKitLayoutTextSearchable/FKTextSearchable.h>
|
#import <FlipperKitLayoutTextSearchable/FKTextSearchable.h>
|
||||||
|
|
||||||
#import "SKSubDescriptor.h"
|
|
||||||
#import "SKComponentLayoutWrapper.h"
|
|
||||||
#import "CKComponent+Sonar.h"
|
#import "CKComponent+Sonar.h"
|
||||||
|
#import "SKComponentLayoutWrapper.h"
|
||||||
|
#import "SKSubDescriptor.h"
|
||||||
#import "Utils.h"
|
#import "Utils.h"
|
||||||
|
|
||||||
@implementation SKComponentLayoutDescriptor
|
@implementation SKComponentLayoutDescriptor {
|
||||||
{
|
NSDictionary<NSNumber*, NSString*>* CKFlexboxAlignSelfEnumMap;
|
||||||
NSDictionary<NSNumber *, NSString *> *CKFlexboxAlignSelfEnumMap;
|
NSDictionary<NSNumber*, NSString*>* CKFlexboxPositionTypeEnumMap;
|
||||||
NSDictionary<NSNumber *, NSString *> *CKFlexboxPositionTypeEnumMap;
|
NSArray<SKSubDescriptor*>* _registeredSubdescriptors;
|
||||||
NSArray<SKSubDescriptor *>*_registeredSubdescriptors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setUp {
|
- (void)setUp {
|
||||||
@@ -51,38 +50,37 @@
|
|||||||
|
|
||||||
- (void)initEnumMaps {
|
- (void)initEnumMaps {
|
||||||
CKFlexboxAlignSelfEnumMap = @{
|
CKFlexboxAlignSelfEnumMap = @{
|
||||||
@(CKFlexboxAlignSelfAuto): @"auto",
|
@(CKFlexboxAlignSelfAuto) : @"auto",
|
||||||
@(CKFlexboxAlignSelfStart): @"start",
|
@(CKFlexboxAlignSelfStart) : @"start",
|
||||||
@(CKFlexboxAlignSelfEnd): @"end",
|
@(CKFlexboxAlignSelfEnd) : @"end",
|
||||||
@(CKFlexboxAlignSelfCenter): @"center",
|
@(CKFlexboxAlignSelfCenter) : @"center",
|
||||||
@(CKFlexboxAlignSelfBaseline): @"baseline",
|
@(CKFlexboxAlignSelfBaseline) : @"baseline",
|
||||||
@(CKFlexboxAlignSelfStretch): @"stretch",
|
@(CKFlexboxAlignSelfStretch) : @"stretch",
|
||||||
};
|
};
|
||||||
|
|
||||||
CKFlexboxPositionTypeEnumMap = @{
|
CKFlexboxPositionTypeEnumMap = @{
|
||||||
@(CKFlexboxPositionTypeRelative): @"relative",
|
@(CKFlexboxPositionTypeRelative) : @"relative",
|
||||||
@(CKFlexboxPositionTypeAbsolute): @"absolute",
|
@(CKFlexboxPositionTypeAbsolute) : @"absolute",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)identifierForNode:(SKComponentLayoutWrapper *)node {
|
- (NSString*)identifierForNode:(SKComponentLayoutWrapper*)node {
|
||||||
return node.identifier;
|
return node.identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)identifierForInvalidation:(SKComponentLayoutWrapper *)node
|
- (NSString*)identifierForInvalidation:(SKComponentLayoutWrapper*)node {
|
||||||
{
|
|
||||||
return [NSString stringWithFormat:@"%p", node.rootNode];
|
return [NSString stringWithFormat:@"%p", node.rootNode];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)nameForNode:(SKComponentLayoutWrapper *)node {
|
- (NSString*)nameForNode:(SKComponentLayoutWrapper*)node {
|
||||||
return [node.component sonar_getName];
|
return [node.component sonar_getName];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)decorationForNode:(SKComponentLayoutWrapper *)node {
|
- (NSString*)decorationForNode:(SKComponentLayoutWrapper*)node {
|
||||||
return [node.component sonar_getDecoration];
|
return [node.component sonar_getDecoration];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)childCountForNode:(SKComponentLayoutWrapper *)node {
|
- (NSUInteger)childCountForNode:(SKComponentLayoutWrapper*)node {
|
||||||
NSUInteger count = node.children.size();
|
NSUInteger count = node.children.size();
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
count = node.component.viewContext.view ? 1 : 0;
|
count = node.component.viewContext.view ? 1 : 0;
|
||||||
@@ -90,7 +88,7 @@
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)childForNode:(SKComponentLayoutWrapper *)node atIndex:(NSUInteger)index {
|
- (id)childForNode:(SKComponentLayoutWrapper*)node atIndex:(NSUInteger)index {
|
||||||
if (node.children.size() == 0) {
|
if (node.children.size() == 0) {
|
||||||
if (node.rootNode == node.component.viewContext.view) {
|
if (node.rootNode == node.component.viewContext.view) {
|
||||||
return nil;
|
return nil;
|
||||||
@@ -100,83 +98,97 @@
|
|||||||
return node.children[index];
|
return node.children[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *)dataForNode:(SKComponentLayoutWrapper *)node {
|
- (NSArray<SKNamed<NSDictionary<NSString*, NSObject*>*>*>*)dataForNode:
|
||||||
NSMutableArray<SKNamed<NSDictionary<NSString *, NSObject *> *> *> *data = [NSMutableArray new];
|
(SKComponentLayoutWrapper*)node {
|
||||||
|
NSMutableArray<SKNamed<NSDictionary<NSString*, NSObject*>*>*>* data =
|
||||||
|
[NSMutableArray new];
|
||||||
|
|
||||||
if (node.isFlexboxChild) {
|
if (node.isFlexboxChild) {
|
||||||
[data addObject: [SKNamed newWithName:@"Layout" withValue:[self propsForFlexboxChild:node.flexboxChild]]];
|
[data
|
||||||
|
addObject:[SKNamed
|
||||||
|
newWithName:@"Layout"
|
||||||
|
withValue:[self
|
||||||
|
propsForFlexboxChild:node.flexboxChild]]];
|
||||||
}
|
}
|
||||||
NSMutableDictionary<NSString *, NSObject *> *extraData = [[NSMutableDictionary alloc] init];
|
NSMutableDictionary<NSString*, NSObject*>* extraData =
|
||||||
|
[[NSMutableDictionary alloc] init];
|
||||||
|
|
||||||
for (SKSubDescriptor *s in _registeredSubdescriptors) {
|
for (SKSubDescriptor* s in _registeredSubdescriptors) {
|
||||||
[extraData setObject:[s getDataForNode:node] forKey:[s getName]];
|
[extraData setObject:[s getDataForNode:node] forKey:[s getName]];
|
||||||
}
|
}
|
||||||
if (extraData.count > 0) {
|
if (extraData.count > 0) {
|
||||||
[data addObject: [SKNamed newWithName:@"Extra Sections" withValue:extraData]];
|
[data addObject:[SKNamed newWithName:@"Extra Sections"
|
||||||
|
withValue:extraData]];
|
||||||
}
|
}
|
||||||
|
|
||||||
[data addObjectsFromArray:[node.component sonar_getData]];
|
[data addObjectsFromArray:[node.component sonar_getData]];
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addSubDescriptors:(nonnull NSArray<SKSubDescriptor *>*)subDescriptors{
|
- (void)addSubDescriptors:(nonnull NSArray<SKSubDescriptor*>*)subDescriptors {
|
||||||
_registeredSubdescriptors = subDescriptors;
|
_registeredSubdescriptors = subDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, NSObject *> *)propsForFlexboxChild:(CKFlexboxComponentChild)child {
|
- (NSDictionary<NSString*, NSObject*>*)propsForFlexboxChild:
|
||||||
|
(CKFlexboxComponentChild)child {
|
||||||
return @{
|
return @{
|
||||||
@"spacingBefore": SKObject(@(child.spacingBefore)),
|
@"spacingBefore" : SKObject(@(child.spacingBefore)),
|
||||||
@"spacingAfter": SKObject(@(child.spacingAfter)),
|
@"spacingAfter" : SKObject(@(child.spacingAfter)),
|
||||||
@"flexGrow": SKObject(@(child.flexGrow)),
|
@"flexGrow" : SKObject(@(child.flexGrow)),
|
||||||
@"flexShrink": SKObject(@(child.flexShrink)),
|
@"flexShrink" : SKObject(@(child.flexShrink)),
|
||||||
@"zIndex": SKObject(@(child.zIndex)),
|
@"zIndex" : SKObject(@(child.zIndex)),
|
||||||
@"sizeConstraints": SKObject(ckcomponentSize(child.sizeConstraints)),
|
@"sizeConstraints" : SKObject(ckcomponentSize(child.sizeConstraints)),
|
||||||
@"useTextRounding": SKObject(@(child.useTextRounding)),
|
@"useTextRounding" : SKObject(@(child.useTextRounding)),
|
||||||
@"margin": flexboxRect(child.margin),
|
@"margin" : flexboxRect(child.margin),
|
||||||
@"flexBasis": relativeDimension(child.flexBasis),
|
@"flexBasis" : relativeDimension(child.flexBasis),
|
||||||
@"padding": flexboxRect(child.padding),
|
@"padding" : flexboxRect(child.padding),
|
||||||
@"alignSelf": CKFlexboxAlignSelfEnumMap[@(child.alignSelf)],
|
@"alignSelf" : CKFlexboxAlignSelfEnumMap[@(child.alignSelf)],
|
||||||
@"position": @{
|
@"position" : @{
|
||||||
@"type": CKFlexboxPositionTypeEnumMap[@(child.position.type)],
|
@"type" : CKFlexboxPositionTypeEnumMap[@(child.position.type)],
|
||||||
@"start": relativeDimension(child.position.start),
|
@"start" : relativeDimension(child.position.start),
|
||||||
@"top": relativeDimension(child.position.top),
|
@"top" : relativeDimension(child.position.top),
|
||||||
@"end": relativeDimension(child.position.end),
|
@"end" : relativeDimension(child.position.end),
|
||||||
@"bottom": relativeDimension(child.position.bottom),
|
@"bottom" : relativeDimension(child.position.bottom),
|
||||||
@"left": relativeDimension(child.position.left),
|
@"left" : relativeDimension(child.position.left),
|
||||||
@"right": relativeDimension(child.position.right),
|
@"right" : relativeDimension(child.position.right),
|
||||||
},
|
},
|
||||||
@"aspectRatio": @(child.aspectRatio.aspectRatio()),
|
@"aspectRatio" : @(child.aspectRatio.aspectRatio()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, SKNodeUpdateData> *)dataMutationsForNode:(SKComponentLayoutWrapper *)node {
|
- (NSDictionary<NSString*, SKNodeUpdateData>*)dataMutationsForNode:
|
||||||
|
(SKComponentLayoutWrapper*)node {
|
||||||
return [node.component sonar_getDataMutations];
|
return [node.component sonar_getDataMutations];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSString *> *> *)attributesForNode:(SKComponentLayoutWrapper *)node {
|
- (NSArray<SKNamed<NSString*>*>*)attributesForNode:
|
||||||
NSMutableArray<SKNamed<NSString *> *> *attributes = [NSMutableArray array];
|
(SKComponentLayoutWrapper*)node {
|
||||||
[attributes addObject:[SKNamed newWithName:@"responder"
|
NSMutableArray<SKNamed<NSString*>*>* attributes = [NSMutableArray array];
|
||||||
withValue:SKObject(NSStringFromClass([node.component.nextResponder class]))]];
|
[attributes
|
||||||
|
addObject:[SKNamed
|
||||||
|
newWithName:@"responder"
|
||||||
|
withValue:SKObject(NSStringFromClass(
|
||||||
|
[node.component.nextResponder class]))]];
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted forNode:(SKComponentLayoutWrapper *)node {
|
- (void)setHighlighted:(BOOL)highlighted
|
||||||
SKHighlightOverlay *overlay = [SKHighlightOverlay sharedInstance];
|
forNode:(SKComponentLayoutWrapper*)node {
|
||||||
|
SKHighlightOverlay* overlay = [SKHighlightOverlay sharedInstance];
|
||||||
if (highlighted) {
|
if (highlighted) {
|
||||||
CKComponentViewContext viewContext = node.component.viewContext;
|
CKComponentViewContext viewContext = node.component.viewContext;
|
||||||
[overlay mountInView: viewContext.view
|
[overlay mountInView:viewContext.view withFrame:viewContext.frame];
|
||||||
withFrame: viewContext.frame];
|
|
||||||
} else {
|
} else {
|
||||||
[overlay unmount];
|
[overlay unmount];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)hitTest:(SKTouch *)touch forNode:(SKComponentLayoutWrapper *)node {
|
- (void)hitTest:(SKTouch*)touch forNode:(SKComponentLayoutWrapper*)node {
|
||||||
if (node.children.size() == 0) {
|
if (node.children.size() == 0) {
|
||||||
UIView *componentView = node.component.viewContext.view;
|
UIView* componentView = node.component.viewContext.view;
|
||||||
if (componentView != nil) {
|
if (componentView != nil) {
|
||||||
if ([touch containedIn: componentView.bounds]) {
|
if ([touch containedIn:componentView.bounds]) {
|
||||||
[touch continueWithChildIndex: 0 withOffset: componentView.bounds.origin];
|
[touch continueWithChildIndex:0 withOffset:componentView.bounds.origin];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,13 +198,10 @@
|
|||||||
for (index = node.children.size() - 1; index >= 0; index--) {
|
for (index = node.children.size() - 1; index >= 0; index--) {
|
||||||
const auto child = node.children[index];
|
const auto child = node.children[index];
|
||||||
|
|
||||||
CGRect frame = {
|
CGRect frame = {.origin = child.position, .size = child.size};
|
||||||
.origin = child.position,
|
|
||||||
.size = child.size
|
|
||||||
};
|
|
||||||
|
|
||||||
if ([touch containedIn: frame]) {
|
if ([touch containedIn:frame]) {
|
||||||
[touch continueWithChildIndex: index withOffset: child.position];
|
[touch continueWithChildIndex:index withOffset:child.position];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,22 +209,26 @@
|
|||||||
[touch finish];
|
[touch finish];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)matchesQuery:(NSString *)query forNode:(id)node {
|
- (BOOL)matchesQuery:(NSString*)query forNode:(id)node {
|
||||||
if ([super matchesQuery:query forNode:node]) {
|
if ([super matchesQuery:query forNode:node]) {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
if ([node isKindOfClass:[SKComponentLayoutWrapper class]]) {
|
if ([node isKindOfClass:[SKComponentLayoutWrapper class]]) {
|
||||||
const auto layoutWrapper = (SKComponentLayoutWrapper *)node;
|
const auto layoutWrapper = (SKComponentLayoutWrapper*)node;
|
||||||
if ([layoutWrapper.component conformsToProtocol:@protocol(FKTextSearchable)]) {
|
if ([layoutWrapper.component
|
||||||
NSString *text = ((id<FKTextSearchable>)layoutWrapper.component).searchableText;
|
conformsToProtocol:@protocol(FKTextSearchable)]) {
|
||||||
|
NSString* text =
|
||||||
|
((id<FKTextSearchable>)layoutWrapper.component).searchableText;
|
||||||
return [self string:text contains:query];
|
return [self string:text contains:query];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)string:(NSString *)string contains:(NSString *)substring {
|
- (BOOL)string:(NSString*)string contains:(NSString*)substring {
|
||||||
return string != nil && substring != nil && [string rangeOfString: substring options: NSCaseInsensitiveSearch].location != NSNotFound;
|
return string != nil && substring != nil &&
|
||||||
|
[string rangeOfString:substring options:NSCaseInsensitiveSearch]
|
||||||
|
.location != NSNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -14,17 +14,18 @@
|
|||||||
|
|
||||||
@interface SKComponentLayoutWrapper : NSObject
|
@interface SKComponentLayoutWrapper : NSObject
|
||||||
|
|
||||||
@property (nonatomic, weak, readonly) CKComponent *component;
|
@property(nonatomic, weak, readonly) CKComponent* component;
|
||||||
@property (nonatomic, readonly) NSString *identifier;
|
@property(nonatomic, readonly) NSString* identifier;
|
||||||
@property (nonatomic, readonly) CGSize size;
|
@property(nonatomic, readonly) CGSize size;
|
||||||
@property (nonatomic, readonly) CGPoint position;
|
@property(nonatomic, readonly) CGPoint position;
|
||||||
@property (nonatomic, readonly) std::vector<SKComponentLayoutWrapper *> children;
|
@property(nonatomic, readonly) std::vector<SKComponentLayoutWrapper*> children;
|
||||||
@property (nonatomic, weak, readonly) id<CKInspectableView> rootNode;
|
@property(nonatomic, weak, readonly) id<CKInspectableView> rootNode;
|
||||||
// Null for layouts which are not direct children of a CKFlexboxComponent
|
// Null for layouts which are not direct children of a CKFlexboxComponent
|
||||||
@property (nonatomic, readonly) BOOL isFlexboxChild;
|
@property(nonatomic, readonly) BOOL isFlexboxChild;
|
||||||
@property (nonatomic, readonly) CKFlexboxComponentChild flexboxChild;
|
@property(nonatomic, readonly) CKFlexboxComponentChild flexboxChild;
|
||||||
|
|
||||||
+ (instancetype)newFromRoot:(id<CKInspectableView>)root;
|
+ (instancetype)newFromRoot:(id<CKInspectableView>)root;
|
||||||
+ (instancetype)newFromRoot:(id<CKInspectableView>)root parentKey:(NSString *)parentKey;
|
+ (instancetype)newFromRoot:(id<CKInspectableView>)root
|
||||||
|
parentKey:(NSString*)parentKey;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,23 +11,27 @@
|
|||||||
|
|
||||||
#import <ComponentKit/CKAnalyticsListenerHelpers.h>
|
#import <ComponentKit/CKAnalyticsListenerHelpers.h>
|
||||||
#import <ComponentKit/CKComponent.h>
|
#import <ComponentKit/CKComponent.h>
|
||||||
#import <ComponentKit/CKComponentInternal.h>
|
|
||||||
#import <ComponentKit/CKComponentRootView.h>
|
|
||||||
#import <ComponentKit/CKComponentAttachController.h>
|
#import <ComponentKit/CKComponentAttachController.h>
|
||||||
#import <ComponentKit/CKComponentAttachControllerInternal.h>
|
#import <ComponentKit/CKComponentAttachControllerInternal.h>
|
||||||
|
#import <ComponentKit/CKComponentInternal.h>
|
||||||
|
#import <ComponentKit/CKComponentRootView.h>
|
||||||
#import <ComponentKit/CKInspectableView.h>
|
#import <ComponentKit/CKInspectableView.h>
|
||||||
|
|
||||||
#import "CKComponent+Sonar.h"
|
#import "CKComponent+Sonar.h"
|
||||||
|
|
||||||
static char const kLayoutWrapperKey = ' ';
|
static char const kLayoutWrapperKey = ' ';
|
||||||
|
|
||||||
static CKFlexboxComponentChild findFlexboxLayoutParams(CKComponent *parent, CKComponent *child) {
|
static CKFlexboxComponentChild findFlexboxLayoutParams(
|
||||||
|
CKComponent* parent,
|
||||||
|
CKComponent* child) {
|
||||||
if ([parent isKindOfClass:[CKFlexboxComponent class]]) {
|
if ([parent isKindOfClass:[CKFlexboxComponent class]]) {
|
||||||
static Ivar ivar = class_getInstanceVariable([CKFlexboxComponent class], "_children");
|
static Ivar ivar =
|
||||||
|
class_getInstanceVariable([CKFlexboxComponent class], "_children");
|
||||||
static ptrdiff_t offset = ivar_getOffset(ivar);
|
static ptrdiff_t offset = ivar_getOffset(ivar);
|
||||||
|
|
||||||
unsigned char *pComponent = (unsigned char*)(__bridge void*)parent;
|
unsigned char* pComponent = (unsigned char*)(__bridge void*)parent;
|
||||||
auto children = (std::vector<CKFlexboxComponentChild> *)(pComponent + offset);
|
auto children =
|
||||||
|
(std::vector<CKFlexboxComponentChild>*)(pComponent + offset);
|
||||||
|
|
||||||
if (children) {
|
if (children) {
|
||||||
for (auto it = children->begin(); it != children->end(); it++) {
|
for (auto it = children->begin(); it != children->end(); it++) {
|
||||||
@@ -47,47 +51,59 @@ static CKFlexboxComponentChild findFlexboxLayoutParams(CKComponent *parent, CKCo
|
|||||||
return [self newFromRoot:root parentKey:@""];
|
return [self newFromRoot:root parentKey:@""];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)newFromRoot:(id<CKInspectableView>)root parentKey:(NSString *)parentKey {
|
+ (instancetype)newFromRoot:(id<CKInspectableView>)root
|
||||||
|
parentKey:(NSString*)parentKey {
|
||||||
const CKComponentLayout layout = [root mountedLayout];
|
const CKComponentLayout layout = [root mountedLayout];
|
||||||
// Check if there is a cached wrapper.
|
// Check if there is a cached wrapper.
|
||||||
if (layout.component) {
|
if (layout.component) {
|
||||||
SKComponentLayoutWrapper *cachedWrapper = objc_getAssociatedObject(layout.component, &kLayoutWrapperKey);
|
SKComponentLayoutWrapper* cachedWrapper =
|
||||||
|
objc_getAssociatedObject(layout.component, &kLayoutWrapperKey);
|
||||||
if (cachedWrapper) {
|
if (cachedWrapper) {
|
||||||
return cachedWrapper;
|
return cachedWrapper;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: Add support for `CKMountable` components.
|
// TODO: Add support for `CKMountable` components.
|
||||||
CKComponent *component = (CKComponent *)layout.component;
|
CKComponent* component = (CKComponent*)layout.component;
|
||||||
CKComponentReuseWrapper *reuseWrapper = CKAnalyticsListenerHelpers::GetReusedNodes(component);
|
CKComponentReuseWrapper* reuseWrapper =
|
||||||
|
CKAnalyticsListenerHelpers::GetReusedNodes(component);
|
||||||
// Create a new layout wrapper.
|
// Create a new layout wrapper.
|
||||||
SKComponentLayoutWrapper *const wrapper =
|
SKComponentLayoutWrapper* const wrapper = [[SKComponentLayoutWrapper alloc]
|
||||||
[[SKComponentLayoutWrapper alloc] initWithLayout:layout
|
initWithLayout:layout
|
||||||
position:CGPointMake(0, 0)
|
position:CGPointMake(0, 0)
|
||||||
parentKey:[NSString stringWithFormat: @"%@%d.", parentKey, component.treeNode.nodeIdentifier]
|
parentKey:[NSString
|
||||||
|
stringWithFormat:@"%@%d.",
|
||||||
|
parentKey,
|
||||||
|
component.treeNode.nodeIdentifier]
|
||||||
reuseWrapper:reuseWrapper
|
reuseWrapper:reuseWrapper
|
||||||
rootNode: root];
|
rootNode:root];
|
||||||
// Cache the result.
|
// Cache the result.
|
||||||
if (component) {
|
if (component) {
|
||||||
objc_setAssociatedObject(component, &kLayoutWrapperKey, wrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
objc_setAssociatedObject(
|
||||||
|
component,
|
||||||
|
&kLayoutWrapperKey,
|
||||||
|
wrapper,
|
||||||
|
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||||
}
|
}
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithLayout:(const CKComponentLayout &)layout
|
- (instancetype)initWithLayout:(const CKComponentLayout&)layout
|
||||||
position:(CGPoint)position
|
position:(CGPoint)position
|
||||||
parentKey:(NSString *)parentKey
|
parentKey:(NSString*)parentKey
|
||||||
reuseWrapper:(CKComponentReuseWrapper *)reuseWrapper
|
reuseWrapper:(CKComponentReuseWrapper*)reuseWrapper
|
||||||
rootNode:(id<CKInspectableView>)node
|
rootNode:(id<CKInspectableView>)node {
|
||||||
{
|
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_rootNode = node;
|
_rootNode = node;
|
||||||
_component = (CKComponent *)layout.component;
|
_component = (CKComponent*)layout.component;
|
||||||
_size = layout.size;
|
_size = layout.size;
|
||||||
_position = position;
|
_position = position;
|
||||||
_identifier = [parentKey stringByAppendingString:layout.component ? NSStringFromClass([layout.component class]) : @"(null)"];
|
_identifier = [parentKey stringByAppendingString:layout.component
|
||||||
|
? NSStringFromClass([layout.component class])
|
||||||
|
: @"(null)"];
|
||||||
|
|
||||||
if (_component && reuseWrapper) {
|
if (_component && reuseWrapper) {
|
||||||
auto const canBeReusedCounter = [reuseWrapper canBeReusedCounter:_component.treeNode.nodeIdentifier];
|
auto const canBeReusedCounter =
|
||||||
|
[reuseWrapper canBeReusedCounter:_component.treeNode.nodeIdentifier];
|
||||||
if (canBeReusedCounter > 0) {
|
if (canBeReusedCounter > 0) {
|
||||||
_component.flipper_canBeReusedCounter = canBeReusedCounter;
|
_component.flipper_canBeReusedCounter = canBeReusedCounter;
|
||||||
}
|
}
|
||||||
@@ -95,18 +111,22 @@ static CKFlexboxComponentChild findFlexboxLayoutParams(CKComponent *parent, CKCo
|
|||||||
|
|
||||||
if (layout.children != nullptr) {
|
if (layout.children != nullptr) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (const auto &child : *layout.children) {
|
for (const auto& child : *layout.children) {
|
||||||
if (child.layout.component == nil) {
|
if (child.layout.component == nil) {
|
||||||
continue; // nil children are allowed, ignore them
|
continue; // nil children are allowed, ignore them
|
||||||
}
|
}
|
||||||
SKComponentLayoutWrapper *childWrapper = [[SKComponentLayoutWrapper alloc] initWithLayout:child.layout
|
SKComponentLayoutWrapper* childWrapper =
|
||||||
|
[[SKComponentLayoutWrapper alloc]
|
||||||
|
initWithLayout:child.layout
|
||||||
position:child.position
|
position:child.position
|
||||||
parentKey:[_identifier stringByAppendingFormat:@"[%d].", index++]
|
parentKey:[_identifier
|
||||||
|
stringByAppendingFormat:@"[%d].", index++]
|
||||||
reuseWrapper:reuseWrapper
|
reuseWrapper:reuseWrapper
|
||||||
rootNode:node
|
rootNode:node];
|
||||||
];
|
childWrapper->_isFlexboxChild =
|
||||||
childWrapper->_isFlexboxChild = [_component isKindOfClass:[CKFlexboxComponent class]];
|
[_component isKindOfClass:[CKFlexboxComponent class]];
|
||||||
childWrapper->_flexboxChild = findFlexboxLayoutParams(_component, (CKComponent *)child.layout.component);
|
childWrapper->_flexboxChild = findFlexboxLayoutParams(
|
||||||
|
_component, (CKComponent*)child.layout.component);
|
||||||
_children.push_back(childWrapper);
|
_children.push_back(childWrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
@class CKComponentRootView;
|
@class CKComponentRootView;
|
||||||
|
|
||||||
@interface SKComponentRootViewDescriptor : SKNodeDescriptor<CKComponentRootView *>
|
@interface SKComponentRootViewDescriptor
|
||||||
|
: SKNodeDescriptor<CKComponentRootView*>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -22,28 +22,30 @@
|
|||||||
|
|
||||||
@implementation SKComponentRootViewDescriptor
|
@implementation SKComponentRootViewDescriptor
|
||||||
|
|
||||||
- (NSString *)identifierForNode:(CKComponentRootView *)node {
|
- (NSString*)identifierForNode:(CKComponentRootView*)node {
|
||||||
return [NSString stringWithFormat: @"%p", node];
|
return [NSString stringWithFormat:@"%p", node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)childCountForNode:(CKComponentRootView *)node {
|
- (NSUInteger)childCountForNode:(CKComponentRootView*)node {
|
||||||
const auto state = CKGetAttachStateForView(node);
|
const auto state = CKGetAttachStateForView(node);
|
||||||
return state == nil ? 0 : 1;
|
return state == nil ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)childForNode:(CKComponentRootView *)node atIndex:(NSUInteger)index {
|
- (id)childForNode:(CKComponentRootView*)node atIndex:(NSUInteger)index {
|
||||||
auto const attachState = CKGetAttachStateForView(node);
|
auto const attachState = CKGetAttachStateForView(node);
|
||||||
return [SKComponentLayoutWrapper newFromRoot:node
|
return [SKComponentLayoutWrapper
|
||||||
parentKey:[NSString stringWithFormat:@"%d.", attachState.scopeIdentifier]];
|
newFromRoot:node
|
||||||
|
parentKey:[NSString
|
||||||
|
stringWithFormat:@"%d.", attachState.scopeIdentifier]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted forNode:(CKComponentRootView *)node {
|
- (void)setHighlighted:(BOOL)highlighted forNode:(CKComponentRootView*)node {
|
||||||
SKNodeDescriptor *viewDescriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* viewDescriptor = [self descriptorForClass:[UIView class]];
|
||||||
[viewDescriptor setHighlighted: highlighted forNode: node];
|
[viewDescriptor setHighlighted:highlighted forNode:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)hitTest:(SKTouch *)touch forNode:(CKComponentRootView *)node {
|
- (void)hitTest:(SKTouch*)touch forNode:(CKComponentRootView*)node {
|
||||||
[touch continueWithChildIndex: 0 withOffset: (CGPoint){ 0, 0 }];
|
[touch continueWithChildIndex:0 withOffset:(CGPoint){0, 0}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,19 +11,19 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
A SKSubDescriptor is an object which knows how to expose an Object of type T
|
A SKSubDescriptor is an object which knows how to expose an Object of type T
|
||||||
to the SKLayoutDescriptor. This class is for frameworks wanting to pass data along
|
to the SKLayoutDescriptor. This class is for frameworks wanting to pass data
|
||||||
through the Layout Descriptor.
|
along through the Layout Descriptor.
|
||||||
*/
|
*/
|
||||||
@interface SKSubDescriptor : NSObject
|
@interface SKSubDescriptor : NSObject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This is the SubDescriptor name.
|
This is the SubDescriptor name.
|
||||||
*/
|
*/
|
||||||
- (NSString *) getName;
|
- (NSString*)getName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This is the data the SubDescriptor wants to pass up to the SKLayoutDescriptor.
|
This is the data the SubDescriptor wants to pass up to the SKLayoutDescriptor.
|
||||||
*/
|
*/
|
||||||
- (NSString *)getDataForNode:(SKComponentLayoutWrapper *)node;
|
- (NSString*)getDataForNode:(SKComponentLayoutWrapper*)node;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -10,15 +10,15 @@
|
|||||||
#import "SKSubDescriptor.h"
|
#import "SKSubDescriptor.h"
|
||||||
#import "SKComponentLayoutWrapper.h"
|
#import "SKComponentLayoutWrapper.h"
|
||||||
|
|
||||||
@implementation SKSubDescriptor
|
@implementation SKSubDescriptor {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, NSObject *> *)getDataForNode:(SKComponentLayoutWrapper *)node {
|
- (NSDictionary<NSString*, NSObject*>*)getDataForNode:
|
||||||
|
(SKComponentLayoutWrapper*)node {
|
||||||
return @{};
|
return @{};
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)getName {
|
- (NSString*)getName {
|
||||||
return @"";
|
return @"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#import <ComponentKit/CKComponent.h>
|
#import <ComponentKit/CKComponent.h>
|
||||||
#import <ComponentKit/CKFlexboxComponent.h>
|
#import <ComponentKit/CKFlexboxComponent.h>
|
||||||
|
|
||||||
NSString *relativeDimension(CKRelativeDimension dimension);
|
NSString* relativeDimension(CKRelativeDimension dimension);
|
||||||
NSDictionary<NSString *, NSString *> *flexboxRect(CKFlexboxSpacing spacing);
|
NSDictionary<NSString*, NSString*>* flexboxRect(CKFlexboxSpacing spacing);
|
||||||
CKRelativeDimension relativeStructDimension(NSString *dimension);
|
CKRelativeDimension relativeStructDimension(NSString* dimension);
|
||||||
NSDictionary<NSString *, NSString *> *ckcomponentSize(CKComponentSize size);
|
NSDictionary<NSString*, NSString*>* ckcomponentSize(CKComponentSize size);
|
||||||
|
|||||||
@@ -9,44 +9,46 @@
|
|||||||
|
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
NSString *relativeDimension(CKRelativeDimension dimension) {
|
NSString* relativeDimension(CKRelativeDimension dimension) {
|
||||||
switch(dimension.type()) {
|
switch (dimension.type()) {
|
||||||
case CKRelativeDimension::Type::PERCENT:
|
case CKRelativeDimension::Type::PERCENT:
|
||||||
return [NSString stringWithFormat: @"%@%%", @(dimension.value())];
|
return [NSString stringWithFormat:@"%@%%", @(dimension.value())];
|
||||||
case CKRelativeDimension::Type::POINTS:
|
case CKRelativeDimension::Type::POINTS:
|
||||||
return [NSString stringWithFormat: @"%@pt", @(dimension.value())];
|
return [NSString stringWithFormat:@"%@pt", @(dimension.value())];
|
||||||
default:
|
default:
|
||||||
return @"auto";
|
return @"auto";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CKRelativeDimension relativeStructDimension(NSString *dimension) {
|
CKRelativeDimension relativeStructDimension(NSString* dimension) {
|
||||||
if ([dimension hasSuffix:@"%"]) {
|
if ([dimension hasSuffix:@"%"]) {
|
||||||
return CKRelativeDimension::Percent([[dimension substringToIndex:([dimension length] - 1)] integerValue]);
|
return CKRelativeDimension::Percent(
|
||||||
|
[[dimension substringToIndex:([dimension length] - 1)] integerValue]);
|
||||||
}
|
}
|
||||||
if ([dimension hasSuffix:@"pt"]) {
|
if ([dimension hasSuffix:@"pt"]) {
|
||||||
return CKRelativeDimension::Points([[dimension substringToIndex:([dimension length] - 2)] integerValue]);
|
return CKRelativeDimension::Points(
|
||||||
|
[[dimension substringToIndex:([dimension length] - 2)] integerValue]);
|
||||||
}
|
}
|
||||||
return CKRelativeDimension::Auto();
|
return CKRelativeDimension::Auto();
|
||||||
}
|
}
|
||||||
|
|
||||||
NSDictionary<NSString *, NSString *> *flexboxRect(CKFlexboxSpacing spacing) {
|
NSDictionary<NSString*, NSString*>* flexboxRect(CKFlexboxSpacing spacing) {
|
||||||
return @{
|
return @{
|
||||||
@"top": relativeDimension(spacing.top.dimension()),
|
@"top" : relativeDimension(spacing.top.dimension()),
|
||||||
@"bottom": relativeDimension(spacing.bottom.dimension()),
|
@"bottom" : relativeDimension(spacing.bottom.dimension()),
|
||||||
@"start": relativeDimension(spacing.start.dimension()),
|
@"start" : relativeDimension(spacing.start.dimension()),
|
||||||
@"end": relativeDimension(spacing.end.dimension())
|
@"end" : relativeDimension(spacing.end.dimension())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
NSDictionary<NSString *, NSString *> *ckcomponentSize(CKComponentSize size) {
|
NSDictionary<NSString*, NSString*>* ckcomponentSize(CKComponentSize size) {
|
||||||
return @{
|
return @{
|
||||||
@"width": relativeDimension(size.width),
|
@"width" : relativeDimension(size.width),
|
||||||
@"height": relativeDimension(size.height),
|
@"height" : relativeDimension(size.height),
|
||||||
@"minWidth": relativeDimension(size.minWidth),
|
@"minWidth" : relativeDimension(size.minWidth),
|
||||||
@"minHeight": relativeDimension(size.minHeight),
|
@"minHeight" : relativeDimension(size.minHeight),
|
||||||
@"maxWidth": relativeDimension(size.maxWidth),
|
@"maxWidth" : relativeDimension(size.maxWidth),
|
||||||
@"maxHeight": relativeDimension(size.maxHeight),
|
@"maxHeight" : relativeDimension(size.maxHeight),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,20 +11,21 @@
|
|||||||
|
|
||||||
#import <FlipperKit/FlipperPlugin.h>
|
#import <FlipperKit/FlipperPlugin.h>
|
||||||
|
|
||||||
#import "SKTapListener.h"
|
|
||||||
#import "SKInvalidation.h"
|
|
||||||
#import "SKDescriptorMapper.h"
|
#import "SKDescriptorMapper.h"
|
||||||
|
#import "SKInvalidation.h"
|
||||||
|
#import "SKTapListener.h"
|
||||||
|
|
||||||
@interface FlipperKitLayoutPlugin : NSObject<FlipperPlugin, SKInvalidationDelegate>
|
@interface FlipperKitLayoutPlugin
|
||||||
|
: NSObject<FlipperPlugin, SKInvalidationDelegate>
|
||||||
|
|
||||||
- (instancetype)initWithRootNode:(id<NSObject>)rootNode
|
- (instancetype)initWithRootNode:(id<NSObject>)rootNode
|
||||||
withDescriptorMapper:(SKDescriptorMapper *)mapper;
|
withDescriptorMapper:(SKDescriptorMapper*)mapper;
|
||||||
|
|
||||||
- (instancetype)initWithRootNode:(id<NSObject>)rootNode
|
- (instancetype)initWithRootNode:(id<NSObject>)rootNode
|
||||||
withTapListener:(id<SKTapListener>)tapListener
|
withTapListener:(id<SKTapListener>)tapListener
|
||||||
withDescriptorMapper:(SKDescriptorMapper *)mapper;
|
withDescriptorMapper:(SKDescriptorMapper*)mapper;
|
||||||
|
|
||||||
@property (nonatomic, readonly, strong) SKDescriptorMapper *descriptorMapper;
|
@property(nonatomic, readonly, strong) SKDescriptorMapper* descriptorMapper;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -13,21 +13,19 @@
|
|||||||
#import <FlipperKit/FlipperConnection.h>
|
#import <FlipperKit/FlipperConnection.h>
|
||||||
#import <FlipperKit/FlipperResponder.h>
|
#import <FlipperKit/FlipperResponder.h>
|
||||||
#import <FlipperKit/SKMacros.h>
|
#import <FlipperKit/SKMacros.h>
|
||||||
|
#import <mutex>
|
||||||
#import "SKDescriptorMapper.h"
|
#import "SKDescriptorMapper.h"
|
||||||
#import "SKNodeDescriptor.h"
|
#import "SKNodeDescriptor.h"
|
||||||
|
#import "SKSearchResultNode.h"
|
||||||
#import "SKTapListener.h"
|
#import "SKTapListener.h"
|
||||||
#import "SKTapListenerImpl.h"
|
#import "SKTapListenerImpl.h"
|
||||||
#import "SKSearchResultNode.h"
|
|
||||||
#import <mutex>
|
|
||||||
|
|
||||||
@implementation FlipperKitLayoutPlugin
|
@implementation FlipperKitLayoutPlugin {
|
||||||
{
|
NSMapTable<NSString*, id>* _trackedObjects;
|
||||||
|
NSString* _lastHighlightedNode;
|
||||||
NSMapTable<NSString *, id> *_trackedObjects;
|
NSMutableSet* _invalidObjects;
|
||||||
NSString *_lastHighlightedNode;
|
|
||||||
NSMutableSet *_invalidObjects;
|
|
||||||
Boolean _invalidateMessageQueued;
|
Boolean _invalidateMessageQueued;
|
||||||
NSDate *_lastInvalidateMessage;
|
NSDate* _lastInvalidateMessage;
|
||||||
std::mutex invalidObjectsMutex;
|
std::mutex invalidObjectsMutex;
|
||||||
|
|
||||||
id<NSObject> _rootNode;
|
id<NSObject> _rootNode;
|
||||||
@@ -35,19 +33,19 @@
|
|||||||
|
|
||||||
id<FlipperConnection> _connection;
|
id<FlipperConnection> _connection;
|
||||||
|
|
||||||
NSMutableSet *_registeredDelegates;
|
NSMutableSet* _registeredDelegates;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithRootNode:(id<NSObject>)rootNode
|
- (instancetype)initWithRootNode:(id<NSObject>)rootNode
|
||||||
withDescriptorMapper:(SKDescriptorMapper *)mapper{
|
withDescriptorMapper:(SKDescriptorMapper*)mapper {
|
||||||
return [self initWithRootNode: rootNode
|
return [self initWithRootNode:rootNode
|
||||||
withTapListener: [SKTapListenerImpl new]
|
withTapListener:[SKTapListenerImpl new]
|
||||||
withDescriptorMapper: mapper];
|
withDescriptorMapper:mapper];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithRootNode:(id<NSObject>)rootNode
|
- (instancetype)initWithRootNode:(id<NSObject>)rootNode
|
||||||
withTapListener:(id<SKTapListener>)tapListener
|
withTapListener:(id<SKTapListener>)tapListener
|
||||||
withDescriptorMapper:(SKDescriptorMapper *)mapper {
|
withDescriptorMapper:(SKDescriptorMapper*)mapper {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_descriptorMapper = mapper;
|
_descriptorMapper = mapper;
|
||||||
_trackedObjects = [NSMapTable strongToWeakObjectsMapTable];
|
_trackedObjects = [NSMapTable strongToWeakObjectsMapTable];
|
||||||
@@ -65,8 +63,7 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)identifier
|
- (NSString*)identifier {
|
||||||
{
|
|
||||||
return @"Inspector";
|
return @"Inspector";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,187 +78,264 @@
|
|||||||
[SKInvalidation enableInvalidations];
|
[SKInvalidation enableInvalidations];
|
||||||
|
|
||||||
// Run setup logic for each descriptor
|
// Run setup logic for each descriptor
|
||||||
for (SKNodeDescriptor *descriptor in _descriptorMapper.allDescriptors) {
|
for (SKNodeDescriptor* descriptor in _descriptorMapper.allDescriptors) {
|
||||||
[descriptor setUp];
|
[descriptor setUp];
|
||||||
}
|
}
|
||||||
|
|
||||||
// In order to avoid a retain cycle (Connection -> Block -> FlipperKitLayoutPlugin -> Connection ...)
|
// In order to avoid a retain cycle (Connection -> Block ->
|
||||||
__weak FlipperKitLayoutPlugin *weakSelf = self;
|
// FlipperKitLayoutPlugin -> Connection ...)
|
||||||
|
__weak FlipperKitLayoutPlugin* weakSelf = self;
|
||||||
|
|
||||||
[connection receive:@"getRoot" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
|
[connection receive:@"getRoot"
|
||||||
FlipperPerformBlockOnMainThread(^{ [weakSelf onCallGetRoot: responder]; }, responder);
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
|
FlipperPerformBlockOnMainThread(
|
||||||
|
^{
|
||||||
|
[weakSelf onCallGetRoot:responder];
|
||||||
|
},
|
||||||
|
responder);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[connection receive:@"getAllNodes" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
|
[connection receive:@"getAllNodes"
|
||||||
FlipperPerformBlockOnMainThread(^{ [weakSelf onCallGetAllNodesWithResponder: responder]; }, responder);
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
|
FlipperPerformBlockOnMainThread(
|
||||||
|
^{
|
||||||
|
[weakSelf onCallGetAllNodesWithResponder:responder];
|
||||||
|
},
|
||||||
|
responder);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[connection receive:@"getNodes" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
|
[connection receive:@"getNodes"
|
||||||
FlipperPerformBlockOnMainThread(^{ [weakSelf onCallGetNodes: params[@"ids"] withResponder: responder]; }, responder);
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
|
FlipperPerformBlockOnMainThread(
|
||||||
|
^{
|
||||||
|
[weakSelf onCallGetNodes:params[@"ids"]
|
||||||
|
withResponder:responder];
|
||||||
|
},
|
||||||
|
responder);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[connection receive:@"setData" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
|
[connection receive:@"setData"
|
||||||
FlipperPerformBlockOnMainThread(^{
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
[weakSelf onCallSetData: params[@"id"]
|
FlipperPerformBlockOnMainThread(
|
||||||
withPath: params[@"path"]
|
^{
|
||||||
toValue: params[@"value"]
|
[weakSelf onCallSetData:params[@"id"]
|
||||||
withConnection: connection];
|
withPath:params[@"path"]
|
||||||
}, responder);
|
toValue:params[@"value"]
|
||||||
|
withConnection:connection];
|
||||||
|
},
|
||||||
|
responder);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[connection receive:@"setHighlighted" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
|
[connection receive:@"setHighlighted"
|
||||||
FlipperPerformBlockOnMainThread(^{ [weakSelf onCallSetHighlighted: params[@"id"] withResponder: responder]; }, responder);
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
|
FlipperPerformBlockOnMainThread(
|
||||||
|
^{
|
||||||
|
[weakSelf onCallSetHighlighted:params[@"id"]
|
||||||
|
withResponder:responder];
|
||||||
|
},
|
||||||
|
responder);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[connection receive:@"setSearchActive" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
|
[connection receive:@"setSearchActive"
|
||||||
FlipperPerformBlockOnMainThread(^{ [weakSelf onCallSetSearchActive: [params[@"active"] boolValue] withConnection: connection]; }, responder);
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
|
FlipperPerformBlockOnMainThread(
|
||||||
|
^{
|
||||||
|
[weakSelf
|
||||||
|
onCallSetSearchActive:[params[@"active"] boolValue]
|
||||||
|
withConnection:connection];
|
||||||
|
},
|
||||||
|
responder);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[connection receive:@"isSearchActive" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
|
[connection receive:@"isSearchActive"
|
||||||
FlipperPerformBlockOnMainThread(^{ [weakSelf onCallIsSearchActiveWithConnection: responder]; }, responder);
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
|
FlipperPerformBlockOnMainThread(
|
||||||
|
^{
|
||||||
|
[weakSelf onCallIsSearchActiveWithConnection:responder];
|
||||||
|
},
|
||||||
|
responder);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[connection receive:@"isConsoleEnabled" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
|
[connection receive:@"isConsoleEnabled"
|
||||||
FlipperPerformBlockOnMainThread(^{ [responder success: @{@"isEnabled": @NO}];}, responder);
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
|
FlipperPerformBlockOnMainThread(
|
||||||
|
^{
|
||||||
|
[responder success:@{@"isEnabled" : @NO}];
|
||||||
|
},
|
||||||
|
responder);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[connection receive:@"getSearchResults" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
|
[connection receive:@"getSearchResults"
|
||||||
FlipperPerformBlockOnMainThread(^{ [weakSelf onCallGetSearchResults: params[@"query"] withResponder: responder]; }, responder);
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
|
FlipperPerformBlockOnMainThread(
|
||||||
|
^{
|
||||||
|
[weakSelf onCallGetSearchResults:params[@"query"]
|
||||||
|
withResponder:responder];
|
||||||
|
},
|
||||||
|
responder);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didDisconnect {
|
- (void)didDisconnect {
|
||||||
// Clear the last highlight if there is any
|
// Clear the last highlight if there is any
|
||||||
[self onCallSetHighlighted: nil withResponder: nil];
|
[self onCallSetHighlighted:nil withResponder:nil];
|
||||||
// Disable search if it is active
|
// Disable search if it is active
|
||||||
[self onCallSetSearchActive: NO withConnection: nil];
|
[self onCallSetSearchActive:NO withConnection:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)onCallGetRoot:(id<FlipperResponder>)responder {
|
- (void)onCallGetRoot:(id<FlipperResponder>)responder {
|
||||||
const auto rootNode= [self getNode: [self trackObject: _rootNode]];
|
const auto rootNode = [self getNode:[self trackObject:_rootNode]];
|
||||||
|
|
||||||
[responder success: rootNode];
|
[responder success:rootNode];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)populateAllNodesFromNode:(nonnull NSString *)identifier inDictionary:(nonnull NSMutableDictionary<NSString*, NSDictionary*> *)mutableDict {
|
- (void)populateAllNodesFromNode:(nonnull NSString*)identifier
|
||||||
NSDictionary *nodeDict = [self getNode:identifier];
|
inDictionary:
|
||||||
|
(nonnull NSMutableDictionary<NSString*, NSDictionary*>*)
|
||||||
|
mutableDict {
|
||||||
|
NSDictionary* nodeDict = [self getNode:identifier];
|
||||||
mutableDict[identifier] = nodeDict;
|
mutableDict[identifier] = nodeDict;
|
||||||
NSArray *arr = nodeDict[@"children"];
|
NSArray* arr = nodeDict[@"children"];
|
||||||
for (NSString *childIdentifier in arr) {
|
for (NSString* childIdentifier in arr) {
|
||||||
[self populateAllNodesFromNode:childIdentifier inDictionary:mutableDict];
|
[self populateAllNodesFromNode:childIdentifier inDictionary:mutableDict];
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)populateAllNodesFromNode:(nonnull NSString *)identifier inArray:(nonnull NSMutableArray<NSDictionary *> *)mutableArray {
|
- (void)populateAllNodesFromNode:(nonnull NSString*)identifier
|
||||||
NSDictionary *nodeDict = [self getNode:identifier];
|
inArray:(nonnull NSMutableArray<NSDictionary*>*)
|
||||||
|
mutableArray {
|
||||||
|
NSDictionary* nodeDict = [self getNode:identifier];
|
||||||
if (nodeDict == nil) {
|
if (nodeDict == nil) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[mutableArray addObject:nodeDict];
|
[mutableArray addObject:nodeDict];
|
||||||
NSArray *children = nodeDict[@"children"];
|
NSArray* children = nodeDict[@"children"];
|
||||||
for (NSString *childIdentifier in children) {
|
for (NSString* childIdentifier in children) {
|
||||||
[self populateAllNodesFromNode:childIdentifier inArray:mutableArray];
|
[self populateAllNodesFromNode:childIdentifier inArray:mutableArray];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)onCallGetAllNodesWithResponder:(nonnull id<FlipperResponder>)responder {
|
- (void)onCallGetAllNodesWithResponder:(nonnull id<FlipperResponder>)responder {
|
||||||
NSMutableArray<NSDictionary*> *allNodes = @[].mutableCopy;
|
NSMutableArray<NSDictionary*>* allNodes = @[].mutableCopy;
|
||||||
NSString *identifier = [self trackObject: _rootNode];
|
NSString* identifier = [self trackObject:_rootNode];
|
||||||
NSDictionary *rootNode = [self getNode: identifier];
|
NSDictionary* rootNode = [self getNode:identifier];
|
||||||
if (!rootNode) {
|
if (!rootNode) {
|
||||||
return [responder error:@{@"error": [NSString stringWithFormat:@"getNode returned nil for the rootNode %@, while getting all the nodes", identifier]}];
|
return [responder error:@{
|
||||||
|
@"error" : [NSString
|
||||||
|
stringWithFormat:
|
||||||
|
@"getNode returned nil for the rootNode %@, while getting all the nodes",
|
||||||
|
identifier]
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
[allNodes addObject:rootNode];
|
[allNodes addObject:rootNode];
|
||||||
NSMutableDictionary *allNodesDict = @{}.mutableCopy;
|
NSMutableDictionary* allNodesDict = @{}.mutableCopy;
|
||||||
[self populateAllNodesFromNode:identifier inDictionary:allNodesDict];
|
[self populateAllNodesFromNode:identifier inDictionary:allNodesDict];
|
||||||
[responder success:@{@"allNodes": @{@"rootElement": identifier, @"elements": allNodesDict}}];
|
[responder success:@{
|
||||||
|
@"allNodes" : @{@"rootElement" : identifier, @"elements" : allNodesDict}
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSMutableArray*)getChildrenForNode:(id)node withDescriptor:(SKNodeDescriptor*)descriptor {
|
- (NSMutableArray*)getChildrenForNode:(id)node
|
||||||
NSMutableArray *children = [NSMutableArray new];
|
withDescriptor:(SKNodeDescriptor*)descriptor {
|
||||||
for (NSUInteger i = 0; i < [descriptor childCountForNode: node]; i++) {
|
NSMutableArray* children = [NSMutableArray new];
|
||||||
id childNode = [descriptor childForNode: node atIndex: i];
|
for (NSUInteger i = 0; i < [descriptor childCountForNode:node]; i++) {
|
||||||
|
id childNode = [descriptor childForNode:node atIndex:i];
|
||||||
|
|
||||||
NSString *childIdentifier = [self trackObject: childNode];
|
NSString* childIdentifier = [self trackObject:childNode];
|
||||||
if (childIdentifier) {
|
if (childIdentifier) {
|
||||||
[children addObject: childIdentifier];
|
[children addObject:childIdentifier];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)onCallGetNodes:(NSArray<NSDictionary *> *)nodeIds withResponder:(id<FlipperResponder>)responder {
|
- (void)onCallGetNodes:(NSArray<NSDictionary*>*)nodeIds
|
||||||
NSMutableArray<NSDictionary *> *elements = [NSMutableArray new];
|
withResponder:(id<FlipperResponder>)responder {
|
||||||
|
NSMutableArray<NSDictionary*>* elements = [NSMutableArray new];
|
||||||
|
|
||||||
for (id nodeId in nodeIds) {
|
for (id nodeId in nodeIds) {
|
||||||
const auto node = [self getNode: nodeId];
|
const auto node = [self getNode:nodeId];
|
||||||
if (node == nil) {
|
if (node == nil) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
[elements addObject: node];
|
[elements addObject:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
[responder success: @{ @"elements": elements }];
|
[responder success:@{@"elements" : elements}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)onCallSetData:(NSString *)objectId
|
- (void)onCallSetData:(NSString*)objectId
|
||||||
withPath:(NSArray<NSString *> *)path
|
withPath:(NSArray<NSString*>*)path
|
||||||
toValue:(id<NSObject>)value
|
toValue:(id<NSObject>)value
|
||||||
withConnection:(id<FlipperConnection>)connection {
|
withConnection:(id<FlipperConnection>)connection {
|
||||||
id node = [_trackedObjects objectForKey: objectId];
|
id node = [_trackedObjects objectForKey:objectId];
|
||||||
if (node == nil) {
|
if (node == nil) {
|
||||||
SKLog(@"node is nil, trying to setData: \
|
SKLog(@"node is nil, trying to setData: \
|
||||||
objectId: %@ \
|
objectId: %@ \
|
||||||
path: %@ \
|
path: %@ \
|
||||||
value: %@",
|
value: %@", objectId, path, value);
|
||||||
objectId, path, value);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sonar sends nil/NSNull on some values when the text-field
|
// Sonar sends nil/NSNull on some values when the text-field
|
||||||
// is empty, disregard these changes otherwise we'll crash.
|
// is empty, disregard these changes otherwise we'll crash.
|
||||||
if (value == nil || [value isKindOfClass: [NSNull class]]) {
|
if (value == nil || [value isKindOfClass:[NSNull class]]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SKNodeDescriptor *descriptor = [_descriptorMapper descriptorForClass: [node class]];
|
SKNodeDescriptor* descriptor =
|
||||||
|
[_descriptorMapper descriptorForClass:[node class]];
|
||||||
|
|
||||||
NSString *dotJoinedPath = [path componentsJoinedByString: @"."];
|
NSString* dotJoinedPath = [path componentsJoinedByString:@"."];
|
||||||
SKNodeUpdateData updateDataForPath = [[descriptor dataMutationsForNode: node] objectForKey: dotJoinedPath];
|
SKNodeUpdateData updateDataForPath =
|
||||||
|
[[descriptor dataMutationsForNode:node] objectForKey:dotJoinedPath];
|
||||||
if (updateDataForPath != nil) {
|
if (updateDataForPath != nil) {
|
||||||
const auto identifierForInvalidation = [descriptor identifierForInvalidation:node];
|
const auto identifierForInvalidation =
|
||||||
id nodeForInvalidation = [_trackedObjects objectForKey:identifierForInvalidation];
|
[descriptor identifierForInvalidation:node];
|
||||||
SKNodeDescriptor *descriptorForInvalidation = [_descriptorMapper descriptorForClass:[nodeForInvalidation class]];
|
id nodeForInvalidation =
|
||||||
|
[_trackedObjects objectForKey:identifierForInvalidation];
|
||||||
|
SKNodeDescriptor* descriptorForInvalidation =
|
||||||
|
[_descriptorMapper descriptorForClass:[nodeForInvalidation class]];
|
||||||
updateDataForPath(value);
|
updateDataForPath(value);
|
||||||
|
|
||||||
NSMutableArray *nodesForInvalidation = [NSMutableArray new];
|
NSMutableArray* nodesForInvalidation = [NSMutableArray new];
|
||||||
[self populateAllNodesFromNode:[descriptorForInvalidation identifierForNode:nodeForInvalidation] inArray:nodesForInvalidation];
|
[self populateAllNodesFromNode:[descriptorForInvalidation
|
||||||
[connection send: @"invalidateWithData" withParams: @{@"nodes": nodesForInvalidation}];
|
identifierForNode:nodeForInvalidation]
|
||||||
|
inArray:nodesForInvalidation];
|
||||||
|
[connection send:@"invalidateWithData"
|
||||||
|
withParams:@{@"nodes" : nodesForInvalidation}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)onCallGetSearchResults:(NSString *)query withResponder:(id<FlipperResponder>)responder {
|
- (void)onCallGetSearchResults:(NSString*)query
|
||||||
const auto alreadyAddedElements = [NSMutableSet<NSString *> new];
|
withResponder:(id<FlipperResponder>)responder {
|
||||||
SKSearchResultNode *matchTree = [self searchForQuery:(NSString *)[query lowercaseString] fromNode:(id)_rootNode withElementsAlreadyAdded: alreadyAddedElements];
|
const auto alreadyAddedElements = [NSMutableSet<NSString*> new];
|
||||||
|
SKSearchResultNode* matchTree =
|
||||||
|
[self searchForQuery:(NSString*)[query lowercaseString]
|
||||||
|
fromNode:(id)_rootNode
|
||||||
|
withElementsAlreadyAdded:alreadyAddedElements];
|
||||||
|
|
||||||
[responder success: @{
|
[responder success:@{
|
||||||
@"results": [matchTree toNSDictionary] ?: [NSNull null],
|
@"results" : [matchTree toNSDictionary] ?: [NSNull null],
|
||||||
@"query": query
|
@"query" : query
|
||||||
}];
|
}];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)onCallSetHighlighted:(NSString *)objectId withResponder:(id<FlipperResponder>)responder {
|
- (void)onCallSetHighlighted:(NSString*)objectId
|
||||||
|
withResponder:(id<FlipperResponder>)responder {
|
||||||
if (_lastHighlightedNode != nil) {
|
if (_lastHighlightedNode != nil) {
|
||||||
id lastHighlightedObject = [_trackedObjects objectForKey: _lastHighlightedNode];
|
id lastHighlightedObject =
|
||||||
|
[_trackedObjects objectForKey:_lastHighlightedNode];
|
||||||
if (lastHighlightedObject == nil) {
|
if (lastHighlightedObject == nil) {
|
||||||
[responder error: @{ @"error": @"unable to get last highlighted object" }];
|
[responder error:@{@"error" : @"unable to get last highlighted object"}];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SKNodeDescriptor *descriptor = [self->_descriptorMapper descriptorForClass: [lastHighlightedObject class]];
|
SKNodeDescriptor* descriptor = [self->_descriptorMapper
|
||||||
[descriptor setHighlighted: NO forNode: lastHighlightedObject];
|
descriptorForClass:[lastHighlightedObject class]];
|
||||||
|
[descriptor setHighlighted:NO forNode:lastHighlightedObject];
|
||||||
|
|
||||||
_lastHighlightedNode = nil;
|
_lastHighlightedNode = nil;
|
||||||
}
|
}
|
||||||
@@ -270,35 +344,37 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
id object = [_trackedObjects objectForKey: objectId];
|
id object = [_trackedObjects objectForKey:objectId];
|
||||||
if (object == nil) {
|
if (object == nil) {
|
||||||
SKLog(@"tried to setHighlighted for untracked id, objectId: %@", objectId);
|
SKLog(@"tried to setHighlighted for untracked id, objectId: %@", objectId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SKNodeDescriptor *descriptor = [self->_descriptorMapper descriptorForClass: [object class]];
|
SKNodeDescriptor* descriptor =
|
||||||
[descriptor setHighlighted: YES forNode: object];
|
[self->_descriptorMapper descriptorForClass:[object class]];
|
||||||
|
[descriptor setHighlighted:YES forNode:object];
|
||||||
|
|
||||||
_lastHighlightedNode = objectId;
|
_lastHighlightedNode = objectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)onCallSetSearchActive:(BOOL)active withConnection:(id<FlipperConnection>)connection {
|
- (void)onCallSetSearchActive:(BOOL)active
|
||||||
|
withConnection:(id<FlipperConnection>)connection {
|
||||||
if (active) {
|
if (active) {
|
||||||
[_tapListener mountWithFrame: [[UIScreen mainScreen] bounds]];
|
[_tapListener mountWithFrame:[[UIScreen mainScreen] bounds]];
|
||||||
__block id<NSObject> rootNode = _rootNode;
|
__block id<NSObject> rootNode = _rootNode;
|
||||||
|
|
||||||
[_tapListener listenForTapWithBlock:^(CGPoint touchPoint) {
|
[_tapListener listenForTapWithBlock:^(CGPoint touchPoint) {
|
||||||
SKTouch *touch =
|
SKTouch* touch = [[SKTouch alloc]
|
||||||
[[SKTouch alloc] initWithTouchPoint: touchPoint
|
initWithTouchPoint:touchPoint
|
||||||
withRootNode: rootNode
|
withRootNode:rootNode
|
||||||
withDescriptorMapper: self->_descriptorMapper
|
withDescriptorMapper:self->_descriptorMapper
|
||||||
finishWithBlock:^(NSArray<NSString *> *path) {
|
finishWithBlock:^(NSArray<NSString*>* path) {
|
||||||
[connection send: @"select"
|
[connection send:@"select" withParams:@{@"path" : path}];
|
||||||
withParams: @{ @"path": path }];
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
SKNodeDescriptor *descriptor = [self->_descriptorMapper descriptorForClass: [rootNode class]];
|
SKNodeDescriptor* descriptor =
|
||||||
[descriptor hitTest: touch forNode: rootNode];
|
[self->_descriptorMapper descriptorForClass:[rootNode class]];
|
||||||
|
[descriptor hitTest:touch forNode:rootNode];
|
||||||
}];
|
}];
|
||||||
} else {
|
} else {
|
||||||
[_tapListener unmount];
|
[_tapListener unmount];
|
||||||
@@ -306,20 +382,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)onCallIsSearchActiveWithConnection:(id<FlipperResponder>)responder {
|
- (void)onCallIsSearchActiveWithConnection:(id<FlipperResponder>)responder {
|
||||||
[responder success: @{ @"isSearchActive": @NO }];
|
[responder success:@{@"isSearchActive" : @NO}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)invalidateNode:(id<NSObject>)node {
|
- (void)invalidateNode:(id<NSObject>)node {
|
||||||
SKNodeDescriptor *descriptor = [_descriptorMapper descriptorForClass: [node class]];
|
SKNodeDescriptor* descriptor =
|
||||||
|
[_descriptorMapper descriptorForClass:[node class]];
|
||||||
if (descriptor == nil) {
|
if (descriptor == nil) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *nodeId = [descriptor identifierForNode: node];
|
NSString* nodeId = [descriptor identifierForNode:node];
|
||||||
if (![_trackedObjects objectForKey: nodeId]) {
|
if (![_trackedObjects objectForKey:nodeId]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[descriptor invalidateNode: node];
|
[descriptor invalidateNode:node];
|
||||||
|
|
||||||
// Collect invalidate messages before sending in a batch
|
// Collect invalidate messages before sending in a batch
|
||||||
std::lock_guard<std::mutex> lock(invalidObjectsMutex);
|
std::lock_guard<std::mutex> lock(invalidObjectsMutex);
|
||||||
@@ -330,7 +407,10 @@
|
|||||||
_invalidateMessageQueued = true;
|
_invalidateMessageQueued = true;
|
||||||
|
|
||||||
if (_lastInvalidateMessage.timeIntervalSinceNow < -1) {
|
if (_lastInvalidateMessage.timeIntervalSinceNow < -1) {
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 500 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
|
dispatch_after(
|
||||||
|
dispatch_time(DISPATCH_TIME_NOW, 500 * NSEC_PER_MSEC),
|
||||||
|
dispatch_get_main_queue(),
|
||||||
|
^{
|
||||||
[self reportInvalidatedObjects];
|
[self reportInvalidatedObjects];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -338,11 +418,13 @@
|
|||||||
|
|
||||||
- (void)reportInvalidatedObjects {
|
- (void)reportInvalidatedObjects {
|
||||||
std::lock_guard<std::mutex> lock(invalidObjectsMutex);
|
std::lock_guard<std::mutex> lock(invalidObjectsMutex);
|
||||||
NSMutableArray *nodes = [NSMutableArray new];
|
NSMutableArray* nodes = [NSMutableArray new];
|
||||||
for (NSString *nodeId in self->_invalidObjects) {
|
for (NSString* nodeId in self->_invalidObjects) {
|
||||||
[nodes addObject: [NSDictionary dictionaryWithObject: nodeId forKey: @"id"]];
|
[nodes addObject:[NSDictionary dictionaryWithObject:nodeId forKey:@"id"]];
|
||||||
}
|
}
|
||||||
[self->_connection send: @"invalidate" withParams: [NSDictionary dictionaryWithObject: nodes forKey: @"nodes"]];
|
[self->_connection send:@"invalidate"
|
||||||
|
withParams:[NSDictionary dictionaryWithObject:nodes
|
||||||
|
forKey:@"nodes"]];
|
||||||
self->_lastInvalidateMessage = [NSDate date];
|
self->_lastInvalidateMessage = [NSDate date];
|
||||||
self->_invalidObjects = [NSMutableSet new];
|
self->_invalidObjects = [NSMutableSet new];
|
||||||
self->_invalidateMessageQueued = false;
|
self->_invalidateMessageQueued = false;
|
||||||
@@ -350,116 +432,125 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateNodeReference:(id<NSObject>)node {
|
- (void)updateNodeReference:(id<NSObject>)node {
|
||||||
SKNodeDescriptor *descriptor = [_descriptorMapper descriptorForClass: [node class]];
|
SKNodeDescriptor* descriptor =
|
||||||
|
[_descriptorMapper descriptorForClass:[node class]];
|
||||||
if (descriptor == nil) {
|
if (descriptor == nil) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *nodeId = [descriptor identifierForNode: node];
|
NSString* nodeId = [descriptor identifierForNode:node];
|
||||||
[_trackedObjects setObject:node forKey:nodeId];
|
[_trackedObjects setObject:node forKey:nodeId];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (SKSearchResultNode *)searchForQuery:(NSString *)query fromNode:(id)node withElementsAlreadyAdded:(NSMutableSet<NSString *> *)alreadyAdded {
|
- (SKSearchResultNode*)searchForQuery:(NSString*)query
|
||||||
SKNodeDescriptor *descriptor = [_descriptorMapper descriptorForClass: [node class]];
|
fromNode:(id)node
|
||||||
|
withElementsAlreadyAdded:(NSMutableSet<NSString*>*)alreadyAdded {
|
||||||
|
SKNodeDescriptor* descriptor =
|
||||||
|
[_descriptorMapper descriptorForClass:[node class]];
|
||||||
if (node == nil || descriptor == nil) {
|
if (node == nil || descriptor == nil) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableArray<SKSearchResultNode *> *childTrees = nil;
|
NSMutableArray<SKSearchResultNode*>* childTrees = nil;
|
||||||
BOOL isMatch = [descriptor matchesQuery: query forNode: node];
|
BOOL isMatch = [descriptor matchesQuery:query forNode:node];
|
||||||
|
|
||||||
NSString *nodeId = [self trackObject: node];
|
NSString* nodeId = [self trackObject:node];
|
||||||
|
|
||||||
for (auto i = 0; i < [descriptor childCountForNode: node]; i++) {
|
for (auto i = 0; i < [descriptor childCountForNode:node]; i++) {
|
||||||
id child = [descriptor childForNode: node atIndex: i];
|
id child = [descriptor childForNode:node atIndex:i];
|
||||||
if (child) {
|
if (child) {
|
||||||
SKSearchResultNode *childTree = [self searchForQuery: query fromNode: child withElementsAlreadyAdded:alreadyAdded];
|
SKSearchResultNode* childTree = [self searchForQuery:query
|
||||||
|
fromNode:child
|
||||||
|
withElementsAlreadyAdded:alreadyAdded];
|
||||||
if (childTree != nil) {
|
if (childTree != nil) {
|
||||||
if (childTrees == nil) {
|
if (childTrees == nil) {
|
||||||
childTrees = [NSMutableArray new];
|
childTrees = [NSMutableArray new];
|
||||||
}
|
}
|
||||||
[childTrees addObject: childTree];
|
[childTrees addObject:childTree];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMatch || childTrees != nil) {
|
if (isMatch || childTrees != nil) {
|
||||||
|
NSDictionary* element = [self getNode:nodeId];
|
||||||
NSDictionary *element = [self getNode: nodeId];
|
|
||||||
if (nodeId == nil || element == nil) {
|
if (nodeId == nil || element == nil) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
NSMutableArray<NSString *> *descriptorChildElements = [element objectForKey: @"children"];
|
NSMutableArray<NSString*>* descriptorChildElements =
|
||||||
NSMutableDictionary *newElement = [element mutableCopy];
|
[element objectForKey:@"children"];
|
||||||
|
NSMutableDictionary* newElement = [element mutableCopy];
|
||||||
|
|
||||||
NSMutableArray<NSString *> *childElementsToReturn = [NSMutableArray new];
|
NSMutableArray<NSString*>* childElementsToReturn = [NSMutableArray new];
|
||||||
for (NSString *child in descriptorChildElements) {
|
for (NSString* child in descriptorChildElements) {
|
||||||
if (![alreadyAdded containsObject: child]) {
|
if (![alreadyAdded containsObject:child]) {
|
||||||
[alreadyAdded addObject: child]; //todo add all at end
|
[alreadyAdded addObject:child]; // todo add all at end
|
||||||
[childElementsToReturn addObject: child];
|
[childElementsToReturn addObject:child];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[newElement setObject: childElementsToReturn forKey: @"children"];
|
[newElement setObject:childElementsToReturn forKey:@"children"];
|
||||||
return [[SKSearchResultNode alloc] initWithNode: nodeId
|
return [[SKSearchResultNode alloc] initWithNode:nodeId
|
||||||
asMatch: isMatch
|
asMatch:isMatch
|
||||||
withElement: newElement
|
withElement:newElement
|
||||||
andChildren: childTrees];
|
andChildren:childTrees];
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary *)getNode:(NSString *)nodeId {
|
- (NSDictionary*)getNode:(NSString*)nodeId {
|
||||||
id<NSObject> node = [_trackedObjects objectForKey: nodeId];
|
id<NSObject> node = [_trackedObjects objectForKey:nodeId];
|
||||||
if (node == nil) {
|
if (node == nil) {
|
||||||
SKLog(@"node is nil, no tracked node found for nodeId: %@", nodeId);
|
SKLog(@"node is nil, no tracked node found for nodeId: %@", nodeId);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
SKNodeDescriptor *nodeDescriptor = [_descriptorMapper descriptorForClass: [node class]];
|
SKNodeDescriptor* nodeDescriptor =
|
||||||
|
[_descriptorMapper descriptorForClass:[node class]];
|
||||||
if (nodeDescriptor == nil) {
|
if (nodeDescriptor == nil) {
|
||||||
SKLog(@"No registered descriptor for class: %@", [node class]);
|
SKLog(@"No registered descriptor for class: %@", [node class]);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableArray *attributes = [NSMutableArray new];
|
NSMutableArray* attributes = [NSMutableArray new];
|
||||||
NSMutableDictionary *data = [NSMutableDictionary new];
|
NSMutableDictionary* data = [NSMutableDictionary new];
|
||||||
|
|
||||||
const auto *nodeAttributes = [nodeDescriptor attributesForNode: node];
|
const auto* nodeAttributes = [nodeDescriptor attributesForNode:node];
|
||||||
for (const SKNamed<NSString *> *namedPair in nodeAttributes) {
|
for (const SKNamed<NSString*>* namedPair in nodeAttributes) {
|
||||||
const auto name = namedPair.name;
|
const auto name = namedPair.name;
|
||||||
if (name) {
|
if (name) {
|
||||||
const NSDictionary *attribute = @{
|
const NSDictionary* attribute = @{
|
||||||
@"name": name,
|
@"name" : name,
|
||||||
@"value": namedPair.value ?: [NSNull null],
|
@"value" : namedPair.value ?: [NSNull null],
|
||||||
};
|
};
|
||||||
[attributes addObject: attribute];
|
[attributes addObject:attribute];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto *nodeData = [nodeDescriptor dataForNode: node];
|
const auto* nodeData = [nodeDescriptor dataForNode:node];
|
||||||
for (const SKNamed<NSDictionary *> *namedPair in nodeData) {
|
for (const SKNamed<NSDictionary*>* namedPair in nodeData) {
|
||||||
data[namedPair.name] = namedPair.value;
|
data[namedPair.name] = namedPair.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableArray *children = [self getChildrenForNode: node withDescriptor:nodeDescriptor];
|
NSMutableArray* children = [self getChildrenForNode:node
|
||||||
|
withDescriptor:nodeDescriptor];
|
||||||
|
|
||||||
NSDictionary *nodeDic =
|
NSDictionary* nodeDic = @{
|
||||||
@{
|
// We shouldn't get nil for id/name/decoration, but let's not crash if we
|
||||||
// We shouldn't get nil for id/name/decoration, but let's not crash if we do.
|
// do.
|
||||||
@"id": [nodeDescriptor identifierForNode: node] ?: @"(unknown)",
|
@"id" : [nodeDescriptor identifierForNode:node] ?: @"(unknown)",
|
||||||
@"name": [nodeDescriptor nameForNode: node] ?: @"(unknown)",
|
@"name" : [nodeDescriptor nameForNode:node] ?: @"(unknown)",
|
||||||
@"children": children,
|
@"children" : children,
|
||||||
@"attributes": attributes,
|
@"attributes" : attributes,
|
||||||
@"data": data,
|
@"data" : data,
|
||||||
@"decoration": [nodeDescriptor decorationForNode: node] ?: @"(unknown)",
|
@"decoration" : [nodeDescriptor decorationForNode:node] ?: @"(unknown)",
|
||||||
};
|
};
|
||||||
|
|
||||||
return nodeDic;
|
return nodeDic;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)trackObject:(id)object {
|
- (NSString*)trackObject:(id)object {
|
||||||
const SKNodeDescriptor *descriptor = [_descriptorMapper descriptorForClass: [object class]];
|
const SKNodeDescriptor* descriptor =
|
||||||
NSString *objectIdentifier = [descriptor identifierForNode: object];
|
[_descriptorMapper descriptorForClass:[object class]];
|
||||||
|
NSString* objectIdentifier = [descriptor identifierForNode:object];
|
||||||
|
|
||||||
if (objectIdentifier == nil) {
|
if (objectIdentifier == nil) {
|
||||||
return nil;
|
return nil;
|
||||||
|
|||||||
@@ -13,10 +13,10 @@
|
|||||||
|
|
||||||
- (instancetype)initWithDefaults;
|
- (instancetype)initWithDefaults;
|
||||||
|
|
||||||
- (SKNodeDescriptor *)descriptorForClass:(Class)cls;
|
- (SKNodeDescriptor*)descriptorForClass:(Class)cls;
|
||||||
|
|
||||||
- (void)registerDescriptor:(SKNodeDescriptor *)descriptor forClass:(Class)cls;
|
- (void)registerDescriptor:(SKNodeDescriptor*)descriptor forClass:(Class)cls;
|
||||||
|
|
||||||
- (NSArray<SKNodeDescriptor *> *)allDescriptors;
|
- (NSArray<SKNodeDescriptor*>*)allDescriptors;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -15,47 +15,51 @@
|
|||||||
#import "SKViewControllerDescriptor.h"
|
#import "SKViewControllerDescriptor.h"
|
||||||
#import "SKViewDescriptor.h"
|
#import "SKViewDescriptor.h"
|
||||||
|
|
||||||
@implementation SKDescriptorMapper
|
@implementation SKDescriptorMapper {
|
||||||
{
|
NSMutableDictionary<NSString*, SKNodeDescriptor*>* _descriptors;
|
||||||
NSMutableDictionary<NSString *, SKNodeDescriptor *> *_descriptors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithDefaults {
|
- (instancetype)initWithDefaults {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_descriptors = [NSMutableDictionary new];
|
_descriptors = [NSMutableDictionary new];
|
||||||
|
|
||||||
[self registerDescriptor: [[SKApplicationDescriptor alloc] initWithDescriptorMapper: self]
|
[self registerDescriptor:[[SKApplicationDescriptor alloc]
|
||||||
forClass: [UIApplication class]];
|
initWithDescriptorMapper:self]
|
||||||
[self registerDescriptor: [[SKViewControllerDescriptor alloc] initWithDescriptorMapper: self]
|
forClass:[UIApplication class]];
|
||||||
forClass: [UIViewController class]];
|
[self registerDescriptor:[[SKViewControllerDescriptor alloc]
|
||||||
[self registerDescriptor: [[SKScrollViewDescriptor alloc] initWithDescriptorMapper: self]
|
initWithDescriptorMapper:self]
|
||||||
forClass: [UIScrollView class]];
|
forClass:[UIViewController class]];
|
||||||
[self registerDescriptor: [[SKButtonDescriptor alloc] initWithDescriptorMapper: self]
|
[self registerDescriptor:[[SKScrollViewDescriptor alloc]
|
||||||
forClass: [UIButton class]];
|
initWithDescriptorMapper:self]
|
||||||
[self registerDescriptor: [[SKViewDescriptor alloc] initWithDescriptorMapper: self]
|
forClass:[UIScrollView class]];
|
||||||
forClass: [UIView class]];
|
[self registerDescriptor:[[SKButtonDescriptor alloc]
|
||||||
|
initWithDescriptorMapper:self]
|
||||||
|
forClass:[UIButton class]];
|
||||||
|
[self registerDescriptor:[[SKViewDescriptor alloc]
|
||||||
|
initWithDescriptorMapper:self]
|
||||||
|
forClass:[UIView class]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (SKNodeDescriptor *)descriptorForClass:(Class)cls {
|
- (SKNodeDescriptor*)descriptorForClass:(Class)cls {
|
||||||
SKNodeDescriptor *classDescriptor = nil;
|
SKNodeDescriptor* classDescriptor = nil;
|
||||||
|
|
||||||
while (classDescriptor == nil && cls != nil) {
|
while (classDescriptor == nil && cls != nil) {
|
||||||
classDescriptor = [_descriptors objectForKey: NSStringFromClass(cls)];
|
classDescriptor = [_descriptors objectForKey:NSStringFromClass(cls)];
|
||||||
cls = [cls superclass];
|
cls = [cls superclass];
|
||||||
}
|
}
|
||||||
|
|
||||||
return classDescriptor;
|
return classDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)registerDescriptor:(SKNodeDescriptor *)descriptor forClass:(Class)cls {
|
- (void)registerDescriptor:(SKNodeDescriptor*)descriptor forClass:(Class)cls {
|
||||||
NSString *className = NSStringFromClass(cls);
|
NSString* className = NSStringFromClass(cls);
|
||||||
_descriptors[className] = descriptor;
|
_descriptors[className] = descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNodeDescriptor *> *)allDescriptors {
|
- (NSArray<SKNodeDescriptor*>*)allDescriptors {
|
||||||
return [_descriptors allValues];
|
return [_descriptors allValues];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,6 @@
|
|||||||
|
|
||||||
+ (void)enableInvalidations;
|
+ (void)enableInvalidations;
|
||||||
|
|
||||||
@property (nonatomic, weak) id<SKInvalidationDelegate> delegate;
|
@property(nonatomic, weak) id<SKInvalidationDelegate> delegate;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
#import "SKInvalidation.h"
|
#import "SKInvalidation.h"
|
||||||
#import "UIView+SKInvalidation.h"
|
|
||||||
#import "UICollectionView+SKInvalidation.h"
|
#import "UICollectionView+SKInvalidation.h"
|
||||||
|
#import "UIView+SKInvalidation.h"
|
||||||
|
|
||||||
@implementation SKInvalidation
|
@implementation SKInvalidation
|
||||||
|
|
||||||
+ (instancetype)sharedInstance {
|
+ (instancetype)sharedInstance {
|
||||||
static SKInvalidation *sInstance = nil;
|
static SKInvalidation* sInstance = nil;
|
||||||
|
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
@@ -32,12 +32,14 @@
|
|||||||
[UIView enableInvalidation];
|
[UIView enableInvalidation];
|
||||||
[UICollectionView enableInvalidations];
|
[UICollectionView enableInvalidations];
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
addObserver:self
|
||||||
selector:@selector(windowDidBecomeVisible:)
|
selector:@selector(windowDidBecomeVisible:)
|
||||||
name:UIWindowDidBecomeVisibleNotification
|
name:UIWindowDidBecomeVisibleNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
addObserver:self
|
||||||
selector:@selector(windowDidBecomeHidden:)
|
selector:@selector(windowDidBecomeHidden:)
|
||||||
name:UIWindowDidBecomeHiddenNotification
|
name:UIWindowDidBecomeHiddenNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
@@ -45,11 +47,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
+ (void)windowDidBecomeVisible:(NSNotification*)notification {
|
+ (void)windowDidBecomeVisible:(NSNotification*)notification {
|
||||||
[[SKInvalidation sharedInstance].delegate invalidateNode:[notification.object nextResponder]];
|
[[SKInvalidation sharedInstance].delegate
|
||||||
|
invalidateNode:[notification.object nextResponder]];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)windowDidBecomeHidden:(NSNotification*)notification {
|
+ (void)windowDidBecomeHidden:(NSNotification*)notification {
|
||||||
[[SKInvalidation sharedInstance].delegate invalidateNode:[notification.object nextResponder]];
|
[[SKInvalidation sharedInstance].delegate
|
||||||
|
invalidateNode:[notification.object nextResponder]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
@interface SKNamed<__covariant T> : NSObject
|
@interface SKNamed<__covariant T> : NSObject
|
||||||
|
|
||||||
+ (instancetype)newWithName:(NSString *)name withValue:(T)value;
|
+ (instancetype)newWithName:(NSString*)name withValue:(T)value;
|
||||||
|
|
||||||
@property (nonatomic, readonly) NSString *name;
|
@property(nonatomic, readonly) NSString* name;
|
||||||
@property (nonatomic, readonly) T value;
|
@property(nonatomic, readonly) T value;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,11 +11,11 @@
|
|||||||
|
|
||||||
@implementation SKNamed
|
@implementation SKNamed
|
||||||
|
|
||||||
+ (instancetype)newWithName:(NSString *)name withValue:(id)value {
|
+ (instancetype)newWithName:(NSString*)name withValue:(id)value {
|
||||||
return [[SKNamed alloc] initWithName: name withValue: value];
|
return [[SKNamed alloc] initWithName:name withValue:value];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithName:(NSString *)name withValue:(id)value {
|
- (instancetype)initWithName:(NSString*)name withValue:(id)value {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_name = name;
|
_name = name;
|
||||||
_value = value;
|
_value = value;
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)description {
|
- (NSString*)description {
|
||||||
return [NSString stringWithFormat:@"%@: %@", _name, _value];
|
return [NSString stringWithFormat:@"%@: %@", _name, _value];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ typedef void (^SKNodeUpdateData)(id value);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
A SKNodeDescriptor is an object which know how to expose an Object of type T
|
A SKNodeDescriptor is an object which know how to expose an Object of type T
|
||||||
to SonarKitLayoutPlugin. This class is the extension point for SonarKitLayoutPlugin and
|
to SonarKitLayoutPlugin. This class is the extension point for
|
||||||
is how custom objects or data can be exposed to Sonar.
|
SonarKitLayoutPlugin and is how custom objects or data can be exposed to Sonar.
|
||||||
*/
|
*/
|
||||||
@interface SKNodeDescriptor<__covariant T> : NSObject
|
@interface SKNodeDescriptor<__covariant T> : NSObject
|
||||||
|
|
||||||
@@ -27,34 +27,35 @@ typedef void (^SKNodeUpdateData)(id value);
|
|||||||
- (void)setUp;
|
- (void)setUp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initializes the node-descriptor with a SKDescriptorMapper which contains mappings
|
Initializes the node-descriptor with a SKDescriptorMapper which contains
|
||||||
between Class -> SKNodeDescriptor<Class>.
|
mappings between Class -> SKNodeDescriptor<Class>.
|
||||||
*/
|
*/
|
||||||
- (instancetype)initWithDescriptorMapper:(SKDescriptorMapper *)mapper;
|
- (instancetype)initWithDescriptorMapper:(SKDescriptorMapper*)mapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Gets the node-descriptor registered for a specific class.
|
Gets the node-descriptor registered for a specific class.
|
||||||
*/
|
*/
|
||||||
- (SKNodeDescriptor *)descriptorForClass:(Class)cls;
|
- (SKNodeDescriptor*)descriptorForClass:(Class)cls;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A globally unique ID used to identify a node in the hierarchy. This is used
|
A globally unique ID used to identify a node in the hierarchy. This is used
|
||||||
in the communication between SonarKitLayoutPlugin and the Sonar desktop application
|
in the communication between SonarKitLayoutPlugin and the Sonar desktop
|
||||||
in order to identify nodes.
|
application in order to identify nodes.
|
||||||
*/
|
*/
|
||||||
- (NSString *)identifierForNode:(T)node;
|
- (NSString*)identifierForNode:(T)node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
An ID which is equal between reflowing components is needed to get the identifier of root
|
An ID which is equal between reflowing components is needed to get the
|
||||||
node of a tree which need to be invalidated on FlipperKitLayoutPlugin side.
|
identifier of root node of a tree which need to be invalidated on
|
||||||
|
FlipperKitLayoutPlugin side.
|
||||||
*/
|
*/
|
||||||
- (NSString *)identifierForInvalidation:(T)node;
|
- (NSString*)identifierForInvalidation:(T)node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The name used to identify this node in the Sonar desktop application. This is what
|
The name used to identify this node in the Sonar desktop application. This is
|
||||||
will be visible in the hierarchy.
|
what will be visible in the hierarchy.
|
||||||
*/
|
*/
|
||||||
- (NSString *)nameForNode:(T)node;
|
- (NSString*)nameForNode:(T)node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The number of children this node exposes in the layout hierarchy.
|
The number of children this node exposes in the layout hierarchy.
|
||||||
@@ -67,29 +68,30 @@ typedef void (^SKNodeUpdateData)(id value);
|
|||||||
- (id)childForNode:(T)node atIndex:(NSUInteger)index;
|
- (id)childForNode:(T)node atIndex:(NSUInteger)index;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the data to show for this node in the sidebar of the Sonar application. The objects
|
Get the data to show for this node in the sidebar of the Sonar application. The
|
||||||
will be shown in order by SKNamed.name as their header.
|
objects will be shown in order by SKNamed.name as their header.
|
||||||
*/
|
*/
|
||||||
- (NSArray<SKNamed<NSDictionary *> *> *)dataForNode:(T)node;
|
- (NSArray<SKNamed<NSDictionary*>*>*)dataForNode:(T)node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the attributes for this node. Attributes will be showed in the Sonar application right
|
Get the attributes for this node. Attributes will be showed in the Sonar
|
||||||
next to the name of the node.
|
application right next to the name of the node.
|
||||||
*/
|
*/
|
||||||
- (NSArray<SKNamed<NSString *> *> *)attributesForNode:(T)node;
|
- (NSArray<SKNamed<NSString*>*>*)attributesForNode:(T)node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A mapping of the path for a specific value, and a block responsible for updating
|
A mapping of the path for a specific value, and a block responsible for
|
||||||
its corresponding value for a specific node.
|
updating its corresponding value for a specific node.
|
||||||
|
|
||||||
The paths (string) is dependent on what `dataForNode` returns (e.g "SKNodeDescriptor.name").
|
The paths (string) is dependent on what `dataForNode` returns (e.g
|
||||||
|
"SKNodeDescriptor.name").
|
||||||
*/
|
*/
|
||||||
- (NSDictionary<NSString *, SKNodeUpdateData> *)dataMutationsForNode:(T)node;
|
- (NSDictionary<NSString*, SKNodeUpdateData>*)dataMutationsForNode:(T)node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This is used in order to highlight any specific node which is currently
|
This is used in order to highlight any specific node which is currently
|
||||||
selected in the Sonar application. The plugin automatically takes care of de-selecting
|
selected in the Sonar application. The plugin automatically takes care of
|
||||||
the previously highlighted node.
|
de-selecting the previously highlighted node.
|
||||||
*/
|
*/
|
||||||
- (void)setHighlighted:(BOOL)highlighted forNode:(T)node;
|
- (void)setHighlighted:(BOOL)highlighted forNode:(T)node;
|
||||||
|
|
||||||
@@ -98,7 +100,7 @@ typedef void (^SKNodeUpdateData)(id value);
|
|||||||
one of the children of the node, or finish the hit testing on this
|
one of the children of the node, or finish the hit testing on this
|
||||||
node.
|
node.
|
||||||
*/
|
*/
|
||||||
- (void)hitTest:(SKTouch *)point forNode:(T)node;
|
- (void)hitTest:(SKTouch*)point forNode:(T)node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Invalidate a specific node. This is called once a node is removed or added
|
Invalidate a specific node. This is called once a node is removed or added
|
||||||
@@ -110,12 +112,12 @@ typedef void (^SKNodeUpdateData)(id value);
|
|||||||
The decoration for this node. Valid values are defined in the Sonar
|
The decoration for this node. Valid values are defined in the Sonar
|
||||||
applictation.
|
applictation.
|
||||||
*/
|
*/
|
||||||
- (NSString *)decorationForNode:(T)node;
|
- (NSString*)decorationForNode:(T)node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Whether the node matches the given query.
|
Whether the node matches the given query.
|
||||||
Used for layout search.
|
Used for layout search.
|
||||||
*/
|
*/
|
||||||
- (BOOL)matchesQuery:(NSString *)query forNode:(T)node;
|
- (BOOL)matchesQuery:(NSString*)query forNode:(T)node;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -10,87 +10,89 @@
|
|||||||
#import "SKNodeDescriptor.h"
|
#import "SKNodeDescriptor.h"
|
||||||
#import <FlipperKitLayoutTextSearchable/FKTextSearchable.h>
|
#import <FlipperKitLayoutTextSearchable/FKTextSearchable.h>
|
||||||
|
|
||||||
@implementation SKNodeDescriptor
|
@implementation SKNodeDescriptor {
|
||||||
{
|
SKDescriptorMapper* _mapper;
|
||||||
SKDescriptorMapper *_mapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setUp {
|
- (void)setUp {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithDescriptorMapper:(SKDescriptorMapper *)mapper {
|
- (instancetype)initWithDescriptorMapper:(SKDescriptorMapper*)mapper {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (SKNodeDescriptor *)descriptorForClass:(Class)cls {
|
- (SKNodeDescriptor*)descriptorForClass:(Class)cls {
|
||||||
return [_mapper descriptorForClass: cls];
|
return [_mapper descriptorForClass:cls];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)identifierForNode:(id)node {
|
- (NSString*)identifierForNode:(id)node {
|
||||||
@throw [NSString stringWithFormat:@"need to implement %@", NSStringFromSelector(_cmd)];
|
@throw [NSString
|
||||||
|
stringWithFormat:@"need to implement %@", NSStringFromSelector(_cmd)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)identifierForInvalidation:(id)node
|
- (NSString*)identifierForInvalidation:(id)node {
|
||||||
{
|
|
||||||
return [self identifierForNode:node];
|
return [self identifierForNode:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)nameForNode:(id)node {
|
- (NSString*)nameForNode:(id)node {
|
||||||
return NSStringFromClass([node class]);
|
return NSStringFromClass([node class]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)childCountForNode:(id)node {
|
- (NSUInteger)childCountForNode:(id)node {
|
||||||
@throw [NSString stringWithFormat:@"need to implement %@", NSStringFromSelector(_cmd)];
|
@throw [NSString
|
||||||
|
stringWithFormat:@"need to implement %@", NSStringFromSelector(_cmd)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)childForNode:(id)node atIndex:(NSUInteger)index {
|
- (id)childForNode:(id)node atIndex:(NSUInteger)index {
|
||||||
@throw [NSString stringWithFormat:@"need to implement %@", NSStringFromSelector(_cmd)];
|
@throw [NSString
|
||||||
|
stringWithFormat:@"need to implement %@", NSStringFromSelector(_cmd)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, SKNodeUpdateData> *)dataMutationsForNode:(id)node {
|
- (NSDictionary<NSString*, SKNodeUpdateData>*)dataMutationsForNode:(id)node {
|
||||||
return @{};
|
return @{};
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSDictionary *> *> *)dataForNode:(id)node {
|
- (NSArray<SKNamed<NSDictionary*>*>*)dataForNode:(id)node {
|
||||||
return @[];
|
return @[];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSString *> *> *)attributesForNode:(id)node {
|
- (NSArray<SKNamed<NSString*>*>*)attributesForNode:(id)node {
|
||||||
return @[];
|
return @[];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted forNode:(id)node {
|
- (void)setHighlighted:(BOOL)highlighted forNode:(id)node {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)hitTest:(SKTouch *)point forNode:(id)node {
|
- (void)hitTest:(SKTouch*)point forNode:(id)node {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)invalidateNode:(id)node {
|
- (void)invalidateNode:(id)node {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)decorationForNode:(id)node {
|
- (NSString*)decorationForNode:(id)node {
|
||||||
return @"";
|
return @"";
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)matchesQuery:(NSString *)query forNode:(id)node {
|
- (BOOL)matchesQuery:(NSString*)query forNode:(id)node {
|
||||||
NSString *name = [self nameForNode: node];
|
NSString* name = [self nameForNode:node];
|
||||||
NSString *text = nil;
|
NSString* text = nil;
|
||||||
if ([node conformsToProtocol:@protocol(FKTextSearchable)]) {
|
if ([node conformsToProtocol:@protocol(FKTextSearchable)]) {
|
||||||
text = [node searchableText];
|
text = [node searchableText];
|
||||||
}
|
}
|
||||||
return [self string:name contains:query] ||
|
return [self string:name contains:query] ||
|
||||||
[self string:[self identifierForNode: node] contains: query] ||
|
[self string:[self identifierForNode:node] contains:query] ||
|
||||||
[self string:text contains:query];
|
[self string:text contains:query];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)string:(NSString *)string contains:(NSString *)substring {
|
- (BOOL)string:(NSString*)string contains:(NSString*)substring {
|
||||||
return string != nil && substring != nil && [string rangeOfString: substring options: NSCaseInsensitiveSearch].location != NSNotFound;
|
return string != nil && substring != nil &&
|
||||||
|
[string rangeOfString:substring options:NSCaseInsensitiveSearch]
|
||||||
|
.location != NSNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,12 +11,12 @@
|
|||||||
|
|
||||||
+ (instancetype)fromSonarValue:(id)sonarValue;
|
+ (instancetype)fromSonarValue:(id)sonarValue;
|
||||||
|
|
||||||
- (NSDictionary<NSString *, id<NSObject>> *)sonarValue;
|
- (NSDictionary<NSString*, id<NSObject>>*)sonarValue;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
class SKObject {
|
class SKObject {
|
||||||
public:
|
public:
|
||||||
SKObject(CGRect rect);
|
SKObject(CGRect rect);
|
||||||
SKObject(CGSize size);
|
SKObject(CGSize size);
|
||||||
SKObject(CGPoint point);
|
SKObject(CGPoint point);
|
||||||
@@ -25,28 +25,30 @@ public:
|
|||||||
SKObject(id<SKSonarValueCoder> value);
|
SKObject(id<SKSonarValueCoder> value);
|
||||||
SKObject(id value);
|
SKObject(id value);
|
||||||
|
|
||||||
operator id<NSObject> () const noexcept {
|
operator id<NSObject>() const noexcept {
|
||||||
return _actual ?: [NSNull null];
|
return _actual ?: [NSNull null];
|
||||||
}
|
}
|
||||||
protected:
|
|
||||||
|
protected:
|
||||||
id<NSObject> _actual;
|
id<NSObject> _actual;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SKMutableObject : public SKObject {
|
class SKMutableObject : public SKObject {
|
||||||
public:
|
public:
|
||||||
SKMutableObject(CGRect rect) : SKObject(rect) { }
|
SKMutableObject(CGRect rect) : SKObject(rect) {}
|
||||||
SKMutableObject(CGSize size) : SKObject(size) { };
|
SKMutableObject(CGSize size) : SKObject(size){};
|
||||||
SKMutableObject(CGPoint point) : SKObject(point) { };
|
SKMutableObject(CGPoint point) : SKObject(point){};
|
||||||
SKMutableObject(UIEdgeInsets insets) : SKObject(insets) { };
|
SKMutableObject(UIEdgeInsets insets) : SKObject(insets){};
|
||||||
SKMutableObject(CGAffineTransform transform) : SKObject(transform) { };
|
SKMutableObject(CGAffineTransform transform) : SKObject(transform){};
|
||||||
SKMutableObject(id<SKSonarValueCoder> value) : SKObject(value) { };
|
SKMutableObject(id<SKSonarValueCoder> value) : SKObject(value){};
|
||||||
SKMutableObject(id value) : SKObject(value) { };
|
SKMutableObject(id value) : SKObject(value){};
|
||||||
|
|
||||||
operator id<NSObject> () {
|
operator id<NSObject>() {
|
||||||
convertToMutable();
|
convertToMutable();
|
||||||
return _actual;
|
return _actual;
|
||||||
}
|
}
|
||||||
protected:
|
|
||||||
|
protected:
|
||||||
BOOL _convertedToMutable = NO;
|
BOOL _convertedToMutable = NO;
|
||||||
void convertToMutable();
|
void convertToMutable();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,86 +10,80 @@
|
|||||||
#import "SKObject.h"
|
#import "SKObject.h"
|
||||||
|
|
||||||
SKObject::SKObject(CGRect rect) {
|
SKObject::SKObject(CGRect rect) {
|
||||||
_actual = @{
|
_actual = @{@"origin" : SKObject(rect.origin), @"size" : SKObject(rect.size)};
|
||||||
@"origin": SKObject(rect.origin),
|
|
||||||
@"size": SKObject(rect.size)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SKObject::SKObject(CGSize size) {
|
SKObject::SKObject(CGSize size) {
|
||||||
_actual = @{
|
_actual = @{@"height" : @(size.height), @"width" : @(size.width)};
|
||||||
@"height": @(size.height),
|
|
||||||
@"width": @(size.width)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SKObject::SKObject(CGPoint point) {
|
SKObject::SKObject(CGPoint point) {
|
||||||
_actual = @{
|
_actual = @{@"x" : @(point.x), @"y" : @(point.y)};
|
||||||
@"x": @(point.x),
|
|
||||||
@"y": @(point.y)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SKObject::SKObject(UIEdgeInsets insets) {
|
SKObject::SKObject(UIEdgeInsets insets) {
|
||||||
_actual = @{
|
_actual = @{
|
||||||
@"top": @(insets.top),
|
@"top" : @(insets.top),
|
||||||
@"bottom": @(insets.bottom),
|
@"bottom" : @(insets.bottom),
|
||||||
@"left": @(insets.left),
|
@"left" : @(insets.left),
|
||||||
@"right": @(insets.right),
|
@"right" : @(insets.right),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
SKObject::SKObject(CGAffineTransform transform) {
|
SKObject::SKObject(CGAffineTransform transform) {
|
||||||
_actual = @{
|
_actual = @{
|
||||||
@"a": @(transform.a),
|
@"a" : @(transform.a),
|
||||||
@"b": @(transform.b),
|
@"b" : @(transform.b),
|
||||||
@"c": @(transform.c),
|
@"c" : @(transform.c),
|
||||||
@"d": @(transform.d),
|
@"d" : @(transform.d),
|
||||||
@"tx": @(transform.tx),
|
@"tx" : @(transform.tx),
|
||||||
@"ty": @(transform.ty),
|
@"ty" : @(transform.ty),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
SKObject::SKObject(id<SKSonarValueCoder> value) : _actual([value sonarValue]) { }
|
SKObject::SKObject(id<SKSonarValueCoder> value) : _actual([value sonarValue]) {}
|
||||||
|
|
||||||
SKObject::SKObject(id value) : _actual(value) { }
|
SKObject::SKObject(id value) : _actual(value) {}
|
||||||
|
|
||||||
static NSString *_objectType(id<NSObject> object) {
|
static NSString* _objectType(id<NSObject> object) {
|
||||||
if ([object isKindOfClass: [NSDictionary class]]) {
|
if ([object isKindOfClass:[NSDictionary class]]) {
|
||||||
return (NSString *)((NSDictionary *)object)[@"__type__"];
|
return (NSString*)((NSDictionary*)object)[@"__type__"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
static id<NSObject> _objectValue(id<NSObject> object) {
|
static id<NSObject> _objectValue(id<NSObject> object) {
|
||||||
if ([object isKindOfClass: [NSDictionary class]]) {
|
if ([object isKindOfClass:[NSDictionary class]]) {
|
||||||
return ((NSDictionary *)object)[@"value"];
|
return ((NSDictionary*)object)[@"value"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSDictionary<NSString *, id<NSObject>> *_SKValue(id<NSObject> object, BOOL isMutable) {
|
static NSDictionary<NSString*, id<NSObject>>* _SKValue(
|
||||||
NSString *type = _objectType(object);
|
id<NSObject> object,
|
||||||
|
BOOL isMutable) {
|
||||||
|
NSString* type = _objectType(object);
|
||||||
id<NSObject> value = _objectValue(object);
|
id<NSObject> value = _objectValue(object);
|
||||||
|
|
||||||
return @{
|
return @{
|
||||||
@"__type__": (type != nil ? type : @"auto"),
|
@"__type__" : (type != nil ? type : @"auto"),
|
||||||
@"__mutable__": @(isMutable),
|
@"__mutable__" : @(isMutable),
|
||||||
@"value": (value != nil ? value : [NSNull null]),
|
@"value" : (value != nil ? value : [NSNull null]),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSDictionary *_SKMutable(const NSDictionary<NSString *, id<NSObject>> *skObject) {
|
static NSDictionary* _SKMutable(
|
||||||
NSMutableDictionary *mutableObject = [NSMutableDictionary new];
|
const NSDictionary<NSString*, id<NSObject>>* skObject) {
|
||||||
for (NSString *key: skObject) {
|
NSMutableDictionary* mutableObject = [NSMutableDictionary new];
|
||||||
|
for (NSString* key : skObject) {
|
||||||
id<NSObject> value = skObject[key];
|
id<NSObject> value = skObject[key];
|
||||||
|
|
||||||
if (_objectType(value) != nil) {
|
if (_objectType(value) != nil) {
|
||||||
mutableObject[key] = _SKValue(value, YES);
|
mutableObject[key] = _SKValue(value, YES);
|
||||||
} else if ([value isKindOfClass: [NSDictionary class]]) {
|
} else if ([value isKindOfClass:[NSDictionary class]]) {
|
||||||
auto objectValue = (NSDictionary<NSString *, id<NSObject>>*) value;
|
auto objectValue = (NSDictionary<NSString*, id<NSObject>>*)value;
|
||||||
mutableObject[key] = _SKMutable(objectValue);
|
mutableObject[key] = _SKMutable(objectValue);
|
||||||
} else {
|
} else {
|
||||||
mutableObject[key] = _SKValue(value, YES);
|
mutableObject[key] = _SKValue(value, YES);
|
||||||
@@ -104,8 +98,9 @@ void SKMutableObject::convertToMutable() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_objectType(_actual) == nil && [_actual isKindOfClass: [NSDictionary class]]) {
|
if (_objectType(_actual) == nil &&
|
||||||
auto object = (const NSDictionary<NSString *, id<NSObject>> *)_actual;
|
[_actual isKindOfClass:[NSDictionary class]]) {
|
||||||
|
auto object = (const NSDictionary<NSString*, id<NSObject>>*)_actual;
|
||||||
_actual = _SKMutable(object);
|
_actual = _SKMutable(object);
|
||||||
} else {
|
} else {
|
||||||
_actual = _SKValue(_actual, YES);
|
_actual = _SKValue(_actual, YES);
|
||||||
|
|||||||
@@ -12,14 +12,14 @@
|
|||||||
|
|
||||||
@interface SKSearchResultNode : NSObject
|
@interface SKSearchResultNode : NSObject
|
||||||
|
|
||||||
@property (nonatomic, copy, readonly) NSString *nodeId;
|
@property(nonatomic, copy, readonly) NSString* nodeId;
|
||||||
|
|
||||||
- (instancetype)initWithNode:(NSString *)nodeId
|
- (instancetype)initWithNode:(NSString*)nodeId
|
||||||
asMatch:(BOOL)isMatch
|
asMatch:(BOOL)isMatch
|
||||||
withElement:(NSDictionary *)element
|
withElement:(NSDictionary*)element
|
||||||
andChildren:(NSArray<SKSearchResultNode *> *)children;
|
andChildren:(NSArray<SKSearchResultNode*>*)children;
|
||||||
|
|
||||||
- (NSDictionary *)toNSDictionary;
|
- (NSDictionary*)toNSDictionary;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
#endif /* SKSearchResultNode_h */
|
#endif /* SKSearchResultNode_h */
|
||||||
|
|||||||
@@ -8,16 +8,16 @@
|
|||||||
#import "SKSearchResultNode.h"
|
#import "SKSearchResultNode.h"
|
||||||
|
|
||||||
@implementation SKSearchResultNode {
|
@implementation SKSearchResultNode {
|
||||||
NSString *_nodeId;
|
NSString* _nodeId;
|
||||||
BOOL _isMatch;
|
BOOL _isMatch;
|
||||||
NSDictionary *_element;
|
NSDictionary* _element;
|
||||||
NSArray<SKSearchResultNode *> *_children;
|
NSArray<SKSearchResultNode*>* _children;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithNode:(NSString *)nodeId
|
- (instancetype)initWithNode:(NSString*)nodeId
|
||||||
asMatch:(BOOL)isMatch
|
asMatch:(BOOL)isMatch
|
||||||
withElement:(NSDictionary *)element
|
withElement:(NSDictionary*)element
|
||||||
andChildren:(NSArray<SKSearchResultNode *> *)children {
|
andChildren:(NSArray<SKSearchResultNode*>*)children {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self) {
|
if (self) {
|
||||||
_nodeId = nodeId;
|
_nodeId = nodeId;
|
||||||
@@ -28,15 +28,15 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary *)toNSDictionary {
|
- (NSDictionary*)toNSDictionary {
|
||||||
if (_element == nil) {
|
if (_element == nil) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
NSMutableArray<NSDictionary *> *childArray;
|
NSMutableArray<NSDictionary*>* childArray;
|
||||||
if (_children) {
|
if (_children) {
|
||||||
childArray = [NSMutableArray new];
|
childArray = [NSMutableArray new];
|
||||||
for (SKSearchResultNode *child in _children) {
|
for (SKSearchResultNode* child in _children) {
|
||||||
NSDictionary *childDict = [child toNSDictionary];
|
NSDictionary* childDict = [child toNSDictionary];
|
||||||
if (childDict) {
|
if (childDict) {
|
||||||
[childArray addObject:childDict];
|
[childArray addObject:childDict];
|
||||||
}
|
}
|
||||||
@@ -45,10 +45,10 @@
|
|||||||
childArray = nil;
|
childArray = nil;
|
||||||
}
|
}
|
||||||
return @{
|
return @{
|
||||||
@"id": _nodeId,
|
@"id" : _nodeId,
|
||||||
@"isMatch": @(_isMatch),
|
@"isMatch" : @(_isMatch),
|
||||||
@"element": _element,
|
@"element" : _element,
|
||||||
@"children": childArray ?: [NSNull null]
|
@"children" : childArray ?: [NSNull null]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ typedef void (^SKTapReceiver)(CGPoint touchPoint);
|
|||||||
|
|
||||||
@protocol SKTapListener
|
@protocol SKTapListener
|
||||||
|
|
||||||
@property (nonatomic, readonly) BOOL isMounted;
|
@property(nonatomic, readonly) BOOL isMounted;
|
||||||
|
|
||||||
- (void)mountWithFrame:(CGRect)frame;
|
- (void)mountWithFrame:(CGRect)frame;
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#import "SKTapListener.h"
|
#import "SKTapListener.h"
|
||||||
|
|
||||||
@interface SKTapListenerImpl : NSObject<SKTapListener, UIGestureRecognizerDelegate>
|
@interface SKTapListenerImpl
|
||||||
|
: NSObject<SKTapListener, UIGestureRecognizerDelegate>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -13,12 +13,11 @@
|
|||||||
|
|
||||||
#import <FlipperKitHighlightOverlay/SKHighlightOverlay.h>
|
#import <FlipperKitHighlightOverlay/SKHighlightOverlay.h>
|
||||||
|
|
||||||
@implementation SKTapListenerImpl
|
@implementation SKTapListenerImpl {
|
||||||
{
|
NSMutableArray<SKTapReceiver>* _receiversWaitingForInput;
|
||||||
NSMutableArray<SKTapReceiver> *_receiversWaitingForInput;
|
UITapGestureRecognizer* _gestureRecognizer;
|
||||||
UITapGestureRecognizer *_gestureRecognizer;
|
|
||||||
|
|
||||||
SKHiddenWindow *_overlayWindow;
|
SKHiddenWindow* _overlayWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@synthesize isMounted = _isMounted;
|
@synthesize isMounted = _isMounted;
|
||||||
@@ -27,7 +26,8 @@
|
|||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_receiversWaitingForInput = [NSMutableArray new];
|
_receiversWaitingForInput = [NSMutableArray new];
|
||||||
|
|
||||||
_gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget: self action: nil];
|
_gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
|
||||||
|
action:nil];
|
||||||
_gestureRecognizer.delegate = self;
|
_gestureRecognizer.delegate = self;
|
||||||
|
|
||||||
_isMounted = NO;
|
_isMounted = NO;
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
_overlayWindow.windowLevel = UIWindowLevelAlert;
|
_overlayWindow.windowLevel = UIWindowLevelAlert;
|
||||||
_overlayWindow.backgroundColor = [SKHighlightOverlay overlayColor];
|
_overlayWindow.backgroundColor = [SKHighlightOverlay overlayColor];
|
||||||
|
|
||||||
[_overlayWindow addGestureRecognizer: _gestureRecognizer];
|
[_overlayWindow addGestureRecognizer:_gestureRecognizer];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[_overlayWindow setFrame: frame];
|
[_overlayWindow setFrame:frame];
|
||||||
[_overlayWindow makeKeyAndVisible];
|
[_overlayWindow makeKeyAndVisible];
|
||||||
_overlayWindow.hidden = NO;
|
_overlayWindow.hidden = NO;
|
||||||
|
|
||||||
@@ -68,15 +68,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)listenForTapWithBlock:(SKTapReceiver)receiver {
|
- (void)listenForTapWithBlock:(SKTapReceiver)receiver {
|
||||||
[_receiversWaitingForInput addObject: receiver];
|
[_receiversWaitingForInput addObject:receiver];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
|
||||||
|
shouldReceiveTouch:(UITouch*)touch {
|
||||||
if ([_receiversWaitingForInput count] == 0) {
|
if ([_receiversWaitingForInput count] == 0) {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGPoint touchPoint = [touch locationInView: _overlayWindow];
|
CGPoint touchPoint = [touch locationInView:_overlayWindow];
|
||||||
|
|
||||||
for (SKTapReceiver recv in _receiversWaitingForInput) {
|
for (SKTapReceiver recv in _receiversWaitingForInput) {
|
||||||
recv(touchPoint);
|
recv(touchPoint);
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
#import "SKDescriptorMapper.h"
|
#import "SKDescriptorMapper.h"
|
||||||
|
|
||||||
typedef void (^SKTouchFinishDelegate)(NSArray<NSString *> *path);
|
typedef void (^SKTouchFinishDelegate)(NSArray<NSString*>* path);
|
||||||
|
|
||||||
@interface SKTouch : NSObject
|
@interface SKTouch : NSObject
|
||||||
|
|
||||||
- (instancetype)initWithTouchPoint:(CGPoint)touchPoint
|
- (instancetype)initWithTouchPoint:(CGPoint)touchPoint
|
||||||
withRootNode:(id<NSObject>)node
|
withRootNode:(id<NSObject>)node
|
||||||
withDescriptorMapper:(SKDescriptorMapper *)mapper
|
withDescriptorMapper:(SKDescriptorMapper*)mapper
|
||||||
finishWithBlock:(SKTouchFinishDelegate)d;
|
finishWithBlock:(SKTouchFinishDelegate)d;
|
||||||
|
|
||||||
- (void)continueWithChildIndex:(NSUInteger)childIndex
|
- (void)continueWithChildIndex:(NSUInteger)childIndex
|
||||||
|
|||||||
@@ -10,20 +10,19 @@
|
|||||||
#import "SKTouch.h"
|
#import "SKTouch.h"
|
||||||
#import "SKNodeDescriptor.h"
|
#import "SKNodeDescriptor.h"
|
||||||
|
|
||||||
@implementation SKTouch
|
@implementation SKTouch {
|
||||||
{
|
|
||||||
SKTouchFinishDelegate _onFinish;
|
SKTouchFinishDelegate _onFinish;
|
||||||
NSMutableArray<NSString *> *_path;
|
NSMutableArray<NSString*>* _path;
|
||||||
|
|
||||||
CGPoint _currentTouchPoint;
|
CGPoint _currentTouchPoint;
|
||||||
id<NSObject> _currentNode;
|
id<NSObject> _currentNode;
|
||||||
|
|
||||||
SKDescriptorMapper *_descriptorMapper;
|
SKDescriptorMapper* _descriptorMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithTouchPoint:(CGPoint)touchPoint
|
- (instancetype)initWithTouchPoint:(CGPoint)touchPoint
|
||||||
withRootNode:(id<NSObject>)node
|
withRootNode:(id<NSObject>)node
|
||||||
withDescriptorMapper:(SKDescriptorMapper *)mapper
|
withDescriptorMapper:(SKDescriptorMapper*)mapper
|
||||||
finishWithBlock:(SKTouchFinishDelegate)finishBlock {
|
finishWithBlock:(SKTouchFinishDelegate)finishBlock {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_onFinish = finishBlock;
|
_onFinish = finishBlock;
|
||||||
@@ -36,17 +35,19 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)continueWithChildIndex:(NSUInteger)childIndex withOffset:(CGPoint)offset {
|
- (void)continueWithChildIndex:(NSUInteger)childIndex
|
||||||
|
withOffset:(CGPoint)offset {
|
||||||
_currentTouchPoint.x -= offset.x;
|
_currentTouchPoint.x -= offset.x;
|
||||||
_currentTouchPoint.y -= offset.y;
|
_currentTouchPoint.y -= offset.y;
|
||||||
|
|
||||||
SKNodeDescriptor *descriptor = [_descriptorMapper descriptorForClass: [_currentNode class]];
|
SKNodeDescriptor* descriptor =
|
||||||
_currentNode = [descriptor childForNode: _currentNode atIndex: childIndex];
|
[_descriptorMapper descriptorForClass:[_currentNode class]];
|
||||||
|
_currentNode = [descriptor childForNode:_currentNode atIndex:childIndex];
|
||||||
|
|
||||||
descriptor = [_descriptorMapper descriptorForClass: [_currentNode class]];
|
descriptor = [_descriptorMapper descriptorForClass:[_currentNode class]];
|
||||||
[_path addObject: [descriptor identifierForNode: _currentNode]];
|
[_path addObject:[descriptor identifierForNode:_currentNode]];
|
||||||
|
|
||||||
[descriptor hitTest: self forNode: _currentNode];
|
[descriptor hitTest:self forNode:_currentNode];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)finish {
|
- (void)finish {
|
||||||
|
|||||||
@@ -18,16 +18,20 @@ FB_LINKABLE(UICollectionView_SKInvalidation)
|
|||||||
+ (void)enableInvalidations {
|
+ (void)enableInvalidations {
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
swizzleMethods([self class], @selector(cellForItemAtIndexPath:), @selector(swizzle_cellForItemAtIndexPath:));
|
swizzleMethods(
|
||||||
|
[self class],
|
||||||
|
@selector(cellForItemAtIndexPath:),
|
||||||
|
@selector(swizzle_cellForItemAtIndexPath:));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UICollectionViewCell *)swizzle_cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
- (UICollectionViewCell*)swizzle_cellForItemAtIndexPath:
|
||||||
|
(NSIndexPath*)indexPath {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[[SKInvalidation sharedInstance].delegate invalidateNode: self];
|
[[SKInvalidation sharedInstance].delegate invalidateNode:self];
|
||||||
});
|
});
|
||||||
|
|
||||||
return [self swizzle_cellForItemAtIndexPath: indexPath];
|
return [self swizzle_cellForItemAtIndexPath:indexPath];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -12,6 +12,6 @@
|
|||||||
#import "SKObject.h"
|
#import "SKObject.h"
|
||||||
|
|
||||||
FB_LINK_REQUIRE_CATEGORY(UIColor_SonarValueCoder)
|
FB_LINK_REQUIRE_CATEGORY(UIColor_SonarValueCoder)
|
||||||
@interface UIColor (SonarValueCoder) <SKSonarValueCoder>
|
@interface UIColor (SonarValueCoder)<SKSonarValueCoder>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
FB_LINKABLE(UIColor_SonarValueCoder)
|
FB_LINKABLE(UIColor_SonarValueCoder)
|
||||||
@implementation UIColor (SonarValueCoder)
|
@implementation UIColor (SonarValueCoder)
|
||||||
|
|
||||||
+ (instancetype)fromSonarValue:(NSNumber *)sonarValue {
|
+ (instancetype)fromSonarValue:(NSNumber*)sonarValue {
|
||||||
NSUInteger intColor = [sonarValue integerValue];
|
NSUInteger intColor = [sonarValue integerValue];
|
||||||
|
|
||||||
CGFloat r, g, b, a;
|
CGFloat r, g, b, a;
|
||||||
@@ -22,10 +22,10 @@ FB_LINKABLE(UIColor_SonarValueCoder)
|
|||||||
r = CGFloat((intColor >> 16) & 0xFF) / 255;
|
r = CGFloat((intColor >> 16) & 0xFF) / 255;
|
||||||
a = CGFloat((intColor >> 24) & 0xFF) / 255;
|
a = CGFloat((intColor >> 24) & 0xFF) / 255;
|
||||||
|
|
||||||
return [[UIColor alloc] initWithRed: r green: g blue: b alpha: a];
|
return [[UIColor alloc] initWithRed:r green:g blue:b alpha:a];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, id<NSObject>> *)sonarValue {
|
- (NSDictionary<NSString*, id<NSObject>>*)sonarValue {
|
||||||
CGColorSpaceRef colorSpace = CGColorGetColorSpace([self CGColor]);
|
CGColorSpaceRef colorSpace = CGColorGetColorSpace([self CGColor]);
|
||||||
CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);
|
CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ FB_LINKABLE(UIColor_SonarValueCoder)
|
|||||||
case kCGColorSpaceModelUnknown:
|
case kCGColorSpaceModelUnknown:
|
||||||
case kCGColorSpaceModelRGB: {
|
case kCGColorSpaceModelRGB: {
|
||||||
CGFloat r, g, b, a;
|
CGFloat r, g, b, a;
|
||||||
[self getRed: &r green: &g blue: &b alpha: &a];
|
[self getRed:&r green:&g blue:&b alpha:&a];
|
||||||
|
|
||||||
red = (NSUInteger)(r * 255) & 0xFF;
|
red = (NSUInteger)(r * 255) & 0xFF;
|
||||||
green = (NSUInteger)(g * 255) & 0xFF;
|
green = (NSUInteger)(g * 255) & 0xFF;
|
||||||
@@ -45,7 +45,7 @@ FB_LINKABLE(UIColor_SonarValueCoder)
|
|||||||
|
|
||||||
case kCGColorSpaceModelMonochrome: {
|
case kCGColorSpaceModelMonochrome: {
|
||||||
CGFloat a, w;
|
CGFloat a, w;
|
||||||
[self getWhite: &w alpha: &a];
|
[self getWhite:&w alpha:&a];
|
||||||
|
|
||||||
red = green = blue = (NSUInteger)(w * 255) & 0xFF;
|
red = green = blue = (NSUInteger)(w * 255) & 0xFF;
|
||||||
alpha = (NSUInteger)(a * 255) & 0xFF;
|
alpha = (NSUInteger)(a * 255) & 0xFF;
|
||||||
@@ -56,11 +56,8 @@ FB_LINKABLE(UIColor_SonarValueCoder)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSUInteger intColor = (alpha << 24) | (red << 16) | (green << 8) | blue;
|
NSUInteger intColor = (alpha << 24) | (red << 16) | (green << 8) | blue;
|
||||||
return @{
|
return
|
||||||
@"__type__": @"color",
|
@{@"__type__" : @"color", @"__mutable__" : @NO, @"value" : @(intColor)};
|
||||||
@"__mutable__": @NO,
|
|
||||||
@"value": @(intColor)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -20,34 +20,42 @@ FB_LINKABLE(UIView_SKInvalidation)
|
|||||||
+ (void)enableInvalidation {
|
+ (void)enableInvalidation {
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
swizzleMethods([self class], @selector(setHidden:), @selector(swizzle_setHidden:));
|
swizzleMethods(
|
||||||
swizzleMethods([self class], @selector(addSubview:), @selector(swizzle_addSubview:));
|
[self class], @selector(setHidden:), @selector(swizzle_setHidden:));
|
||||||
swizzleMethods([self class], @selector(removeFromSuperview), @selector(swizzle_removeFromSuperview));
|
swizzleMethods(
|
||||||
|
[self class], @selector(addSubview:), @selector(swizzle_addSubview:));
|
||||||
|
swizzleMethods(
|
||||||
|
[self class],
|
||||||
|
@selector(removeFromSuperview),
|
||||||
|
@selector(swizzle_removeFromSuperview));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)swizzle_setHidden:(BOOL)hidden {
|
- (void)swizzle_setHidden:(BOOL)hidden {
|
||||||
[self swizzle_setHidden: hidden];
|
[self swizzle_setHidden:hidden];
|
||||||
|
|
||||||
id<SKInvalidationDelegate> delegate = [SKInvalidation sharedInstance].delegate;
|
id<SKInvalidationDelegate> delegate =
|
||||||
|
[SKInvalidation sharedInstance].delegate;
|
||||||
if (delegate != nil) {
|
if (delegate != nil) {
|
||||||
[delegate invalidateNode: self.superview];
|
[delegate invalidateNode:self.superview];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)swizzle_addSubview:(UIView *)view {
|
- (void)swizzle_addSubview:(UIView*)view {
|
||||||
[self swizzle_addSubview: view];
|
[self swizzle_addSubview:view];
|
||||||
|
|
||||||
id<SKInvalidationDelegate> delegate = [SKInvalidation sharedInstance].delegate;
|
id<SKInvalidationDelegate> delegate =
|
||||||
|
[SKInvalidation sharedInstance].delegate;
|
||||||
if (delegate != nil) {
|
if (delegate != nil) {
|
||||||
[delegate invalidateNode: view];
|
[delegate invalidateNode:view];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)swizzle_removeFromSuperview {
|
- (void)swizzle_removeFromSuperview {
|
||||||
id<SKInvalidationDelegate> delegate = [SKInvalidation sharedInstance].delegate;
|
id<SKInvalidationDelegate> delegate =
|
||||||
|
[SKInvalidation sharedInstance].delegate;
|
||||||
if (delegate != nil && self.superview != nil) {
|
if (delegate != nil && self.superview != nil) {
|
||||||
[delegate invalidateNode: self.superview];
|
[delegate invalidateNode:self.superview];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self swizzle_removeFromSuperview];
|
[self swizzle_removeFromSuperview];
|
||||||
|
|||||||
@@ -9,6 +9,6 @@
|
|||||||
|
|
||||||
#import "SKNodeDescriptor.h"
|
#import "SKNodeDescriptor.h"
|
||||||
|
|
||||||
@interface SKApplicationDescriptor : SKNodeDescriptor<UIApplication *>
|
@interface SKApplicationDescriptor : SKNodeDescriptor<UIApplication*>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,38 +9,40 @@
|
|||||||
|
|
||||||
#import "SKApplicationDescriptor.h"
|
#import "SKApplicationDescriptor.h"
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
#import "SKDescriptorMapper.h"
|
#import "SKDescriptorMapper.h"
|
||||||
#import "SKHiddenWindow.h"
|
#import "SKHiddenWindow.h"
|
||||||
#import <objc/runtime.h>
|
|
||||||
|
|
||||||
@implementation SKApplicationDescriptor
|
@implementation SKApplicationDescriptor
|
||||||
|
|
||||||
- (NSString *)identifierForNode:(UIApplication *)node {
|
- (NSString*)identifierForNode:(UIApplication*)node {
|
||||||
return [NSString stringWithFormat: @"%p", node];
|
return [NSString stringWithFormat:@"%p", node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)childCountForNode:(UIApplication *)node {
|
- (NSUInteger)childCountForNode:(UIApplication*)node {
|
||||||
return [[self visibleChildrenForNode: node] count];
|
return [[self visibleChildrenForNode:node] count];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)childForNode:(UIApplication *)node atIndex:(NSUInteger)index {
|
- (id)childForNode:(UIApplication*)node atIndex:(NSUInteger)index {
|
||||||
return [self visibleChildrenForNode: node][index];
|
return [self visibleChildrenForNode:node][index];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted forNode:(UIApplication *)node {
|
- (void)setHighlighted:(BOOL)highlighted forNode:(UIApplication*)node {
|
||||||
SKNodeDescriptor *windowDescriptor = [self descriptorForClass: [UIWindow class]];
|
SKNodeDescriptor* windowDescriptor =
|
||||||
[windowDescriptor setHighlighted: highlighted forNode: [node keyWindow]];
|
[self descriptorForClass:[UIWindow class]];
|
||||||
|
[windowDescriptor setHighlighted:highlighted forNode:[node keyWindow]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)hitTest:(SKTouch *)touch forNode:(UIApplication *)node {
|
- (void)hitTest:(SKTouch*)touch forNode:(UIApplication*)node {
|
||||||
for (NSInteger index = [self childCountForNode: node] - 1; index >= 0; index--) {
|
for (NSInteger index = [self childCountForNode:node] - 1; index >= 0;
|
||||||
UIWindow *child = [self childForNode: node atIndex: index];
|
index--) {
|
||||||
|
UIWindow* child = [self childForNode:node atIndex:index];
|
||||||
if (child.isHidden || child.alpha <= 0) {
|
if (child.isHidden || child.alpha <= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([touch containedIn: child.frame]) {
|
if ([touch containedIn:child.frame]) {
|
||||||
[touch continueWithChildIndex: index withOffset: child.frame.origin];
|
[touch continueWithChildIndex:index withOffset:child.frame.origin];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,16 +50,17 @@
|
|||||||
[touch finish];
|
[touch finish];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<UIWindow *> *)visibleChildrenForNode:(UIApplication *)node {
|
- (NSArray<UIWindow*>*)visibleChildrenForNode:(UIApplication*)node {
|
||||||
NSMutableArray<UIWindow *> *children = [NSMutableArray new];
|
NSMutableArray<UIWindow*>* children = [NSMutableArray new];
|
||||||
for (UIWindow *window in node.windows) {
|
for (UIWindow* window in node.windows) {
|
||||||
if ([window isKindOfClass: [SKHiddenWindow class]]
|
if ([window isKindOfClass:[SKHiddenWindow class]] ||
|
||||||
|| [window isKindOfClass:objc_lookUpClass("FBAccessibilityOverlayWindow")]
|
[window
|
||||||
|| [window isKindOfClass:objc_lookUpClass("UITextEffectsWindow")]
|
isKindOfClass:objc_lookUpClass("FBAccessibilityOverlayWindow")] ||
|
||||||
|| [window isKindOfClass:objc_lookUpClass("FBStatusBarTrackingWindow")]) {
|
[window isKindOfClass:objc_lookUpClass("UITextEffectsWindow")] ||
|
||||||
|
[window isKindOfClass:objc_lookUpClass("FBStatusBarTrackingWindow")]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
[children addObject: window];
|
[children addObject:window];
|
||||||
}
|
}
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,6 @@
|
|||||||
|
|
||||||
@class UIButton;
|
@class UIButton;
|
||||||
|
|
||||||
@interface SKButtonDescriptor : SKNodeDescriptor<UIButton *>
|
@interface SKButtonDescriptor : SKNodeDescriptor<UIButton*>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -15,44 +15,48 @@
|
|||||||
|
|
||||||
@implementation SKButtonDescriptor
|
@implementation SKButtonDescriptor
|
||||||
|
|
||||||
- (NSString *)identifierForNode:(UIButton *)node {
|
- (NSString*)identifierForNode:(UIButton*)node {
|
||||||
return [NSString stringWithFormat: @"%p", node];
|
return [NSString stringWithFormat:@"%p", node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)childCountForNode:(UIButton *)node {
|
- (NSUInteger)childCountForNode:(UIButton*)node {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)childForNode:(UIButton *)node atIndex:(NSUInteger)index {
|
- (id)childForNode:(UIButton*)node atIndex:(NSUInteger)index {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSDictionary *> *> *)dataForNode:(UIButton *)node {
|
- (NSArray<SKNamed<NSDictionary*>*>*)dataForNode:(UIButton*)node {
|
||||||
SKNodeDescriptor *viewDescriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* viewDescriptor = [self descriptorForClass:[UIView class]];
|
||||||
auto *viewData = [viewDescriptor dataForNode: node];
|
auto* viewData = [viewDescriptor dataForNode:node];
|
||||||
|
|
||||||
NSMutableArray *data = [NSMutableArray new];
|
NSMutableArray* data = [NSMutableArray new];
|
||||||
[data addObjectsFromArray: viewData];
|
[data addObjectsFromArray:viewData];
|
||||||
[data addObject:
|
[data addObject:[SKNamed
|
||||||
[SKNamed newWithName: @"UIButton"
|
newWithName:@"UIButton"
|
||||||
withValue: @{
|
withValue:@{
|
||||||
@"focused": @(node.focused),
|
@"focused" : @(node.focused),
|
||||||
@"enabled": SKMutableObject(@(node.enabled)),
|
@"enabled" : SKMutableObject(@(node.enabled)),
|
||||||
@"highlighted": SKMutableObject(@(node.highlighted)),
|
@"highlighted" : SKMutableObject(@(node.highlighted)),
|
||||||
@"titleEdgeInsets": SKObject(node.titleEdgeInsets),
|
@"titleEdgeInsets" : SKObject(node.titleEdgeInsets),
|
||||||
@"titleLabel": SKMutableObject(node.titleLabel.attributedText.string.stringByStandardizingPath),
|
@"titleLabel" : SKMutableObject(
|
||||||
@"currentTitleColor": SKMutableObject(node.currentTitleColor),
|
node.titleLabel.attributedText.string
|
||||||
}]
|
.stringByStandardizingPath),
|
||||||
];
|
@"currentTitleColor" :
|
||||||
|
SKMutableObject(node.currentTitleColor),
|
||||||
|
}]];
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, SKNodeUpdateData> *)dataMutationsForNode:(UIButton *)node {
|
- (NSDictionary<NSString*, SKNodeUpdateData>*)dataMutationsForNode:
|
||||||
NSDictionary *buttonMutations = @{
|
(UIButton*)node {
|
||||||
@"UIButton.titleLabel": ^(NSString *newValue) {
|
NSDictionary* buttonMutations =
|
||||||
[node setTitle: newValue forState: node.state];
|
@{@"UIButton.titleLabel" : ^(NSString* newValue){
|
||||||
},
|
[node setTitle:newValue forState:node.state];
|
||||||
|
}
|
||||||
|
,
|
||||||
@"UIButton.currentTitleColor": ^(NSNumber *newValue) {
|
@"UIButton.currentTitleColor": ^(NSNumber *newValue) {
|
||||||
[node setTitleColor: [UIColor fromSonarValue: newValue] forState: node.state];
|
[node setTitleColor: [UIColor fromSonarValue: newValue] forState: node.state];
|
||||||
},
|
},
|
||||||
@@ -62,29 +66,30 @@
|
|||||||
@"UIButton.enabled": ^(NSNumber *enabled) {
|
@"UIButton.enabled": ^(NSNumber *enabled) {
|
||||||
[node setEnabled: [enabled boolValue]];
|
[node setEnabled: [enabled boolValue]];
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
;
|
||||||
|
|
||||||
SKNodeDescriptor *viewDescriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* viewDescriptor = [self descriptorForClass:[UIView class]];
|
||||||
NSDictionary *viewMutations = [viewDescriptor dataMutationsForNode: node];
|
NSDictionary* viewMutations = [viewDescriptor dataMutationsForNode:node];
|
||||||
|
|
||||||
NSMutableDictionary *mutations = [NSMutableDictionary new];
|
NSMutableDictionary* mutations = [NSMutableDictionary new];
|
||||||
[mutations addEntriesFromDictionary: buttonMutations];
|
[mutations addEntriesFromDictionary:buttonMutations];
|
||||||
[mutations addEntriesFromDictionary: viewMutations];
|
[mutations addEntriesFromDictionary:viewMutations];
|
||||||
|
|
||||||
return mutations;
|
return mutations;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSString *> *> *)attributesForNode:(UIScrollView *)node {
|
- (NSArray<SKNamed<NSString*>*>*)attributesForNode:(UIScrollView*)node {
|
||||||
SKNodeDescriptor *descriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* descriptor = [self descriptorForClass:[UIView class]];
|
||||||
return [descriptor attributesForNode: node];
|
return [descriptor attributesForNode:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted forNode:(UIButton *)node {
|
- (void)setHighlighted:(BOOL)highlighted forNode:(UIButton*)node {
|
||||||
SKNodeDescriptor *viewDescriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* viewDescriptor = [self descriptorForClass:[UIView class]];
|
||||||
[viewDescriptor setHighlighted: highlighted forNode: node];
|
[viewDescriptor setHighlighted:highlighted forNode:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)hitTest:(SKTouch *)touch forNode:(UIButton *)node {
|
- (void)hitTest:(SKTouch*)touch forNode:(UIButton*)node {
|
||||||
[touch finish];
|
[touch finish];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,6 @@
|
|||||||
|
|
||||||
#import "SKNodeDescriptor.h"
|
#import "SKNodeDescriptor.h"
|
||||||
|
|
||||||
@interface SKScrollViewDescriptor : SKNodeDescriptor<UIScrollView *>
|
@interface SKScrollViewDescriptor : SKNodeDescriptor<UIScrollView*>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -13,55 +13,56 @@
|
|||||||
|
|
||||||
@implementation SKScrollViewDescriptor
|
@implementation SKScrollViewDescriptor
|
||||||
|
|
||||||
- (NSString *)identifierForNode:(UIScrollView *)node {
|
- (NSString*)identifierForNode:(UIScrollView*)node {
|
||||||
SKNodeDescriptor *descriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* descriptor = [self descriptorForClass:[UIView class]];
|
||||||
return [descriptor identifierForNode: node];
|
return [descriptor identifierForNode:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)childCountForNode:(UIScrollView *)node {
|
- (NSUInteger)childCountForNode:(UIScrollView*)node {
|
||||||
SKNodeDescriptor *descriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* descriptor = [self descriptorForClass:[UIView class]];
|
||||||
return [descriptor childCountForNode: node];
|
return [descriptor childCountForNode:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)childForNode:(UIScrollView *)node atIndex:(NSUInteger)index {
|
- (id)childForNode:(UIScrollView*)node atIndex:(NSUInteger)index {
|
||||||
SKNodeDescriptor *descriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* descriptor = [self descriptorForClass:[UIView class]];
|
||||||
return [descriptor childForNode: node atIndex: index];
|
return [descriptor childForNode:node atIndex:index];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)dataForNode:(UIScrollView *)node {
|
- (id)dataForNode:(UIScrollView*)node {
|
||||||
SKNodeDescriptor *descriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* descriptor = [self descriptorForClass:[UIView class]];
|
||||||
return [descriptor dataForNode:node];
|
return [descriptor dataForNode:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)dataMutationsForNode:(UIScrollView *)node {
|
- (id)dataMutationsForNode:(UIScrollView*)node {
|
||||||
SKNodeDescriptor *descriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* descriptor = [self descriptorForClass:[UIView class]];
|
||||||
return [descriptor dataMutationsForNode:node];
|
return [descriptor dataMutationsForNode:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSString *> *> *)attributesForNode:(UIScrollView *)node {
|
- (NSArray<SKNamed<NSString*>*>*)attributesForNode:(UIScrollView*)node {
|
||||||
SKNodeDescriptor *descriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* descriptor = [self descriptorForClass:[UIView class]];
|
||||||
return [descriptor attributesForNode: node];
|
return [descriptor attributesForNode:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted forNode:(UIScrollView *)node {
|
- (void)setHighlighted:(BOOL)highlighted forNode:(UIScrollView*)node {
|
||||||
SKNodeDescriptor *descriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* descriptor = [self descriptorForClass:[UIView class]];
|
||||||
[descriptor setHighlighted: highlighted forNode: node];
|
[descriptor setHighlighted:highlighted forNode:node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)hitTest:(SKTouch *)touch forNode:(UIScrollView *)node {
|
- (void)hitTest:(SKTouch*)touch forNode:(UIScrollView*)node {
|
||||||
for (NSInteger index = [self childCountForNode: node] - 1; index >= 0; index--) {
|
for (NSInteger index = [self childCountForNode:node] - 1; index >= 0;
|
||||||
id<NSObject> childNode = [self childForNode: node atIndex: index];
|
index--) {
|
||||||
|
id<NSObject> childNode = [self childForNode:node atIndex:index];
|
||||||
CGRect frame;
|
CGRect frame;
|
||||||
|
|
||||||
if ([childNode isKindOfClass: [UIViewController class]]) {
|
if ([childNode isKindOfClass:[UIViewController class]]) {
|
||||||
UIViewController *child = (UIViewController *)childNode;
|
UIViewController* child = (UIViewController*)childNode;
|
||||||
if (child.view.isHidden) {
|
if (child.view.isHidden) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame = child.view.frame;
|
frame = child.view.frame;
|
||||||
} else {
|
} else {
|
||||||
UIView *child = (UIView *)childNode;
|
UIView* child = (UIView*)childNode;
|
||||||
if (child.isHidden) {
|
if (child.isHidden) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -72,8 +73,8 @@
|
|||||||
frame.origin.x -= node.contentOffset.x;
|
frame.origin.x -= node.contentOffset.x;
|
||||||
frame.origin.y -= node.contentOffset.y;
|
frame.origin.y -= node.contentOffset.y;
|
||||||
|
|
||||||
if ([touch containedIn: frame]) {
|
if ([touch containedIn:frame]) {
|
||||||
[touch continueWithChildIndex: index withOffset: frame.origin];
|
[touch continueWithChildIndex:index withOffset:frame.origin];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,6 @@
|
|||||||
|
|
||||||
#import "SKNodeDescriptor.h"
|
#import "SKNodeDescriptor.h"
|
||||||
|
|
||||||
@interface SKViewControllerDescriptor : SKNodeDescriptor<UIViewController *>
|
@interface SKViewControllerDescriptor : SKNodeDescriptor<UIViewController*>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -13,38 +13,35 @@
|
|||||||
|
|
||||||
@implementation SKViewControllerDescriptor
|
@implementation SKViewControllerDescriptor
|
||||||
|
|
||||||
- (NSString *)identifierForNode:(UIViewController *)node {
|
- (NSString*)identifierForNode:(UIViewController*)node {
|
||||||
return [NSString stringWithFormat: @"%p", node];
|
return [NSString stringWithFormat:@"%p", node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)childCountForNode:(UIViewController *)node {
|
- (NSUInteger)childCountForNode:(UIViewController*)node {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)childForNode:(UIViewController *)node atIndex:(NSUInteger)index {
|
- (id)childForNode:(UIViewController*)node atIndex:(NSUInteger)index {
|
||||||
return node.view;
|
return node.view;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlightedForNode:(UIViewController *)node {
|
- (void)setHighlightedForNode:(UIViewController*)node {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSString *> *> *)attributesForNode:(UIViewController *)node {
|
- (NSArray<SKNamed<NSString*>*>*)attributesForNode:(UIViewController*)node {
|
||||||
return @[
|
return @[ [SKNamed newWithName:@"addr"
|
||||||
[SKNamed newWithName: @"addr"
|
withValue:[NSString stringWithFormat:@"%p", node]] ];
|
||||||
withValue: [NSString stringWithFormat: @"%p", node]]
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted forNode:(UIViewController *)node {
|
- (void)setHighlighted:(BOOL)highlighted forNode:(UIViewController*)node {
|
||||||
SKNodeDescriptor *descriptor = [self descriptorForClass: [UIView class]];
|
SKNodeDescriptor* descriptor = [self descriptorForClass:[UIView class]];
|
||||||
[descriptor setHighlighted: highlighted forNode: node.view];
|
[descriptor setHighlighted:highlighted forNode:node.view];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)hitTest:(SKTouch *)touch forNode:(UIViewController *)node {
|
- (void)hitTest:(SKTouch*)touch forNode:(UIViewController*)node {
|
||||||
[touch continueWithChildIndex: 0 withOffset: (CGPoint){ 0, 0}];
|
[touch continueWithChildIndex:0 withOffset:(CGPoint){0, 0}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#import "SKNodeDescriptor.h"
|
#import "SKNodeDescriptor.h"
|
||||||
|
|
||||||
@interface SKViewDescriptor : SKNodeDescriptor<UIView *>
|
@interface SKViewDescriptor : SKNodeDescriptor<UIView*>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -9,59 +9,61 @@
|
|||||||
|
|
||||||
#import "SKViewDescriptor.h"
|
#import "SKViewDescriptor.h"
|
||||||
|
|
||||||
|
#import <FlipperKitHighlightOverlay/SKHighlightOverlay.h>
|
||||||
|
#import <YogaKit/UIView+Yoga.h>
|
||||||
#import "SKDescriptorMapper.h"
|
#import "SKDescriptorMapper.h"
|
||||||
#import "SKNamed.h"
|
#import "SKNamed.h"
|
||||||
#import "SKObject.h"
|
#import "SKObject.h"
|
||||||
#import "SKYogaKitHelper.h"
|
#import "SKYogaKitHelper.h"
|
||||||
#import "UIColor+SKSonarValueCoder.h"
|
#import "UIColor+SKSonarValueCoder.h"
|
||||||
#import <YogaKit/UIView+Yoga.h>
|
|
||||||
#import <FlipperKitHighlightOverlay/SKHighlightOverlay.h>
|
|
||||||
|
|
||||||
@implementation SKViewDescriptor
|
@implementation SKViewDescriptor
|
||||||
|
|
||||||
static NSDictionary *YGDirectionEnumMap = nil;
|
static NSDictionary* YGDirectionEnumMap = nil;
|
||||||
static NSDictionary *YGFlexDirectionEnumMap = nil;
|
static NSDictionary* YGFlexDirectionEnumMap = nil;
|
||||||
static NSDictionary *YGJustifyEnumMap = nil;
|
static NSDictionary* YGJustifyEnumMap = nil;
|
||||||
static NSDictionary *YGAlignEnumMap = nil;
|
static NSDictionary* YGAlignEnumMap = nil;
|
||||||
static NSDictionary *YGPositionTypeEnumMap = nil;
|
static NSDictionary* YGPositionTypeEnumMap = nil;
|
||||||
static NSDictionary *YGWrapEnumMap = nil;
|
static NSDictionary* YGWrapEnumMap = nil;
|
||||||
static NSDictionary *YGOverflowEnumMap = nil;
|
static NSDictionary* YGOverflowEnumMap = nil;
|
||||||
static NSDictionary *YGDisplayEnumMap = nil;
|
static NSDictionary* YGDisplayEnumMap = nil;
|
||||||
static NSDictionary *YGUnitEnumMap = nil;
|
static NSDictionary* YGUnitEnumMap = nil;
|
||||||
|
|
||||||
- (instancetype)initWithDescriptorMapper:(SKDescriptorMapper *)mapper {
|
- (instancetype)initWithDescriptorMapper:(SKDescriptorMapper*)mapper {
|
||||||
if (self = [super initWithDescriptorMapper: mapper]) {
|
if (self = [super initWithDescriptorMapper:mapper]) {
|
||||||
initEnumDictionaries();
|
initEnumDictionaries();
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)identifierForNode:(UIView *)node {
|
- (NSString*)identifierForNode:(UIView*)node {
|
||||||
return [NSString stringWithFormat: @"%p", node];
|
return [NSString stringWithFormat:@"%p", node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)childCountForNode:(UIView *)node {
|
- (NSUInteger)childCountForNode:(UIView*)node {
|
||||||
return [[self validChildrenForNode: node] count];
|
return [[self validChildrenForNode:node] count];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)childForNode:(UIView *)node atIndex:(NSUInteger)index {
|
- (id)childForNode:(UIView*)node atIndex:(NSUInteger)index {
|
||||||
return [[self validChildrenForNode:node] objectAtIndex: index];
|
return [[self validChildrenForNode:node] objectAtIndex:index];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *)validChildrenForNode:(UIView *)node {
|
- (NSArray*)validChildrenForNode:(UIView*)node {
|
||||||
NSMutableArray *validChildren = [NSMutableArray new];
|
NSMutableArray* validChildren = [NSMutableArray new];
|
||||||
|
|
||||||
// Use UIViewControllers for children which responds to a different
|
// Use UIViewControllers for children which responds to a different
|
||||||
// viewController than their parent
|
// viewController than their parent
|
||||||
for (UIView *child in node.subviews) {
|
for (UIView* child in node.subviews) {
|
||||||
BOOL responderIsUIViewController = [child.nextResponder isKindOfClass: [UIViewController class]];
|
BOOL responderIsUIViewController =
|
||||||
|
[child.nextResponder isKindOfClass:[UIViewController class]];
|
||||||
|
|
||||||
if (!child.isHidden) {
|
if (!child.isHidden) {
|
||||||
if (responderIsUIViewController && child.nextResponder != node.nextResponder) {
|
if (responderIsUIViewController &&
|
||||||
[validChildren addObject: child.nextResponder];
|
child.nextResponder != node.nextResponder) {
|
||||||
|
[validChildren addObject:child.nextResponder];
|
||||||
} else {
|
} else {
|
||||||
[validChildren addObject: child];
|
[validChildren addObject:child];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,121 +71,165 @@ static NSDictionary *YGUnitEnumMap = nil;
|
|||||||
return validChildren;
|
return validChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSDictionary *> *> *)dataForNode:(UIView *)node {
|
- (NSArray<SKNamed<NSDictionary*>*>*)dataForNode:(UIView*)node {
|
||||||
return [NSArray arrayWithObjects:
|
return [NSArray
|
||||||
[SKNamed newWithName: @"UIView"
|
arrayWithObjects:
|
||||||
withValue: @{
|
[SKNamed
|
||||||
@"frame": SKMutableObject(node.frame),
|
newWithName:@"UIView"
|
||||||
@"bounds": SKObject(node.bounds),
|
withValue:@{
|
||||||
@"center": SKObject(node.center),
|
@"frame" : SKMutableObject(node.frame),
|
||||||
@"layoutMargins": SKObject(node.layoutMargins),
|
@"bounds" : SKObject(node.bounds),
|
||||||
@"clipsToBounds": @(node.clipsToBounds),
|
@"center" : SKObject(node.center),
|
||||||
@"alpha": SKMutableObject(@(node.alpha)),
|
@"layoutMargins" : SKObject(node.layoutMargins),
|
||||||
@"tag": @(node.tag),
|
@"clipsToBounds" : @(node.clipsToBounds),
|
||||||
@"backgroundColor": SKMutableObject(node.backgroundColor)
|
@"alpha" : SKMutableObject(@(node.alpha)),
|
||||||
|
@"tag" : @(node.tag),
|
||||||
|
@"backgroundColor" : SKMutableObject(node.backgroundColor)
|
||||||
}],
|
}],
|
||||||
[SKNamed newWithName: @"CALayer"
|
[SKNamed
|
||||||
withValue: @{
|
newWithName:@"CALayer"
|
||||||
@"shadowColor": SKMutableObject([UIColor colorWithCGColor:node.layer.shadowColor]),
|
withValue:@{
|
||||||
@"shadowOpacity": SKMutableObject(@(node.layer.shadowOpacity)),
|
@"shadowColor" : SKMutableObject(
|
||||||
@"shadowRadius": SKMutableObject(@(node.layer.shadowRadius)),
|
[UIColor colorWithCGColor:node.layer.shadowColor]),
|
||||||
@"shadowOffset": SKMutableObject(node.layer.shadowOffset),
|
@"shadowOpacity" :
|
||||||
@"backgroundColor": SKMutableObject([UIColor colorWithCGColor:node.layer.backgroundColor]),
|
SKMutableObject(@(node.layer.shadowOpacity)),
|
||||||
@"borderColor": SKMutableObject([UIColor colorWithCGColor:node.layer.borderColor]),
|
@"shadowRadius" : SKMutableObject(@(node.layer.shadowRadius)),
|
||||||
@"borderWidth": SKMutableObject(@(node.layer.borderWidth)),
|
@"shadowOffset" : SKMutableObject(node.layer.shadowOffset),
|
||||||
@"cornerRadius": SKMutableObject(@(node.layer.cornerRadius)),
|
@"backgroundColor" : SKMutableObject(
|
||||||
@"masksToBounds": SKMutableObject(@(node.layer.masksToBounds)),
|
[UIColor colorWithCGColor:node.layer.backgroundColor]),
|
||||||
|
@"borderColor" : SKMutableObject(
|
||||||
|
[UIColor colorWithCGColor:node.layer.borderColor]),
|
||||||
|
@"borderWidth" : SKMutableObject(@(node.layer.borderWidth)),
|
||||||
|
@"cornerRadius" : SKMutableObject(@(node.layer.cornerRadius)),
|
||||||
|
@"masksToBounds" :
|
||||||
|
SKMutableObject(@(node.layer.masksToBounds)),
|
||||||
}],
|
}],
|
||||||
[SKNamed newWithName: @"Accessibility"
|
[SKNamed newWithName:@"Accessibility"
|
||||||
withValue: @{
|
withValue:@{
|
||||||
@"isAccessibilityElement": SKMutableObject(@(node.isAccessibilityElement)),
|
@"isAccessibilityElement" :
|
||||||
@"accessibilityLabel": SKMutableObject(node.accessibilityLabel ?: @""),
|
SKMutableObject(@(node.isAccessibilityElement)),
|
||||||
@"accessibilityIdentifier": SKMutableObject(node.accessibilityIdentifier ?: @""),
|
@"accessibilityLabel" :
|
||||||
@"accessibilityValue": SKMutableObject(node.accessibilityValue ?: @""),
|
SKMutableObject(node.accessibilityLabel ?: @""),
|
||||||
@"accessibilityHint": SKMutableObject(node.accessibilityHint ?: @""),
|
@"accessibilityIdentifier" :
|
||||||
@"accessibilityTraits": AccessibilityTraitsDict(node.accessibilityTraits),
|
SKMutableObject(node.accessibilityIdentifier ?: @""),
|
||||||
@"accessibilityViewIsModal": SKMutableObject(@(node.accessibilityViewIsModal)),
|
@"accessibilityValue" :
|
||||||
@"shouldGroupAccessibilityChildren": SKMutableObject(@(node.shouldGroupAccessibilityChildren)),
|
SKMutableObject(node.accessibilityValue ?: @""),
|
||||||
|
@"accessibilityHint" :
|
||||||
|
SKMutableObject(node.accessibilityHint ?: @""),
|
||||||
|
@"accessibilityTraits" :
|
||||||
|
AccessibilityTraitsDict(node.accessibilityTraits),
|
||||||
|
@"accessibilityViewIsModal" :
|
||||||
|
SKMutableObject(@(node.accessibilityViewIsModal)),
|
||||||
|
@"shouldGroupAccessibilityChildren" : SKMutableObject(
|
||||||
|
@(node.shouldGroupAccessibilityChildren)),
|
||||||
}],
|
}],
|
||||||
!node.isYogaEnabled ? nil :
|
!node.isYogaEnabled
|
||||||
[SKNamed newWithName: @"YGLayout"
|
? nil
|
||||||
withValue: @{
|
: [SKNamed
|
||||||
@"direction": SKMutableObject(YGDirectionEnumMap[@(node.yoga.direction)]),
|
newWithName:@"YGLayout"
|
||||||
@"justifyContent": SKMutableObject(YGJustifyEnumMap[@(node.yoga.justifyContent)]),
|
withValue:@{
|
||||||
@"aligns": @{
|
@"direction" : SKMutableObject(
|
||||||
@"alignContent": SKMutableObject(YGAlignEnumMap[@(node.yoga.alignContent)]),
|
YGDirectionEnumMap[@(node.yoga.direction)]),
|
||||||
@"alignItems": SKMutableObject(YGAlignEnumMap[@(node.yoga.alignItems)]),
|
@"justifyContent" : SKMutableObject(
|
||||||
@"alignSelf": SKMutableObject(YGAlignEnumMap[@(node.yoga.alignSelf)]),
|
YGJustifyEnumMap[@(node.yoga.justifyContent)]),
|
||||||
|
@"aligns" : @{
|
||||||
|
@"alignContent" : SKMutableObject(
|
||||||
|
YGAlignEnumMap[@(node.yoga.alignContent)]),
|
||||||
|
@"alignItems" : SKMutableObject(
|
||||||
|
YGAlignEnumMap[@(node.yoga.alignItems)]),
|
||||||
|
@"alignSelf" : SKMutableObject(
|
||||||
|
YGAlignEnumMap[@(node.yoga.alignSelf)]),
|
||||||
},
|
},
|
||||||
@"position": @{
|
@"position" : @{
|
||||||
@"type": SKMutableObject(YGPositionTypeEnumMap[@(node.yoga.position)]),
|
@"type" : SKMutableObject(
|
||||||
@"left": SKYGValueObject(node.yoga.left),
|
YGPositionTypeEnumMap[@(node.yoga.position)]),
|
||||||
@"top": SKYGValueObject(node.yoga.top),
|
@"left" : SKYGValueObject(node.yoga.left),
|
||||||
@"right": SKYGValueObject(node.yoga.right),
|
@"top" : SKYGValueObject(node.yoga.top),
|
||||||
@"bottom": SKYGValueObject(node.yoga.bottom),
|
@"right" : SKYGValueObject(node.yoga.right),
|
||||||
@"start": SKYGValueObject(node.yoga.start),
|
@"bottom" : SKYGValueObject(node.yoga.bottom),
|
||||||
@"end": SKYGValueObject(node.yoga.end),
|
@"start" : SKYGValueObject(node.yoga.start),
|
||||||
|
@"end" : SKYGValueObject(node.yoga.end),
|
||||||
},
|
},
|
||||||
@"overflow": SKMutableObject(YGOverflowEnumMap[@(node.yoga.overflow)]),
|
@"overflow" : SKMutableObject(
|
||||||
@"display": SKMutableObject(YGDisplayEnumMap[@(node.yoga.display)]),
|
YGOverflowEnumMap[@(node.yoga.overflow)]),
|
||||||
@"flex": @{
|
@"display" : SKMutableObject(
|
||||||
@"flexDirection": SKMutableObject(YGFlexDirectionEnumMap[@(node.yoga.flexDirection)]),
|
YGDisplayEnumMap[@(node.yoga.display)]),
|
||||||
@"flexWrap": SKMutableObject(YGWrapEnumMap[@(node.yoga.flexWrap)]),
|
@"flex" : @{
|
||||||
@"flexGrow": SKMutableObject(@(node.yoga.flexGrow)),
|
@"flexDirection" :
|
||||||
@"flexShrink": SKMutableObject(@(node.yoga.flexShrink)),
|
SKMutableObject(YGFlexDirectionEnumMap[
|
||||||
@"flexBasis": SKYGValueObject(node.yoga.flexBasis),
|
@(node.yoga.flexDirection)]),
|
||||||
|
@"flexWrap" : SKMutableObject(
|
||||||
|
YGWrapEnumMap[@(node.yoga.flexWrap)]),
|
||||||
|
@"flexGrow" : SKMutableObject(@(node.yoga.flexGrow)),
|
||||||
|
@"flexShrink" :
|
||||||
|
SKMutableObject(@(node.yoga.flexShrink)),
|
||||||
|
@"flexBasis" : SKYGValueObject(node.yoga.flexBasis),
|
||||||
},
|
},
|
||||||
@"margin": @{
|
@"margin" : @{
|
||||||
@"left": SKYGValueObject(node.yoga.marginLeft),
|
@"left" : SKYGValueObject(node.yoga.marginLeft),
|
||||||
@"top": SKYGValueObject(node.yoga.marginTop),
|
@"top" : SKYGValueObject(node.yoga.marginTop),
|
||||||
@"right": SKYGValueObject(node.yoga.marginRight),
|
@"right" : SKYGValueObject(node.yoga.marginRight),
|
||||||
@"bottom": SKYGValueObject(node.yoga.marginBottom),
|
@"bottom" : SKYGValueObject(node.yoga.marginBottom),
|
||||||
@"start": SKYGValueObject(node.yoga.marginStart),
|
@"start" : SKYGValueObject(node.yoga.marginStart),
|
||||||
@"end": SKYGValueObject(node.yoga.marginEnd),
|
@"end" : SKYGValueObject(node.yoga.marginEnd),
|
||||||
@"horizontal": SKYGValueObject(node.yoga.marginHorizontal),
|
@"horizontal" :
|
||||||
@"vertical": SKYGValueObject(node.yoga.marginVertical),
|
SKYGValueObject(node.yoga.marginHorizontal),
|
||||||
@"all": SKYGValueObject(node.yoga.margin),
|
@"vertical" :
|
||||||
|
SKYGValueObject(node.yoga.marginVertical),
|
||||||
|
@"all" : SKYGValueObject(node.yoga.margin),
|
||||||
},
|
},
|
||||||
@"padding": @{
|
@"padding" : @{
|
||||||
@"left": SKYGValueObject(node.yoga.paddingLeft),
|
@"left" : SKYGValueObject(node.yoga.paddingLeft),
|
||||||
@"top": SKYGValueObject(node.yoga.paddingTop),
|
@"top" : SKYGValueObject(node.yoga.paddingTop),
|
||||||
@"right": SKYGValueObject(node.yoga.paddingRight),
|
@"right" : SKYGValueObject(node.yoga.paddingRight),
|
||||||
@"bottom": SKYGValueObject(node.yoga.paddingBottom),
|
@"bottom" : SKYGValueObject(node.yoga.paddingBottom),
|
||||||
@"start": SKYGValueObject(node.yoga.paddingStart),
|
@"start" : SKYGValueObject(node.yoga.paddingStart),
|
||||||
@"end": SKYGValueObject(node.yoga.paddingEnd),
|
@"end" : SKYGValueObject(node.yoga.paddingEnd),
|
||||||
@"horizontal": SKYGValueObject(node.yoga.paddingHorizontal),
|
@"horizontal" :
|
||||||
@"vertical": SKYGValueObject(node.yoga.paddingVertical),
|
SKYGValueObject(node.yoga.paddingHorizontal),
|
||||||
@"all": SKYGValueObject(node.yoga.padding),
|
@"vertical" :
|
||||||
|
SKYGValueObject(node.yoga.paddingVertical),
|
||||||
|
@"all" : SKYGValueObject(node.yoga.padding),
|
||||||
},
|
},
|
||||||
@"border": @{
|
@"border" : @{
|
||||||
@"leftWidth": SKMutableObject(@(node.yoga.borderLeftWidth)),
|
@"leftWidth" :
|
||||||
@"topWidth": SKMutableObject(@(node.yoga.borderTopWidth)),
|
SKMutableObject(@(node.yoga.borderLeftWidth)),
|
||||||
@"rightWidth": SKMutableObject(@(node.yoga.borderRightWidth)),
|
@"topWidth" :
|
||||||
@"bottomWidth": SKMutableObject(@(node.yoga.borderBottomWidth)),
|
SKMutableObject(@(node.yoga.borderTopWidth)),
|
||||||
@"startWidth": SKMutableObject(@(node.yoga.borderStartWidth)),
|
@"rightWidth" :
|
||||||
@"endWidth": SKMutableObject(@(node.yoga.borderEndWidth)),
|
SKMutableObject(@(node.yoga.borderRightWidth)),
|
||||||
@"all": SKMutableObject(@(node.yoga.borderWidth)),
|
@"bottomWidth" :
|
||||||
|
SKMutableObject(@(node.yoga.borderBottomWidth)),
|
||||||
|
@"startWidth" :
|
||||||
|
SKMutableObject(@(node.yoga.borderStartWidth)),
|
||||||
|
@"endWidth" :
|
||||||
|
SKMutableObject(@(node.yoga.borderEndWidth)),
|
||||||
|
@"all" : SKMutableObject(@(node.yoga.borderWidth)),
|
||||||
},
|
},
|
||||||
@"dimensions": @{
|
@"dimensions" : @{
|
||||||
@"width": SKYGValueObject(node.yoga.width),
|
@"width" : SKYGValueObject(node.yoga.width),
|
||||||
@"height": SKYGValueObject(node.yoga.height),
|
@"height" : SKYGValueObject(node.yoga.height),
|
||||||
@"minWidth": SKYGValueObject(node.yoga.minWidth),
|
@"minWidth" : SKYGValueObject(node.yoga.minWidth),
|
||||||
@"minHeight": SKYGValueObject(node.yoga.minHeight),
|
@"minHeight" : SKYGValueObject(node.yoga.minHeight),
|
||||||
@"maxWidth": SKYGValueObject(node.yoga.maxWidth),
|
@"maxWidth" : SKYGValueObject(node.yoga.maxWidth),
|
||||||
@"maxHeight": SKYGValueObject(node.yoga.maxHeight),
|
@"maxHeight" : SKYGValueObject(node.yoga.maxHeight),
|
||||||
},
|
},
|
||||||
@"aspectRatio": SKMutableObject(@(node.yoga.aspectRatio)),
|
@"aspectRatio" :
|
||||||
@"resolvedDirection": SKObject(YGDirectionEnumMap[@(node.yoga.resolvedDirection)]),
|
SKMutableObject(@(node.yoga.aspectRatio)),
|
||||||
|
@"resolvedDirection" : SKObject(
|
||||||
|
YGDirectionEnumMap[@(node.yoga.resolvedDirection)]),
|
||||||
}],
|
}],
|
||||||
nil];
|
nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, SKNodeUpdateData> *)dataMutationsForNode:(UIView *)node {
|
- (NSDictionary<NSString*, SKNodeUpdateData>*)dataMutationsForNode:
|
||||||
|
(UIView*)node {
|
||||||
return @{
|
return @{
|
||||||
// UIView
|
// UIView
|
||||||
@"UIView.alpha": ^(NSNumber *value) {
|
@"UIView.alpha" : ^(NSNumber* value){
|
||||||
node.alpha = [value floatValue];
|
node.alpha = [value floatValue];
|
||||||
},
|
}
|
||||||
|
,
|
||||||
@"UIView.backgroundColor": ^(NSNumber *value) {
|
@"UIView.backgroundColor": ^(NSNumber *value) {
|
||||||
node.backgroundColor = [UIColor fromSonarValue: value];
|
node.backgroundColor = [UIColor fromSonarValue: value];
|
||||||
},
|
},
|
||||||
@@ -415,43 +461,43 @@ static NSDictionary *YGUnitEnumMap = nil;
|
|||||||
@"Accessibility.shouldGroupAccessibilityChildren": ^(NSNumber *value) {
|
@"Accessibility.shouldGroupAccessibilityChildren": ^(NSNumber *value) {
|
||||||
node.shouldGroupAccessibilityChildren = [value boolValue];
|
node.shouldGroupAccessibilityChildren = [value boolValue];
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<SKNamed<NSString *> *> *)attributesForNode:(UIView *)node {
|
- (NSArray<SKNamed<NSString*>*>*)attributesForNode:(UIView*)node {
|
||||||
return @[
|
return @[ [SKNamed newWithName:@"addr"
|
||||||
[SKNamed newWithName: @"addr"
|
withValue:[NSString stringWithFormat:@"%p", node]] ];
|
||||||
withValue: [NSString stringWithFormat: @"%p", node]]
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted forNode:(UIView *)node {
|
- (void)setHighlighted:(BOOL)highlighted forNode:(UIView*)node {
|
||||||
SKHighlightOverlay *overlay = [SKHighlightOverlay sharedInstance];
|
SKHighlightOverlay* overlay = [SKHighlightOverlay sharedInstance];
|
||||||
if (highlighted == YES) {
|
if (highlighted == YES) {
|
||||||
[overlay mountInView: node withFrame: node.bounds];
|
[overlay mountInView:node withFrame:node.bounds];
|
||||||
} else {
|
} else {
|
||||||
[overlay unmount];
|
[overlay unmount];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)hitTest:(SKTouch *)touch forNode:(UIView *)node {
|
- (void)hitTest:(SKTouch*)touch forNode:(UIView*)node {
|
||||||
for (NSInteger index = [self childCountForNode: node] - 1; index >= 0; index--) {
|
for (NSInteger index = [self childCountForNode:node] - 1; index >= 0;
|
||||||
id<NSObject> childNode = [self childForNode: node atIndex: index];
|
index--) {
|
||||||
UIView *viewForNode = nil;
|
id<NSObject> childNode = [self childForNode:node atIndex:index];
|
||||||
|
UIView* viewForNode = nil;
|
||||||
|
|
||||||
if ([childNode isKindOfClass: [UIViewController class]]) {
|
if ([childNode isKindOfClass:[UIViewController class]]) {
|
||||||
UIViewController *child = (UIViewController *)childNode;
|
UIViewController* child = (UIViewController*)childNode;
|
||||||
viewForNode = child.view;
|
viewForNode = child.view;
|
||||||
} else {
|
} else {
|
||||||
viewForNode = (UIView *)childNode;
|
viewForNode = (UIView*)childNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewForNode.isHidden || viewForNode.alpha <= 0) {
|
if (viewForNode.isHidden || viewForNode.alpha <= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([touch containedIn: viewForNode.frame]) {
|
if ([touch containedIn:viewForNode.frame]) {
|
||||||
[touch continueWithChildIndex: index withOffset: viewForNode.frame.origin ];
|
[touch continueWithChildIndex:index withOffset:viewForNode.frame.origin];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,72 +509,72 @@ static void initEnumDictionaries() {
|
|||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
YGDirectionEnumMap = @{
|
YGDirectionEnumMap = @{
|
||||||
@(YGDirectionInherit): @"inherit",
|
@(YGDirectionInherit) : @"inherit",
|
||||||
@(YGDirectionLTR): @"LTR",
|
@(YGDirectionLTR) : @"LTR",
|
||||||
@(YGDirectionRTL): @"RTL",
|
@(YGDirectionRTL) : @"RTL",
|
||||||
};
|
};
|
||||||
|
|
||||||
YGFlexDirectionEnumMap = @{
|
YGFlexDirectionEnumMap = @{
|
||||||
@(YGFlexDirectionColumn): @"column",
|
@(YGFlexDirectionColumn) : @"column",
|
||||||
@(YGFlexDirectionColumnReverse): @"column-reverse",
|
@(YGFlexDirectionColumnReverse) : @"column-reverse",
|
||||||
@(YGFlexDirectionRow): @"row",
|
@(YGFlexDirectionRow) : @"row",
|
||||||
@(YGFlexDirectionRowReverse): @"row-reverse",
|
@(YGFlexDirectionRowReverse) : @"row-reverse",
|
||||||
};
|
};
|
||||||
|
|
||||||
YGJustifyEnumMap = @{
|
YGJustifyEnumMap = @{
|
||||||
@(YGJustifyFlexStart): @"flex-start",
|
@(YGJustifyFlexStart) : @"flex-start",
|
||||||
@(YGJustifyCenter): @"center",
|
@(YGJustifyCenter) : @"center",
|
||||||
@(YGJustifyFlexEnd): @"flex-end",
|
@(YGJustifyFlexEnd) : @"flex-end",
|
||||||
@(YGJustifySpaceBetween): @"space-between",
|
@(YGJustifySpaceBetween) : @"space-between",
|
||||||
@(YGJustifySpaceAround): @"space-around",
|
@(YGJustifySpaceAround) : @"space-around",
|
||||||
};
|
};
|
||||||
|
|
||||||
YGAlignEnumMap = @{
|
YGAlignEnumMap = @{
|
||||||
@(YGAlignAuto): @"auto",
|
@(YGAlignAuto) : @"auto",
|
||||||
@(YGAlignFlexStart): @"flex-start",
|
@(YGAlignFlexStart) : @"flex-start",
|
||||||
@(YGAlignCenter): @"end",
|
@(YGAlignCenter) : @"end",
|
||||||
@(YGAlignFlexEnd): @"flex-end",
|
@(YGAlignFlexEnd) : @"flex-end",
|
||||||
@(YGAlignStretch): @"stretch",
|
@(YGAlignStretch) : @"stretch",
|
||||||
@(YGAlignBaseline): @"baseline",
|
@(YGAlignBaseline) : @"baseline",
|
||||||
@(YGAlignSpaceBetween): @"space-between",
|
@(YGAlignSpaceBetween) : @"space-between",
|
||||||
@(YGAlignSpaceAround): @"space-around",
|
@(YGAlignSpaceAround) : @"space-around",
|
||||||
};
|
};
|
||||||
|
|
||||||
YGPositionTypeEnumMap = @{
|
YGPositionTypeEnumMap = @{
|
||||||
@(YGPositionTypeRelative): @"relative",
|
@(YGPositionTypeRelative) : @"relative",
|
||||||
@(YGPositionTypeAbsolute): @"absolute",
|
@(YGPositionTypeAbsolute) : @"absolute",
|
||||||
};
|
};
|
||||||
|
|
||||||
YGWrapEnumMap = @{
|
YGWrapEnumMap = @{
|
||||||
@(YGWrapNoWrap): @"no-wrap",
|
@(YGWrapNoWrap) : @"no-wrap",
|
||||||
@(YGWrapWrap): @"wrap",
|
@(YGWrapWrap) : @"wrap",
|
||||||
@(YGWrapWrapReverse): @"wrap-reverse",
|
@(YGWrapWrapReverse) : @"wrap-reverse",
|
||||||
};
|
};
|
||||||
|
|
||||||
YGOverflowEnumMap = @{
|
YGOverflowEnumMap = @{
|
||||||
@(YGOverflowVisible): @"visible",
|
@(YGOverflowVisible) : @"visible",
|
||||||
@(YGOverflowHidden): @"hidden",
|
@(YGOverflowHidden) : @"hidden",
|
||||||
@(YGOverflowScroll): @"scroll",
|
@(YGOverflowScroll) : @"scroll",
|
||||||
};
|
};
|
||||||
|
|
||||||
YGDisplayEnumMap = @{
|
YGDisplayEnumMap = @{
|
||||||
@(YGDisplayFlex): @"flex",
|
@(YGDisplayFlex) : @"flex",
|
||||||
@(YGDisplayNone): @"none",
|
@(YGDisplayNone) : @"none",
|
||||||
};
|
};
|
||||||
|
|
||||||
YGUnitEnumMap = @{
|
YGUnitEnumMap = @{
|
||||||
@(YGUnitUndefined): @"undefined",
|
@(YGUnitUndefined) : @"undefined",
|
||||||
@(YGUnitPoint): @"point",
|
@(YGUnitPoint) : @"point",
|
||||||
@(YGUnitPercent): @"percent",
|
@(YGUnitPercent) : @"percent",
|
||||||
@(YGUnitAuto): @"auto",
|
@(YGUnitAuto) : @"auto",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSDictionary *SKYGValueObject(YGValue value) {
|
static NSDictionary* SKYGValueObject(YGValue value) {
|
||||||
return @{
|
return @{
|
||||||
@"value": SKMutableObject(@(value.value)),
|
@"value" : SKMutableObject(@(value.value)),
|
||||||
@"unit": SKMutableObject(YGUnitEnumMap[@(value.unit)]),
|
@"unit" : SKMutableObject(YGUnitEnumMap[@(value.unit)]),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,36 +583,60 @@ static NSDictionary *SKYGValueObject(YGValue value) {
|
|||||||
e.g. originalTraits = UIAccessibilityTraitButton | UIAccessibilityTraitSelected
|
e.g. originalTraits = UIAccessibilityTraitButton | UIAccessibilityTraitSelected
|
||||||
toggleTraits = UIAccessibilityTraitImage
|
toggleTraits = UIAccessibilityTraitImage
|
||||||
toggleValue = YES
|
toggleValue = YES
|
||||||
return value = UIAccessibilityTraitButton | UIAccessibilityTraitSelected | UIAccessibilityTraitImage
|
return value = UIAccessibilityTraitButton | UIAccessibilityTraitSelected |
|
||||||
|
UIAccessibilityTraitImage
|
||||||
*/
|
*/
|
||||||
static UIAccessibilityTraits AccessibilityTraitsToggle(UIAccessibilityTraits originalTraits, UIAccessibilityTraits toggleTraits, BOOL toggleValue) {
|
static UIAccessibilityTraits AccessibilityTraitsToggle(
|
||||||
// NEGATE all bits of toggleTraits from originalTraits and OR it against either toggleTraits or 0 (UIAccessibilityTraitNone) based on toggleValue
|
UIAccessibilityTraits originalTraits,
|
||||||
UIAccessibilityTraits bitsValue = toggleValue ? toggleTraits : UIAccessibilityTraitNone;
|
UIAccessibilityTraits toggleTraits,
|
||||||
|
BOOL toggleValue) {
|
||||||
|
// NEGATE all bits of toggleTraits from originalTraits and OR it against
|
||||||
|
// either toggleTraits or 0 (UIAccessibilityTraitNone) based on toggleValue
|
||||||
|
UIAccessibilityTraits bitsValue =
|
||||||
|
toggleValue ? toggleTraits : UIAccessibilityTraitNone;
|
||||||
return (originalTraits & ~(toggleTraits)) | bitsValue;
|
return (originalTraits & ~(toggleTraits)) | bitsValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSDictionary *AccessibilityTraitsDict(UIAccessibilityTraits accessibilityTraits) {
|
static NSDictionary* AccessibilityTraitsDict(
|
||||||
NSMutableDictionary *traitsDict = [NSMutableDictionary new];
|
UIAccessibilityTraits accessibilityTraits) {
|
||||||
|
NSMutableDictionary* traitsDict = [NSMutableDictionary new];
|
||||||
[traitsDict addEntriesFromDictionary:@{
|
[traitsDict addEntriesFromDictionary:@{
|
||||||
@"UIAccessibilityTraitButton": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitButton))),
|
@"UIAccessibilityTraitButton" : SKMutableObject(
|
||||||
@"UIAccessibilityTraitLink": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitLink))),
|
@(!!(accessibilityTraits & UIAccessibilityTraitButton))),
|
||||||
@"UIAccessibilityTraitHeader": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitHeader))),
|
@"UIAccessibilityTraitLink" :
|
||||||
@"UIAccessibilityTraitSearchField": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitSearchField))),
|
SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitLink))),
|
||||||
@"UIAccessibilityTraitImage": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitImage))),
|
@"UIAccessibilityTraitHeader" : SKMutableObject(
|
||||||
@"UIAccessibilityTraitSelected": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitSelected))),
|
@(!!(accessibilityTraits & UIAccessibilityTraitHeader))),
|
||||||
@"UIAccessibilityTraitPlaysSound": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitPlaysSound))),
|
@"UIAccessibilityTraitSearchField" : SKMutableObject(
|
||||||
@"UIAccessibilityTraitKeyboardKey": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitKeyboardKey))),
|
@(!!(accessibilityTraits & UIAccessibilityTraitSearchField))),
|
||||||
@"UIAccessibilityTraitStaticText": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitStaticText))),
|
@"UIAccessibilityTraitImage" :
|
||||||
@"UIAccessibilityTraitSummaryElement": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitSummaryElement))),
|
SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitImage))),
|
||||||
@"UIAccessibilityTraitNotEnabled": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitNotEnabled))),
|
@"UIAccessibilityTraitSelected" : SKMutableObject(
|
||||||
@"UIAccessibilityTraitUpdatesFrequently": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitUpdatesFrequently))),
|
@(!!(accessibilityTraits & UIAccessibilityTraitSelected))),
|
||||||
@"UIAccessibilityTraitStartsMediaSession": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitStartsMediaSession))),
|
@"UIAccessibilityTraitPlaysSound" : SKMutableObject(
|
||||||
@"UIAccessibilityTraitAdjustable": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitAdjustable))),
|
@(!!(accessibilityTraits & UIAccessibilityTraitPlaysSound))),
|
||||||
@"UIAccessibilityTraitAllowsDirectInteraction": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitAllowsDirectInteraction))),
|
@"UIAccessibilityTraitKeyboardKey" : SKMutableObject(
|
||||||
@"UIAccessibilityTraitCausesPageTurn": SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitCausesPageTurn))),
|
@(!!(accessibilityTraits & UIAccessibilityTraitKeyboardKey))),
|
||||||
|
@"UIAccessibilityTraitStaticText" : SKMutableObject(
|
||||||
|
@(!!(accessibilityTraits & UIAccessibilityTraitStaticText))),
|
||||||
|
@"UIAccessibilityTraitSummaryElement" : SKMutableObject(
|
||||||
|
@(!!(accessibilityTraits & UIAccessibilityTraitSummaryElement))),
|
||||||
|
@"UIAccessibilityTraitNotEnabled" : SKMutableObject(
|
||||||
|
@(!!(accessibilityTraits & UIAccessibilityTraitNotEnabled))),
|
||||||
|
@"UIAccessibilityTraitUpdatesFrequently" : SKMutableObject(
|
||||||
|
@(!!(accessibilityTraits & UIAccessibilityTraitUpdatesFrequently))),
|
||||||
|
@"UIAccessibilityTraitStartsMediaSession" : SKMutableObject(
|
||||||
|
@(!!(accessibilityTraits & UIAccessibilityTraitStartsMediaSession))),
|
||||||
|
@"UIAccessibilityTraitAdjustable" : SKMutableObject(
|
||||||
|
@(!!(accessibilityTraits & UIAccessibilityTraitAdjustable))),
|
||||||
|
@"UIAccessibilityTraitAllowsDirectInteraction" : SKMutableObject(@(
|
||||||
|
!!(accessibilityTraits & UIAccessibilityTraitAllowsDirectInteraction))),
|
||||||
|
@"UIAccessibilityTraitCausesPageTurn" : SKMutableObject(
|
||||||
|
@(!!(accessibilityTraits & UIAccessibilityTraitCausesPageTurn))),
|
||||||
}];
|
}];
|
||||||
if (@available(iOS 10.0, *)) {
|
if (@available(iOS 10.0, *)) {
|
||||||
traitsDict[@"UIAccessibilityTraitTabBar"] = SKMutableObject(@(!!(accessibilityTraits & UIAccessibilityTraitTabBar)));
|
traitsDict[@"UIAccessibilityTraitTabBar"] = SKMutableObject(
|
||||||
|
@(!!(accessibilityTraits & UIAccessibilityTraitTabBar)));
|
||||||
}
|
}
|
||||||
return traitsDict;
|
return traitsDict;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
as keys in C++ STL
|
as keys in C++ STL
|
||||||
*/
|
*/
|
||||||
class SKObjectHash {
|
class SKObjectHash {
|
||||||
public:
|
public:
|
||||||
size_t operator()(const NSObject *x) const {
|
size_t operator()(const NSObject* x) const {
|
||||||
return (size_t)[x hash];
|
return (size_t)[x hash];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,12 +16,16 @@ void swizzleMethods(Class cls, SEL original, SEL swissled) {
|
|||||||
Method originalMethod = class_getInstanceMethod(cls, original);
|
Method originalMethod = class_getInstanceMethod(cls, original);
|
||||||
Method swissledMethod = class_getInstanceMethod(cls, swissled);
|
Method swissledMethod = class_getInstanceMethod(cls, swissled);
|
||||||
|
|
||||||
BOOL didAddMethod = class_addMethod(cls, original,
|
BOOL didAddMethod = class_addMethod(
|
||||||
|
cls,
|
||||||
|
original,
|
||||||
method_getImplementation(swissledMethod),
|
method_getImplementation(swissledMethod),
|
||||||
method_getTypeEncoding(swissledMethod));
|
method_getTypeEncoding(swissledMethod));
|
||||||
|
|
||||||
if (didAddMethod) {
|
if (didAddMethod) {
|
||||||
class_replaceMethod(cls, swissled,
|
class_replaceMethod(
|
||||||
|
cls,
|
||||||
|
swissled,
|
||||||
method_getImplementation(originalMethod),
|
method_getImplementation(originalMethod),
|
||||||
method_getTypeEncoding(originalMethod));
|
method_getTypeEncoding(originalMethod));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -8,24 +8,30 @@
|
|||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
#define APPLY_ENUM_TO_YOGA_PROPERTY(varName, enumName) \
|
#define APPLY_ENUM_TO_YOGA_PROPERTY(varName, enumName) \
|
||||||
^(NSString *newValue) { \
|
^(NSString * newValue) { \
|
||||||
NSNumber *varName = [[enumName##EnumMap allKeysForObject:newValue] lastObject]; \
|
NSNumber* varName = \
|
||||||
if (varName == nil) { return; } \
|
[[enumName##EnumMap allKeysForObject:newValue] lastObject]; \
|
||||||
node.yoga.varName = (enumName)[varName unsignedIntegerValue]; \
|
if (varName == nil) { \
|
||||||
}
|
return; \
|
||||||
|
} \
|
||||||
|
node.yoga.varName = (enumName)[varName unsignedIntegerValue]; \
|
||||||
|
}
|
||||||
|
|
||||||
#define APPLY_VALUE_TO_YGVALUE(varName) \
|
#define APPLY_VALUE_TO_YGVALUE(varName) \
|
||||||
^(NSNumber *value) { \
|
^(NSNumber * value) { \
|
||||||
YGValue newValue = node.yoga.varName; \
|
YGValue newValue = node.yoga.varName; \
|
||||||
newValue.value = [value floatValue]; \
|
newValue.value = [value floatValue]; \
|
||||||
node.yoga.varName = newValue; \
|
node.yoga.varName = newValue; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define APPLY_UNIT_TO_YGVALUE(varName, enumName) \
|
#define APPLY_UNIT_TO_YGVALUE(varName, enumName) \
|
||||||
^(NSString *value) { \
|
^(NSString * value) { \
|
||||||
NSNumber *varName = [[enumName##EnumMap allKeysForObject:value] lastObject]; \
|
NSNumber* varName = \
|
||||||
if (varName == nil) { return; } \
|
[[enumName##EnumMap allKeysForObject:value] lastObject]; \
|
||||||
YGValue newValue = node.yoga.varName; \
|
if (varName == nil) { \
|
||||||
newValue.unit = (enumName)[varName unsignedIntegerValue]; \
|
return; \
|
||||||
node.yoga.varName = newValue; \
|
} \
|
||||||
}
|
YGValue newValue = node.yoga.varName; \
|
||||||
|
newValue.unit = (enumName)[varName unsignedIntegerValue]; \
|
||||||
|
node.yoga.varName = newValue; \
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
@protocol FKTextSearchable <NSObject>
|
@protocol FKTextSearchable<NSObject>
|
||||||
|
|
||||||
- (NSString *)searchableText;
|
- (NSString*)searchableText;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -7,9 +7,8 @@
|
|||||||
|
|
||||||
#import "SKTapListenerMock.h"
|
#import "SKTapListenerMock.h"
|
||||||
|
|
||||||
@implementation SKTapListenerMock
|
@implementation SKTapListenerMock {
|
||||||
{
|
NSMutableArray<SKTapReceiver>* _tapReceivers;
|
||||||
NSMutableArray<SKTapReceiver> *_tapReceivers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@synthesize isMounted;
|
@synthesize isMounted;
|
||||||
@@ -23,7 +22,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)listenForTapWithBlock:(SKTapReceiver)receiver {
|
- (void)listenForTapWithBlock:(SKTapReceiver)receiver {
|
||||||
[_tapReceivers addObject: receiver];
|
[_tapReceivers addObject:receiver];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)tapAt:(CGPoint)point {
|
- (void)tapAt:(CGPoint)point {
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
#if FB_SONARKIT_ENABLED
|
#if FB_SONARKIT_ENABLED
|
||||||
|
|
||||||
|
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
|
||||||
#import <FlipperKitLayoutPlugin/SKDescriptorMapper.h>
|
#import <FlipperKitLayoutPlugin/SKDescriptorMapper.h>
|
||||||
#import <FlipperKitLayoutPlugin/SKNodeDescriptor.h>
|
#import <FlipperKitLayoutPlugin/SKNodeDescriptor.h>
|
||||||
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
|
|
||||||
#import <FlipperKitTestUtils/FlipperConnectionMock.h>
|
#import <FlipperKitTestUtils/FlipperConnectionMock.h>
|
||||||
#import <FlipperKitTestUtils/FlipperResponderMock.h>
|
#import <FlipperKitTestUtils/FlipperResponderMock.h>
|
||||||
|
|
||||||
@@ -22,9 +22,8 @@
|
|||||||
@interface SonarKitLayoutPluginTests : XCTestCase
|
@interface SonarKitLayoutPluginTests : XCTestCase
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation SonarKitLayoutPluginTests
|
@implementation SonarKitLayoutPluginTests {
|
||||||
{
|
SKDescriptorMapper* _descriptorMapper;
|
||||||
SKDescriptorMapper *_descriptorMapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setUp {
|
- (void)setUp {
|
||||||
@@ -32,217 +31,235 @@
|
|||||||
|
|
||||||
_descriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
|
_descriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
|
||||||
|
|
||||||
[_descriptorMapper registerDescriptor: [TestNodeDescriptor new]
|
[_descriptorMapper registerDescriptor:[TestNodeDescriptor new]
|
||||||
forClass: [TestNode class]];
|
forClass:[TestNode class]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testGetRoot {
|
- (void)testGetRoot {
|
||||||
FlipperKitLayoutPlugin *plugin = [[FlipperKitLayoutPlugin alloc]
|
FlipperKitLayoutPlugin* plugin = [[FlipperKitLayoutPlugin alloc]
|
||||||
initWithRootNode: [[TestNode alloc] initWithName: @"rootNode"]
|
initWithRootNode:[[TestNode alloc] initWithName:@"rootNode"]
|
||||||
withTapListener: nil
|
withTapListener:nil
|
||||||
withDescriptorMapper: _descriptorMapper];
|
withDescriptorMapper:_descriptorMapper];
|
||||||
|
|
||||||
FlipperConnectionMock *connection = [FlipperConnectionMock new];
|
FlipperConnectionMock* connection = [FlipperConnectionMock new];
|
||||||
FlipperResponderMock *responder = [FlipperResponderMock new];
|
FlipperResponderMock* responder = [FlipperResponderMock new];
|
||||||
[plugin didConnect:connection];
|
[plugin didConnect:connection];
|
||||||
|
|
||||||
SonarReceiver receiver = connection.receivers[@"getRoot"];
|
SonarReceiver receiver = connection.receivers[@"getRoot"];
|
||||||
receiver(@{}, responder);
|
receiver(@{}, responder);
|
||||||
|
|
||||||
XCTAssertTrue(([responder.successes containsObject: @{
|
XCTAssertTrue(([responder.successes containsObject:@{
|
||||||
@"id": @"rootNode",
|
@"id" : @"rootNode",
|
||||||
@"name": @"TestNode",
|
@"name" : @"TestNode",
|
||||||
@"children": @[],
|
@"children" : @[],
|
||||||
@"attributes": @[],
|
@"attributes" : @[],
|
||||||
@"data": @{},
|
@"data" : @{},
|
||||||
@"decoration": @"",
|
@"decoration" : @"",
|
||||||
}]));
|
}]));
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testGetEmptyNodes {
|
- (void)testGetEmptyNodes {
|
||||||
FlipperKitLayoutPlugin *plugin = [FlipperKitLayoutPlugin new];
|
FlipperKitLayoutPlugin* plugin = [FlipperKitLayoutPlugin new];
|
||||||
FlipperConnectionMock *connection = [FlipperConnectionMock new];
|
FlipperConnectionMock* connection = [FlipperConnectionMock new];
|
||||||
FlipperResponderMock *responder = [FlipperResponderMock new];
|
FlipperResponderMock* responder = [FlipperResponderMock new];
|
||||||
[plugin didConnect:connection];
|
[plugin didConnect:connection];
|
||||||
|
|
||||||
SonarReceiver receiver = connection.receivers[@"getNodes"];
|
SonarReceiver receiver = connection.receivers[@"getNodes"];
|
||||||
receiver(@{@"ids": @[]}, responder);
|
receiver(@{@"ids" : @[]}, responder);
|
||||||
|
|
||||||
XCTAssertTrue(([responder.successes containsObject:@{@"elements": @[]}]));
|
XCTAssertTrue(([responder.successes containsObject:@{@"elements" : @[]}]));
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testGetNodes {
|
- (void)testGetNodes {
|
||||||
TestNode *rootNode = [[TestNode alloc] initWithName: @"rootNode"];
|
TestNode* rootNode = [[TestNode alloc] initWithName:@"rootNode"];
|
||||||
NSArray *childNodes = @[
|
NSArray* childNodes = @[
|
||||||
[[TestNode alloc] initWithName: @"testNode1"],
|
[[TestNode alloc] initWithName:@"testNode1"],
|
||||||
[[TestNode alloc] initWithName: @"testNode2"],
|
[[TestNode alloc] initWithName:@"testNode2"],
|
||||||
[[TestNode alloc] initWithName: @"testNode3"],
|
[[TestNode alloc] initWithName:@"testNode3"],
|
||||||
];
|
];
|
||||||
|
|
||||||
rootNode.children = childNodes;
|
rootNode.children = childNodes;
|
||||||
|
|
||||||
FlipperKitLayoutPlugin *plugin = [[FlipperKitLayoutPlugin alloc] initWithRootNode: rootNode
|
FlipperKitLayoutPlugin* plugin =
|
||||||
withTapListener: nil
|
[[FlipperKitLayoutPlugin alloc] initWithRootNode:rootNode
|
||||||
withDescriptorMapper: _descriptorMapper];
|
withTapListener:nil
|
||||||
|
withDescriptorMapper:_descriptorMapper];
|
||||||
|
|
||||||
FlipperConnectionMock *connection = [FlipperConnectionMock new];
|
FlipperConnectionMock* connection = [FlipperConnectionMock new];
|
||||||
FlipperResponderMock *responder = [FlipperResponderMock new];
|
FlipperResponderMock* responder = [FlipperResponderMock new];
|
||||||
[plugin didConnect:connection];
|
[plugin didConnect:connection];
|
||||||
|
|
||||||
// Ensure that nodes are tracked
|
// Ensure that nodes are tracked
|
||||||
connection.receivers[@"getRoot"](@{}, responder);
|
connection.receivers[@"getRoot"](@{}, responder);
|
||||||
|
|
||||||
SonarReceiver receiver = connection.receivers[@"getNodes"];
|
SonarReceiver receiver = connection.receivers[@"getNodes"];
|
||||||
receiver(@{@"ids": @[ @"testNode1", @"testNode2", @"testNode3" ]}, responder);
|
receiver(
|
||||||
|
@{@"ids" : @[ @"testNode1", @"testNode2", @"testNode3" ]}, responder);
|
||||||
|
|
||||||
XCTAssertTrue(([responder.successes containsObject:@{@"elements": @[
|
XCTAssertTrue(([responder.successes containsObject:@{
|
||||||
|
@"elements" : @[
|
||||||
@{
|
@{
|
||||||
@"id": @"testNode1",
|
@"id" : @"testNode1",
|
||||||
@"name": @"TestNode",
|
@"name" : @"TestNode",
|
||||||
@"children": @[],
|
@"children" : @[],
|
||||||
@"attributes": @[],
|
@"attributes" : @[],
|
||||||
@"data": @{},
|
@"data" : @{},
|
||||||
@"decoration": @"",
|
@"decoration" : @"",
|
||||||
},
|
},
|
||||||
@{
|
@{
|
||||||
@"id": @"testNode2",
|
@"id" : @"testNode2",
|
||||||
@"name": @"TestNode",
|
@"name" : @"TestNode",
|
||||||
@"children": @[],
|
@"children" : @[],
|
||||||
@"attributes": @[],
|
@"attributes" : @[],
|
||||||
@"data": @{},
|
@"data" : @{},
|
||||||
@"decoration": @"",
|
@"decoration" : @"",
|
||||||
},
|
},
|
||||||
@{
|
@{
|
||||||
@"id": @"testNode3",
|
@"id" : @"testNode3",
|
||||||
@"name": @"TestNode",
|
@"name" : @"TestNode",
|
||||||
@"children": @[],
|
@"children" : @[],
|
||||||
@"attributes": @[],
|
@"attributes" : @[],
|
||||||
@"data": @{},
|
@"data" : @{},
|
||||||
@"decoration": @"",
|
@"decoration" : @"",
|
||||||
},
|
},
|
||||||
]}]));
|
]
|
||||||
|
}]));
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testSetHighlighted {
|
- (void)testSetHighlighted {
|
||||||
TestNode *rootNode = [[TestNode alloc] initWithName: @"rootNode"];
|
TestNode* rootNode = [[TestNode alloc] initWithName:@"rootNode"];
|
||||||
|
|
||||||
TestNode *testNode1 = [[TestNode alloc] initWithName: @"testNode1"];
|
TestNode* testNode1 = [[TestNode alloc] initWithName:@"testNode1"];
|
||||||
TestNode *testNode2 = [[TestNode alloc] initWithName: @"testNode2"];
|
TestNode* testNode2 = [[TestNode alloc] initWithName:@"testNode2"];
|
||||||
NSArray *childNodes = @[ testNode1, testNode2 ];
|
NSArray* childNodes = @[ testNode1, testNode2 ];
|
||||||
|
|
||||||
rootNode.children = childNodes;
|
rootNode.children = childNodes;
|
||||||
|
|
||||||
FlipperKitLayoutPlugin *plugin = [[FlipperKitLayoutPlugin alloc] initWithRootNode: rootNode
|
FlipperKitLayoutPlugin* plugin =
|
||||||
withTapListener: nil
|
[[FlipperKitLayoutPlugin alloc] initWithRootNode:rootNode
|
||||||
withDescriptorMapper: _descriptorMapper];
|
withTapListener:nil
|
||||||
|
withDescriptorMapper:_descriptorMapper];
|
||||||
|
|
||||||
FlipperConnectionMock *connection = [FlipperConnectionMock new];
|
FlipperConnectionMock* connection = [FlipperConnectionMock new];
|
||||||
FlipperResponderMock *responder = [FlipperResponderMock new];
|
FlipperResponderMock* responder = [FlipperResponderMock new];
|
||||||
[plugin didConnect:connection];
|
[plugin didConnect:connection];
|
||||||
|
|
||||||
// Setup in order to track nodes successfully
|
// Setup in order to track nodes successfully
|
||||||
connection.receivers[@"getRoot"](@{}, responder);
|
connection.receivers[@"getRoot"](@{}, responder);
|
||||||
SonarReceiver getNodesCall = connection.receivers[@"getNodes"];
|
SonarReceiver getNodesCall = connection.receivers[@"getNodes"];
|
||||||
getNodesCall(@{@"ids": @[ @"testNode1", @"testNode2" ]}, responder);
|
getNodesCall(@{@"ids" : @[ @"testNode1", @"testNode2" ]}, responder);
|
||||||
|
|
||||||
SonarReceiver setHighlighted = connection.receivers[@"setHighlighted"];
|
SonarReceiver setHighlighted = connection.receivers[@"setHighlighted"];
|
||||||
setHighlighted(@{@"id":@"testNode2"}, responder);
|
setHighlighted(@{@"id" : @"testNode2"}, responder);
|
||||||
|
|
||||||
XCTAssertTrue(testNode2.highlighted);
|
XCTAssertTrue(testNode2.highlighted);
|
||||||
|
|
||||||
setHighlighted(@{@"id":@"testNode1"}, responder);
|
setHighlighted(@{@"id" : @"testNode1"}, responder);
|
||||||
|
|
||||||
// Ensure that old highlight was removed
|
// Ensure that old highlight was removed
|
||||||
XCTAssertTrue(testNode1.highlighted && !testNode2.highlighted);
|
XCTAssertTrue(testNode1.highlighted && !testNode2.highlighted);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testSetSearchActive {
|
- (void)testSetSearchActive {
|
||||||
TestNode *rootNode = [[TestNode alloc] initWithName: @"rootNode"
|
TestNode* rootNode = [[TestNode alloc] initWithName:@"rootNode"
|
||||||
withFrame: CGRectMake(0, 0, 20, 60)];
|
withFrame:CGRectMake(0, 0, 20, 60)];
|
||||||
|
|
||||||
TestNode *testNode1 = [[TestNode alloc] initWithName: @"testNode1"
|
TestNode* testNode1 =
|
||||||
withFrame: CGRectMake(20, 20, 20, 20)];
|
[[TestNode alloc] initWithName:@"testNode1"
|
||||||
TestNode *testNode2 = [[TestNode alloc] initWithName: @"testNode2"
|
withFrame:CGRectMake(20, 20, 20, 20)];
|
||||||
withFrame: CGRectMake(20, 40, 20, 20)];
|
TestNode* testNode2 =
|
||||||
TestNode *testNode3 = [[TestNode alloc] initWithName: @"testNode3"
|
[[TestNode alloc] initWithName:@"testNode2"
|
||||||
withFrame: CGRectMake(25, 42, 5, 5)];
|
withFrame:CGRectMake(20, 40, 20, 20)];
|
||||||
|
TestNode* testNode3 =
|
||||||
|
[[TestNode alloc] initWithName:@"testNode3"
|
||||||
|
withFrame:CGRectMake(25, 42, 5, 5)];
|
||||||
|
|
||||||
rootNode.children = @[ testNode1, testNode2 ];
|
rootNode.children = @[ testNode1, testNode2 ];
|
||||||
testNode2.children = @[ testNode3 ];
|
testNode2.children = @[ testNode3 ];
|
||||||
|
|
||||||
SKTapListenerMock *tapListener = [SKTapListenerMock new];
|
SKTapListenerMock* tapListener = [SKTapListenerMock new];
|
||||||
FlipperKitLayoutPlugin *plugin = [[FlipperKitLayoutPlugin alloc] initWithRootNode: rootNode
|
FlipperKitLayoutPlugin* plugin =
|
||||||
withTapListener: tapListener
|
[[FlipperKitLayoutPlugin alloc] initWithRootNode:rootNode
|
||||||
withDescriptorMapper: _descriptorMapper];
|
withTapListener:tapListener
|
||||||
|
withDescriptorMapper:_descriptorMapper];
|
||||||
|
|
||||||
FlipperConnectionMock *connection = [FlipperConnectionMock new];
|
FlipperConnectionMock* connection = [FlipperConnectionMock new];
|
||||||
FlipperResponderMock *responder = [FlipperResponderMock new];
|
FlipperResponderMock* responder = [FlipperResponderMock new];
|
||||||
[plugin didConnect:connection];
|
[plugin didConnect:connection];
|
||||||
|
|
||||||
connection.receivers[@"setSearchActive"](@{@"active":@YES}, responder);
|
connection.receivers[@"setSearchActive"](@{@"active" : @YES}, responder);
|
||||||
|
|
||||||
// Fake a tap at `testNode3`
|
// Fake a tap at `testNode3`
|
||||||
[tapListener tapAt: (CGPoint){ 26, 43 }];
|
[tapListener tapAt:(CGPoint){26, 43}];
|
||||||
|
|
||||||
XCTAssertTrue(([connection.sent[@"select"] containsObject: @{ @"path": @[ @"testNode2", @"testNode3" ] }]));
|
XCTAssertTrue(([connection.sent[@"select"]
|
||||||
|
containsObject:@{@"path" : @[ @"testNode2", @"testNode3" ]}]));
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testSetSearchActiveMountAndUnmount {
|
- (void)testSetSearchActiveMountAndUnmount {
|
||||||
TestNode *rootNode = [[TestNode alloc] initWithName: @"rootNode"];
|
TestNode* rootNode = [[TestNode alloc] initWithName:@"rootNode"];
|
||||||
|
|
||||||
SKTapListenerMock *tapListener = [SKTapListenerMock new];
|
SKTapListenerMock* tapListener = [SKTapListenerMock new];
|
||||||
FlipperKitLayoutPlugin *plugin = [[FlipperKitLayoutPlugin alloc] initWithRootNode: rootNode
|
FlipperKitLayoutPlugin* plugin =
|
||||||
withTapListener: tapListener
|
[[FlipperKitLayoutPlugin alloc] initWithRootNode:rootNode
|
||||||
withDescriptorMapper: _descriptorMapper];
|
withTapListener:tapListener
|
||||||
|
withDescriptorMapper:_descriptorMapper];
|
||||||
|
|
||||||
FlipperConnectionMock *connection = [FlipperConnectionMock new];
|
FlipperConnectionMock* connection = [FlipperConnectionMock new];
|
||||||
FlipperResponderMock *responder = [FlipperResponderMock new];
|
FlipperResponderMock* responder = [FlipperResponderMock new];
|
||||||
[plugin didConnect:connection];
|
[plugin didConnect:connection];
|
||||||
|
|
||||||
SonarReceiver setSearchActive = connection.receivers[@"setSearchActive"];
|
SonarReceiver setSearchActive = connection.receivers[@"setSearchActive"];
|
||||||
setSearchActive(@{@"active":@YES}, responder);
|
setSearchActive(@{@"active" : @YES}, responder);
|
||||||
|
|
||||||
XCTAssertTrue(tapListener.isMounted);
|
XCTAssertTrue(tapListener.isMounted);
|
||||||
|
|
||||||
setSearchActive(@{@"active":@NO}, responder);
|
setSearchActive(@{@"active" : @NO}, responder);
|
||||||
XCTAssertTrue(! tapListener.isMounted);
|
XCTAssertTrue(!tapListener.isMounted);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testSetData {
|
- (void)testSetData {
|
||||||
TestNode *rootNode = [[TestNode alloc] initWithName: @"rootNode"
|
TestNode* rootNode = [[TestNode alloc] initWithName:@"rootNode"
|
||||||
withFrame: CGRectMake(0, 0, 20, 60)];
|
withFrame:CGRectMake(0, 0, 20, 60)];
|
||||||
|
|
||||||
TestNode *testNode1 = [[TestNode alloc] initWithName: @"testNode1"
|
TestNode* testNode1 =
|
||||||
withFrame: CGRectMake(20, 20, 20, 20)];
|
[[TestNode alloc] initWithName:@"testNode1"
|
||||||
TestNode *testNode2 = [[TestNode alloc] initWithName: @"testNode2"
|
withFrame:CGRectMake(20, 20, 20, 20)];
|
||||||
withFrame: CGRectMake(20, 40, 20, 20)];
|
TestNode* testNode2 =
|
||||||
TestNode *testNode3 = [[TestNode alloc] initWithName: @"testNode3"
|
[[TestNode alloc] initWithName:@"testNode2"
|
||||||
withFrame: CGRectMake(25, 42, 5, 5)];
|
withFrame:CGRectMake(20, 40, 20, 20)];
|
||||||
|
TestNode* testNode3 =
|
||||||
|
[[TestNode alloc] initWithName:@"testNode3"
|
||||||
|
withFrame:CGRectMake(25, 42, 5, 5)];
|
||||||
|
|
||||||
rootNode.children = @[ testNode1, testNode2 ];
|
rootNode.children = @[ testNode1, testNode2 ];
|
||||||
testNode2.children = @[ testNode3 ];
|
testNode2.children = @[ testNode3 ];
|
||||||
|
|
||||||
SKTapListenerMock *tapListener = [SKTapListenerMock new];
|
SKTapListenerMock* tapListener = [SKTapListenerMock new];
|
||||||
FlipperKitLayoutPlugin *plugin = [[FlipperKitLayoutPlugin alloc] initWithRootNode: rootNode
|
FlipperKitLayoutPlugin* plugin =
|
||||||
withTapListener: tapListener
|
[[FlipperKitLayoutPlugin alloc] initWithRootNode:rootNode
|
||||||
withDescriptorMapper: _descriptorMapper];
|
withTapListener:tapListener
|
||||||
|
withDescriptorMapper:_descriptorMapper];
|
||||||
|
|
||||||
FlipperConnectionMock *connection = [FlipperConnectionMock new];
|
FlipperConnectionMock* connection = [FlipperConnectionMock new];
|
||||||
FlipperResponderMock *responder = [FlipperResponderMock new];
|
FlipperResponderMock* responder = [FlipperResponderMock new];
|
||||||
[plugin didConnect:connection];
|
[plugin didConnect:connection];
|
||||||
|
|
||||||
// Setup in order to track nodes successfully
|
// Setup in order to track nodes successfully
|
||||||
connection.receivers[@"getRoot"](@{}, responder);
|
connection.receivers[@"getRoot"](@{}, responder);
|
||||||
connection.receivers[@"getNodes"](@{ @"ids": @[ @"testNode2" ] }, responder);
|
connection.receivers[@"getNodes"](@{@"ids" : @[ @"testNode2" ]}, responder);
|
||||||
|
|
||||||
// Modify the name of testNode3
|
// Modify the name of testNode3
|
||||||
connection.receivers[@"setData"](@{
|
connection.receivers[@"setData"](
|
||||||
@"id": @"testNode3",
|
@{
|
||||||
@"path": @[ @"TestNode", @"name" ],
|
@"id" : @"testNode3",
|
||||||
@"value": @"changedNameForTestNode3",
|
@"path" : @[ @"TestNode", @"name" ],
|
||||||
}, responder);
|
@"value" : @"changedNameForTestNode3",
|
||||||
|
},
|
||||||
|
responder);
|
||||||
|
|
||||||
XCTAssertTrue([testNode3.nodeName isEqualToString: @"changedNameForTestNode3"]);
|
XCTAssertTrue(
|
||||||
|
[testNode3.nodeName isEqualToString:@"changedNameForTestNode3"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
@interface TestNode : NSObject
|
@interface TestNode : NSObject
|
||||||
|
|
||||||
@property (nonatomic, copy) NSString *nodeName;
|
@property(nonatomic, copy) NSString* nodeName;
|
||||||
@property (nonatomic, copy) NSArray<TestNode *> *children;
|
@property(nonatomic, copy) NSArray<TestNode*>* children;
|
||||||
|
|
||||||
@property (nonatomic, assign) BOOL highlighted;
|
@property(nonatomic, assign) BOOL highlighted;
|
||||||
@property (nonatomic, assign) CGRect frame;
|
@property(nonatomic, assign) CGRect frame;
|
||||||
|
|
||||||
- (instancetype)initWithName:(NSString *)name;
|
- (instancetype)initWithName:(NSString*)name;
|
||||||
- (instancetype)initWithName:(NSString *)name withFrame:(CGRect)frame;
|
- (instancetype)initWithName:(NSString*)name withFrame:(CGRect)frame;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,12 +9,11 @@
|
|||||||
|
|
||||||
@implementation TestNode
|
@implementation TestNode
|
||||||
|
|
||||||
- (instancetype)initWithName:(NSString *)name {
|
- (instancetype)initWithName:(NSString*)name {
|
||||||
return [self initWithName: name
|
return [self initWithName:name withFrame:CGRectZero];
|
||||||
withFrame: CGRectZero];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithName:(NSString *)name withFrame:(CGRect)frame {
|
- (instancetype)initWithName:(NSString*)name withFrame:(CGRect)frame {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_nodeName = name;
|
_nodeName = name;
|
||||||
_frame = frame;
|
_frame = frame;
|
||||||
|
|||||||
@@ -9,5 +9,5 @@
|
|||||||
|
|
||||||
#import "TestNode.h"
|
#import "TestNode.h"
|
||||||
|
|
||||||
@interface TestNodeDescriptor : SKNodeDescriptor<TestNode *>
|
@interface TestNodeDescriptor : SKNodeDescriptor<TestNode*>
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,27 +9,27 @@
|
|||||||
|
|
||||||
@implementation TestNodeDescriptor
|
@implementation TestNodeDescriptor
|
||||||
|
|
||||||
- (NSString *)identifierForNode:(TestNode *)node {
|
- (NSString*)identifierForNode:(TestNode*)node {
|
||||||
return node.nodeName;
|
return node.nodeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)childCountForNode:(TestNode *)node {
|
- (NSUInteger)childCountForNode:(TestNode*)node {
|
||||||
return [node.children count];
|
return [node.children count];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)childForNode:(TestNode *)node atIndex:(NSUInteger)index {
|
- (id)childForNode:(TestNode*)node atIndex:(NSUInteger)index {
|
||||||
return [node.children objectAtIndex: index];
|
return [node.children objectAtIndex:index];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHighlighted:(BOOL)highlighted forNode:(TestNode *)node {
|
- (void)setHighlighted:(BOOL)highlighted forNode:(TestNode*)node {
|
||||||
node.highlighted = highlighted;
|
node.highlighted = highlighted;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)hitTest:(SKTouch *)touch forNode:(TestNode *)node {
|
- (void)hitTest:(SKTouch*)touch forNode:(TestNode*)node {
|
||||||
NSUInteger index = [node.children count] - 1;
|
NSUInteger index = [node.children count] - 1;
|
||||||
for (TestNode *childNode in [node.children reverseObjectEnumerator]) {
|
for (TestNode* childNode in [node.children reverseObjectEnumerator]) {
|
||||||
if ([touch containedIn: childNode.frame]) {
|
if ([touch containedIn:childNode.frame]) {
|
||||||
[touch continueWithChildIndex: index withOffset: node.frame.origin];
|
[touch continueWithChildIndex:index withOffset:node.frame.origin];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,12 +39,13 @@
|
|||||||
[touch finish];
|
[touch finish];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary<NSString *, SKNodeUpdateData> *)dataMutationsForNode:(TestNode *)node {
|
- (NSDictionary<NSString*, SKNodeUpdateData>*)dataMutationsForNode:
|
||||||
return @{
|
(TestNode*)node {
|
||||||
@"TestNode.name": ^(NSString *newName) {
|
return @{@"TestNode.name" : ^(NSString* newName){
|
||||||
node.nodeName = newName;
|
node.nodeName = newName;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -13,12 +13,16 @@
|
|||||||
#import "SKBufferingPlugin.h"
|
#import "SKBufferingPlugin.h"
|
||||||
#import "SKNetworkReporter.h"
|
#import "SKNetworkReporter.h"
|
||||||
|
|
||||||
@interface FlipperKitNetworkPlugin : SKBufferingPlugin <SKNetworkReporterDelegate>
|
@interface FlipperKitNetworkPlugin
|
||||||
|
: SKBufferingPlugin<SKNetworkReporterDelegate>
|
||||||
|
|
||||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
|
||||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter queue:(dispatch_queue_t)queue; //For test purposes
|
NS_DESIGNATED_INITIALIZER;
|
||||||
|
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
|
||||||
|
queue:(dispatch_queue_t)
|
||||||
|
queue; // For test purposes
|
||||||
|
|
||||||
@property (strong, nonatomic) id<SKNetworkAdapterDelegate> adapter;
|
@property(strong, nonatomic) id<SKNetworkAdapterDelegate> adapter;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if FB_SONARKIT_ENABLED
|
#if FB_SONARKIT_ENABLED
|
||||||
#import <vector>
|
#import "FlipperKitNetworkPlugin.h"
|
||||||
#import <iostream>
|
#import <iostream>
|
||||||
#import <memory>
|
#import <memory>
|
||||||
#import "FlipperKitNetworkPlugin.h"
|
#import <vector>
|
||||||
#import "SKNetworkReporter.h"
|
|
||||||
#import "SonarKitNetworkPlugin+CPPInitialization.h"
|
|
||||||
#import "SKBufferingPlugin+CPPInitialization.h"
|
#import "SKBufferingPlugin+CPPInitialization.h"
|
||||||
#import "SKDispatchQueue.h"
|
#import "SKDispatchQueue.h"
|
||||||
|
#import "SKNetworkReporter.h"
|
||||||
|
#import "SonarKitNetworkPlugin+CPPInitialization.h"
|
||||||
|
|
||||||
@interface FlipperKitNetworkPlugin ()
|
@interface FlipperKitNetworkPlugin ()
|
||||||
|
|
||||||
@@ -27,20 +27,26 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)init {
|
- (instancetype)init {
|
||||||
if (self = [super initWithQueue:dispatch_queue_create("com.sonarkit.network.buffer", DISPATCH_QUEUE_SERIAL)]) {
|
if (self = [super initWithQueue:dispatch_queue_create(
|
||||||
|
"com.sonarkit.network.buffer",
|
||||||
|
DISPATCH_QUEUE_SERIAL)]) {
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter {
|
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter {
|
||||||
if (self = [super initWithQueue:dispatch_queue_create("com.sonarkit.network.buffer", DISPATCH_QUEUE_SERIAL)]) {
|
if (self = [super initWithQueue:dispatch_queue_create(
|
||||||
|
"com.sonarkit.network.buffer",
|
||||||
|
DISPATCH_QUEUE_SERIAL)]) {
|
||||||
adapter.delegate = self;
|
adapter.delegate = self;
|
||||||
_adapter = adapter;
|
_adapter = adapter;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter queue:(dispatch_queue_t)queue; {
|
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
|
||||||
|
queue:(dispatch_queue_t)queue;
|
||||||
|
{
|
||||||
if (self = [super initWithQueue:queue]) {
|
if (self = [super initWithQueue:queue]) {
|
||||||
adapter.delegate = self;
|
adapter.delegate = self;
|
||||||
_adapter = adapter;
|
_adapter = adapter;
|
||||||
@@ -50,63 +56,60 @@
|
|||||||
|
|
||||||
#pragma mark - SKNetworkReporterDelegate
|
#pragma mark - SKNetworkReporterDelegate
|
||||||
|
|
||||||
|
- (void)didObserveRequest:(SKRequestInfo*)request {
|
||||||
- (void)didObserveRequest:(SKRequestInfo *)request
|
NSMutableArray<NSDictionary<NSString*, id>*>* headers = [NSMutableArray new];
|
||||||
{
|
for (NSString* key in [request.request.allHTTPHeaderFields allKeys]) {
|
||||||
NSMutableArray<NSDictionary<NSString *, id> *> *headers = [NSMutableArray new];
|
NSDictionary<NSString*, id>* header =
|
||||||
for (NSString *key in [request.request.allHTTPHeaderFields allKeys]) {
|
@{@"key" : key, @"value" : request.request.allHTTPHeaderFields[key]};
|
||||||
NSDictionary<NSString *, id> *header = @{
|
[headers addObject:header];
|
||||||
@"key": key,
|
|
||||||
@"value": request.request.allHTTPHeaderFields[key]
|
|
||||||
};
|
|
||||||
[headers addObject: header];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *body = request.body;
|
NSString* body = request.body;
|
||||||
|
|
||||||
[self send:@"newRequest"
|
[self send:@"newRequest"
|
||||||
sonarObject:@{
|
sonarObject:@{
|
||||||
@"id": @(request.identifier),
|
@"id" : @(request.identifier),
|
||||||
@"timestamp": @(request.timestamp),
|
@"timestamp" : @(request.timestamp),
|
||||||
@"method": request.request.HTTPMethod ?: [NSNull null],
|
@"method" : request.request.HTTPMethod ?: [NSNull null],
|
||||||
@"url": [request.request.URL absoluteString] ?: [NSNull null],
|
@"url" : [request.request.URL absoluteString] ?: [NSNull null],
|
||||||
@"headers": headers,
|
@"headers" : headers,
|
||||||
@"data": body ? body : [NSNull null]
|
@"data" : body ? body : [NSNull null]
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didObserveResponse:(SKResponseInfo *)response
|
- (void)didObserveResponse:(SKResponseInfo*)response {
|
||||||
{
|
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response.response;
|
||||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response.response;
|
|
||||||
|
|
||||||
NSMutableArray<NSDictionary<NSString *, id> *> *headers = [NSMutableArray new];
|
NSMutableArray<NSDictionary<NSString*, id>*>* headers = [NSMutableArray new];
|
||||||
for (NSString *key in [httpResponse.allHeaderFields allKeys]) {
|
for (NSString* key in [httpResponse.allHeaderFields allKeys]) {
|
||||||
NSDictionary<NSString *, id> *header = @{
|
NSDictionary<NSString*, id>* header =
|
||||||
@"key": key,
|
@{@"key" : key, @"value" : httpResponse.allHeaderFields[key]};
|
||||||
@"value": httpResponse.allHeaderFields[key]
|
[headers addObject:header];
|
||||||
};
|
|
||||||
[headers addObject: header];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *body = response.body;
|
NSString* body = response.body;
|
||||||
|
|
||||||
[self send:@"newResponse"
|
[self send:@"newResponse"
|
||||||
sonarObject:@{
|
sonarObject:@{
|
||||||
@"id": @(response.identifier),
|
@"id" : @(response.identifier),
|
||||||
@"timestamp": @(response.timestamp),
|
@"timestamp" : @(response.timestamp),
|
||||||
@"status": @(httpResponse.statusCode),
|
@"status" : @(httpResponse.statusCode),
|
||||||
@"reason": [NSHTTPURLResponse localizedStringForStatusCode: httpResponse.statusCode] ?: [NSNull null],
|
@"reason" : [NSHTTPURLResponse
|
||||||
@"headers": headers,
|
localizedStringForStatusCode:httpResponse.statusCode]
|
||||||
@"data": body ? body : [NSNull null]
|
?: [NSNull null],
|
||||||
|
@"headers" : headers,
|
||||||
|
@"data" : body ? body : [NSNull null]
|
||||||
}];
|
}];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation FlipperKitNetworkPlugin (CPPInitialization)
|
@implementation FlipperKitNetworkPlugin (CPPInitialization)
|
||||||
|
|
||||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter dispatchQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)queue {
|
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
|
||||||
|
dispatchQueue:
|
||||||
|
(std::shared_ptr<facebook::flipper::DispatchQueue>)
|
||||||
|
queue {
|
||||||
if (self = [super initWithDispatchQueue:queue]) {
|
if (self = [super initWithDispatchQueue:queue]) {
|
||||||
adapter.delegate = self;
|
adapter.delegate = self;
|
||||||
_adapter = adapter;
|
_adapter = adapter;
|
||||||
|
|||||||
@@ -8,21 +8,24 @@
|
|||||||
#if FB_SONARKIT_ENABLED
|
#if FB_SONARKIT_ENABLED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#import "SKBufferingPlugin.h"
|
|
||||||
#import "SKDispatchQueue.h"
|
|
||||||
#import <iostream>
|
#import <iostream>
|
||||||
#import <memory>
|
#import <memory>
|
||||||
|
#import "SKBufferingPlugin.h"
|
||||||
|
#import "SKDispatchQueue.h"
|
||||||
|
|
||||||
struct CachedEvent {
|
struct CachedEvent {
|
||||||
NSString *method;
|
NSString* method;
|
||||||
NSDictionary<NSString *, id> *sonarObject;
|
NSDictionary<NSString*, id>* sonarObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@interface SKBufferingPlugin (CPPInitialization)
|
||||||
|
|
||||||
@interface SKBufferingPlugin(CPPInitialization)
|
- (instancetype)initWithVectorEventSize:(NSUInteger)size
|
||||||
|
connectionAccessQueue:
|
||||||
- (instancetype)initWithVectorEventSize:(NSUInteger)size connectionAccessQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)connectionAccessQueue;
|
(std::shared_ptr<facebook::flipper::DispatchQueue>)
|
||||||
- (instancetype)initWithDispatchQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)queue;
|
connectionAccessQueue;
|
||||||
|
- (instancetype)initWithDispatchQueue:
|
||||||
|
(std::shared_ptr<facebook::flipper::DispatchQueue>)queue;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
|
|
||||||
- (instancetype)initWithQueue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithQueue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
||||||
- (void)send:(NSString *)method sonarObject:(NSDictionary<NSString *, id> *)sonarObject;
|
- (void)send:(NSString*)method
|
||||||
|
sonarObject:(NSDictionary<NSString*, id>*)sonarObject;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -9,17 +9,18 @@
|
|||||||
|
|
||||||
#import <vector>
|
#import <vector>
|
||||||
|
|
||||||
#import "SKBufferingPlugin.h"
|
|
||||||
#import <FlipperKit/FlipperConnection.h>
|
#import <FlipperKit/FlipperConnection.h>
|
||||||
#import "SKDispatchQueue.h"
|
|
||||||
#import "SKBufferingPlugin+CPPInitialization.h"
|
#import "SKBufferingPlugin+CPPInitialization.h"
|
||||||
|
#import "SKBufferingPlugin.h"
|
||||||
|
#import "SKDispatchQueue.h"
|
||||||
|
|
||||||
static const NSUInteger bufferSize = 500;
|
static const NSUInteger bufferSize = 500;
|
||||||
|
|
||||||
@interface SKBufferingPlugin()
|
@interface SKBufferingPlugin ()
|
||||||
|
|
||||||
@property(assign, nonatomic) std::vector<CachedEvent> ringBuffer;
|
@property(assign, nonatomic) std::vector<CachedEvent> ringBuffer;
|
||||||
@property(assign, nonatomic) std::shared_ptr<facebook::flipper::DispatchQueue> connectionAccessQueue;
|
@property(assign, nonatomic) std::shared_ptr<facebook::flipper::DispatchQueue>
|
||||||
|
connectionAccessQueue;
|
||||||
@property(strong, nonatomic) id<FlipperConnection> connection;
|
@property(strong, nonatomic) id<FlipperConnection> connection;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -35,12 +36,13 @@ static const NSUInteger bufferSize = 500;
|
|||||||
- (instancetype)initWithQueue:(dispatch_queue_t)queue {
|
- (instancetype)initWithQueue:(dispatch_queue_t)queue {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_ringBuffer.reserve(bufferSize);
|
_ringBuffer.reserve(bufferSize);
|
||||||
_connectionAccessQueue = std::make_shared<facebook::flipper::GCDQueue>(queue);
|
_connectionAccessQueue =
|
||||||
|
std::make_shared<facebook::flipper::GCDQueue>(queue);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)identifier {
|
- (NSString*)identifier {
|
||||||
// Note: This must match with the javascript pulgin identifier!!
|
// Note: This must match with the javascript pulgin identifier!!
|
||||||
return @"Network";
|
return @"Network";
|
||||||
}
|
}
|
||||||
@@ -62,9 +64,8 @@ static const NSUInteger bufferSize = 500;
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)send:(NSString*)method
|
||||||
- (void)send:(NSString *)method
|
sonarObject:(NSDictionary<NSString*, id>*)sonarObject {
|
||||||
sonarObject:(NSDictionary<NSString *, id> *)sonarObject {
|
|
||||||
_connectionAccessQueue->async(^{
|
_connectionAccessQueue->async(^{
|
||||||
if (self->_connection) {
|
if (self->_connection) {
|
||||||
[self->_connection send:method withParams:sonarObject];
|
[self->_connection send:method withParams:sonarObject];
|
||||||
@@ -72,17 +73,15 @@ static const NSUInteger bufferSize = 500;
|
|||||||
if (self->_ringBuffer.size() == bufferSize) {
|
if (self->_ringBuffer.size() == bufferSize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self->_ringBuffer.push_back({
|
self->_ringBuffer.push_back(
|
||||||
.method = method,
|
{.method = method, .sonarObject = sonarObject});
|
||||||
.sonarObject = sonarObject
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)sendBufferedEvents {
|
- (void)sendBufferedEvents {
|
||||||
NSAssert(_connection, @"connection object cannot be nil");
|
NSAssert(_connection, @"connection object cannot be nil");
|
||||||
for (const auto &event : _ringBuffer) {
|
for (const auto& event : _ringBuffer) {
|
||||||
[_connection send:event.method withParams:event.sonarObject];
|
[_connection send:event.method withParams:event.sonarObject];
|
||||||
}
|
}
|
||||||
_ringBuffer.clear();
|
_ringBuffer.clear();
|
||||||
@@ -90,22 +89,23 @@ static const NSUInteger bufferSize = 500;
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation SKBufferingPlugin(CPPInitialization)
|
@implementation SKBufferingPlugin (CPPInitialization)
|
||||||
|
|
||||||
- (instancetype)initWithVectorEventSize:(NSUInteger)size connectionAccessQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)connectionAccessQueue {
|
- (instancetype)initWithVectorEventSize:(NSUInteger)size
|
||||||
|
connectionAccessQueue:
|
||||||
|
(std::shared_ptr<facebook::flipper::DispatchQueue>)
|
||||||
|
connectionAccessQueue {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_ringBuffer.reserve(size);
|
_ringBuffer.reserve(size);
|
||||||
_connectionAccessQueue = connectionAccessQueue;
|
_connectionAccessQueue = connectionAccessQueue;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
- (instancetype)initWithDispatchQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)queue {
|
- (instancetype)initWithDispatchQueue:
|
||||||
return [self initWithVectorEventSize:bufferSize
|
(std::shared_ptr<facebook::flipper::DispatchQueue>)queue {
|
||||||
connectionAccessQueue:queue];
|
return [self initWithVectorEventSize:bufferSize connectionAccessQueue:queue];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,31 +12,28 @@
|
|||||||
#import <dispatch/dispatch.h>
|
#import <dispatch/dispatch.h>
|
||||||
|
|
||||||
namespace facebook {
|
namespace facebook {
|
||||||
namespace flipper {
|
namespace flipper {
|
||||||
class DispatchQueue
|
class DispatchQueue {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual void async(dispatch_block_t block) = 0;
|
virtual void async(dispatch_block_t block) = 0;
|
||||||
virtual ~DispatchQueue() { }
|
virtual ~DispatchQueue() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GCDQueue: public DispatchQueue
|
class GCDQueue : public DispatchQueue {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
GCDQueue(dispatch_queue_t underlyingQueue)
|
GCDQueue(dispatch_queue_t underlyingQueue)
|
||||||
:_underlyingQueue(underlyingQueue) { }
|
: _underlyingQueue(underlyingQueue) {}
|
||||||
|
|
||||||
void async(dispatch_block_t block) override
|
void async(dispatch_block_t block) override {
|
||||||
{
|
|
||||||
dispatch_async(_underlyingQueue, block);
|
dispatch_async(_underlyingQueue, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~GCDQueue() { }
|
virtual ~GCDQueue() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
dispatch_queue_t _underlyingQueue;
|
dispatch_queue_t _underlyingQueue;
|
||||||
};
|
};
|
||||||
}
|
} // namespace flipper
|
||||||
}
|
} // namespace facebook
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,13 +11,13 @@
|
|||||||
|
|
||||||
@protocol SKNetworkReporterDelegate
|
@protocol SKNetworkReporterDelegate
|
||||||
|
|
||||||
- (void)didObserveRequest:(SKRequestInfo *)request;
|
- (void)didObserveRequest:(SKRequestInfo*)request;
|
||||||
- (void)didObserveResponse:(SKResponseInfo *)response;
|
- (void)didObserveResponse:(SKResponseInfo*)response;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@protocol SKNetworkAdapterDelegate
|
@protocol SKNetworkAdapterDelegate
|
||||||
|
|
||||||
@property (weak, nonatomic) id<SKNetworkReporterDelegate> delegate;
|
@property(weak, nonatomic) id<SKNetworkReporterDelegate> delegate;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -7,13 +7,16 @@
|
|||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface SKRequestInfo: NSObject
|
@interface SKRequestInfo : NSObject
|
||||||
@property(assign, readwrite) int64_t identifier;
|
@property(assign, readwrite) int64_t identifier;
|
||||||
@property(assign, readwrite) uint64_t timestamp;
|
@property(assign, readwrite) uint64_t timestamp;
|
||||||
@property(strong, nonatomic) NSURLRequest* request;
|
@property(strong, nonatomic) NSURLRequest* request;
|
||||||
@property(strong, nonatomic) NSString* body;
|
@property(strong, nonatomic) NSString* body;
|
||||||
|
|
||||||
- (instancetype)initWithIdentifier:(int64_t)identifier timestamp:(uint64_t)timestamp request:(NSURLRequest*)request data:(NSData *)data;
|
- (instancetype)initWithIdentifier:(int64_t)identifier
|
||||||
- (void)setBodyFromData:(NSData * _Nullable)data;
|
timestamp:(uint64_t)timestamp
|
||||||
|
request:(NSURLRequest*)request
|
||||||
|
data:(NSData*)data;
|
||||||
|
- (void)setBodyFromData:(NSData* _Nullable)data;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -13,21 +13,23 @@
|
|||||||
@synthesize request = _request;
|
@synthesize request = _request;
|
||||||
@synthesize body = _body;
|
@synthesize body = _body;
|
||||||
|
|
||||||
- (instancetype)initWithIdentifier:(int64_t)identifier timestamp:(uint64_t)timestamp request:(NSURLRequest *)request data:(NSData *)data{
|
- (instancetype)initWithIdentifier:(int64_t)identifier
|
||||||
|
timestamp:(uint64_t)timestamp
|
||||||
if (self = [super init]){
|
request:(NSURLRequest*)request
|
||||||
|
data:(NSData*)data {
|
||||||
|
if (self = [super init]) {
|
||||||
_identifier = identifier;
|
_identifier = identifier;
|
||||||
_timestamp = timestamp;
|
_timestamp = timestamp;
|
||||||
_request = request;
|
_request = request;
|
||||||
_body = data ? [data base64EncodedStringWithOptions: 0]
|
_body = data ? [data base64EncodedStringWithOptions:0]
|
||||||
: [request.HTTPBody base64EncodedStringWithOptions: 0];
|
: [request.HTTPBody base64EncodedStringWithOptions:0];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setBodyFromData:(NSData * _Nullable)data {
|
- (void)setBodyFromData:(NSData* _Nullable)data {
|
||||||
self.body = data ? [data base64EncodedStringWithOptions: 0]
|
self.body = data ? [data base64EncodedStringWithOptions:0]
|
||||||
: [self.request.HTTPBody base64EncodedStringWithOptions: 0];
|
: [self.request.HTTPBody base64EncodedStringWithOptions:0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -14,7 +14,10 @@
|
|||||||
@property(strong, nonatomic) NSURLResponse* response;
|
@property(strong, nonatomic) NSURLResponse* response;
|
||||||
@property(strong, nonatomic) NSString* body;
|
@property(strong, nonatomic) NSString* body;
|
||||||
|
|
||||||
- (instancetype)initWithIndentifier:(int64_t)identifier timestamp:(uint64_t)timestamp response:(NSURLResponse *)response data:(NSData *)data;
|
- (instancetype)initWithIndentifier:(int64_t)identifier
|
||||||
- (void)setBodyFromData:(NSData * _Nullable)data;
|
timestamp:(uint64_t)timestamp
|
||||||
|
response:(NSURLResponse*)response
|
||||||
|
data:(NSData*)data;
|
||||||
|
- (void)setBodyFromData:(NSData* _Nullable)data;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -13,19 +13,24 @@
|
|||||||
@synthesize response = _response;
|
@synthesize response = _response;
|
||||||
@synthesize body = _body;
|
@synthesize body = _body;
|
||||||
|
|
||||||
- (instancetype)initWithIndentifier:(int64_t)identifier timestamp:(uint64_t)timestamp response:(NSURLResponse *)response data:(NSData *)data {
|
- (instancetype)initWithIndentifier:(int64_t)identifier
|
||||||
if(self = [super init]) {
|
timestamp:(uint64_t)timestamp
|
||||||
|
response:(NSURLResponse*)response
|
||||||
|
data:(NSData*)data {
|
||||||
|
if (self = [super init]) {
|
||||||
_identifier = identifier;
|
_identifier = identifier;
|
||||||
_timestamp = timestamp;
|
_timestamp = timestamp;
|
||||||
_response = response;
|
_response = response;
|
||||||
_body = [SKResponseInfo shouldStripReponseBodyWithResponse:response] ? nil : [data base64EncodedStringWithOptions: 0];
|
_body = [SKResponseInfo shouldStripReponseBodyWithResponse:response]
|
||||||
|
? nil
|
||||||
|
: [data base64EncodedStringWithOptions:0];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (BOOL) shouldStripReponseBodyWithResponse:(NSURLResponse *)response {
|
+ (BOOL)shouldStripReponseBodyWithResponse:(NSURLResponse*)response {
|
||||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
|
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
|
||||||
NSString *contentType = httpResponse.allHeaderFields[@"content-type"];
|
NSString* contentType = httpResponse.allHeaderFields[@"content-type"];
|
||||||
if (!contentType) {
|
if (!contentType) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
@@ -35,8 +40,10 @@
|
|||||||
[contentType containsString:@"application/zip"];
|
[contentType containsString:@"application/zip"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setBodyFromData:(NSData *_Nullable)data {
|
- (void)setBodyFromData:(NSData* _Nullable)data {
|
||||||
self.body = [SKResponseInfo shouldStripReponseBodyWithResponse:self.response] ? nil : [data base64EncodedStringWithOptions: 0];
|
self.body = [SKResponseInfo shouldStripReponseBodyWithResponse:self.response]
|
||||||
|
? nil
|
||||||
|
: [data base64EncodedStringWithOptions:0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -8,11 +8,14 @@
|
|||||||
#if FB_SONARKIT_ENABLED
|
#if FB_SONARKIT_ENABLED
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#import <memory>
|
||||||
#import "FlipperKitNetworkPlugin.h"
|
#import "FlipperKitNetworkPlugin.h"
|
||||||
#import "SKDispatchQueue.h"
|
#import "SKDispatchQueue.h"
|
||||||
#import <memory>
|
|
||||||
|
|
||||||
@interface FlipperKitNetworkPlugin(CPPInitialization)
|
@interface FlipperKitNetworkPlugin (CPPInitialization)
|
||||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter dispatchQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)queue;
|
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
|
||||||
|
dispatchQueue:
|
||||||
|
(std::shared_ptr<facebook::flipper::DispatchQueue>)
|
||||||
|
queue;
|
||||||
@end
|
@end
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,10 +21,13 @@
|
|||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
FOUNDATION_EXTERN NSString *const kFLEXNetworkObserverEnabledStateChangedNotification;
|
FOUNDATION_EXTERN NSString* const
|
||||||
|
kFLEXNetworkObserverEnabledStateChangedNotification;
|
||||||
|
|
||||||
/// This class swizzles NSURLConnection and NSURLSession delegate methods to observe events in the URL loading system.
|
/// This class swizzles NSURLConnection and NSURLSession delegate methods to
|
||||||
/// High level network events are sent to the default FLEXNetworkRecorder instance which maintains the request history and caches response bodies.
|
/// observe events in the URL loading system. High level network events are sent
|
||||||
|
/// to the default FLEXNetworkRecorder instance which maintains the request
|
||||||
|
/// history and caches response bodies.
|
||||||
@interface FLEXNetworkObserver : NSObject
|
@interface FLEXNetworkObserver : NSObject
|
||||||
|
|
||||||
+ (void)start;
|
+ (void)start;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -10,60 +10,70 @@
|
|||||||
#import <FlipperKitNetworkPlugin/SKNetworkReporter.h>
|
#import <FlipperKitNetworkPlugin/SKNetworkReporter.h>
|
||||||
|
|
||||||
// Notifications posted when the record is updated
|
// Notifications posted when the record is updated
|
||||||
extern NSString *const kFLEXNetworkRecorderNewTransactionNotification;
|
extern NSString* const kFLEXNetworkRecorderNewTransactionNotification;
|
||||||
extern NSString *const kFLEXNetworkRecorderTransactionUpdatedNotification;
|
extern NSString* const kFLEXNetworkRecorderTransactionUpdatedNotification;
|
||||||
extern NSString *const kFLEXNetworkRecorderUserInfoTransactionKey;
|
extern NSString* const kFLEXNetworkRecorderUserInfoTransactionKey;
|
||||||
extern NSString *const kFLEXNetworkRecorderTransactionsClearedNotification;
|
extern NSString* const kFLEXNetworkRecorderTransactionsClearedNotification;
|
||||||
|
|
||||||
@class FLEXNetworkTransaction;
|
@class FLEXNetworkTransaction;
|
||||||
|
|
||||||
@interface FLEXNetworkRecorder : NSObject
|
@interface FLEXNetworkRecorder : NSObject
|
||||||
|
|
||||||
/// In general, it only makes sense to have one recorder for the entire application.
|
/// In general, it only makes sense to have one recorder for the entire
|
||||||
|
/// application.
|
||||||
+ (instancetype)defaultRecorder;
|
+ (instancetype)defaultRecorder;
|
||||||
|
|
||||||
@property (nonatomic, weak) id<SKNetworkReporterDelegate> delegate;
|
@property(nonatomic, weak) id<SKNetworkReporterDelegate> delegate;
|
||||||
|
|
||||||
/// Defaults to 25 MB if never set. Values set here are presisted across launches of the app.
|
/// Defaults to 25 MB if never set. Values set here are presisted across
|
||||||
@property (nonatomic, assign) NSUInteger responseCacheByteLimit;
|
/// launches of the app.
|
||||||
|
@property(nonatomic, assign) NSUInteger responseCacheByteLimit;
|
||||||
|
|
||||||
/// If NO, the recorder not cache will not cache response for content types with an "image", "video", or "audio" prefix.
|
/// If NO, the recorder not cache will not cache response for content types with
|
||||||
@property (nonatomic, assign) BOOL shouldCacheMediaResponses;
|
/// an "image", "video", or "audio" prefix.
|
||||||
|
@property(nonatomic, assign) BOOL shouldCacheMediaResponses;
|
||||||
@property (nonatomic, copy) NSArray<NSString *> *hostBlacklist;
|
|
||||||
|
|
||||||
|
@property(nonatomic, copy) NSArray<NSString*>* hostBlacklist;
|
||||||
|
|
||||||
// Accessing recorded network activity
|
// Accessing recorded network activity
|
||||||
|
|
||||||
/// Array of FLEXNetworkTransaction objects ordered by start time with the newest first.
|
/// Array of FLEXNetworkTransaction objects ordered by start time with the
|
||||||
- (NSArray<FLEXNetworkTransaction *> *)networkTransactions;
|
/// newest first.
|
||||||
|
- (NSArray<FLEXNetworkTransaction*>*)networkTransactions;
|
||||||
|
|
||||||
/// The full response data IFF it hasn't been purged due to memory pressure.
|
/// The full response data IFF it hasn't been purged due to memory pressure.
|
||||||
- (NSData *)cachedResponseBodyForTransaction:(FLEXNetworkTransaction *)transaction;
|
- (NSData*)cachedResponseBodyForTransaction:
|
||||||
|
(FLEXNetworkTransaction*)transaction;
|
||||||
|
|
||||||
/// Dumps all network transactions and cached response bodies.
|
/// Dumps all network transactions and cached response bodies.
|
||||||
- (void)clearRecordedActivity;
|
- (void)clearRecordedActivity;
|
||||||
|
|
||||||
|
|
||||||
// Recording network activity
|
// Recording network activity
|
||||||
|
|
||||||
/// Call when app is about to send HTTP request.
|
/// Call when app is about to send HTTP request.
|
||||||
- (void)recordRequestWillBeSentWithRequestID:(NSString *)requestID request:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse;
|
- (void)recordRequestWillBeSentWithRequestID:(NSString*)requestID
|
||||||
|
request:(NSURLRequest*)request
|
||||||
|
redirectResponse:(NSURLResponse*)redirectResponse;
|
||||||
|
|
||||||
/// Call when HTTP response is available.
|
/// Call when HTTP response is available.
|
||||||
- (void)recordResponseReceivedWithRequestID:(NSString *)requestID response:(NSURLResponse *)response;
|
- (void)recordResponseReceivedWithRequestID:(NSString*)requestID
|
||||||
|
response:(NSURLResponse*)response;
|
||||||
|
|
||||||
/// Call when data chunk is received over the network.
|
/// Call when data chunk is received over the network.
|
||||||
- (void)recordDataReceivedWithRequestID:(NSString *)requestID dataLength:(int64_t)dataLength;
|
- (void)recordDataReceivedWithRequestID:(NSString*)requestID
|
||||||
|
dataLength:(int64_t)dataLength;
|
||||||
|
|
||||||
/// Call when HTTP request has finished loading.
|
/// Call when HTTP request has finished loading.
|
||||||
- (void)recordLoadingFinishedWithRequestID:(NSString *)requestID responseBody:(NSData *)responseBody;
|
- (void)recordLoadingFinishedWithRequestID:(NSString*)requestID
|
||||||
|
responseBody:(NSData*)responseBody;
|
||||||
|
|
||||||
/// Call when HTTP request has failed to load.
|
/// Call when HTTP request has failed to load.
|
||||||
- (void)recordLoadingFailedWithRequestID:(NSString *)requestID error:(NSError *)error;
|
- (void)recordLoadingFailedWithRequestID:(NSString*)requestID
|
||||||
|
error:(NSError*)error;
|
||||||
|
|
||||||
/// Call to set the request mechanism anytime after recordRequestWillBeSent... has been called.
|
/// Call to set the request mechanism anytime after recordRequestWillBeSent...
|
||||||
/// This string can be set to anything useful about the API used to make the request.
|
/// has been called. This string can be set to anything useful about the API
|
||||||
- (void)recordMechanism:(NSString *)mechanism forRequestID:(NSString *)requestID;
|
/// used to make the request.
|
||||||
|
- (void)recordMechanism:(NSString*)mechanism forRequestID:(NSString*)requestID;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -10,49 +10,60 @@
|
|||||||
#import "FLEXNetworkTransaction.h"
|
#import "FLEXNetworkTransaction.h"
|
||||||
#import "FLEXUtility.h"
|
#import "FLEXUtility.h"
|
||||||
|
|
||||||
NSString *const kFLEXNetworkRecorderNewTransactionNotification = @"kFLEXNetworkRecorderNewTransactionNotification";
|
NSString* const kFLEXNetworkRecorderNewTransactionNotification =
|
||||||
NSString *const kFLEXNetworkRecorderTransactionUpdatedNotification = @"kFLEXNetworkRecorderTransactionUpdatedNotification";
|
@"kFLEXNetworkRecorderNewTransactionNotification";
|
||||||
NSString *const kFLEXNetworkRecorderUserInfoTransactionKey = @"transaction";
|
NSString* const kFLEXNetworkRecorderTransactionUpdatedNotification =
|
||||||
NSString *const kFLEXNetworkRecorderTransactionsClearedNotification = @"kFLEXNetworkRecorderTransactionsClearedNotification";
|
@"kFLEXNetworkRecorderTransactionUpdatedNotification";
|
||||||
|
NSString* const kFLEXNetworkRecorderUserInfoTransactionKey = @"transaction";
|
||||||
|
NSString* const kFLEXNetworkRecorderTransactionsClearedNotification =
|
||||||
|
@"kFLEXNetworkRecorderTransactionsClearedNotification";
|
||||||
|
|
||||||
NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.responseCacheLimit";
|
NSString* const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey =
|
||||||
|
@"com.flex.responseCacheLimit";
|
||||||
|
|
||||||
@interface FLEXNetworkRecorder ()
|
@interface FLEXNetworkRecorder ()
|
||||||
|
|
||||||
@property (nonatomic, strong) NSCache *responseCache;
|
@property(nonatomic, strong) NSCache* responseCache;
|
||||||
@property (nonatomic, strong) NSMutableArray<FLEXNetworkTransaction *> *orderedTransactions;
|
@property(nonatomic, strong)
|
||||||
@property (nonatomic, strong) NSMutableDictionary<NSString *, FLEXNetworkTransaction *> *networkTransactionsForRequestIdentifiers;
|
NSMutableArray<FLEXNetworkTransaction*>* orderedTransactions;
|
||||||
@property (nonatomic, strong) dispatch_queue_t queue;
|
@property(nonatomic, strong)
|
||||||
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *identifierDict;
|
NSMutableDictionary<NSString*, FLEXNetworkTransaction*>*
|
||||||
|
networkTransactionsForRequestIdentifiers;
|
||||||
|
@property(nonatomic, strong) dispatch_queue_t queue;
|
||||||
|
@property(nonatomic, strong)
|
||||||
|
NSMutableDictionary<NSString*, NSNumber*>* identifierDict;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation FLEXNetworkRecorder
|
@implementation FLEXNetworkRecorder
|
||||||
|
|
||||||
- (instancetype)init
|
- (instancetype)init {
|
||||||
{
|
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self) {
|
if (self) {
|
||||||
_responseCache = [NSCache new];
|
_responseCache = [NSCache new];
|
||||||
NSUInteger responseCacheLimit = [[[NSUserDefaults standardUserDefaults] objectForKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey] unsignedIntegerValue];
|
NSUInteger responseCacheLimit = [[[NSUserDefaults standardUserDefaults]
|
||||||
|
objectForKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey]
|
||||||
|
unsignedIntegerValue];
|
||||||
if (responseCacheLimit) {
|
if (responseCacheLimit) {
|
||||||
[_responseCache setTotalCostLimit:responseCacheLimit];
|
[_responseCache setTotalCostLimit:responseCacheLimit];
|
||||||
} else {
|
} else {
|
||||||
// Default to 25 MB max. The cache will purge earlier if there is memory pressure.
|
// Default to 25 MB max. The cache will purge earlier if there is memory
|
||||||
|
// pressure.
|
||||||
[_responseCache setTotalCostLimit:25 * 1024 * 1024];
|
[_responseCache setTotalCostLimit:25 * 1024 * 1024];
|
||||||
}
|
}
|
||||||
_orderedTransactions = [NSMutableArray array];
|
_orderedTransactions = [NSMutableArray array];
|
||||||
_networkTransactionsForRequestIdentifiers = [NSMutableDictionary dictionary];
|
_networkTransactionsForRequestIdentifiers =
|
||||||
|
[NSMutableDictionary dictionary];
|
||||||
|
|
||||||
// Serial queue used because we use mutable objects that are not thread safe
|
// Serial queue used because we use mutable objects that are not thread safe
|
||||||
_queue = dispatch_queue_create("com.flex.FLEXNetworkRecorder", DISPATCH_QUEUE_SERIAL);
|
_queue = dispatch_queue_create(
|
||||||
|
"com.flex.FLEXNetworkRecorder", DISPATCH_QUEUE_SERIAL);
|
||||||
_identifierDict = [NSMutableDictionary dictionary];
|
_identifierDict = [NSMutableDictionary dictionary];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)defaultRecorder
|
+ (instancetype)defaultRecorder {
|
||||||
{
|
static FLEXNetworkRecorder* defaultRecorder = nil;
|
||||||
static FLEXNetworkRecorder *defaultRecorder = nil;
|
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
defaultRecorder = [[[self class] alloc] init];
|
defaultRecorder = [[[self class] alloc] init];
|
||||||
@@ -66,33 +77,31 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
|||||||
_delegate = delegate;
|
_delegate = delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)responseCacheByteLimit
|
- (NSUInteger)responseCacheByteLimit {
|
||||||
{
|
|
||||||
return [self.responseCache totalCostLimit];
|
return [self.responseCache totalCostLimit];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setResponseCacheByteLimit:(NSUInteger)responseCacheByteLimit
|
- (void)setResponseCacheByteLimit:(NSUInteger)responseCacheByteLimit {
|
||||||
{
|
|
||||||
[self.responseCache setTotalCostLimit:responseCacheByteLimit];
|
[self.responseCache setTotalCostLimit:responseCacheByteLimit];
|
||||||
[[NSUserDefaults standardUserDefaults] setObject:@(responseCacheByteLimit) forKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey];
|
[[NSUserDefaults standardUserDefaults]
|
||||||
|
setObject:@(responseCacheByteLimit)
|
||||||
|
forKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<FLEXNetworkTransaction *> *)networkTransactions
|
- (NSArray<FLEXNetworkTransaction*>*)networkTransactions {
|
||||||
{
|
__block NSArray<FLEXNetworkTransaction*>* transactions = nil;
|
||||||
__block NSArray<FLEXNetworkTransaction *> *transactions = nil;
|
|
||||||
dispatch_sync(self.queue, ^{
|
dispatch_sync(self.queue, ^{
|
||||||
transactions = [self.orderedTransactions copy];
|
transactions = [self.orderedTransactions copy];
|
||||||
});
|
});
|
||||||
return transactions;
|
return transactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSData *)cachedResponseBodyForTransaction:(FLEXNetworkTransaction *)transaction
|
- (NSData*)cachedResponseBodyForTransaction:
|
||||||
{
|
(FLEXNetworkTransaction*)transaction {
|
||||||
return [self.responseCache objectForKey:transaction.requestID];
|
return [self.responseCache objectForKey:transaction.requestID];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)clearRecordedActivity
|
- (void)clearRecordedActivity {
|
||||||
{
|
|
||||||
dispatch_async(self.queue, ^{
|
dispatch_async(self.queue, ^{
|
||||||
[self.responseCache removeAllObjects];
|
[self.responseCache removeAllObjects];
|
||||||
[self.orderedTransactions removeAllObjects];
|
[self.orderedTransactions removeAllObjects];
|
||||||
@@ -102,54 +111,64 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
|||||||
|
|
||||||
#pragma mark - Network Events
|
#pragma mark - Network Events
|
||||||
|
|
||||||
- (void)recordRequestWillBeSentWithRequestID:(NSString *)requestID request:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
|
- (void)recordRequestWillBeSentWithRequestID:(NSString*)requestID
|
||||||
{
|
request:(NSURLRequest*)request
|
||||||
|
redirectResponse:(NSURLResponse*)redirectResponse {
|
||||||
if (![self.identifierDict objectForKey:requestID]) {
|
if (![self.identifierDict objectForKey:requestID]) {
|
||||||
self.identifierDict[requestID] = [NSNumber random];
|
self.identifierDict[requestID] = [NSNumber random];
|
||||||
}
|
}
|
||||||
NSDate *startDate = [NSDate date];
|
NSDate* startDate = [NSDate date];
|
||||||
|
|
||||||
if (redirectResponse) {
|
if (redirectResponse) {
|
||||||
[self recordResponseReceivedWithRequestID:requestID response:redirectResponse];
|
[self recordResponseReceivedWithRequestID:requestID
|
||||||
|
response:redirectResponse];
|
||||||
[self recordLoadingFinishedWithRequestID:requestID responseBody:nil];
|
[self recordLoadingFinishedWithRequestID:requestID responseBody:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_async(self.queue, ^{
|
dispatch_async(self.queue, ^{
|
||||||
SKRequestInfo *info = [[SKRequestInfo alloc] initWithIdentifier:self.identifierDict[requestID].longLongValue timestamp:[NSDate timestamp] request:request data:request.HTTPBody];
|
SKRequestInfo* info = [[SKRequestInfo alloc]
|
||||||
|
initWithIdentifier:self.identifierDict[requestID].longLongValue
|
||||||
|
timestamp:[NSDate timestamp]
|
||||||
|
request:request
|
||||||
|
data:request.HTTPBody];
|
||||||
[self.delegate didObserveRequest:info];
|
[self.delegate didObserveRequest:info];
|
||||||
|
|
||||||
FLEXNetworkTransaction *transaction = [FLEXNetworkTransaction new];
|
FLEXNetworkTransaction* transaction = [FLEXNetworkTransaction new];
|
||||||
transaction.requestID = requestID;
|
transaction.requestID = requestID;
|
||||||
transaction.request = request;
|
transaction.request = request;
|
||||||
transaction.startTime = startDate;
|
transaction.startTime = startDate;
|
||||||
|
|
||||||
[self.orderedTransactions insertObject:transaction atIndex:0];
|
[self.orderedTransactions insertObject:transaction atIndex:0];
|
||||||
[self.networkTransactionsForRequestIdentifiers setObject:transaction forKey:requestID];
|
[self.networkTransactionsForRequestIdentifiers setObject:transaction
|
||||||
|
forKey:requestID];
|
||||||
transaction.transactionState = FLEXNetworkTransactionStateAwaitingResponse;
|
transaction.transactionState = FLEXNetworkTransactionStateAwaitingResponse;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call when HTTP response is available.
|
/// Call when HTTP response is available.
|
||||||
- (void)recordResponseReceivedWithRequestID:(NSString *)requestID response:(NSURLResponse *)response
|
- (void)recordResponseReceivedWithRequestID:(NSString*)requestID
|
||||||
{
|
response:(NSURLResponse*)response {
|
||||||
NSDate *responseDate = [NSDate date];
|
NSDate* responseDate = [NSDate date];
|
||||||
|
|
||||||
dispatch_async(self.queue, ^{
|
dispatch_async(self.queue, ^{
|
||||||
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
|
FLEXNetworkTransaction* transaction =
|
||||||
|
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||||
if (!transaction) {
|
if (!transaction) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
transaction.response = response;
|
transaction.response = response;
|
||||||
transaction.transactionState = FLEXNetworkTransactionStateReceivingData;
|
transaction.transactionState = FLEXNetworkTransactionStateReceivingData;
|
||||||
transaction.latency = -[transaction.startTime timeIntervalSinceDate:responseDate];
|
transaction.latency =
|
||||||
|
-[transaction.startTime timeIntervalSinceDate:responseDate];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call when data chunk is received over the network.
|
/// Call when data chunk is received over the network.
|
||||||
- (void)recordDataReceivedWithRequestID:(NSString *)requestID dataLength:(int64_t)dataLength
|
- (void)recordDataReceivedWithRequestID:(NSString*)requestID
|
||||||
{
|
dataLength:(int64_t)dataLength {
|
||||||
dispatch_async(self.queue, ^{
|
dispatch_async(self.queue, ^{
|
||||||
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
|
FLEXNetworkTransaction* transaction =
|
||||||
|
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||||
if (!transaction) {
|
if (!transaction) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -158,45 +177,59 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Call when HTTP request has finished loading.
|
/// Call when HTTP request has finished loading.
|
||||||
- (void)recordLoadingFinishedWithRequestID:(NSString *)requestID responseBody:(NSData *)responseBody
|
- (void)recordLoadingFinishedWithRequestID:(NSString*)requestID
|
||||||
{
|
responseBody:(NSData*)responseBody {
|
||||||
NSDate *finishedDate = [NSDate date];
|
NSDate* finishedDate = [NSDate date];
|
||||||
dispatch_async(self.queue, ^{
|
dispatch_async(self.queue, ^{
|
||||||
|
FLEXNetworkTransaction* transaction =
|
||||||
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
|
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||||
if (!transaction) {
|
if (!transaction) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
transaction.transactionState = FLEXNetworkTransactionStateFinished;
|
transaction.transactionState = FLEXNetworkTransactionStateFinished;
|
||||||
transaction.duration = -[transaction.startTime timeIntervalSinceDate:finishedDate];
|
transaction.duration =
|
||||||
SKResponseInfo *responseInfo = [[SKResponseInfo alloc] initWithIndentifier:self.identifierDict[requestID].longLongValue timestamp:[NSDate timestamp] response:transaction.response data:responseBody];
|
-[transaction.startTime timeIntervalSinceDate:finishedDate];
|
||||||
self.identifierDict[requestID] = nil; //Clear the entry
|
SKResponseInfo* responseInfo = [[SKResponseInfo alloc]
|
||||||
|
initWithIndentifier:self.identifierDict[requestID].longLongValue
|
||||||
|
timestamp:[NSDate timestamp]
|
||||||
|
response:transaction.response
|
||||||
|
data:responseBody];
|
||||||
|
self.identifierDict[requestID] = nil; // Clear the entry
|
||||||
[self.delegate didObserveResponse:responseInfo];
|
[self.delegate didObserveResponse:responseInfo];
|
||||||
|
|
||||||
BOOL shouldCache = [responseBody length] > 0;
|
BOOL shouldCache = [responseBody length] > 0;
|
||||||
if (!self.shouldCacheMediaResponses) {
|
if (!self.shouldCacheMediaResponses) {
|
||||||
NSArray<NSString *> *ignoredMIMETypePrefixes = @[ @"audio", @"image", @"video" ];
|
NSArray<NSString*>* ignoredMIMETypePrefixes =
|
||||||
for (NSString *ignoredPrefix in ignoredMIMETypePrefixes) {
|
@[ @"audio", @"image", @"video" ];
|
||||||
shouldCache = shouldCache && ![transaction.response.MIMEType hasPrefix:ignoredPrefix];
|
for (NSString* ignoredPrefix in ignoredMIMETypePrefixes) {
|
||||||
|
shouldCache = shouldCache &&
|
||||||
|
![transaction.response.MIMEType hasPrefix:ignoredPrefix];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldCache) {
|
if (shouldCache) {
|
||||||
[self.responseCache setObject:responseBody forKey:requestID cost:[responseBody length]];
|
[self.responseCache setObject:responseBody
|
||||||
|
forKey:requestID
|
||||||
|
cost:[responseBody length]];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)recordLoadingFailedWithRequestID:(NSString *)requestID error:(NSError *)error
|
- (void)recordLoadingFailedWithRequestID:(NSString*)requestID
|
||||||
{
|
error:(NSError*)error {
|
||||||
dispatch_async(self.queue, ^{
|
dispatch_async(self.queue, ^{
|
||||||
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
|
FLEXNetworkTransaction* transaction =
|
||||||
|
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||||
if (!transaction) {
|
if (!transaction) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SKResponseInfo *responseInfo = [[SKResponseInfo alloc] initWithIndentifier:self.identifierDict[requestID].longLongValue timestamp:[NSDate timestamp] response:transaction.response data: nil];
|
SKResponseInfo* responseInfo = [[SKResponseInfo alloc]
|
||||||
self.identifierDict[requestID] = nil; //Clear the entry
|
initWithIndentifier:self.identifierDict[requestID].longLongValue
|
||||||
|
timestamp:[NSDate timestamp]
|
||||||
|
response:transaction.response
|
||||||
|
data:nil];
|
||||||
|
self.identifierDict[requestID] = nil; // Clear the entry
|
||||||
[self.delegate didObserveResponse:responseInfo];
|
[self.delegate didObserveResponse:responseInfo];
|
||||||
transaction.transactionState = FLEXNetworkTransactionStateFailed;
|
transaction.transactionState = FLEXNetworkTransactionStateFailed;
|
||||||
transaction.duration = -[transaction.startTime timeIntervalSinceNow];
|
transaction.duration = -[transaction.startTime timeIntervalSinceNow];
|
||||||
@@ -204,10 +237,10 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)recordMechanism:(NSString *)mechanism forRequestID:(NSString *)requestID
|
- (void)recordMechanism:(NSString*)mechanism forRequestID:(NSString*)requestID {
|
||||||
{
|
|
||||||
dispatch_async(self.queue, ^{
|
dispatch_async(self.queue, ^{
|
||||||
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
|
FLEXNetworkTransaction* transaction =
|
||||||
|
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||||
if (!transaction) {
|
if (!transaction) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,26 +19,28 @@ typedef NS_ENUM(NSInteger, FLEXNetworkTransactionState) {
|
|||||||
|
|
||||||
@interface FLEXNetworkTransaction : NSObject
|
@interface FLEXNetworkTransaction : NSObject
|
||||||
|
|
||||||
@property (nonatomic, copy) NSString *requestID;
|
@property(nonatomic, copy) NSString* requestID;
|
||||||
|
|
||||||
@property (nonatomic, strong) NSURLRequest *request;
|
@property(nonatomic, strong) NSURLRequest* request;
|
||||||
@property (nonatomic, strong) NSURLResponse *response;
|
@property(nonatomic, strong) NSURLResponse* response;
|
||||||
@property (nonatomic, copy) NSString *requestMechanism;
|
@property(nonatomic, copy) NSString* requestMechanism;
|
||||||
@property (nonatomic, assign) FLEXNetworkTransactionState transactionState;
|
@property(nonatomic, assign) FLEXNetworkTransactionState transactionState;
|
||||||
@property (nonatomic, strong) NSError *error;
|
@property(nonatomic, strong) NSError* error;
|
||||||
|
|
||||||
@property (nonatomic, strong) NSDate *startTime;
|
@property(nonatomic, strong) NSDate* startTime;
|
||||||
@property (nonatomic, assign) NSTimeInterval latency;
|
@property(nonatomic, assign) NSTimeInterval latency;
|
||||||
@property (nonatomic, assign) NSTimeInterval duration;
|
@property(nonatomic, assign) NSTimeInterval duration;
|
||||||
|
|
||||||
@property (nonatomic, assign) int64_t receivedDataLength;
|
@property(nonatomic, assign) int64_t receivedDataLength;
|
||||||
|
|
||||||
/// Only applicable for image downloads. A small thumbnail to preview the full response.
|
/// Only applicable for image downloads. A small thumbnail to preview the full
|
||||||
@property (nonatomic, strong) UIImage *responseThumbnail;
|
/// response.
|
||||||
|
@property(nonatomic, strong) UIImage* responseThumbnail;
|
||||||
|
|
||||||
/// Populated lazily. Handles both normal HTTPBody data and HTTPBodyStreams.
|
/// Populated lazily. Handles both normal HTTPBody data and HTTPBodyStreams.
|
||||||
@property (nonatomic, strong, readonly) NSData *cachedRequestBody;
|
@property(nonatomic, strong, readonly) NSData* cachedRequestBody;
|
||||||
|
|
||||||
+ (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state;
|
+ (NSString*)readableStringFromTransactionState:
|
||||||
|
(FLEXNetworkTransactionState)state;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,33 +9,38 @@
|
|||||||
|
|
||||||
@interface FLEXNetworkTransaction ()
|
@interface FLEXNetworkTransaction ()
|
||||||
|
|
||||||
@property (nonatomic, strong, readwrite) NSData *cachedRequestBody;
|
@property(nonatomic, strong, readwrite) NSData* cachedRequestBody;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation FLEXNetworkTransaction
|
@implementation FLEXNetworkTransaction
|
||||||
|
|
||||||
- (NSString *)description
|
- (NSString*)description {
|
||||||
{
|
NSString* description = [super description];
|
||||||
NSString *description = [super description];
|
|
||||||
|
|
||||||
description = [description stringByAppendingFormat:@" id = %@;", self.requestID];
|
description =
|
||||||
description = [description stringByAppendingFormat:@" url = %@;", self.request.URL];
|
[description stringByAppendingFormat:@" id = %@;", self.requestID];
|
||||||
description = [description stringByAppendingFormat:@" duration = %f;", self.duration];
|
description =
|
||||||
description = [description stringByAppendingFormat:@" receivedDataLength = %lld", self.receivedDataLength];
|
[description stringByAppendingFormat:@" url = %@;", self.request.URL];
|
||||||
|
description =
|
||||||
|
[description stringByAppendingFormat:@" duration = %f;", self.duration];
|
||||||
|
description =
|
||||||
|
[description stringByAppendingFormat:@" receivedDataLength = %lld",
|
||||||
|
self.receivedDataLength];
|
||||||
|
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSData *)cachedRequestBody {
|
- (NSData*)cachedRequestBody {
|
||||||
if (!_cachedRequestBody) {
|
if (!_cachedRequestBody) {
|
||||||
if (self.request.HTTPBody != nil) {
|
if (self.request.HTTPBody != nil) {
|
||||||
_cachedRequestBody = self.request.HTTPBody;
|
_cachedRequestBody = self.request.HTTPBody;
|
||||||
} else if ([self.request.HTTPBodyStream conformsToProtocol:@protocol(NSCopying)]) {
|
} else if ([self.request.HTTPBodyStream
|
||||||
NSInputStream *bodyStream = [self.request.HTTPBodyStream copy];
|
conformsToProtocol:@protocol(NSCopying)]) {
|
||||||
|
NSInputStream* bodyStream = [self.request.HTTPBodyStream copy];
|
||||||
const NSUInteger bufferSize = 1024;
|
const NSUInteger bufferSize = 1024;
|
||||||
uint8_t buffer[bufferSize];
|
uint8_t buffer[bufferSize];
|
||||||
NSMutableData *data = [NSMutableData data];
|
NSMutableData* data = [NSMutableData data];
|
||||||
[bodyStream open];
|
[bodyStream open];
|
||||||
NSInteger readBytes = 0;
|
NSInteger readBytes = 0;
|
||||||
do {
|
do {
|
||||||
@@ -49,9 +54,9 @@
|
|||||||
return _cachedRequestBody;
|
return _cachedRequestBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state
|
+ (NSString*)readableStringFromTransactionState:
|
||||||
{
|
(FLEXNetworkTransactionState)state {
|
||||||
NSString *readableString = nil;
|
NSString* readableString = nil;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case FLEXNetworkTransactionStateUnstarted:
|
case FLEXNetworkTransactionStateUnstarted:
|
||||||
readableString = @"Unstarted";
|
readableString = @"Unstarted";
|
||||||
|
|||||||
@@ -12,13 +12,15 @@
|
|||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
#define FLEXFloor(x) (floor([[UIScreen mainScreen] scale] * (x)) / [[UIScreen mainScreen] scale])
|
#define FLEXFloor(x) \
|
||||||
|
(floor([[UIScreen mainScreen] scale] * (x)) / [[UIScreen mainScreen] scale])
|
||||||
|
|
||||||
#define FLEX_AT_LEAST_IOS11_SDK defined(__IPHONE_11_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0)
|
#define FLEX_AT_LEAST_IOS11_SDK \
|
||||||
|
defined(__IPHONE_11_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0)
|
||||||
|
|
||||||
@interface NSNumber (SonarUtility)
|
@interface NSNumber (SonarUtility)
|
||||||
|
|
||||||
+ (NSNumber *)random;
|
+ (NSNumber*)random;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -32,8 +34,18 @@
|
|||||||
// Swizzling utilities
|
// Swizzling utilities
|
||||||
|
|
||||||
+ (SEL)swizzledSelectorForSelector:(SEL)selector;
|
+ (SEL)swizzledSelectorForSelector:(SEL)selector;
|
||||||
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls;
|
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector
|
||||||
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)className withBlock:(id)block swizzledSelector:(SEL)swizzledSelector;
|
class:(Class)cls;
|
||||||
+ (void)replaceImplementationOfSelector:(SEL)selector withSelector:(SEL)swizzledSelector forClass:(Class)cls withMethodDescription:(struct objc_method_description)methodDescription implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock;
|
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector
|
||||||
|
onClass:(Class)className
|
||||||
|
withBlock:(id)block
|
||||||
|
swizzledSelector:(SEL)swizzledSelector;
|
||||||
|
+ (void)replaceImplementationOfSelector:(SEL)selector
|
||||||
|
withSelector:(SEL)swizzledSelector
|
||||||
|
forClass:(Class)cls
|
||||||
|
withMethodDescription:
|
||||||
|
(struct objc_method_description)methodDescription
|
||||||
|
implementationBlock:(id)implementationBlock
|
||||||
|
undefinedBlock:(id)undefinedBlock;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -7,26 +7,28 @@
|
|||||||
|
|
||||||
#import "FLEXUtility.h"
|
#import "FLEXUtility.h"
|
||||||
|
|
||||||
#import <objc/runtime.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#import <zlib.h>
|
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
#include <mach/mach_time.h>
|
#include <mach/mach_time.h>
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
#import <zlib.h>
|
||||||
|
|
||||||
#import <ImageIO/ImageIO.h>
|
#import <ImageIO/ImageIO.h>
|
||||||
|
|
||||||
@implementation FLEXUtility
|
@implementation FLEXUtility
|
||||||
|
|
||||||
+ (SEL)swizzledSelectorForSelector:(SEL)selector
|
+ (SEL)swizzledSelectorForSelector:(SEL)selector {
|
||||||
{
|
return NSSelectorFromString(
|
||||||
return NSSelectorFromString([NSString stringWithFormat:@"_flex_swizzle_%x_%@", arc4random(), NSStringFromSelector(selector)]);
|
[NSString stringWithFormat:@"_flex_swizzle_%x_%@",
|
||||||
|
arc4random(),
|
||||||
|
NSStringFromSelector(selector)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls
|
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector
|
||||||
{
|
class:(Class)cls {
|
||||||
if ([cls instancesRespondToSelector:selector]) {
|
if ([cls instancesRespondToSelector:selector]) {
|
||||||
unsigned int numMethods = 0;
|
unsigned int numMethods = 0;
|
||||||
Method *methods = class_copyMethodList(cls, &numMethods);
|
Method* methods = class_copyMethodList(cls, &numMethods);
|
||||||
|
|
||||||
BOOL implementsSelector = NO;
|
BOOL implementsSelector = NO;
|
||||||
for (int index = 0; index < numMethods; index++) {
|
for (int index = 0; index < numMethods; index++) {
|
||||||
@@ -47,32 +49,46 @@
|
|||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)className withBlock:(id)block swizzledSelector:(SEL)swizzledSelector
|
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector
|
||||||
{
|
onClass:(Class)className
|
||||||
// This method is only intended for swizzling methods that are know to exist on the class.
|
withBlock:(id)block
|
||||||
// Bail if that isn't the case.
|
swizzledSelector:(SEL)swizzledSelector {
|
||||||
|
// This method is only intended for swizzling methods that are know to exist
|
||||||
|
// on the class. Bail if that isn't the case.
|
||||||
Method originalMethod = class_getInstanceMethod(className, originalSelector);
|
Method originalMethod = class_getInstanceMethod(className, originalSelector);
|
||||||
if (!originalMethod) {
|
if (!originalMethod) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMP implementation = imp_implementationWithBlock(block);
|
IMP implementation = imp_implementationWithBlock(block);
|
||||||
class_addMethod(className, swizzledSelector, implementation, method_getTypeEncoding(originalMethod));
|
class_addMethod(
|
||||||
|
className,
|
||||||
|
swizzledSelector,
|
||||||
|
implementation,
|
||||||
|
method_getTypeEncoding(originalMethod));
|
||||||
Method newMethod = class_getInstanceMethod(className, swizzledSelector);
|
Method newMethod = class_getInstanceMethod(className, swizzledSelector);
|
||||||
method_exchangeImplementations(originalMethod, newMethod);
|
method_exchangeImplementations(originalMethod, newMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)replaceImplementationOfSelector:(SEL)selector withSelector:(SEL)swizzledSelector forClass:(Class)cls withMethodDescription:(struct objc_method_description)methodDescription implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock
|
+ (void)replaceImplementationOfSelector:(SEL)selector
|
||||||
{
|
withSelector:(SEL)swizzledSelector
|
||||||
|
forClass:(Class)cls
|
||||||
|
withMethodDescription:
|
||||||
|
(struct objc_method_description)methodDescription
|
||||||
|
implementationBlock:(id)implementationBlock
|
||||||
|
undefinedBlock:(id)undefinedBlock {
|
||||||
if ([self instanceRespondsButDoesNotImplementSelector:selector class:cls]) {
|
if ([self instanceRespondsButDoesNotImplementSelector:selector class:cls]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMP implementation = imp_implementationWithBlock((id)([cls instancesRespondToSelector:selector] ? implementationBlock : undefinedBlock));
|
IMP implementation = imp_implementationWithBlock((id)(
|
||||||
|
[cls instancesRespondToSelector:selector] ? implementationBlock
|
||||||
|
: undefinedBlock));
|
||||||
|
|
||||||
Method oldMethod = class_getInstanceMethod(cls, selector);
|
Method oldMethod = class_getInstanceMethod(cls, selector);
|
||||||
if (oldMethod) {
|
if (oldMethod) {
|
||||||
class_addMethod(cls, swizzledSelector, implementation, methodDescription.types);
|
class_addMethod(
|
||||||
|
cls, swizzledSelector, implementation, methodDescription.types);
|
||||||
|
|
||||||
Method newMethod = class_getInstanceMethod(cls, swizzledSelector);
|
Method newMethod = class_getInstanceMethod(cls, swizzledSelector);
|
||||||
|
|
||||||
@@ -86,7 +102,7 @@
|
|||||||
|
|
||||||
@implementation NSNumber (SonarUtility)
|
@implementation NSNumber (SonarUtility)
|
||||||
|
|
||||||
+ (NSNumber *)random {
|
+ (NSNumber*)random {
|
||||||
int64_t identifier;
|
int64_t identifier;
|
||||||
arc4random_buf(&identifier, sizeof(int64_t));
|
arc4random_buf(&identifier, sizeof(int64_t));
|
||||||
return @(identifier);
|
return @(identifier);
|
||||||
@@ -96,8 +112,7 @@
|
|||||||
|
|
||||||
@implementation NSDate (SonarUtility)
|
@implementation NSDate (SonarUtility)
|
||||||
|
|
||||||
+ (uint64_t)getTimeNanoseconds
|
+ (uint64_t)getTimeNanoseconds {
|
||||||
{
|
|
||||||
static struct mach_timebase_info tb_info = {0};
|
static struct mach_timebase_info tb_info = {0};
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
#if FB_SONARKIT_ENABLED
|
#if FB_SONARKIT_ENABLED
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#import <FlipperKitNetworkPlugin/SKNetworkReporter.h>
|
#import <FlipperKitNetworkPlugin/SKNetworkReporter.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@interface SKIOSNetworkAdapter : NSObject<SKNetworkAdapterDelegate>
|
@interface SKIOSNetworkAdapter : NSObject<SKNetworkAdapterDelegate>
|
||||||
- (instancetype)init NS_DESIGNATED_INITIALIZER;
|
- (instancetype)init NS_DESIGNATED_INITIALIZER;
|
||||||
@property (weak, nonatomic) id<SKNetworkReporterDelegate> delegate;
|
@property(weak, nonatomic) id<SKNetworkReporterDelegate> delegate;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
@implementation SKIOSNetworkAdapter
|
@implementation SKIOSNetworkAdapter
|
||||||
@synthesize delegate = _delegate;
|
@synthesize delegate = _delegate;
|
||||||
- (instancetype)init{
|
- (instancetype)init {
|
||||||
if (self=[super init]){
|
if (self = [super init]) {
|
||||||
_delegate = nil;
|
_delegate = nil;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
+ (instancetype)sharedInstance;
|
+ (instancetype)sharedInstance;
|
||||||
+ (UIColor*)overlayColor;
|
+ (UIColor*)overlayColor;
|
||||||
|
|
||||||
- (void)mountInView:(UIView *)view withFrame:(CGRect)frame;
|
- (void)mountInView:(UIView*)view withFrame:(CGRect)frame;
|
||||||
- (void)unmount;
|
- (void)unmount;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,13 +9,12 @@
|
|||||||
|
|
||||||
#import "SKHighlightOverlay.h"
|
#import "SKHighlightOverlay.h"
|
||||||
|
|
||||||
@implementation SKHighlightOverlay
|
@implementation SKHighlightOverlay {
|
||||||
{
|
CALayer* _overlayLayer;
|
||||||
CALayer *_overlayLayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (instancetype)sharedInstance {
|
+ (instancetype)sharedInstance {
|
||||||
static SKHighlightOverlay *sharedInstance = nil;
|
static SKHighlightOverlay* sharedInstance = nil;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
sharedInstance = [self new];
|
sharedInstance = [self new];
|
||||||
@@ -32,12 +31,12 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mountInView:(UIView *)view withFrame:(CGRect)frame {
|
- (void)mountInView:(UIView*)view withFrame:(CGRect)frame {
|
||||||
[CATransaction begin];
|
[CATransaction begin];
|
||||||
[CATransaction setValue:(id)kCFBooleanTrue
|
[CATransaction setValue:(id)kCFBooleanTrue
|
||||||
forKey:kCATransactionDisableActions];
|
forKey:kCATransactionDisableActions];
|
||||||
_overlayLayer.frame = frame;
|
_overlayLayer.frame = frame;
|
||||||
[view.layer addSublayer: _overlayLayer];
|
[view.layer addSublayer:_overlayLayer];
|
||||||
[CATransaction commit];
|
[CATransaction commit];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +45,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
+ (UIColor*)overlayColor {
|
+ (UIColor*)overlayColor {
|
||||||
return [UIColor colorWithRed:136.0 / 255.0 green:117.0 / 255.0 blue:197.0 / 255.0 alpha:0.6];
|
return [UIColor colorWithRed:136.0 / 255.0
|
||||||
|
green:117.0 / 255.0
|
||||||
|
blue:197.0 / 255.0
|
||||||
|
alpha:0.6];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -13,8 +13,7 @@
|
|||||||
|
|
||||||
#import "Plugins.h"
|
#import "Plugins.h"
|
||||||
|
|
||||||
void FlipperKitReactPluginInit(FlipperClient *client)
|
void FlipperKitReactPluginInit(FlipperClient* client) {
|
||||||
{
|
|
||||||
[client addPlugin:[FlipperKitReactPlugin new]];
|
[client addPlugin:[FlipperKitReactPlugin new]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
* LICENSE file in the root directory of this source tree.
|
* LICENSE file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#import <FlipperKit/FlipperPlugin.h>
|
#import <FlipperKit/FlipperPlugin.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@interface FKUserDefaultsPlugin : NSObject <FlipperPlugin>
|
@interface FKUserDefaultsPlugin : NSObject<FlipperPlugin>
|
||||||
|
|
||||||
- (instancetype)initWithSuiteName:(nullable NSString *)suiteName;
|
- (instancetype)initWithSuiteName:(nullable NSString*)suiteName;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -10,15 +10,15 @@
|
|||||||
#import <FlipperKit/FlipperResponder.h>
|
#import <FlipperKit/FlipperResponder.h>
|
||||||
#import "FKUserDefaultsSwizzleUtility.h"
|
#import "FKUserDefaultsSwizzleUtility.h"
|
||||||
|
|
||||||
static NSString *const kStandardUserDefaultsName = @"Standard UserDefaults";
|
static NSString* const kStandardUserDefaultsName = @"Standard UserDefaults";
|
||||||
static NSString *const kAppSuiteUserDefaultsName = @"App Suite UserDefaults";
|
static NSString* const kAppSuiteUserDefaultsName = @"App Suite UserDefaults";
|
||||||
|
|
||||||
@interface FKUserDefaultsPlugin ()
|
@interface FKUserDefaultsPlugin ()
|
||||||
@property (nonatomic, strong) id<FlipperConnection> flipperConnection;
|
@property(nonatomic, strong) id<FlipperConnection> flipperConnection;
|
||||||
@property (nonatomic, strong) NSUserDefaults *standardUserDefaults;
|
@property(nonatomic, strong) NSUserDefaults* standardUserDefaults;
|
||||||
@property (nonatomic, strong) NSUserDefaults *appSuiteUserDefaults;
|
@property(nonatomic, strong) NSUserDefaults* appSuiteUserDefaults;
|
||||||
@property (nonatomic, copy) NSString *key;
|
@property(nonatomic, copy) NSString* key;
|
||||||
@property (nonatomic, copy) NSString *suiteName;
|
@property(nonatomic, copy) NSString* suiteName;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation FKUserDefaultsPlugin
|
@implementation FKUserDefaultsPlugin
|
||||||
@@ -27,13 +27,20 @@ static NSString *const kAppSuiteUserDefaultsName = @"App Suite UserDefaults";
|
|||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_standardUserDefaults = [NSUserDefaults standardUserDefaults];
|
_standardUserDefaults = [NSUserDefaults standardUserDefaults];
|
||||||
__weak typeof(self) weakSelf = self;
|
__weak typeof(self) weakSelf = self;
|
||||||
[FKUserDefaultsSwizzleUtility swizzleSelector:@selector(setObject:forKey:) class:[NSUserDefaults class] block:^(NSInvocation * _Nonnull invocation) {
|
[FKUserDefaultsSwizzleUtility
|
||||||
|
swizzleSelector:@selector(setObject:forKey:)
|
||||||
|
class:[NSUserDefaults class]
|
||||||
|
block:^(NSInvocation* _Nonnull invocation) {
|
||||||
__unsafe_unretained id firstArg = nil;
|
__unsafe_unretained id firstArg = nil;
|
||||||
__unsafe_unretained id secondArg = nil;
|
__unsafe_unretained id secondArg = nil;
|
||||||
[invocation getArgument:&firstArg atIndex:2];
|
[invocation getArgument:&firstArg atIndex:2];
|
||||||
[invocation getArgument:&secondArg atIndex:3];
|
[invocation getArgument:&secondArg atIndex:3];
|
||||||
[invocation invoke];
|
[invocation invoke];
|
||||||
[weakSelf userDefaults:([invocation.target isKindOfClass:[NSUserDefaults class]] ? invocation.target : nil)
|
[weakSelf userDefaults:([invocation.target
|
||||||
|
isKindOfClass:[NSUserDefaults
|
||||||
|
class]]
|
||||||
|
? invocation.target
|
||||||
|
: nil)
|
||||||
changedWithValue:firstArg
|
changedWithValue:firstArg
|
||||||
key:secondArg];
|
key:secondArg];
|
||||||
}];
|
}];
|
||||||
@@ -41,11 +48,12 @@ static NSString *const kAppSuiteUserDefaultsName = @"App Suite UserDefaults";
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithSuiteName:(NSString *)suiteName {
|
- (instancetype)initWithSuiteName:(NSString*)suiteName {
|
||||||
if (self = [self init]) {
|
if (self = [self init]) {
|
||||||
_suiteName = suiteName;
|
_suiteName = suiteName;
|
||||||
if (_suiteName) {
|
if (_suiteName) {
|
||||||
_appSuiteUserDefaults = [[NSUserDefaults alloc] initWithSuiteName:_suiteName];
|
_appSuiteUserDefaults =
|
||||||
|
[[NSUserDefaults alloc] initWithSuiteName:_suiteName];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@@ -53,19 +61,25 @@ static NSString *const kAppSuiteUserDefaultsName = @"App Suite UserDefaults";
|
|||||||
|
|
||||||
- (void)didConnect:(id<FlipperConnection>)connection {
|
- (void)didConnect:(id<FlipperConnection>)connection {
|
||||||
self.flipperConnection = connection;
|
self.flipperConnection = connection;
|
||||||
[connection receive:@"getAllSharedPreferences" withBlock:^(NSDictionary *params, id<FlipperResponder> responder) {
|
[connection receive:@"getAllSharedPreferences"
|
||||||
NSMutableDictionary *userDefaults = [NSMutableDictionary new];
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
userDefaults[kStandardUserDefaultsName] = [self.standardUserDefaults dictionaryRepresentation];
|
NSMutableDictionary* userDefaults = [NSMutableDictionary new];
|
||||||
|
userDefaults[kStandardUserDefaultsName] =
|
||||||
|
[self.standardUserDefaults dictionaryRepresentation];
|
||||||
if (self.appSuiteUserDefaults) {
|
if (self.appSuiteUserDefaults) {
|
||||||
userDefaults[kAppSuiteUserDefaultsName] = [self.appSuiteUserDefaults dictionaryRepresentation];
|
userDefaults[kAppSuiteUserDefaultsName] =
|
||||||
|
[self.appSuiteUserDefaults dictionaryRepresentation];
|
||||||
}
|
}
|
||||||
[responder success:userDefaults];
|
[responder success:userDefaults];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[connection receive:@"setSharedPreference" withBlock:^(NSDictionary *params , id<FlipperResponder> responder) {
|
[connection receive:@"setSharedPreference"
|
||||||
NSUserDefaults *sharedPreferences = [self sharedPreferencesForParams:params];
|
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||||
NSString *preferenceName = params[@"preferenceName"];
|
NSUserDefaults* sharedPreferences =
|
||||||
[sharedPreferences setObject:params[@"preferenceValue"] forKey:preferenceName];
|
[self sharedPreferencesForParams:params];
|
||||||
|
NSString* preferenceName = params[@"preferenceName"];
|
||||||
|
[sharedPreferences setObject:params[@"preferenceValue"]
|
||||||
|
forKey:preferenceName];
|
||||||
[responder success:[sharedPreferences dictionaryRepresentation]];
|
[responder success:[sharedPreferences dictionaryRepresentation]];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
@@ -74,30 +88,32 @@ static NSString *const kAppSuiteUserDefaultsName = @"App Suite UserDefaults";
|
|||||||
self.flipperConnection = nil;
|
self.flipperConnection = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)identifier {
|
- (NSString*)identifier {
|
||||||
return @"Preferences";
|
return @"Preferences";
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Private methods
|
#pragma mark - Private methods
|
||||||
|
|
||||||
- (NSUserDefaults *)sharedPreferencesForParams:(NSDictionary *)params {
|
- (NSUserDefaults*)sharedPreferencesForParams:(NSDictionary*)params {
|
||||||
NSString *const sharedPreferencesNameKey = @"sharedPreferencesName";
|
NSString* const sharedPreferencesNameKey = @"sharedPreferencesName";
|
||||||
if (![params[sharedPreferencesNameKey] isKindOfClass:[NSString class]]) {
|
if (![params[sharedPreferencesNameKey] isKindOfClass:[NSString class]]) {
|
||||||
return _standardUserDefaults;
|
return _standardUserDefaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *sharedPreferencesName = params[sharedPreferencesNameKey];
|
NSString* sharedPreferencesName = params[sharedPreferencesNameKey];
|
||||||
return ([sharedPreferencesName isEqualToString:kAppSuiteUserDefaultsName]
|
return (
|
||||||
|
[sharedPreferencesName isEqualToString:kAppSuiteUserDefaultsName]
|
||||||
? _appSuiteUserDefaults
|
? _appSuiteUserDefaults
|
||||||
: _standardUserDefaults);
|
: _standardUserDefaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)userDefaults:(NSUserDefaults *)userDefaults changedWithValue:(id)value key:(NSString *)key {
|
- (void)userDefaults:(NSUserDefaults*)userDefaults
|
||||||
|
changedWithValue:(id)value
|
||||||
|
key:(NSString*)key {
|
||||||
NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] * 1000;
|
NSTimeInterval interval = [[NSDate date] timeIntervalSince1970] * 1000;
|
||||||
NSString *intervalStr = [NSString stringWithFormat:@"%f", interval];
|
NSString* intervalStr = [NSString stringWithFormat:@"%f", interval];
|
||||||
NSMutableDictionary *params = [@{@"name":key,
|
NSMutableDictionary* params =
|
||||||
@"time":intervalStr
|
[@{@"name" : key, @"time" : intervalStr} mutableCopy];
|
||||||
} mutableCopy];
|
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
[params setObject:@"YES" forKey:@"deleted"];
|
[params setObject:@"YES" forKey:@"deleted"];
|
||||||
@@ -105,11 +121,12 @@ static NSString *const kAppSuiteUserDefaultsName = @"App Suite UserDefaults";
|
|||||||
[params setObject:value forKey:@"value"];
|
[params setObject:value forKey:@"value"];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *sharedPreferencesName = (userDefaults == _standardUserDefaults
|
NSString* sharedPreferencesName =
|
||||||
? kStandardUserDefaultsName
|
(userDefaults == _standardUserDefaults ? kStandardUserDefaultsName
|
||||||
: kAppSuiteUserDefaultsName);
|
: kAppSuiteUserDefaultsName);
|
||||||
[params setObject:sharedPreferencesName forKey:@"preferences"];
|
[params setObject:sharedPreferencesName forKey:@"preferences"];
|
||||||
[self.flipperConnection send:@"sharedPreferencesChange" withParams:[params copy]];
|
[self.flipperConnection send:@"sharedPreferencesChange"
|
||||||
|
withParams:[params copy]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@interface FKUserDefaultsSwizzleUtility : NSObject
|
@interface FKUserDefaultsSwizzleUtility : NSObject
|
||||||
|
|
||||||
+ (void)swizzleSelector:(SEL)selector class:(Class)aClass block:(void(^)(NSInvocation *invocation))block;
|
+ (void)swizzleSelector:(SEL)selector
|
||||||
|
class:(Class)aClass
|
||||||
|
block:(void (^)(NSInvocation* invocation))block;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user