Merge branch '0.227' into universalBuild
This commit is contained in:
@@ -463,7 +463,7 @@
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/FlipperKit/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(OTHER_CFLAGS)",
|
||||
@@ -540,7 +540,7 @@
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/FlipperKit/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(OTHER_CFLAGS)",
|
||||
|
||||
@@ -35,6 +35,10 @@
|
||||
[self sendInternal:method withParams:params];
|
||||
}
|
||||
|
||||
- (void)send:(NSString*)method withRawParams:(NSString*)params {
|
||||
conn_->sendRaw([method UTF8String], [params UTF8String]);
|
||||
}
|
||||
|
||||
- (void)send:(NSString*)method withArrayParams:(NSArray*)params {
|
||||
[self sendInternal:method withParams:params];
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#import "FlipperStateUpdateListener.h"
|
||||
|
||||
/**
|
||||
Represents a connection between the Sonar desktop och client side. Manages the
|
||||
Represents a connection between the Flipper desktop client side. Manages the
|
||||
lifecycle of attached plugin instances.
|
||||
*/
|
||||
@interface FlipperClient : NSObject
|
||||
@@ -41,41 +41,48 @@ this client.
|
||||
- (NSObject<FlipperPlugin>*)pluginWithIdentifier:(NSString*)identifier;
|
||||
|
||||
/**
|
||||
Establish a connection to the Sonar desktop.
|
||||
Establish a connection to the Flipper desktop.
|
||||
*/
|
||||
- (void)start;
|
||||
|
||||
/**
|
||||
Stop the connection to the Sonar desktop.
|
||||
Stop the connection to the Flipper desktop.
|
||||
*/
|
||||
- (void)stop;
|
||||
|
||||
/**
|
||||
Get the log of state changes from the sonar client
|
||||
Get the log of state changes from the Flipper client.
|
||||
*/
|
||||
- (NSString*)getState;
|
||||
|
||||
/**
|
||||
Get the current summarized state of the sonar client
|
||||
Get the current summarized state of the Flipper client.
|
||||
*/
|
||||
- (NSArray<NSDictionary*>*)getStateElements;
|
||||
|
||||
/**
|
||||
Subscribe a ViewController to state update change notifications
|
||||
Return true if the app is connected to Flipper desktop. Otherwise, returns
|
||||
false.
|
||||
|
||||
*/
|
||||
- (BOOL)isConnected;
|
||||
|
||||
/**
|
||||
Subscribe a ViewController to state update change notifications.
|
||||
*/
|
||||
- (void)subscribeForUpdates:(id<FlipperStateUpdateListener>)controller;
|
||||
|
||||
/**
|
||||
Sets the certificate provider responsible for obtaining certificates
|
||||
Sets the certificate provider responsible for obtaining certificates.
|
||||
*/
|
||||
- (void)setCertificateProvider:(id<FlipperKitCertificateProvider>)provider;
|
||||
|
||||
/**
|
||||
Get the certificate provider of Flipper Client
|
||||
Get the certificate provider of Flipper Client.
|
||||
*/
|
||||
- (id<FlipperKitCertificateProvider>)getCertificateProvider;
|
||||
|
||||
// initializers are disabled. You must use `+[FlipperClient sharedClient]`
|
||||
// Initializers are disabled. You must use `+[FlipperClient sharedClient]`
|
||||
// instance.
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
@@ -182,6 +182,10 @@ using WrapperPlugin = facebook::flipper::FlipperCppWrapperPlugin;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (BOOL)isConnected {
|
||||
return _cppClient->isConnected();
|
||||
}
|
||||
|
||||
- (NSString*)getState {
|
||||
return @(_cppClient->getState().c_str());
|
||||
}
|
||||
|
||||
@@ -23,6 +23,11 @@ Invoke a method on the Sonar desktop plugin with with a matching identifier.
|
||||
*/
|
||||
- (void)send:(NSString*)method withParams:(NSDictionary*)params;
|
||||
|
||||
/**
|
||||
Invoke a method on the Sonar desktop plugin with with a matching identifier.
|
||||
*/
|
||||
- (void)send:(NSString*)method withRawParams:(NSString*)params;
|
||||
|
||||
/**
|
||||
Invoke a method on the Sonar desktop plugin with with a matching identifier.
|
||||
*/
|
||||
|
||||
@@ -37,6 +37,7 @@ static NSString* const kSKCellIdentifier =
|
||||
cell.textLabel.font = [UIFont fontWithName:@"Arial" size:10];
|
||||
cell.textLabel.text = [self.elements[row][@"state"]
|
||||
stringByAppendingString:self.elements[row][@"name"]];
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
@@ -52,12 +53,19 @@ static NSString* const kSKCellIdentifier =
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
self.view.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
self.stateTable = [[UITableView alloc]
|
||||
initWithFrame:CGRectMake(
|
||||
0, 0, self.view.bounds.size.width, STATE_VIEW_HEIGHT)];
|
||||
|
||||
self.scrollView = [[UIScrollView alloc]
|
||||
initWithFrame:CGRectMake(
|
||||
0,
|
||||
STATE_VIEW_HEIGHT,
|
||||
self.view.frame.size.width,
|
||||
self.view.frame.size.height - 100 - STATE_VIEW_HEIGHT)];
|
||||
|
||||
self.logLabel =
|
||||
[[UILabel alloc] initWithFrame:CGRectMake(
|
||||
0,
|
||||
@@ -66,11 +74,9 @@ static NSString* const kSKCellIdentifier =
|
||||
self.scrollView.frame.size.height)];
|
||||
self.logLabel.numberOfLines = 0;
|
||||
self.logLabel.font = [UIFont systemFontOfSize:10.0f];
|
||||
|
||||
[self.scrollView addSubview:self.logLabel];
|
||||
|
||||
self.stateTable = [[UITableView alloc]
|
||||
initWithFrame:CGRectMake(
|
||||
0, 0, self.view.bounds.size.width, STATE_VIEW_HEIGHT)];
|
||||
[self.stateTable registerClass:[UITableViewCell class]
|
||||
forCellReuseIdentifier:kSKCellIdentifier];
|
||||
self.stateTable.rowHeight = 14;
|
||||
@@ -104,10 +110,11 @@ static NSString* const kSKCellIdentifier =
|
||||
[self.logLabel sizeToFit];
|
||||
self.scrollView.contentSize = self.logLabel.frame.size;
|
||||
|
||||
// Scroll to bottom
|
||||
CGPoint bottomOffset = CGPointMake(
|
||||
0,
|
||||
self.scrollView.contentSize.height - self.scrollView.bounds.size.height);
|
||||
CGFloat y = 0;
|
||||
if (self.scrollView.contentSize.height > self.scrollView.bounds.size.height) {
|
||||
y = self.scrollView.contentSize.height - self.scrollView.bounds.size.height;
|
||||
}
|
||||
CGPoint bottomOffset = CGPointMake(0, y);
|
||||
[self.scrollView setContentOffset:bottomOffset animated:YES];
|
||||
}
|
||||
|
||||
|
||||
@@ -166,25 +166,26 @@ static constexpr int connectionKeepaliveSeconds = 10;
|
||||
}
|
||||
|
||||
- (void)disconnect {
|
||||
[_dispatchQueue cancelAllOperations];
|
||||
|
||||
if ([_keepAlive isValid]) {
|
||||
[_keepAlive invalidate];
|
||||
}
|
||||
_keepAlive = nil;
|
||||
|
||||
// Manually trigger a 'close' event as SocketRocket close method will
|
||||
// not notify the delegate. SocketRocket only triggers the close event
|
||||
// when the connection is closed from the server.
|
||||
_eventHandler(facebook::flipper::SocketEvent::CLOSE);
|
||||
__weak auto weakSelf = self;
|
||||
NSBlockOperation* disconnectOperation =
|
||||
[NSBlockOperation blockOperationWithBlock:^{
|
||||
__strong auto strongSelf = weakSelf;
|
||||
// Clear the socket delegate before close. Ensures that we won't get
|
||||
// any messages after the disconnect takes place.
|
||||
if (strongSelf->_socket) {
|
||||
[strongSelf->_socket setDelegate:nil];
|
||||
[strongSelf->_socket close];
|
||||
|
||||
if (_socket) {
|
||||
// Clear the socket delegate before close. Ensures that we won't get
|
||||
// any messages after the disconnect takes place.
|
||||
_socket.delegate = nil;
|
||||
[_socket close];
|
||||
_socket = nil;
|
||||
};
|
||||
strongSelf->_socket = nil;
|
||||
}
|
||||
}];
|
||||
|
||||
[_dispatchQueue addOperations:@[ disconnectOperation ] waitUntilFinished:YES];
|
||||
}
|
||||
|
||||
- (void)send:(NSString*)message
|
||||
@@ -192,10 +193,12 @@ static constexpr int connectionKeepaliveSeconds = 10;
|
||||
__weak auto weakSelf = self;
|
||||
[_dispatchQueue addOperationWithBlock:^{
|
||||
__strong auto strongSelf = weakSelf;
|
||||
NSError* error = nil;
|
||||
[strongSelf->_socket sendString:message error:&error];
|
||||
if (completionHandler) {
|
||||
completionHandler(error);
|
||||
if (strongSelf) {
|
||||
NSError* error = nil;
|
||||
[strongSelf->_socket sendString:message error:&error];
|
||||
if (completionHandler) {
|
||||
completionHandler(error);
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -210,7 +213,9 @@ static constexpr int connectionKeepaliveSeconds = 10;
|
||||
__weak auto weakSelf = self;
|
||||
[_dispatchQueue addOperationWithBlock:^{
|
||||
__strong auto strongSelf = weakSelf;
|
||||
[strongSelf->_socket sendPing:nil error:nil];
|
||||
if (strongSelf) {
|
||||
[strongSelf->_socket sendPing:nil error:nil];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -251,7 +256,6 @@ static constexpr int connectionKeepaliveSeconds = 10;
|
||||
_keepAlive = nil;
|
||||
|
||||
_eventHandler(facebook::flipper::SocketEvent::CLOSE);
|
||||
_socket = nil;
|
||||
}
|
||||
|
||||
- (void)_webSocketDidReceiveMessage:(id)message {
|
||||
|
||||
@@ -39,7 +39,7 @@ class FlipperWebSocket : public FlipperSocket {
|
||||
virtual void setEventHandler(SocketEventHandler eventHandler) override;
|
||||
virtual void setMessageHandler(SocketMessageHandler messageHandler) override;
|
||||
|
||||
virtual bool connect(FlipperConnectionManager* manager) override;
|
||||
virtual void connect(FlipperConnectionManager* manager) override;
|
||||
virtual void disconnect() override;
|
||||
|
||||
virtual void send(const folly::dynamic& message, SocketSendHandler completion)
|
||||
|
||||
@@ -53,9 +53,9 @@ void FlipperWebSocket::setMessageHandler(SocketMessageHandler messageHandler) {
|
||||
messageHandler_ = std::move(messageHandler);
|
||||
}
|
||||
|
||||
bool FlipperWebSocket::connect(FlipperConnectionManager* manager) {
|
||||
void FlipperWebSocket::connect(FlipperConnectionManager* manager) {
|
||||
if (socket_ != NULL) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string connectionURL = endpoint_.secure ? "wss://" : "ws://";
|
||||
@@ -72,43 +72,16 @@ bool FlipperWebSocket::connect(FlipperConnectionManager* manager) {
|
||||
connectionURL += payload;
|
||||
}
|
||||
|
||||
__block bool fullfilled = false;
|
||||
__block std::promise<bool> promise;
|
||||
auto connected = promise.get_future();
|
||||
|
||||
NSURL* urlObjc = [NSURL
|
||||
URLWithString:[NSString stringWithUTF8String:connectionURL.c_str()]];
|
||||
|
||||
auto eventHandler = eventHandler_;
|
||||
socket_ = [[FlipperPlatformWebSocket alloc] initWithURL:urlObjc];
|
||||
socket_.eventHandler = ^(SocketEvent event) {
|
||||
/**
|
||||
Only fulfill the promise the first time the event handler is used. If the
|
||||
open event is received, then set the promise value to true. For any other
|
||||
event, consider a failure and set to false.
|
||||
*/
|
||||
if (!fullfilled) {
|
||||
fullfilled = true;
|
||||
if (event == SocketEvent::OPEN) {
|
||||
promise.set_value(true);
|
||||
} else if (event == SocketEvent::SSL_ERROR) {
|
||||
try {
|
||||
promise.set_exception(
|
||||
std::make_exception_ptr(SSLException("SSL handshake failed")));
|
||||
} catch (...) {
|
||||
// set_exception() may throw an exception
|
||||
// In that case, just set the value to false.
|
||||
promise.set_value(false);
|
||||
}
|
||||
} else {
|
||||
promise.set_value(false);
|
||||
}
|
||||
}
|
||||
eventHandler(event);
|
||||
eventHandler_(event);
|
||||
};
|
||||
auto messageHandler = messageHandler_;
|
||||
|
||||
socket_.messageHandler = ^(const std::string& message) {
|
||||
messageHandler(message);
|
||||
messageHandler_(message);
|
||||
};
|
||||
|
||||
if (endpoint_.secure) {
|
||||
@@ -119,19 +92,12 @@ bool FlipperWebSocket::connect(FlipperConnectionManager* manager) {
|
||||
return std::string("");
|
||||
}
|
||||
strncpy(password, pkcs12.second.c_str(), length);
|
||||
password[length - 1] = '\0';
|
||||
return pkcs12.first;
|
||||
};
|
||||
}
|
||||
|
||||
[socket_ connect];
|
||||
|
||||
auto state = connected.wait_for(std::chrono::seconds(10));
|
||||
if (state == std::future_status::ready) {
|
||||
return connected.get();
|
||||
}
|
||||
|
||||
disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
void FlipperWebSocket::disconnect() {
|
||||
@@ -155,6 +121,14 @@ void FlipperWebSocket::send(
|
||||
if (socket_ == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure the payload size is valid before sending.
|
||||
// The maximum allowed size for a message payload is 2^53 - 1. But that is
|
||||
// for the entire message, including any additional metadata.
|
||||
if (message.length() > pow(2, 53) - 1) {
|
||||
throw std::length_error("Payload is too big to send");
|
||||
}
|
||||
|
||||
NSString* messageObjc = [NSString stringWithUTF8String:message.c_str()];
|
||||
[socket_ send:messageObjc
|
||||
withCompletionHandler:^(NSError*) {
|
||||
@@ -163,9 +137,9 @@ void FlipperWebSocket::send(
|
||||
}
|
||||
|
||||
/**
|
||||
Only ever used for insecure connections to receive the device_id from a
|
||||
signCertificate request. If the intended usage ever changes, then a better
|
||||
approach needs to be put in place.
|
||||
* Only ever used for insecure connections to receive the device_id from a
|
||||
* signCertificate request. If the intended usage ever changes, then a better
|
||||
* approach needs to be put in place.
|
||||
*/
|
||||
void FlipperWebSocket::sendExpectResponse(
|
||||
const std::string& message,
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
@protocol FlipperConnection;
|
||||
|
||||
typedef void (^ConnectBlock)(id<FlipperConnection>);
|
||||
typedef void (^DisconnectBlock)();
|
||||
typedef void (^DisconnectBlock)(void);
|
||||
|
||||
@interface BlockBasedSonarPlugin : NSObject<FlipperPlugin>
|
||||
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
[self sendInternal:method withParams:params loggedTo:&_sent];
|
||||
}
|
||||
|
||||
- (void)send:(NSString*)method withRawParams:(NSString*)params {
|
||||
[self sendInternal:method withParams:params loggedTo:&_sent];
|
||||
}
|
||||
|
||||
- (void)send:(NSString*)method withArrayParams:(NSArray*)params {
|
||||
[self sendInternal:method withParams:params loggedTo:&_sentWithArray];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <objc/NSObjCRuntime.h>
|
||||
|
||||
@interface DatabaseExecuteSqlResponse : NSObject
|
||||
|
||||
@property(nonatomic, strong) NSString* type;
|
||||
@property(nonatomic, strong) NSArray* columns;
|
||||
@property(nonatomic, strong) NSArray* values;
|
||||
@property(nonatomic, strong) NSNumber* insertedId;
|
||||
@property(nonatomic, assign) NSInteger affectedCount;
|
||||
|
||||
- (instancetype)initWithType:(NSString*)type
|
||||
columns:(NSArray*)columns
|
||||
values:(NSArray*)values
|
||||
insertedId:(NSNumber*)insertedId
|
||||
affectedCount:(NSInteger)affectedCount;
|
||||
|
||||
@end
|
||||
|
||||
@interface DatabaseExecuteSqlRequest : NSObject
|
||||
|
||||
@property(nonatomic, assign, readonly) NSInteger databaseId;
|
||||
@property(nonatomic, copy, readonly) NSString* value;
|
||||
|
||||
- (instancetype)initWithDatabaseId:(NSInteger)databaseId value:(NSString*)value;
|
||||
+ (DatabaseExecuteSqlRequest*)getExecuteSqlRequestFromDictionary:
|
||||
(NSDictionary*)dictionary;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "DatabaseExecuteSql.h"
|
||||
#include <objc/NSObjCRuntime.h>
|
||||
|
||||
@implementation DatabaseExecuteSqlResponse
|
||||
|
||||
- (instancetype)initWithType:(NSString*)type
|
||||
columns:(NSArray*)columns
|
||||
values:(NSArray*)values
|
||||
insertedId:(NSNumber*)insertedId
|
||||
affectedCount:(NSInteger)affectedCount {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_type = type;
|
||||
_columns = [columns copy];
|
||||
_values = [values copy];
|
||||
_insertedId = insertedId;
|
||||
_affectedCount = affectedCount;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation DatabaseExecuteSqlRequest
|
||||
|
||||
- (instancetype)initWithDatabaseId:(NSInteger)databaseId
|
||||
value:(NSString*)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_databaseId = databaseId;
|
||||
_value = [value copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (DatabaseExecuteSqlRequest*)getExecuteSqlRequestFromDictionary:
|
||||
(NSDictionary*)dictionary {
|
||||
NSInteger databaseId = [dictionary[@"databaseId"] integerValue];
|
||||
NSString* value = dictionary[@"value"];
|
||||
if (databaseId <= 0 || value.length == 0) {
|
||||
return nil;
|
||||
}
|
||||
return [[DatabaseExecuteSqlRequest alloc] initWithDatabaseId:databaseId
|
||||
value:value];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface DatabaseGetTableDataResponse : NSObject
|
||||
|
||||
@property(nonatomic, strong, readonly) NSArray<NSString*>* columns;
|
||||
@property(nonatomic, strong, readonly) NSArray<NSArray*>* values;
|
||||
@property(nonatomic, assign, readonly) NSInteger start;
|
||||
@property(nonatomic, assign, readonly) NSInteger count;
|
||||
@property(nonatomic, assign, readonly) NSInteger total;
|
||||
|
||||
- (instancetype)initWithColumns:(NSArray<NSString*>*)columns
|
||||
values:(NSArray<NSArray*>*)values
|
||||
start:(NSInteger)start
|
||||
count:(NSInteger)count
|
||||
total:(NSInteger)total;
|
||||
|
||||
@end
|
||||
|
||||
@interface DatabaseGetTableDataRequest : NSObject
|
||||
|
||||
@property(nonatomic, assign, readonly) NSInteger databaseId;
|
||||
@property(nonatomic, copy, readonly) NSString* table;
|
||||
@property(nonatomic, copy, readonly) NSString* order;
|
||||
@property(nonatomic, assign, readonly) BOOL reverse;
|
||||
@property(nonatomic, assign, readonly) NSInteger start;
|
||||
@property(nonatomic, assign, readonly) NSInteger count;
|
||||
|
||||
- (instancetype)initWithDatabaseId:(NSInteger)databaseId
|
||||
table:(NSString*)table
|
||||
order:(NSString*)order
|
||||
reverse:(BOOL)reverse
|
||||
start:(NSInteger)start
|
||||
count:(NSInteger)count;
|
||||
|
||||
+ (DatabaseGetTableDataRequest*)getTableDataRequestFromDictionary:
|
||||
(NSDictionary*)dictionary;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "DatabaseGetTableData.h"
|
||||
|
||||
@implementation DatabaseGetTableDataResponse
|
||||
|
||||
- (instancetype)initWithColumns:(NSArray<NSString*>*)columns
|
||||
values:(NSArray<NSArray*>*)values
|
||||
start:(NSInteger)start
|
||||
count:(NSInteger)count
|
||||
total:(NSInteger)total {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_columns = [columns copy];
|
||||
_values = [values copy];
|
||||
_start = start;
|
||||
_count = count;
|
||||
_total = total;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation DatabaseGetTableDataRequest
|
||||
|
||||
- (instancetype)initWithDatabaseId:(NSInteger)databaseId
|
||||
table:(NSString*)table
|
||||
order:(NSString*)order
|
||||
reverse:(BOOL)reverse
|
||||
start:(NSInteger)start
|
||||
count:(NSInteger)count {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_databaseId = databaseId;
|
||||
_table = [table copy];
|
||||
_order = [order copy];
|
||||
_reverse = reverse;
|
||||
_start = start;
|
||||
_count = count;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (DatabaseGetTableDataRequest*)getTableDataRequestFromDictionary:
|
||||
(NSDictionary*)dictionary {
|
||||
NSInteger databaseId = [dictionary[@"databaseId"] integerValue];
|
||||
NSString* table = dictionary[@"table"];
|
||||
NSString* order = dictionary[@"order"];
|
||||
BOOL reverse = [dictionary[@"reverse"] boolValue];
|
||||
NSInteger start = [dictionary[@"start"] integerValue];
|
||||
NSInteger count = [dictionary[@"count"] integerValue];
|
||||
if (databaseId <= 0 || table.length == 0) {
|
||||
return nil;
|
||||
}
|
||||
return [[DatabaseGetTableDataRequest alloc] initWithDatabaseId:databaseId
|
||||
table:table
|
||||
order:order
|
||||
reverse:reverse
|
||||
start:start
|
||||
count:count];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface DatabaseGetTableInfoResponse : NSObject
|
||||
|
||||
@property(nonatomic, strong) NSString* definition;
|
||||
|
||||
- (instancetype)initWithDefinition:(NSString*)definition;
|
||||
|
||||
@end
|
||||
|
||||
@interface DatabaseGetTableInfoRequest : NSObject
|
||||
|
||||
@property(nonatomic, assign, readonly) NSInteger databaseId;
|
||||
@property(nonatomic, copy, readonly) NSString* table;
|
||||
|
||||
- (instancetype)initWithDatabaseId:(NSInteger)databaseId table:(NSString*)table;
|
||||
+ (DatabaseGetTableInfoRequest*)getTableInfoRequestFromDictionary:
|
||||
(NSDictionary*)dictionary;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "DatabaseGetTableInfo.h"
|
||||
|
||||
@implementation DatabaseGetTableInfoResponse
|
||||
|
||||
- (instancetype)initWithDefinition:(NSString*)definition {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_definition = definition;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation DatabaseGetTableInfoRequest
|
||||
|
||||
- (instancetype)initWithDatabaseId:(NSInteger)databaseId
|
||||
table:(NSString*)table {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_databaseId = databaseId;
|
||||
_table = [table copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (DatabaseGetTableInfoRequest*)getTableInfoRequestFromDictionary:
|
||||
(NSDictionary*)dictionary {
|
||||
NSNumber* databaseId = @([dictionary[@"databaseId"] integerValue]);
|
||||
NSString* table = dictionary[@"table"];
|
||||
if (databaseId == nil || table == nil) {
|
||||
return nil;
|
||||
}
|
||||
return [[DatabaseGetTableInfoRequest alloc]
|
||||
initWithDatabaseId:databaseId.intValue
|
||||
table:table];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface DatabaseGetTableStructureResponse : NSObject
|
||||
|
||||
@property(nonatomic, strong, readonly) NSArray<NSString*>* structureColumns;
|
||||
@property(nonatomic, strong, readonly)
|
||||
NSArray<NSArray<NSString*>*>* structureValues;
|
||||
@property(nonatomic, strong, readonly) NSArray<NSString*>* indexesColumns;
|
||||
@property(nonatomic, strong, readonly)
|
||||
NSArray<NSArray<NSString*>*>* indexesValues;
|
||||
|
||||
- (instancetype)
|
||||
initWithStructureColumns:(NSArray<NSString*>*)structureColumns
|
||||
structureValues:(NSArray<NSArray<NSString*>*>*)structureValues
|
||||
indexesColumns:(NSArray<NSString*>*)indexesColumns
|
||||
indexesValues:(NSArray<NSArray<NSString*>*>*)indexesValues;
|
||||
|
||||
@end
|
||||
|
||||
@interface DatabaseGetTableStructureRequest : NSObject
|
||||
|
||||
@property(nonatomic, assign, readonly) NSInteger databaseId;
|
||||
@property(nonatomic, copy, readonly) NSString* table;
|
||||
|
||||
- (instancetype)initWithDatabaseId:(NSInteger)databaseId table:(NSString*)table;
|
||||
+ (DatabaseGetTableStructureRequest*)getTableStructureRequestFromDictionary:
|
||||
(NSDictionary*)dictionary;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "DatabaseGetTableStructure.h"
|
||||
|
||||
@implementation DatabaseGetTableStructureResponse
|
||||
|
||||
- (instancetype)
|
||||
initWithStructureColumns:(NSArray<NSString*>*)structureColumns
|
||||
structureValues:(NSArray<NSArray<NSString*>*>*)structureValues
|
||||
indexesColumns:(NSArray<NSString*>*)indexesColumns
|
||||
indexesValues:(NSArray<NSArray<NSString*>*>*)indexesValues {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_structureColumns = [structureColumns copy];
|
||||
_structureValues = [structureValues copy];
|
||||
_indexesColumns = [indexesColumns copy];
|
||||
_indexesValues = [indexesValues copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation DatabaseGetTableStructureRequest
|
||||
|
||||
- (instancetype)initWithDatabaseId:(NSInteger)databaseId
|
||||
table:(NSString*)table {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_databaseId = databaseId;
|
||||
_table = [table copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (DatabaseGetTableStructureRequest*)getTableStructureRequestFromDictionary:
|
||||
(NSDictionary*)params {
|
||||
int databaseId = [params[@"databaseId"] integerValue];
|
||||
NSString* table = params[@"table"];
|
||||
if (databaseId <= 0 || !table) {
|
||||
return nil;
|
||||
}
|
||||
return [[DatabaseGetTableStructureRequest alloc] initWithDatabaseId:databaseId
|
||||
table:table];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol DatabaseDescriptor<NSObject>
|
||||
- (NSString*)name;
|
||||
@end
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DatabaseDescriptor.h"
|
||||
#import "DatabaseDriver.h"
|
||||
|
||||
@interface DatabaseDescriptorHolder : NSObject
|
||||
|
||||
@property(nonatomic, assign, readonly) NSInteger identifier;
|
||||
@property(nonatomic, strong, readonly) id<DatabaseDriver> databaseDriver;
|
||||
@property(nonatomic, strong, readonly) id<DatabaseDescriptor>
|
||||
databaseDescriptor;
|
||||
|
||||
- (instancetype)initWithIdentifier:(NSInteger)identifier
|
||||
databaseDriver:(id<DatabaseDriver>)databaseDriver
|
||||
databaseDescriptor:(id<DatabaseDescriptor>)databaseDescriptor;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "DatabaseDescriptorHolder.h"
|
||||
|
||||
@implementation DatabaseDescriptorHolder
|
||||
|
||||
- (instancetype)initWithIdentifier:(NSInteger)identifier
|
||||
databaseDriver:(id<DatabaseDriver>)databaseDriver
|
||||
databaseDescriptor:(id<DatabaseDescriptor>)databaseDescriptor {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_identifier = identifier;
|
||||
_databaseDriver = databaseDriver;
|
||||
_databaseDescriptor = databaseDescriptor;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol DatabaseDescriptor;
|
||||
@class DatabaseGetTableStructureResponse;
|
||||
@class DatabaseGetTableInfoResponse;
|
||||
@class DatabaseGetTableDataResponse;
|
||||
@class DatabaseExecuteSqlResponse;
|
||||
|
||||
@protocol DatabaseDriver<NSObject>
|
||||
- (NSArray<id<DatabaseDescriptor>>*)getDatabases;
|
||||
- (NSArray<NSString*>*)getTableNames:(id<DatabaseDescriptor>)databaseDescriptor;
|
||||
- (DatabaseGetTableStructureResponse*)
|
||||
getTableStructureWithDatabaseDescriptor:
|
||||
(id<DatabaseDescriptor>)databaseDescriptor
|
||||
forTable:(NSString*)tableName;
|
||||
- (DatabaseGetTableInfoResponse*)
|
||||
getTableInfoWithDatabaseDescriptor:
|
||||
(id<DatabaseDescriptor>)databaseDescriptor
|
||||
forTable:(NSString*)tableName;
|
||||
|
||||
- (DatabaseGetTableDataResponse*)
|
||||
getTableDataWithDatabaseDescriptor:
|
||||
(id<DatabaseDescriptor>)databaseDescriptor
|
||||
forTable:(NSString*)tableName
|
||||
order:(NSString*)order
|
||||
reverse:(BOOL)reverse
|
||||
start:(NSInteger)start
|
||||
count:(NSInteger)count;
|
||||
- (DatabaseExecuteSqlResponse*)executeSQL:(NSString*)sql;
|
||||
@end
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, DatabasesErrorCodes) {
|
||||
DatabasesErrorCodesInvalidRequest = 1,
|
||||
DatabasesErrorCodesDatabaseInvalid = 2,
|
||||
DatabasesErrorCodesSqlExecutionException = 3,
|
||||
};
|
||||
|
||||
static NSString* const kDatabasesErrorCodesInvalidRequestMessage =
|
||||
@"The request received was invalid";
|
||||
static NSString* const kDatabasesErrorCodesDatabaseInvalidMessage =
|
||||
@"Could not access database";
|
||||
static NSString* const kDatabasesErrorCodesSqlExecutionExceptionMessage =
|
||||
@"SQL execution exception: ";
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol DatabaseDriver;
|
||||
@protocol DatabaseDescriptor;
|
||||
@protocol FlipperConnection;
|
||||
|
||||
@interface DatabasesManager : NSObject
|
||||
|
||||
@property(nonatomic, strong) id<FlipperConnection> connection;
|
||||
|
||||
- (instancetype)init;
|
||||
- (void)setConnection:(id<FlipperConnection>)connection;
|
||||
- (BOOL)isConnected;
|
||||
- (void)addDatabaseDriver:(id<DatabaseDriver>)driver;
|
||||
- (void)removeDatabaseDriver:(id<DatabaseDriver>)driver;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "DatabasesManager.h"
|
||||
#import <FlipperKit/FlipperClient.h>
|
||||
#import <FlipperKit/FlipperConnection.h>
|
||||
#import <FlipperKit/FlipperResponder.h>
|
||||
#include <Foundation/Foundation.h>
|
||||
#import "DatabaseDescriptor.h"
|
||||
#import "DatabaseDescriptorHolder.h"
|
||||
#import "DatabaseDriver.h"
|
||||
#import "DatabaseErrorCodes.h"
|
||||
#import "DatabaseExecuteSql.h"
|
||||
#import "DatabaseGetTableData.h"
|
||||
#import "DatabaseGetTableInfo.h"
|
||||
#import "DatabaseGetTableStructure.h"
|
||||
#import "ObjectMapper.h"
|
||||
|
||||
@interface DatabasesManager ()
|
||||
|
||||
@property(nonatomic, strong)
|
||||
NSMutableDictionary<NSNumber*, DatabaseDescriptorHolder*>*
|
||||
databaseDescriptorHolders;
|
||||
@property(nonatomic, strong)
|
||||
NSMutableSet<DatabaseDescriptorHolder*>* databaseDescriptorHolderSet;
|
||||
@property(nonatomic, strong) NSMutableSet<id<DatabaseDriver>>* databaseDrivers;
|
||||
|
||||
@end
|
||||
|
||||
@implementation DatabasesManager
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_databaseDrivers = [NSMutableSet new];
|
||||
_databaseDescriptorHolders = [NSMutableDictionary new];
|
||||
_databaseDescriptorHolderSet = [NSMutableSet new];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setConnection:(id<FlipperConnection>)connection {
|
||||
_connection = connection;
|
||||
if (connection) {
|
||||
[self listenForCommands];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isConnected {
|
||||
return _connection != nil;
|
||||
}
|
||||
|
||||
- (void)listenForCommands {
|
||||
[self.connection
|
||||
receive:@"databaseList"
|
||||
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||
NSInteger databaseId = 1;
|
||||
[self.databaseDescriptorHolders removeAllObjects];
|
||||
[self.databaseDescriptorHolderSet removeAllObjects];
|
||||
|
||||
for (id<DatabaseDriver> databaseDriver in self.databaseDrivers) {
|
||||
NSArray<id<DatabaseDescriptor>>* databaseDescriptorList =
|
||||
[databaseDriver getDatabases];
|
||||
for (id<DatabaseDescriptor> databaseDescriptor in
|
||||
databaseDescriptorList) {
|
||||
DatabaseDescriptorHolder* databaseDescriptorHolder =
|
||||
[[DatabaseDescriptorHolder alloc]
|
||||
initWithIdentifier:databaseId
|
||||
databaseDriver:databaseDriver
|
||||
databaseDescriptor:databaseDescriptor];
|
||||
self.databaseDescriptorHolders[@(databaseId)] =
|
||||
databaseDescriptorHolder;
|
||||
[self.databaseDescriptorHolderSet
|
||||
addObject:databaseDescriptorHolder];
|
||||
databaseId++;
|
||||
}
|
||||
}
|
||||
|
||||
id result = [ObjectMapper
|
||||
databaseListToFlipperArray:self.databaseDescriptorHolderSet];
|
||||
[responder success:result];
|
||||
}];
|
||||
|
||||
[self.connection
|
||||
receive:@"getTableData"
|
||||
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||
DatabaseGetTableDataRequest* request = [DatabaseGetTableDataRequest
|
||||
getTableDataRequestFromDictionary:params];
|
||||
if (!request) {
|
||||
[DatabasesManager raiseInvalidRequestError:responder];
|
||||
return;
|
||||
}
|
||||
DatabaseDescriptorHolder* descriptorHolder =
|
||||
self.databaseDescriptorHolders[@(request.databaseId)];
|
||||
if (!descriptorHolder) {
|
||||
[DatabasesManager raiseDatabaseInvalidError:responder];
|
||||
return;
|
||||
}
|
||||
|
||||
@try {
|
||||
DatabaseGetTableDataResponse* tableDataResponse =
|
||||
[descriptorHolder.databaseDriver
|
||||
getTableDataWithDatabaseDescriptor:descriptorHolder
|
||||
.databaseDescriptor
|
||||
forTable:request.table
|
||||
order:request.order
|
||||
reverse:request.reverse
|
||||
start:request.start
|
||||
count:request.count];
|
||||
NSDictionary* response = [ObjectMapper
|
||||
databaseGetTableDataResponseToDictionary:tableDataResponse];
|
||||
[responder success:response];
|
||||
} @catch (NSException* exception) {
|
||||
NSString* reason = exception.reason ?: @"Unknown error";
|
||||
NSDictionary* errorResponse = [ObjectMapper
|
||||
errorWithCode:DatabasesErrorCodesSqlExecutionException
|
||||
message:[kDatabasesErrorCodesSqlExecutionExceptionMessage
|
||||
stringByAppendingString:reason]];
|
||||
[responder error:errorResponse];
|
||||
}
|
||||
}];
|
||||
|
||||
[self.connection
|
||||
receive:@"getTableStructure"
|
||||
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||
DatabaseGetTableStructureRequest* request =
|
||||
[DatabaseGetTableStructureRequest
|
||||
getTableStructureRequestFromDictionary:params];
|
||||
|
||||
if (!request) {
|
||||
[DatabasesManager raiseInvalidRequestError:responder];
|
||||
return;
|
||||
}
|
||||
DatabaseDescriptorHolder* descriptorHolder =
|
||||
self.databaseDescriptorHolders[@(request.databaseId)];
|
||||
if (!descriptorHolder) {
|
||||
[DatabasesManager raiseDatabaseInvalidError:responder];
|
||||
return;
|
||||
}
|
||||
|
||||
@try {
|
||||
DatabaseGetTableStructureResponse* tableStructure =
|
||||
[descriptorHolder.databaseDriver
|
||||
getTableStructureWithDatabaseDescriptor:
|
||||
descriptorHolder.databaseDescriptor
|
||||
forTable:request.table];
|
||||
NSDictionary* response = [ObjectMapper
|
||||
databaseGetTableStructureResponseToDictionary:tableStructure];
|
||||
[responder success:response];
|
||||
} @catch (NSException* exception) {
|
||||
NSString* reason = exception.reason ?: @"Unknown error";
|
||||
NSDictionary* errorResponse = [ObjectMapper
|
||||
errorWithCode:DatabasesErrorCodesSqlExecutionException
|
||||
message:[kDatabasesErrorCodesSqlExecutionExceptionMessage
|
||||
stringByAppendingString:reason]];
|
||||
[responder error:errorResponse];
|
||||
}
|
||||
}];
|
||||
|
||||
[self.connection
|
||||
receive:@"getTableInfo"
|
||||
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||
DatabaseGetTableInfoRequest* request = [DatabaseGetTableInfoRequest
|
||||
getTableInfoRequestFromDictionary:params];
|
||||
if (!request) {
|
||||
[DatabasesManager raiseInvalidRequestError:responder];
|
||||
return;
|
||||
}
|
||||
DatabaseDescriptorHolder* descriptorHolder =
|
||||
self.databaseDescriptorHolders[@(request.databaseId)];
|
||||
if (!descriptorHolder) {
|
||||
[DatabasesManager raiseDatabaseInvalidError:responder];
|
||||
return;
|
||||
}
|
||||
|
||||
@try {
|
||||
DatabaseGetTableInfoResponse* tableInfo =
|
||||
[descriptorHolder.databaseDriver
|
||||
getTableInfoWithDatabaseDescriptor:descriptorHolder
|
||||
.databaseDescriptor
|
||||
forTable:request.table];
|
||||
NSDictionary* response =
|
||||
[ObjectMapper databaseGetTableInfoResponseToDictionary:tableInfo];
|
||||
[responder success:response];
|
||||
} @catch (NSException* exception) {
|
||||
NSString* reason = exception.reason ?: @"Unknown error";
|
||||
NSDictionary* errorResponse = [ObjectMapper
|
||||
errorWithCode:DatabasesErrorCodesSqlExecutionException
|
||||
message:[kDatabasesErrorCodesSqlExecutionExceptionMessage
|
||||
stringByAppendingString:reason]];
|
||||
[responder error:errorResponse];
|
||||
}
|
||||
}];
|
||||
|
||||
[self.connection
|
||||
receive:@"execute"
|
||||
withBlock:^(NSDictionary* params, id<FlipperResponder> responder) {
|
||||
DatabaseExecuteSqlRequest* request = [DatabaseExecuteSqlRequest
|
||||
getExecuteSqlRequestFromDictionary:params];
|
||||
if (!request) {
|
||||
[DatabasesManager raiseInvalidRequestError:responder];
|
||||
return;
|
||||
}
|
||||
DatabaseDescriptorHolder* descriptorHolder =
|
||||
self.databaseDescriptorHolders[@(request.databaseId)];
|
||||
if (!descriptorHolder) {
|
||||
[DatabasesManager raiseDatabaseInvalidError:responder];
|
||||
return;
|
||||
}
|
||||
@try {
|
||||
DatabaseExecuteSqlResponse* sqlResponse =
|
||||
[descriptorHolder.databaseDriver executeSQL:request.value];
|
||||
NSDictionary* response =
|
||||
[ObjectMapper databaseExecuteSqlResponseToDictionary:sqlResponse];
|
||||
[responder success:response];
|
||||
} @catch (NSException* exception) {
|
||||
NSString* reason = exception.reason ?: @"Unknown error";
|
||||
NSDictionary* errorResponse = [ObjectMapper
|
||||
errorWithCode:DatabasesErrorCodesSqlExecutionException
|
||||
message:[kDatabasesErrorCodesSqlExecutionExceptionMessage
|
||||
stringByAppendingString:reason]];
|
||||
[responder error:errorResponse];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)addDatabaseDriver:(id<DatabaseDriver>)driver {
|
||||
if ([self.databaseDrivers containsObject:driver]) {
|
||||
return;
|
||||
}
|
||||
[self.databaseDrivers addObject:driver];
|
||||
}
|
||||
|
||||
- (void)removeDatabaseDriver:(id<DatabaseDriver>)driver {
|
||||
if (![self.databaseDrivers containsObject:driver]) {
|
||||
return;
|
||||
}
|
||||
[self.databaseDrivers removeObject:driver];
|
||||
}
|
||||
|
||||
+ (void)raiseInvalidRequestError:(id<FlipperResponder>)responder {
|
||||
NSDictionary* errorResponse =
|
||||
[ObjectMapper errorWithCode:DatabasesErrorCodesInvalidRequest
|
||||
message:kDatabasesErrorCodesInvalidRequestMessage];
|
||||
[responder error:errorResponse];
|
||||
}
|
||||
|
||||
+ (void)raiseDatabaseInvalidError:(id<FlipperResponder>)responder {
|
||||
NSDictionary* errorResponse =
|
||||
[ObjectMapper errorWithCode:DatabasesErrorCodesDatabaseInvalid
|
||||
message:kDatabasesErrorCodesDatabaseInvalidMessage];
|
||||
[responder error:errorResponse];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <FlipperKit/FlipperPlugin.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DatabaseDriver.h"
|
||||
|
||||
@class DatabasesManager;
|
||||
|
||||
@interface FlipperKitDatabasesPlugin : NSObject<FlipperPlugin>
|
||||
@property(nonatomic, strong) DatabasesManager* databasesManager;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+ (instancetype)sharedInstance;
|
||||
- (void)addDatabaseDriver:(id<DatabaseDriver>)driver;
|
||||
- (void)removeDatabaseDriver:(id<DatabaseDriver>)driver;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
#import "FlipperKitDatabasesPlugin.h"
|
||||
#import <FlipperKit/FlipperClient.h>
|
||||
#import <FlipperKit/FlipperConnection.h>
|
||||
#import <FlipperKit/FlipperResponder.h>
|
||||
#import "DatabaseDriver.h"
|
||||
#import "DatabasesManager.h"
|
||||
#import "MockDatabaseDriver.h"
|
||||
|
||||
@interface FlipperKitDatabasesPlugin ()
|
||||
@property(strong, nonatomic) id<FlipperConnection> connection;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FlipperKitDatabasesPlugin
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_databasesManager = [DatabasesManager new];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)sharedInstance {
|
||||
static FlipperKitDatabasesPlugin* sInstance = nil;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sInstance = [FlipperKitDatabasesPlugin new];
|
||||
});
|
||||
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
- (void)didConnect:(id<FlipperConnection>)connection {
|
||||
self.connection = connection;
|
||||
[self.databasesManager setConnection:connection];
|
||||
}
|
||||
|
||||
- (void)didDisconnect {
|
||||
[self.databasesManager setConnection:nil];
|
||||
}
|
||||
|
||||
- (NSString*)identifier {
|
||||
return @"Databases";
|
||||
}
|
||||
|
||||
- (BOOL)runInBackground {
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)addDatabaseDriver:(id<DatabaseDriver>)driver {
|
||||
[self.databasesManager addDatabaseDriver:driver];
|
||||
}
|
||||
|
||||
- (void)removeDatabaseDriver:(id<DatabaseDriver>)driver {
|
||||
[self.databasesManager addDatabaseDriver:driver];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DatabaseDescriptor.h"
|
||||
|
||||
@interface MockDatabaseDescriptor : NSObject<DatabaseDescriptor>
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "MockDatabaseDescriptor.h"
|
||||
|
||||
@implementation MockDatabaseDescriptor
|
||||
|
||||
- (NSString*)name {
|
||||
return @"MockDatabase";
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <FlipperKitDatabasesPlugin/DatabaseDriver.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface MockDatabaseDriver : NSObject<DatabaseDriver>
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "MockDatabaseDriver.h"
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <objc/NSObjCRuntime.h>
|
||||
#import "DatabaseExecuteSql.h"
|
||||
#import "DatabaseGetTableData.h"
|
||||
#import "DatabaseGetTableInfo.h"
|
||||
#import "DatabaseGetTableStructure.h"
|
||||
#import "MockDatabaseDescriptor.h"
|
||||
|
||||
@implementation MockDatabaseDriver
|
||||
|
||||
- (NSArray<id<DatabaseDescriptor>>*)getDatabases {
|
||||
MockDatabaseDescriptor* mockDescriptor =
|
||||
[[MockDatabaseDescriptor alloc] init];
|
||||
return @[ mockDescriptor ];
|
||||
}
|
||||
|
||||
- (NSArray<NSString*>*)getTableNames:
|
||||
(id<DatabaseDescriptor>)databaseDescriptor {
|
||||
return @[ @"MockTable1", @"MockTable2" ];
|
||||
}
|
||||
|
||||
- (DatabaseGetTableStructureResponse*)
|
||||
getTableStructureWithDatabaseDescriptor:
|
||||
(id<DatabaseDescriptor>)databaseDescriptor
|
||||
forTable:(NSString*)tableName {
|
||||
NSMutableArray<NSString*>* structureColumns =
|
||||
[NSMutableArray arrayWithObjects:@"id", @"name", @"age", nil];
|
||||
NSMutableArray<NSArray<NSString*>*>* structureValues =
|
||||
[NSMutableArray arrayWithObjects:@[ @"1", @"John", @"25" ],
|
||||
@[ @"2", @"Jane", @"30" ],
|
||||
nil];
|
||||
NSMutableArray<NSString*>* indexesColumns = [NSMutableArray
|
||||
arrayWithObjects:@"index_name", @"unique", @"indexed_column_name", nil];
|
||||
NSMutableArray<NSArray<NSString*>*>* indexesValues = [NSMutableArray
|
||||
arrayWithObjects:@[ @"index_name1", @"false", @"id,name" ],
|
||||
@[ @"index_name2", @"true", @"age" ],
|
||||
nil];
|
||||
|
||||
return [[DatabaseGetTableStructureResponse alloc]
|
||||
initWithStructureColumns:[structureColumns copy]
|
||||
structureValues:[structureValues copy]
|
||||
indexesColumns:[indexesColumns copy]
|
||||
indexesValues:[indexesValues copy]];
|
||||
}
|
||||
|
||||
- (DatabaseGetTableInfoResponse*)
|
||||
getTableInfoWithDatabaseDescriptor:
|
||||
(id<DatabaseDescriptor>)databaseDescriptor
|
||||
forTable:(NSString*)tableName {
|
||||
return [[DatabaseGetTableInfoResponse alloc]
|
||||
initWithDefinition:@"This is mocked table definition"];
|
||||
}
|
||||
|
||||
- (DatabaseGetTableDataResponse*)
|
||||
getTableDataWithDatabaseDescriptor:
|
||||
(id<DatabaseDescriptor>)databaseDescriptor
|
||||
forTable:(NSString*)tableName
|
||||
order:(NSString*)order
|
||||
reverse:(BOOL)reverse
|
||||
start:(NSInteger)start
|
||||
count:(NSInteger)count {
|
||||
NSMutableArray* columns = [NSMutableArray array];
|
||||
NSMutableArray* values = [NSMutableArray array];
|
||||
NSUInteger numColums = 10;
|
||||
NSUInteger numRows = 100;
|
||||
for (int i = 0; i < numColums; i++) {
|
||||
NSString* columnName = [NSString stringWithFormat:@"column%d", i + 1];
|
||||
[columns addObject:columnName];
|
||||
}
|
||||
|
||||
for (int i = 0; i < numRows; i++) {
|
||||
NSMutableArray* valueRow = [NSMutableArray array];
|
||||
for (int j = 0; j < numColums; j++) {
|
||||
[valueRow addObject:[NSString stringWithFormat:@"value%d", j]];
|
||||
}
|
||||
[values addObject:valueRow];
|
||||
}
|
||||
|
||||
return [[DatabaseGetTableDataResponse alloc] initWithColumns:[columns copy]
|
||||
values:[values copy]
|
||||
start:0
|
||||
count:numRows
|
||||
total:numRows];
|
||||
}
|
||||
|
||||
- (DatabaseExecuteSqlResponse*)executeSQL:(NSString*)sql {
|
||||
// Generate a mock response with a random type
|
||||
NSString* type;
|
||||
NSArray* columns = @[ @"id", @"name", @"age" ];
|
||||
NSMutableArray* values = [NSMutableArray array];
|
||||
NSUInteger numRows = 100;
|
||||
for (int i = 0; i < numRows; i++) {
|
||||
NSUInteger randomAge = arc4random_uniform(40);
|
||||
[values addObject:@[
|
||||
@(i),
|
||||
[NSString stringWithFormat:@"Name %d", i],
|
||||
@(randomAge)
|
||||
]];
|
||||
}
|
||||
|
||||
// Randomly select a type
|
||||
NSArray<NSString*>* types = @[ @"select", @"insert", @"update_delete" ];
|
||||
int index = arc4random_uniform((u_int32_t)types.count);
|
||||
type = types[index];
|
||||
|
||||
// Set affectedCount and insertedId based on type
|
||||
NSInteger affectedCount = 0;
|
||||
NSNumber* insertedId = nil;
|
||||
if ([type isEqualToString:@"insert"]) {
|
||||
affectedCount = 1;
|
||||
insertedId = @(15);
|
||||
} else if ([type isEqualToString:@"update_delete"]) {
|
||||
affectedCount = values.count;
|
||||
}
|
||||
|
||||
DatabaseExecuteSqlResponse* response =
|
||||
[[DatabaseExecuteSqlResponse alloc] initWithType:type
|
||||
columns:columns
|
||||
values:[values copy]
|
||||
insertedId:insertedId
|
||||
affectedCount:affectedCount];
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class DatabaseDescriptorHolder;
|
||||
@class DatabaseExecuteSqlResponse;
|
||||
@class DatabaseGetTableDataResponse;
|
||||
@class DatabaseGetTableInfoResponse;
|
||||
@class DatabaseGetTableStructureResponse;
|
||||
|
||||
@interface ObjectMapper : NSObject
|
||||
|
||||
+ (NSMutableArray*)databaseListToFlipperArray:
|
||||
(NSMutableSet<DatabaseDescriptorHolder*>*)databaseDescriptorHolderSet;
|
||||
+ (NSDictionary*)databaseGetTableDataResponseToDictionary:
|
||||
(DatabaseGetTableDataResponse*)response;
|
||||
+ (NSDictionary*)databaseGetTableStructureResponseToDictionary:
|
||||
(DatabaseGetTableStructureResponse*)response;
|
||||
+ (NSDictionary*)databaseGetTableInfoResponseToDictionary:
|
||||
(DatabaseGetTableInfoResponse*)response;
|
||||
+ (NSDictionary*)databaseExecuteSqlResponseToDictionary:
|
||||
(DatabaseExecuteSqlResponse*)response;
|
||||
+ (NSDictionary*)errorWithCode:(NSInteger)code message:(NSString*)message;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "ObjectMapper.h"
|
||||
#include <Foundation/Foundation.h>
|
||||
#import "DatabaseDescriptorHolder.h"
|
||||
#import "DatabaseExecuteSql.h"
|
||||
#import "DatabaseGetTableData.h"
|
||||
#import "DatabaseGetTableInfo.h"
|
||||
#import "DatabaseGetTableStructure.h"
|
||||
|
||||
@implementation ObjectMapper
|
||||
|
||||
static const int MAX_BLOB_LENGTH = 100 * 1024;
|
||||
static NSString* const UNKNOWN_BLOB_LABEL_FORMAT = @"{%d-byte %@ blob}";
|
||||
|
||||
+ (NSMutableArray*)databaseListToFlipperArray:
|
||||
(NSMutableSet<DatabaseDescriptorHolder*>*)databaseDescriptorHolderSet {
|
||||
NSMutableArray* result = [NSMutableArray new];
|
||||
|
||||
for (DatabaseDescriptorHolder* holder in databaseDescriptorHolderSet) {
|
||||
NSArray<NSString*>* tables =
|
||||
[holder.databaseDriver getTableNames:holder.databaseDescriptor];
|
||||
NSArray<NSString*>* sortedTableNames =
|
||||
[tables sortedArrayUsingSelector:@selector(compare:)];
|
||||
NSString* idString = [NSString stringWithFormat:@"%ld", holder.identifier];
|
||||
|
||||
NSDictionary* databaseInfo = @{
|
||||
@"id" : idString,
|
||||
@"name" : holder.databaseDescriptor.name,
|
||||
@"tables" : sortedTableNames
|
||||
};
|
||||
[result addObject:databaseInfo];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (NSDictionary*)databaseGetTableDataResponseToDictionary:
|
||||
(DatabaseGetTableDataResponse*)response {
|
||||
NSMutableArray* rows = [NSMutableArray array];
|
||||
for (NSArray* row in response.values) {
|
||||
NSMutableArray* rowValues = [NSMutableArray array];
|
||||
for (id item in row) {
|
||||
[rowValues addObject:[self objectAndTypeToFlipperObject:item]];
|
||||
}
|
||||
[rows addObject:rowValues];
|
||||
}
|
||||
|
||||
return @{
|
||||
@"columns" : response.columns,
|
||||
@"values" : rows,
|
||||
@"start" : @(response.start),
|
||||
@"count" : @(response.count),
|
||||
@"total" : @(response.total)
|
||||
};
|
||||
}
|
||||
|
||||
+ (NSDictionary*)errorWithCode:(NSInteger)code message:(NSString*)message {
|
||||
return @{@"code" : @(code), @"message" : message};
|
||||
}
|
||||
|
||||
+ (NSDictionary*)databaseGetTableStructureResponseToDictionary:
|
||||
(DatabaseGetTableStructureResponse*)response {
|
||||
NSMutableArray* structureValues = [NSMutableArray array];
|
||||
for (NSArray* row in response.structureValues) {
|
||||
NSMutableArray* rowValues = [NSMutableArray array];
|
||||
for (id item in row) {
|
||||
[rowValues addObject:[self objectAndTypeToFlipperObject:item]];
|
||||
}
|
||||
[structureValues addObject:rowValues];
|
||||
}
|
||||
|
||||
NSMutableArray* indexesValues = [NSMutableArray array];
|
||||
for (NSArray* row in response.indexesValues) {
|
||||
NSMutableArray* rowValues = [NSMutableArray array];
|
||||
for (id item in row) {
|
||||
[rowValues addObject:[self objectAndTypeToFlipperObject:item]];
|
||||
}
|
||||
[indexesValues addObject:rowValues];
|
||||
}
|
||||
|
||||
return @{
|
||||
@"structureColumns" : response.structureColumns,
|
||||
@"structureValues" : structureValues,
|
||||
@"indexesColumns" : response.indexesColumns,
|
||||
@"indexesValues" : indexesValues
|
||||
};
|
||||
}
|
||||
|
||||
+ (NSDictionary*)databaseGetTableInfoResponseToDictionary:
|
||||
(DatabaseGetTableInfoResponse*)response {
|
||||
return @{
|
||||
@"definition" : response.definition,
|
||||
};
|
||||
}
|
||||
|
||||
+ (NSDictionary*)databaseExecuteSqlResponseToDictionary:
|
||||
(DatabaseExecuteSqlResponse*)response {
|
||||
NSMutableArray* rows = [NSMutableArray array];
|
||||
if (response.values) {
|
||||
for (NSArray* row in response.values) {
|
||||
NSMutableArray* rowValues = [NSMutableArray array];
|
||||
for (id item in row) {
|
||||
[rowValues addObject:[self objectAndTypeToFlipperObject:item]];
|
||||
}
|
||||
[rows addObject:rowValues];
|
||||
}
|
||||
}
|
||||
|
||||
NSMutableDictionary* result = [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"type" : response.type,
|
||||
@"columns" : response.columns,
|
||||
@"values" : rows,
|
||||
@"affectedCount" : @(response.affectedCount)
|
||||
}];
|
||||
|
||||
if (response.insertedId) {
|
||||
result[@"insertedId"] = response.insertedId;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (NSDictionary*)objectAndTypeToFlipperObject:(id)object {
|
||||
if (!object || [object isKindOfClass:[NSNull class]]) {
|
||||
return @{@"type" : @"null"};
|
||||
} else if ([object isKindOfClass:[NSNumber class]]) {
|
||||
NSNumber* number = (NSNumber*)object;
|
||||
NSString* type = [NSString stringWithUTF8String:[number objCType]];
|
||||
|
||||
if ([type isEqualToString:@"i"]) {
|
||||
return @{@"type" : @"integer", @"value" : number};
|
||||
} else if ([type isEqualToString:@"f"] || [type isEqualToString:@"d"]) {
|
||||
return @{@"type" : @"float", @"value" : number};
|
||||
} else if ([type isEqualToString:@"B"]) {
|
||||
return @{@"type" : @"boolean", @"value" : number};
|
||||
} else {
|
||||
return @{@"type" : @"integer", @"value" : @([number integerValue])};
|
||||
}
|
||||
|
||||
return @{@"type" : @"integer", @"value" : object};
|
||||
} else if ([object isKindOfClass:[NSDecimalNumber class]]) {
|
||||
return @{@"type" : @"float", @"value" : object};
|
||||
} else if ([object isKindOfClass:[NSString class]]) {
|
||||
return @{@"type" : @"string", @"value" : object};
|
||||
} else if ([object isKindOfClass:[NSData class]]) {
|
||||
NSString* blobString = [self blobToString:(NSData*)object];
|
||||
return @{@"type" : @"blob", @"value" : blobString};
|
||||
} else if ([object isKindOfClass:[NSDictionary class]]) {
|
||||
// Usualy the dictionary is a Json blob, and we can parse it as string.
|
||||
NSError* error;
|
||||
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:object
|
||||
options:0
|
||||
error:&error];
|
||||
if (!jsonData) {
|
||||
NSString* reason = [NSString
|
||||
stringWithFormat:@"NSDictionary is not in a json format: %@",
|
||||
[error localizedDescription]];
|
||||
@throw [NSException exceptionWithName:@"InvalidArgumentException"
|
||||
reason:reason
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
NSString* jsonString = [[NSString alloc] initWithData:jsonData
|
||||
encoding:NSUTF8StringEncoding];
|
||||
return @{@"type" : @"blob", @"value" : jsonString};
|
||||
|
||||
} else if ([object isKindOfClass:[NSValue class]]) {
|
||||
return @{@"type" : @"boolean", @"value" : object};
|
||||
} else {
|
||||
@throw [NSException exceptionWithName:@"InvalidArgumentException"
|
||||
reason:@"type of Object is invalid"
|
||||
userInfo:nil];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSString*)blobToString:(NSData*)data {
|
||||
const uint8_t* bytes = data.bytes;
|
||||
uint length = data.length;
|
||||
|
||||
if (length <= MAX_BLOB_LENGTH) {
|
||||
if ([self fastIsAscii:bytes length:length]) {
|
||||
NSStringEncoding encoding = NSASCIIStringEncoding;
|
||||
return [[NSString alloc] initWithBytesNoCopy:(void*)bytes
|
||||
length:length
|
||||
encoding:encoding
|
||||
freeWhenDone:NO];
|
||||
} else {
|
||||
// try UTF-8
|
||||
NSStringEncoding encoding = NSUTF8StringEncoding;
|
||||
return [[NSString alloc] initWithBytesNoCopy:(void*)bytes
|
||||
length:length
|
||||
encoding:encoding
|
||||
freeWhenDone:NO];
|
||||
}
|
||||
}
|
||||
return
|
||||
[NSString stringWithFormat:UNKNOWN_BLOB_LABEL_FORMAT, length, @"binary"];
|
||||
}
|
||||
|
||||
+ (BOOL)fastIsAscii:(const uint8_t*)bytes length:(NSUInteger)length {
|
||||
for (int i = 0; i < length; i++) {
|
||||
uint8_t b = bytes[i];
|
||||
if ((b & ~0x7f) != 0) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -11,7 +11,7 @@
|
||||
#import <FlipperKitLayoutTextSearchable/FKTextSearchable.h>
|
||||
|
||||
@implementation SKNodeDescriptor {
|
||||
id<SKDescriptorMapperProtocol> _mapper;
|
||||
__weak id<SKDescriptorMapperProtocol> _mapper;
|
||||
}
|
||||
|
||||
- (void)setUp {
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define APPLY_ENUM_TO_YOGA_PROPERTY(varName, enumName) \
|
||||
^(NSString * newValue) { \
|
||||
NSNumber* varName = \
|
||||
[[enumName##EnumMap allKeysForObject:newValue] lastObject]; \
|
||||
if (varName == nil) { \
|
||||
return; \
|
||||
} \
|
||||
node.yoga.varName = (enumName)[varName unsignedIntegerValue]; \
|
||||
}
|
||||
|
||||
#define APPLY_VALUE_TO_YGVALUE(varName) \
|
||||
^(NSNumber * value) { \
|
||||
YGValue newValue = node.yoga.varName; \
|
||||
newValue.value = [value floatValue]; \
|
||||
node.yoga.varName = newValue; \
|
||||
}
|
||||
|
||||
#define APPLY_UNIT_TO_YGVALUE(varName, enumName) \
|
||||
^(NSString * value) { \
|
||||
NSNumber* varName = \
|
||||
[[enumName##EnumMap allKeysForObject:value] lastObject]; \
|
||||
if (varName == nil) { \
|
||||
return; \
|
||||
} \
|
||||
YGValue newValue = node.yoga.varName; \
|
||||
newValue.unit = (enumName)[varName unsignedIntegerValue]; \
|
||||
node.yoga.varName = newValue; \
|
||||
}
|
||||
@@ -11,8 +11,6 @@
|
||||
|
||||
#import <FlipperKitLayoutHelpers/SKNodeDescriptor.h>
|
||||
|
||||
@class SKDescriptorMapper;
|
||||
|
||||
@interface SKViewControllerDescriptor : SKNodeDescriptor<UIViewController*>
|
||||
|
||||
@end
|
||||
|
||||
@@ -14,29 +14,13 @@
|
||||
#import <FlipperKitLayoutHelpers/SKHiddenWindow.h>
|
||||
#import <FlipperKitLayoutHelpers/SKNamed.h>
|
||||
#import <FlipperKitLayoutHelpers/SKObject.h>
|
||||
#import <FlipperKitLayoutHelpers/SKYogaKitHelper.h>
|
||||
#import <FlipperKitLayoutHelpers/UIColor+SKSonarValueCoder.h>
|
||||
#import <YogaKit/UIView+Yoga.h>
|
||||
|
||||
@implementation SKViewDescriptor
|
||||
|
||||
static NSDictionary* YGDirectionEnumMap = nil;
|
||||
static NSDictionary* YGFlexDirectionEnumMap = nil;
|
||||
static NSDictionary* YGJustifyEnumMap = nil;
|
||||
static NSDictionary* YGAlignEnumMap = nil;
|
||||
static NSDictionary* YGPositionTypeEnumMap = nil;
|
||||
static NSDictionary* YGWrapEnumMap = nil;
|
||||
static NSDictionary* YGOverflowEnumMap = nil;
|
||||
static NSDictionary* YGDisplayEnumMap = nil;
|
||||
static NSDictionary* YGUnitEnumMap = nil;
|
||||
|
||||
- (instancetype)initWithDescriptorMapper:
|
||||
(id<SKDescriptorMapperProtocol>)mapper {
|
||||
if (self = [super initWithDescriptorMapper:mapper]) {
|
||||
initEnumDictionaries();
|
||||
}
|
||||
|
||||
return self;
|
||||
return [super initWithDescriptorMapper:mapper];
|
||||
}
|
||||
|
||||
- (NSString*)identifierForNode:(UIView*)node {
|
||||
@@ -125,102 +109,6 @@ static NSDictionary* YGUnitEnumMap = nil;
|
||||
@"shouldGroupAccessibilityChildren" : SKMutableObject(
|
||||
@(node.shouldGroupAccessibilityChildren)),
|
||||
}],
|
||||
!node.isYogaEnabled
|
||||
? nil
|
||||
: [SKNamed
|
||||
newWithName:@"YGLayout"
|
||||
withValue:@{
|
||||
@"direction" : SKMutableObject(
|
||||
YGDirectionEnumMap[@(node.yoga.direction)]),
|
||||
@"justifyContent" : SKMutableObject(
|
||||
YGJustifyEnumMap[@(node.yoga.justifyContent)]),
|
||||
@"aligns" : @{
|
||||
@"alignContent" : SKMutableObject(
|
||||
YGAlignEnumMap[@(node.yoga.alignContent)]),
|
||||
@"alignItems" : SKMutableObject(
|
||||
YGAlignEnumMap[@(node.yoga.alignItems)]),
|
||||
@"alignSelf" : SKMutableObject(
|
||||
YGAlignEnumMap[@(node.yoga.alignSelf)]),
|
||||
},
|
||||
@"position" : @{
|
||||
@"type" : SKMutableObject(
|
||||
YGPositionTypeEnumMap[@(node.yoga.position)]),
|
||||
@"left" : SKYGValueObject(node.yoga.left),
|
||||
@"top" : SKYGValueObject(node.yoga.top),
|
||||
@"right" : SKYGValueObject(node.yoga.right),
|
||||
@"bottom" : SKYGValueObject(node.yoga.bottom),
|
||||
@"start" : SKYGValueObject(node.yoga.start),
|
||||
@"end" : SKYGValueObject(node.yoga.end),
|
||||
},
|
||||
@"overflow" : SKMutableObject(
|
||||
YGOverflowEnumMap[@(node.yoga.overflow)]),
|
||||
@"display" : SKMutableObject(
|
||||
YGDisplayEnumMap[@(node.yoga.display)]),
|
||||
@"flex" : @{
|
||||
@"flexDirection" :
|
||||
SKMutableObject(YGFlexDirectionEnumMap[
|
||||
@(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" : @{
|
||||
@"left" : SKYGValueObject(node.yoga.marginLeft),
|
||||
@"top" : SKYGValueObject(node.yoga.marginTop),
|
||||
@"right" : SKYGValueObject(node.yoga.marginRight),
|
||||
@"bottom" : SKYGValueObject(node.yoga.marginBottom),
|
||||
@"start" : SKYGValueObject(node.yoga.marginStart),
|
||||
@"end" : SKYGValueObject(node.yoga.marginEnd),
|
||||
@"horizontal" :
|
||||
SKYGValueObject(node.yoga.marginHorizontal),
|
||||
@"vertical" :
|
||||
SKYGValueObject(node.yoga.marginVertical),
|
||||
@"all" : SKYGValueObject(node.yoga.margin),
|
||||
},
|
||||
@"padding" : @{
|
||||
@"left" : SKYGValueObject(node.yoga.paddingLeft),
|
||||
@"top" : SKYGValueObject(node.yoga.paddingTop),
|
||||
@"right" : SKYGValueObject(node.yoga.paddingRight),
|
||||
@"bottom" : SKYGValueObject(node.yoga.paddingBottom),
|
||||
@"start" : SKYGValueObject(node.yoga.paddingStart),
|
||||
@"end" : SKYGValueObject(node.yoga.paddingEnd),
|
||||
@"horizontal" :
|
||||
SKYGValueObject(node.yoga.paddingHorizontal),
|
||||
@"vertical" :
|
||||
SKYGValueObject(node.yoga.paddingVertical),
|
||||
@"all" : SKYGValueObject(node.yoga.padding),
|
||||
},
|
||||
@"border" : @{
|
||||
@"leftWidth" :
|
||||
SKMutableObject(@(node.yoga.borderLeftWidth)),
|
||||
@"topWidth" :
|
||||
SKMutableObject(@(node.yoga.borderTopWidth)),
|
||||
@"rightWidth" :
|
||||
SKMutableObject(@(node.yoga.borderRightWidth)),
|
||||
@"bottomWidth" :
|
||||
SKMutableObject(@(node.yoga.borderBottomWidth)),
|
||||
@"startWidth" :
|
||||
SKMutableObject(@(node.yoga.borderStartWidth)),
|
||||
@"endWidth" :
|
||||
SKMutableObject(@(node.yoga.borderEndWidth)),
|
||||
@"all" : SKMutableObject(@(node.yoga.borderWidth)),
|
||||
},
|
||||
@"dimensions" : @{
|
||||
@"width" : SKYGValueObject(node.yoga.width),
|
||||
@"height" : SKYGValueObject(node.yoga.height),
|
||||
@"minWidth" : SKYGValueObject(node.yoga.minWidth),
|
||||
@"minHeight" : SKYGValueObject(node.yoga.minHeight),
|
||||
@"maxWidth" : SKYGValueObject(node.yoga.maxWidth),
|
||||
@"maxHeight" : SKYGValueObject(node.yoga.maxHeight),
|
||||
},
|
||||
@"aspectRatio" :
|
||||
SKMutableObject(@(node.yoga.aspectRatio)),
|
||||
@"resolvedDirection" : SKObject(
|
||||
YGDirectionEnumMap[@(node.yoga.resolvedDirection)]),
|
||||
}],
|
||||
nil];
|
||||
}
|
||||
|
||||
@@ -290,109 +178,6 @@ static NSDictionary* YGUnitEnumMap = nil;
|
||||
@"CALayer.masksToBounds": ^(NSNumber *value) {
|
||||
node.layer.masksToBounds = [value boolValue];
|
||||
},
|
||||
// YGLayout
|
||||
@"YGLayout.direction": APPLY_ENUM_TO_YOGA_PROPERTY(direction, YGDirection),
|
||||
@"YGLayout.justifyContent": APPLY_ENUM_TO_YOGA_PROPERTY(justifyContent, YGJustify),
|
||||
@"YGLayout.aligns.alignContent": APPLY_ENUM_TO_YOGA_PROPERTY(alignContent, YGAlign),
|
||||
@"YGLayout.aligns.alignItems": APPLY_ENUM_TO_YOGA_PROPERTY(alignItems, YGAlign),
|
||||
@"YGLayout.aligns.alignSelf": APPLY_ENUM_TO_YOGA_PROPERTY(alignSelf, YGAlign),
|
||||
@"YGLayout.position.type": APPLY_ENUM_TO_YOGA_PROPERTY(position, YGPositionType),
|
||||
@"YGLayout.position.left.value": APPLY_VALUE_TO_YGVALUE(left),
|
||||
@"YGLayout.position.left.unit": APPLY_UNIT_TO_YGVALUE(left, YGUnit),
|
||||
@"YGLayout.position.top.value": APPLY_VALUE_TO_YGVALUE(top),
|
||||
@"YGLayout.position.top.unit": APPLY_UNIT_TO_YGVALUE(top, YGUnit),
|
||||
@"YGLayout.position.right.value": APPLY_VALUE_TO_YGVALUE(right),
|
||||
@"YGLayout.position.right.unit": APPLY_UNIT_TO_YGVALUE(right, YGUnit),
|
||||
@"YGLayout.position.bottom.value": APPLY_VALUE_TO_YGVALUE(bottom),
|
||||
@"YGLayout.position.bottom.unit": APPLY_UNIT_TO_YGVALUE(bottom, YGUnit),
|
||||
@"YGLayout.position.start.value": APPLY_VALUE_TO_YGVALUE(start),
|
||||
@"YGLayout.position.start.unit": APPLY_UNIT_TO_YGVALUE(start, YGUnit),
|
||||
@"YGLayout.position.end.value": APPLY_VALUE_TO_YGVALUE(end),
|
||||
@"YGLayout.position.end.unit": APPLY_UNIT_TO_YGVALUE(end, YGUnit),
|
||||
@"YGLayout.overflow": APPLY_ENUM_TO_YOGA_PROPERTY(overflow, YGOverflow),
|
||||
@"YGLayout.display": APPLY_ENUM_TO_YOGA_PROPERTY(display, YGDisplay),
|
||||
@"YGLayout.flex.flexDirection": APPLY_ENUM_TO_YOGA_PROPERTY(flexDirection, YGFlexDirection),
|
||||
@"YGLayout.flex.flexWrap": APPLY_ENUM_TO_YOGA_PROPERTY(flexWrap, YGWrap),
|
||||
@"YGLayout.flex.flexGrow": ^(NSNumber *value) {
|
||||
node.yoga.flexGrow = [value floatValue];
|
||||
},
|
||||
@"YGLayout.flex.flexShrink": ^(NSNumber *value) {
|
||||
node.yoga.flexShrink = [value floatValue];
|
||||
},
|
||||
@"YGLayout.flex.flexBasis.value": APPLY_VALUE_TO_YGVALUE(flexBasis),
|
||||
@"YGLayout.flex.flexBasis.unit": APPLY_UNIT_TO_YGVALUE(flexBasis, YGUnit),
|
||||
@"YGLayout.margin.left.value": APPLY_VALUE_TO_YGVALUE(marginLeft),
|
||||
@"YGLayout.margin.left.unit": APPLY_UNIT_TO_YGVALUE(marginLeft, YGUnit),
|
||||
@"YGLayout.margin.top.value": APPLY_VALUE_TO_YGVALUE(marginTop),
|
||||
@"YGLayout.margin.top.unit": APPLY_UNIT_TO_YGVALUE(marginTop, YGUnit),
|
||||
@"YGLayout.margin.right.value": APPLY_VALUE_TO_YGVALUE(marginRight),
|
||||
@"YGLayout.margin.right.unit": APPLY_UNIT_TO_YGVALUE(marginRight, YGUnit),
|
||||
@"YGLayout.margin.bottom.value": APPLY_VALUE_TO_YGVALUE(marginBottom),
|
||||
@"YGLayout.margin.bottom.unit": APPLY_UNIT_TO_YGVALUE(marginBottom, YGUnit),
|
||||
@"YGLayout.margin.start.value": APPLY_VALUE_TO_YGVALUE(marginStart),
|
||||
@"YGLayout.margin.start.unit": APPLY_UNIT_TO_YGVALUE(marginStart, YGUnit),
|
||||
@"YGLayout.margin.end.value": APPLY_VALUE_TO_YGVALUE(marginEnd),
|
||||
@"YGLayout.margin.end.unit": APPLY_UNIT_TO_YGVALUE(marginEnd, YGUnit),
|
||||
@"YGLayout.margin.horizontal.value": APPLY_VALUE_TO_YGVALUE(marginHorizontal),
|
||||
@"YGLayout.margin.horizontal.unit": APPLY_UNIT_TO_YGVALUE(marginHorizontal, YGUnit),
|
||||
@"YGLayout.margin.vertical.value": APPLY_VALUE_TO_YGVALUE(marginVertical),
|
||||
@"YGLayout.margin.vertical.unit": APPLY_UNIT_TO_YGVALUE(marginVertical, YGUnit),
|
||||
@"YGLayout.margin.all.value": APPLY_VALUE_TO_YGVALUE(margin),
|
||||
@"YGLayout.margin.all.unit": APPLY_UNIT_TO_YGVALUE(margin, YGUnit),
|
||||
@"YGLayout.padding.left.value": APPLY_VALUE_TO_YGVALUE(paddingLeft),
|
||||
@"YGLayout.padding.left.unit": APPLY_UNIT_TO_YGVALUE(paddingLeft, YGUnit),
|
||||
@"YGLayout.padding.top.value": APPLY_VALUE_TO_YGVALUE(paddingTop),
|
||||
@"YGLayout.padding.top.unit": APPLY_UNIT_TO_YGVALUE(paddingTop, YGUnit),
|
||||
@"YGLayout.padding.right.value": APPLY_VALUE_TO_YGVALUE(paddingRight),
|
||||
@"YGLayout.padding.right.unit": APPLY_UNIT_TO_YGVALUE(paddingRight, YGUnit),
|
||||
@"YGLayout.padding.bottom.value": APPLY_VALUE_TO_YGVALUE(paddingBottom),
|
||||
@"YGLayout.padding.bottom.unit": APPLY_UNIT_TO_YGVALUE(paddingBottom, YGUnit),
|
||||
@"YGLayout.padding.start.value": APPLY_VALUE_TO_YGVALUE(paddingStart),
|
||||
@"YGLayout.padding.start.unit": APPLY_UNIT_TO_YGVALUE(paddingStart, YGUnit),
|
||||
@"YGLayout.padding.end.value": APPLY_VALUE_TO_YGVALUE(paddingEnd),
|
||||
@"YGLayout.padding.end.unit": APPLY_UNIT_TO_YGVALUE(paddingEnd, YGUnit),
|
||||
@"YGLayout.padding.horizontal.value": APPLY_VALUE_TO_YGVALUE(paddingHorizontal),
|
||||
@"YGLayout.padding.horizontal.unit": APPLY_UNIT_TO_YGVALUE(paddingHorizontal, YGUnit),
|
||||
@"YGLayout.padding.vertical.value": APPLY_VALUE_TO_YGVALUE(paddingVertical),
|
||||
@"YGLayout.padding.vertical.unit": APPLY_UNIT_TO_YGVALUE(paddingVertical, YGUnit),
|
||||
@"YGLayout.padding.all.value": APPLY_VALUE_TO_YGVALUE(padding),
|
||||
@"YGLayout.padding.all.unit": APPLY_UNIT_TO_YGVALUE(padding, YGUnit),
|
||||
@"YGLayout.border.leftWidth": ^(NSNumber *value) {
|
||||
node.yoga.borderLeftWidth = [value floatValue];
|
||||
},
|
||||
@"YGLayout.border.topWidth": ^(NSNumber *value) {
|
||||
node.yoga.borderTopWidth = [value floatValue];
|
||||
},
|
||||
@"YGLayout.border.rightWidth": ^(NSNumber *value) {
|
||||
node.yoga.borderRightWidth = [value floatValue];
|
||||
},
|
||||
@"YGLayout.border.bottomWidth": ^(NSNumber *value) {
|
||||
node.yoga.borderBottomWidth = [value floatValue];
|
||||
},
|
||||
@"YGLayout.border.startWidth": ^(NSNumber *value) {
|
||||
node.yoga.borderStartWidth = [value floatValue];
|
||||
},
|
||||
@"YGLayout.border.endWidth": ^(NSNumber *value) {
|
||||
node.yoga.borderEndWidth = [value floatValue];
|
||||
},
|
||||
@"YGLayout.border.all": ^(NSNumber *value) {
|
||||
node.yoga.borderWidth = [value floatValue];
|
||||
},
|
||||
@"YGLayout.dimensions.width.value": APPLY_VALUE_TO_YGVALUE(width),
|
||||
@"YGLayout.dimensions.width.unit": APPLY_UNIT_TO_YGVALUE(width, YGUnit),
|
||||
@"YGLayout.dimensions.height.value": APPLY_VALUE_TO_YGVALUE(height),
|
||||
@"YGLayout.dimensions.height.unit": APPLY_UNIT_TO_YGVALUE(height, YGUnit),
|
||||
@"YGLayout.dimensions.minWidth.value": APPLY_VALUE_TO_YGVALUE(minWidth),
|
||||
@"YGLayout.dimensions.minWidth.unit": APPLY_UNIT_TO_YGVALUE(minWidth, YGUnit),
|
||||
@"YGLayout.dimensions.minHeight.value": APPLY_VALUE_TO_YGVALUE(minHeight),
|
||||
@"YGLayout.dimensions.minHeight.unit": APPLY_UNIT_TO_YGVALUE(minHeight, YGUnit),
|
||||
@"YGLayout.dimensions.maxWidth.value": APPLY_VALUE_TO_YGVALUE(maxWidth),
|
||||
@"YGLayout.dimensions.maxWidth.unit": APPLY_UNIT_TO_YGVALUE(maxWidth, YGUnit),
|
||||
@"YGLayout.dimensions.maxHeight.value": APPLY_VALUE_TO_YGVALUE(maxHeight),
|
||||
@"YGLayout.dimensions.maxHeight.unit": APPLY_UNIT_TO_YGVALUE(maxHeight, YGUnit),
|
||||
@"YGLayout.aspectRatio": ^(NSNumber *value) {
|
||||
node.yoga.aspectRatio = [value floatValue];
|
||||
},
|
||||
// Accessibility
|
||||
@"Accessibility.isAccessibilityElement": ^(NSNumber *value) {
|
||||
node.isAccessibilityElement = [value boolValue];
|
||||
@@ -544,79 +329,6 @@ return dataMutations;
|
||||
}
|
||||
}
|
||||
|
||||
static void initEnumDictionaries() {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
YGDirectionEnumMap = @{
|
||||
@(YGDirectionInherit) : @"inherit",
|
||||
@(YGDirectionLTR) : @"LTR",
|
||||
@(YGDirectionRTL) : @"RTL",
|
||||
};
|
||||
|
||||
YGFlexDirectionEnumMap = @{
|
||||
@(YGFlexDirectionColumn) : @"column",
|
||||
@(YGFlexDirectionColumnReverse) : @"column-reverse",
|
||||
@(YGFlexDirectionRow) : @"row",
|
||||
@(YGFlexDirectionRowReverse) : @"row-reverse",
|
||||
};
|
||||
|
||||
YGJustifyEnumMap = @{
|
||||
@(YGJustifyFlexStart) : @"flex-start",
|
||||
@(YGJustifyCenter) : @"center",
|
||||
@(YGJustifyFlexEnd) : @"flex-end",
|
||||
@(YGJustifySpaceBetween) : @"space-between",
|
||||
@(YGJustifySpaceAround) : @"space-around",
|
||||
};
|
||||
|
||||
YGAlignEnumMap = @{
|
||||
@(YGAlignAuto) : @"auto",
|
||||
@(YGAlignFlexStart) : @"flex-start",
|
||||
@(YGAlignCenter) : @"end",
|
||||
@(YGAlignFlexEnd) : @"flex-end",
|
||||
@(YGAlignStretch) : @"stretch",
|
||||
@(YGAlignBaseline) : @"baseline",
|
||||
@(YGAlignSpaceBetween) : @"space-between",
|
||||
@(YGAlignSpaceAround) : @"space-around",
|
||||
};
|
||||
|
||||
YGPositionTypeEnumMap = @{
|
||||
@(YGPositionTypeRelative) : @"relative",
|
||||
@(YGPositionTypeAbsolute) : @"absolute",
|
||||
};
|
||||
|
||||
YGWrapEnumMap = @{
|
||||
@(YGWrapNoWrap) : @"no-wrap",
|
||||
@(YGWrapWrap) : @"wrap",
|
||||
@(YGWrapWrapReverse) : @"wrap-reverse",
|
||||
};
|
||||
|
||||
YGOverflowEnumMap = @{
|
||||
@(YGOverflowVisible) : @"visible",
|
||||
@(YGOverflowHidden) : @"hidden",
|
||||
@(YGOverflowScroll) : @"scroll",
|
||||
};
|
||||
|
||||
YGDisplayEnumMap = @{
|
||||
@(YGDisplayFlex) : @"flex",
|
||||
@(YGDisplayNone) : @"none",
|
||||
};
|
||||
|
||||
YGUnitEnumMap = @{
|
||||
@(YGUnitUndefined) : @"undefined",
|
||||
@(YGUnitPoint) : @"point",
|
||||
@(YGUnitPercent) : @"percent",
|
||||
@(YGUnitAuto) : @"auto",
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
static NSDictionary* SKYGValueObject(YGValue value) {
|
||||
return @{
|
||||
@"value" : SKMutableObject(@(value.value)),
|
||||
@"unit" : SKMutableObject(YGUnitEnumMap[@(value.unit)]),
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
Takes the originalTraits, and set all bits from toggleTraits to the toggleValue
|
||||
e.g. originalTraits = UIAccessibilityTraitButton | UIAccessibilityTraitSelected
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class UIDFrameworkEventMetadata;
|
||||
@class UIDFrameworkEvent;
|
||||
|
||||
@protocol UIDFrameworkEventManager<NSObject>
|
||||
|
||||
- (void)registerEventMetadata:(UIDFrameworkEventMetadata*)eventMetadata;
|
||||
- (void)emitEvent:(UIDFrameworkEvent*)event;
|
||||
- (NSArray<UIDFrameworkEventMetadata*>*)eventsMetadata;
|
||||
- (NSArray<UIDFrameworkEvent*>*)events;
|
||||
- (void)enable;
|
||||
- (void)disable;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UIDFrameworkEventManager.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDSerialFrameworkEventManager : NSObject<UIDFrameworkEventManager>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDSerialFrameworkEventManager.h"
|
||||
|
||||
@interface UIDSerialFrameworkEventManager () {
|
||||
dispatch_queue_t _queue;
|
||||
NSMutableArray<UIDFrameworkEventMetadata*>* _eventMetadata;
|
||||
NSMutableArray<UIDFrameworkEvent*>* _events;
|
||||
BOOL _enabled;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDSerialFrameworkEventManager
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_enabled = false;
|
||||
_eventMetadata = [NSMutableArray new];
|
||||
_events = [NSMutableArray new];
|
||||
_queue = dispatch_queue_create(
|
||||
"ui-debugger.framework-events", DISPATCH_QUEUE_SERIAL);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)emitEvent:(nonnull UIDFrameworkEvent*)event {
|
||||
dispatch_async(_queue, ^{
|
||||
if (self->_enabled) {
|
||||
[self->_events addObject:event];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)registerEventMetadata:
|
||||
(nonnull UIDFrameworkEventMetadata*)eventMetadata {
|
||||
[_eventMetadata addObject:eventMetadata];
|
||||
}
|
||||
|
||||
- (NSArray<UIDFrameworkEventMetadata*>*)eventsMetadata {
|
||||
return [_eventMetadata copy];
|
||||
}
|
||||
|
||||
- (NSArray<UIDFrameworkEvent*>*)events {
|
||||
__block NSArray* events = nil;
|
||||
dispatch_sync(_queue, ^{
|
||||
events = [_events copy];
|
||||
[_events removeAllObjects];
|
||||
});
|
||||
return events ?: @[];
|
||||
}
|
||||
|
||||
- (void)enable {
|
||||
dispatch_async(_queue, ^{
|
||||
self->_enabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
- (void)disable {
|
||||
dispatch_async(_queue, ^{
|
||||
self->_enabled = false;
|
||||
[self->_events removeAllObjects];
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
@protocol UIDConnectionListener
|
||||
|
||||
- (void)onDidConnect;
|
||||
- (void)onDidDisconnect;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <FlipperKit/FlipperConnection.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UIDConnectionListener.h"
|
||||
#import "UIDFrameworkEventManager.h"
|
||||
#import "UIDUpdateDigester.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class UIDDescriptorRegister;
|
||||
@class UIDTreeObserverFactory;
|
||||
@class UIDFrameworkEvent;
|
||||
@class UIDFrameworkEventMetadata;
|
||||
|
||||
@interface UIDContext : NSObject
|
||||
|
||||
@property(nonatomic, nullable) UIApplication* application;
|
||||
@property(nonatomic, nullable) id<FlipperConnection> connection;
|
||||
@property(nonatomic, readonly) UIDDescriptorRegister* descriptorRegister;
|
||||
@property(nonatomic, readonly) UIDTreeObserverFactory* observerFactory;
|
||||
@property(nonatomic, nullable) id<UIDUpdateDigester> updateDigester;
|
||||
@property(nonatomic, strong, readonly) id<UIDFrameworkEventManager>
|
||||
frameworkEventManager;
|
||||
|
||||
- (instancetype)initWithApplication:(UIApplication*)application
|
||||
descriptorRegister:(UIDDescriptorRegister*)descriptorRegister
|
||||
observerFactory:(UIDTreeObserverFactory*)observerFactory;
|
||||
|
||||
- (NSSet<id<UIDConnectionListener>>*)connectionListeners;
|
||||
- (void)addConnectionListener:(id<UIDConnectionListener>)listener;
|
||||
- (void)removeConnectionListener:(id<UIDConnectionListener>)listener;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDContext.h"
|
||||
#import "UIDDescriptorRegister.h"
|
||||
#import "UIDSerialFrameworkEventManager.h"
|
||||
#import "UIDTreeObserverFactory.h"
|
||||
|
||||
@interface UIDContext () {
|
||||
NSMutableSet<id<UIDConnectionListener>>* _connectionListeners;
|
||||
dispatch_queue_t _accessQueue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDContext
|
||||
|
||||
- (instancetype)initWithApplication:(UIApplication*)application
|
||||
descriptorRegister:(UIDDescriptorRegister*)descriptorRegister
|
||||
observerFactory:(UIDTreeObserverFactory*)observerFactory {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_application = application;
|
||||
_descriptorRegister = descriptorRegister;
|
||||
_observerFactory = observerFactory;
|
||||
_connection = nil;
|
||||
_frameworkEventManager = [UIDSerialFrameworkEventManager new];
|
||||
_connectionListeners = [NSMutableSet new];
|
||||
_accessQueue =
|
||||
dispatch_queue_create("ui-debugger.context", DISPATCH_QUEUE_SERIAL);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSSet<id<UIDConnectionListener>>*)connectionListeners {
|
||||
__block NSSet* listeners = nil;
|
||||
dispatch_sync(_accessQueue, ^{
|
||||
listeners = [_connectionListeners copy];
|
||||
});
|
||||
|
||||
return listeners;
|
||||
}
|
||||
|
||||
- (void)addConnectionListener:(id<UIDConnectionListener>)listener {
|
||||
dispatch_sync(_accessQueue, ^{
|
||||
[_connectionListeners addObject:listener];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)removeConnectionListener:(id<UIDConnectionListener>)listener {
|
||||
dispatch_sync(_accessQueue, ^{
|
||||
[_connectionListeners removeObject:listener];
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol UIDUpdate
|
||||
@end
|
||||
|
||||
@interface UIDSubtreeUpdate : NSObject<UIDUpdate>
|
||||
|
||||
@property(nonatomic) NSString* observerType;
|
||||
@property(nonatomic) NSUInteger rootId;
|
||||
@property(nonatomic) NSArray* nodes;
|
||||
@property(nonatomic) NSTimeInterval timestamp;
|
||||
@property(nonatomic) long traversalMS;
|
||||
@property(nonatomic) long snapshotMS;
|
||||
@property(nonatomic) UIImage* snapshot;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDUpdate.h"
|
||||
|
||||
@implementation UIDSubtreeUpdate
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UIDUpdate.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol UIDUpdateDigester
|
||||
|
||||
- (void)digest:(id<UIDUpdate>)update;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UIDNodeDescriptor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
A chained descriptor is a special type of descriptor that models the
|
||||
inheritance hierarchy in native UI frameworks. With this setup you can define
|
||||
a descriptor for each class in the inheritance chain and given that we record
|
||||
the super class's descriptor we can automatically aggregate the results for
|
||||
each descriptor in the inheritance hierarchy in a chain.
|
||||
|
||||
The result is that each descriptor in the inheritance chain only exports the
|
||||
attributes that it knows about but we still get all the attributes from the
|
||||
parent classes.
|
||||
*/
|
||||
@interface UIDChainedDescriptor<__covariant T> : UIDNodeDescriptor<T>
|
||||
|
||||
@property(strong, nonatomic) UIDChainedDescriptor* parent;
|
||||
|
||||
/** The children this node exposes in the inspector. */
|
||||
- (NSArray<id<NSObject>>*)aggregateChildrenOfNode:(T)node;
|
||||
|
||||
/**
|
||||
Get the attributes to show for this node in the sidebar of the inspector. The
|
||||
object will be shown in order and with a header matching the given name.
|
||||
*/
|
||||
- (void)aggregateAttributes:(UIDMutableAttributes*)attributes forNode:(id)node;
|
||||
|
||||
/**
|
||||
These are shown inline in the tree view on the desktop, will likely be removed
|
||||
in the future.
|
||||
*/
|
||||
- (void)aggregateInlineAttributes:(UIDMutableInlineAttributes*)attributes
|
||||
forNode:(id)node;
|
||||
|
||||
- (NSSet<NSString*>*)aggregateTagsForNode:(id)node;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDChainedDescriptor.h"
|
||||
#import "UIDInspectable.h"
|
||||
|
||||
@implementation UIDChainedDescriptor
|
||||
|
||||
- (NSSet<NSString*>*)tagsForNode:(id)node {
|
||||
NSSet* tags = [self aggregateTagsForNode:node] ?: [_parent tagsForNode:node];
|
||||
return tags ?: [NSSet set];
|
||||
}
|
||||
|
||||
- (NSSet<NSString*>*)aggregateTagsForNode:(id)node {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (UIDBounds*)boundsForNode:(id)node {
|
||||
return [_parent boundsForNode:node];
|
||||
}
|
||||
|
||||
- (id<NSObject>)activeChildForNode:(id)node {
|
||||
return [_parent activeChildForNode:node];
|
||||
}
|
||||
|
||||
- (UIImage*)snapshotForNode:(id)node {
|
||||
return [_parent snapshotForNode:node];
|
||||
}
|
||||
|
||||
- (NSArray<id<NSObject>>*)childrenOfNode:(id)node {
|
||||
NSArray<id<NSObject>>* children = [self aggregateChildrenOfNode:node];
|
||||
if (!children) {
|
||||
children = [_parent childrenOfNode:node];
|
||||
}
|
||||
|
||||
return children != NULL ? children : [NSArray array];
|
||||
}
|
||||
|
||||
- (NSArray<id<NSObject>>*)aggregateChildrenOfNode:(id)node {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (UIDAttributes*)attributesForNode:(id)node {
|
||||
UIDMutableAttributes* attributes = [NSMutableDictionary new];
|
||||
[self aggregateAttributes:attributes forNode:node];
|
||||
|
||||
UIDChainedDescriptor* currentDescriptor = _parent;
|
||||
while (currentDescriptor) {
|
||||
[currentDescriptor aggregateAttributes:attributes forNode:node];
|
||||
currentDescriptor = currentDescriptor.parent;
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
- (void)aggregateAttributes:(UIDMutableAttributes*)attributes forNode:(id)node {
|
||||
}
|
||||
|
||||
- (UIDInlineAttributes*)inlineAttributesForNode:(id)node {
|
||||
UIDMutableInlineAttributes* attributes = [NSMutableDictionary new];
|
||||
|
||||
[attributes addEntriesFromDictionary:[super inlineAttributesForNode:node]];
|
||||
|
||||
[self aggregateInlineAttributes:attributes forNode:node];
|
||||
|
||||
UIDChainedDescriptor* currentDescriptor = _parent;
|
||||
while (currentDescriptor) {
|
||||
[currentDescriptor aggregateInlineAttributes:attributes forNode:node];
|
||||
currentDescriptor = currentDescriptor.parent;
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
- (void)aggregateInlineAttributes:(UIDMutableInlineAttributes*)attributes
|
||||
forNode:(id)node {
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDBounds.h"
|
||||
#import "UIDInspectable.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol UIDDescriptor<NSObject>
|
||||
|
||||
/**
|
||||
A globally unique ID used to identify a node in the hierarchy.
|
||||
*/
|
||||
- (NSUInteger)UID_identifier;
|
||||
|
||||
/**
|
||||
The name used to identify this node in the inspector. Does not need to be
|
||||
unique. A good default is to use the class name of the node.
|
||||
*/
|
||||
- (NSString*)UID_name;
|
||||
|
||||
/**
|
||||
Get the attributes to show for this node in the sidebar of the inspector. The
|
||||
object will be shown in order and with a header matching the given name.
|
||||
*/
|
||||
- (void)UID_aggregateAttributes:(UIDMutableAttributes*)attributes;
|
||||
|
||||
@optional
|
||||
|
||||
/**
|
||||
These are shown inline in the tree view on the desktop, will likely be removed
|
||||
in the future.
|
||||
*/
|
||||
- (UIDInlineAttributes*)UID_inlineAttributes;
|
||||
|
||||
/** The children this node exposes in the inspector. */
|
||||
- (NSArray<id<NSObject>>*)UID_children;
|
||||
|
||||
/** Should be w.r.t the direct parent */
|
||||
- (UIDBounds*)UID_bounds;
|
||||
|
||||
/**
|
||||
If the type has the concept of overlapping children, then this indicates
|
||||
which child is active / on top, we will only listen to / traverse this child.
|
||||
If return null we assume all children are 'active'.
|
||||
*/
|
||||
- (id<NSObject>)UID_activeChild;
|
||||
|
||||
/** Get a snapshot of the node. */
|
||||
- (UIImage*)UID_snapshot;
|
||||
|
||||
/**
|
||||
Set of tags to describe this node in an abstract way for the UI. Unfortunately
|
||||
this can't be an enum as we have to plugin 3rd party frameworks dynamically.
|
||||
*/
|
||||
- (NSSet<NSString*>*)UID_tags;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UIDNodeDescriptor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDDescriptorRegister : NSObject
|
||||
|
||||
+ (instancetype)defaultRegister;
|
||||
|
||||
- (void)registerDescriptor:(UIDNodeDescriptor*)descriptor forClass:(Class)clazz;
|
||||
- (UIDNodeDescriptor*)descriptorForClass:(Class)clazz;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDDescriptorRegister.h"
|
||||
#import <objc/runtime.h>
|
||||
#import "UIDChainedDescriptor.h"
|
||||
#import "UIDUIAccessibilityElementDescriptor.h"
|
||||
#import "UIDUIApplicationDescriptor.h"
|
||||
#import "UIDUILabelDescriptor.h"
|
||||
#import "UIDUINavigationControllerDescriptor.h"
|
||||
#import "UIDUITabBarControllerDescriptor.h"
|
||||
#import "UIDUIViewControllerDescriptor.h"
|
||||
#import "UIDUIViewDescriptor.h"
|
||||
#import "UIDUIWindowDescriptor.h"
|
||||
|
||||
@interface UIDDescriptorRegister ()
|
||||
|
||||
- (void)prepareChain;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDDescriptorRegister {
|
||||
NSMutableDictionary<NSString*, UIDNodeDescriptor*>* _register;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_register = [NSMutableDictionary new];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)defaultRegister {
|
||||
static UIDDescriptorRegister* defaultRegister = nil;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
defaultRegister = [UIDDescriptorRegister new];
|
||||
|
||||
[defaultRegister registerDescriptor:[UIDUIApplicationDescriptor new]
|
||||
forClass:[UIApplication class]];
|
||||
[defaultRegister registerDescriptor:[UIDUIWindowDescriptor new]
|
||||
forClass:[UIWindow class]];
|
||||
[defaultRegister registerDescriptor:[UIDUIViewControllerDescriptor new]
|
||||
forClass:[UIViewController class]];
|
||||
[defaultRegister registerDescriptor:[UIDUIViewDescriptor new]
|
||||
forClass:[UIView class]];
|
||||
[defaultRegister registerDescriptor:[UIDUILabelDescriptor new]
|
||||
forClass:[UILabel class]];
|
||||
[defaultRegister
|
||||
registerDescriptor:[UIDUIAccessibilityElementDescriptor new]
|
||||
forClass:[UIAccessibilityElement class]];
|
||||
});
|
||||
|
||||
return defaultRegister;
|
||||
}
|
||||
|
||||
- (void)registerDescriptor:(UIDNodeDescriptor*)descriptor
|
||||
forClass:(Class)clazz {
|
||||
NSString* key = NSStringFromClass(clazz);
|
||||
_register[key] = descriptor;
|
||||
|
||||
[self prepareChain];
|
||||
}
|
||||
|
||||
- (UIDNodeDescriptor*)descriptorForClass:(Class)clazz {
|
||||
UIDNodeDescriptor* classDescriptor = nil;
|
||||
|
||||
while (classDescriptor == nil && clazz != nil) {
|
||||
classDescriptor = [_register objectForKey:NSStringFromClass(clazz)];
|
||||
clazz = [clazz superclass];
|
||||
}
|
||||
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
- (void)prepareChain {
|
||||
NSEnumerator* enumerator = [_register keyEnumerator];
|
||||
NSString* key;
|
||||
|
||||
while ((key = [enumerator nextObject])) {
|
||||
UIDNodeDescriptor* descriptor = [_register objectForKey:key];
|
||||
if ([descriptor isKindOfClass:[UIDChainedDescriptor class]]) {
|
||||
UIDChainedDescriptor* chainedDescriptor =
|
||||
(UIDChainedDescriptor*)descriptor;
|
||||
|
||||
Class clazz = NSClassFromString(key);
|
||||
Class superclass = [clazz superclass];
|
||||
|
||||
UIDNodeDescriptor* superDescriptor = [self descriptorForClass:superclass];
|
||||
if ([superDescriptor isKindOfClass:[UIDChainedDescriptor class]]) {
|
||||
chainedDescriptor.parent = (UIDChainedDescriptor*)superDescriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UIDMetadata.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FOUNDATION_EXPORT NSString* const UIDEBUGGER_METADATA_TYPE_IDENTIFIER;
|
||||
FOUNDATION_EXPORT NSString* const UIDEBUGGER_METADATA_TYPE_ATTRIBUTE;
|
||||
FOUNDATION_EXPORT NSString* const UIDEBUGGER_METADATA_TYPE_LAYOUT;
|
||||
FOUNDATION_EXPORT NSString* const UIDEBUGGER_METADATA_TYPE_DOCUMENTATION;
|
||||
|
||||
@interface UIDMetadataRegister : NSObject
|
||||
|
||||
+ (instancetype)shared;
|
||||
|
||||
- (UIDMetadataId)registerMetadataWithType:(NSString*)type name:(NSString*)name;
|
||||
|
||||
- (UIDMetadataId)registerMetadataWithType:(NSString*)type
|
||||
name:(NSString*)name
|
||||
isMutable:(bool)isMutable
|
||||
definedBy:(UIDMetadataId)parent;
|
||||
|
||||
- (UIDMetadataId)registerMetadataWithType:(NSString*)type
|
||||
name:(NSString*)name
|
||||
isMutable:(bool)isMutable
|
||||
definedBy:(UIDMetadataId)parent
|
||||
customAttributes:
|
||||
(nullable NSDictionary<NSString*, id>*)
|
||||
customAttributes;
|
||||
|
||||
- (NSDictionary<UIDMetadataId, UIDMetadata*>*)extractPendingMetadata;
|
||||
|
||||
- (UIDMetadataId)findMetadataDefinedBy:(UIDMetadataId)definedById
|
||||
name:(NSString*)name;
|
||||
- (UIDMetadataId)findRootMetadataWithName:(NSString*)name;
|
||||
|
||||
- (void)reset;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDMetadataRegister.h"
|
||||
|
||||
NSString* const UIDEBUGGER_METADATA_TYPE_IDENTIFIER = @"identity";
|
||||
NSString* const UIDEBUGGER_METADATA_TYPE_ATTRIBUTE = @"attribute";
|
||||
NSString* const UIDEBUGGER_METADATA_TYPE_LAYOUT = @"layout";
|
||||
NSString* const UIDEBUGGER_METADATA_TYPE_DOCUMENTATION = @"documentation";
|
||||
|
||||
typedef NSMutableDictionary<NSString*, UIDMetadata*>* UIDNamedMetadata;
|
||||
@interface UIDMetadataRegister () {
|
||||
NSMutableDictionary<UIDMetadataId, UIDNamedMetadata>* _register;
|
||||
NSMutableArray<UIDMetadata*>* _pending;
|
||||
uint32_t _generator;
|
||||
|
||||
UIDMetadataId _rootId;
|
||||
NSLock* _lock;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDMetadataRegister
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_lock = [NSLock new];
|
||||
_register = [NSMutableDictionary new];
|
||||
_pending = [NSMutableArray new];
|
||||
|
||||
_rootId = @0;
|
||||
_generator = 0;
|
||||
|
||||
[_register setObject:[NSMutableDictionary new] forKey:_rootId];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)shared {
|
||||
static UIDMetadataRegister* instance = nil;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
instance = [UIDMetadataRegister new];
|
||||
});
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (UIDMetadataId)registerMetadataWithType:(NSString*)type name:(NSString*)name {
|
||||
return [self registerMetadataWithType:type
|
||||
name:name
|
||||
isMutable:false
|
||||
definedBy:_rootId];
|
||||
}
|
||||
|
||||
- (UIDMetadataId)registerMetadataWithType:(NSString*)type
|
||||
name:(NSString*)name
|
||||
isMutable:(bool)isMutable
|
||||
definedBy:(UIDMetadataId)parent {
|
||||
return [self registerMetadataWithType:type
|
||||
name:name
|
||||
isMutable:isMutable
|
||||
definedBy:parent
|
||||
customAttributes:nil];
|
||||
}
|
||||
|
||||
- (UIDMetadataId)registerMetadataWithType:(NSString*)type
|
||||
name:(NSString*)name
|
||||
isMutable:(bool)isMutable
|
||||
definedBy:(UIDMetadataId)parent
|
||||
customAttributes:
|
||||
(nullable NSDictionary<NSString*, id>*)
|
||||
customAttributes {
|
||||
if (!parent) {
|
||||
parent = _rootId;
|
||||
}
|
||||
|
||||
UIDMetadataId identifier = @(++_generator);
|
||||
UIDMetadata* metadata =
|
||||
[[UIDMetadata alloc] initWithIdentifier:identifier
|
||||
type:type
|
||||
name:name
|
||||
isMutable:isMutable
|
||||
parent:parent
|
||||
possibleValues:nil
|
||||
tags:nil
|
||||
customAttributes:customAttributes];
|
||||
|
||||
[_lock lock];
|
||||
if (![_register objectForKey:parent]) {
|
||||
[_register setObject:[NSMutableDictionary new] forKey:parent];
|
||||
}
|
||||
[[_register objectForKey:parent] setObject:metadata forKey:name];
|
||||
|
||||
[_pending addObject:metadata];
|
||||
[_lock unlock];
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
||||
- (UIDMetadataId)findRootMetadataWithName:(NSString*)name {
|
||||
return [self findMetadataDefinedBy:_rootId name:name];
|
||||
}
|
||||
|
||||
- (UIDMetadataId)findMetadataDefinedBy:(UIDMetadataId)parentId
|
||||
name:(NSString*)name {
|
||||
[_lock lock];
|
||||
UIDMetadata* metadata = [[_register objectForKey:parentId] objectForKey:name];
|
||||
[_lock unlock];
|
||||
if (metadata) {
|
||||
return metadata.identifier;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSDictionary<UIDMetadataId, UIDMetadata*>*)extractPendingMetadata {
|
||||
NSMutableDictionary* pendingMetadata = [NSMutableDictionary new];
|
||||
[_lock lock];
|
||||
for (UIDMetadata* metadata in _pending) {
|
||||
[pendingMetadata setObject:metadata forKey:metadata.identifier];
|
||||
}
|
||||
[_pending removeAllObjects];
|
||||
[_lock unlock];
|
||||
return pendingMetadata;
|
||||
}
|
||||
|
||||
- (void)reset {
|
||||
[_lock lock];
|
||||
[_pending removeAllObjects];
|
||||
for (id key in _register) {
|
||||
UIDNamedMetadata value = [_register objectForKey:key];
|
||||
[_pending addObjectsFromArray:value.allValues];
|
||||
}
|
||||
[_lock unlock];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDBounds.h"
|
||||
#import "UIDInspectable.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDNodeDescriptor<__covariant T> : NSObject
|
||||
|
||||
/**
|
||||
A globally unique ID used to identify a node in the hierarchy.
|
||||
*/
|
||||
- (NSUInteger)identifierForNode:(T)node;
|
||||
|
||||
/**
|
||||
The name used to identify this node in the inspector. Does not need to be
|
||||
unique. A good default is to use the class name of the node.
|
||||
*/
|
||||
- (NSString*)nameForNode:(T)node;
|
||||
|
||||
/**
|
||||
Get the attributes to show for this node in the sidebar of the inspector. The
|
||||
object will be shown in order and with a header matching the given name.
|
||||
*/
|
||||
- (UIDAttributes*)attributesForNode:(T)node;
|
||||
|
||||
/**
|
||||
These are shown inline in the tree view on the desktop, will likely be removed
|
||||
in the future.
|
||||
*/
|
||||
- (UIDInlineAttributes*)inlineAttributesForNode:(T)node;
|
||||
|
||||
/**
|
||||
These contain additional contextual data (currently: Bloks node metadata).
|
||||
*/
|
||||
- (UIDGenericAttributes*)hiddenAttributesForNode:(T)node;
|
||||
|
||||
/** The children this node exposes in the inspector. */
|
||||
- (NSArray<id<NSObject>>*)childrenOfNode:(T)node;
|
||||
|
||||
/** Should be w.r.t the direct parent */
|
||||
- (UIDBounds*)boundsForNode:(T)node;
|
||||
|
||||
/**
|
||||
If the type has the concept of overlapping children, then this indicates
|
||||
which child is active / on top, we will only listen to / traverse this child.
|
||||
If return null we assume all children are 'active'.
|
||||
*/
|
||||
- (id<NSObject>)activeChildForNode:(T)node;
|
||||
|
||||
/** Get a snapshot of the node. */
|
||||
- (UIImage*)snapshotForNode:(T)node;
|
||||
|
||||
/**
|
||||
Set of tags to describe this node in an abstract way for the UI. Unfortunately
|
||||
this can't be an enum as we have to plugin 3rd party frameworks dynamically.
|
||||
*/
|
||||
- (NSSet<NSString*>*)tagsForNode:(T)node;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDNodeDescriptor.h"
|
||||
|
||||
@implementation UIDNodeDescriptor
|
||||
|
||||
- (NSUInteger)identifierForNode:(id)node {
|
||||
return [node hash];
|
||||
}
|
||||
|
||||
- (NSString*)nameForNode:(id)node {
|
||||
return NSStringFromClass([node class]);
|
||||
}
|
||||
|
||||
- (UIDInlineAttributes*)inlineAttributesForNode:(id)node {
|
||||
return @{@"address" : [NSString stringWithFormat:@"%p", node]};
|
||||
}
|
||||
|
||||
- (UIDGenericAttributes*)hiddenAttributesForNode:(id)node {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (UIDAttributes*)attributesForNode:(id)node {
|
||||
return [NSDictionary dictionary];
|
||||
}
|
||||
|
||||
- (NSArray<id<NSObject>>*)childrenOfNode:(id)node {
|
||||
return [NSArray array];
|
||||
}
|
||||
|
||||
- (NSSet<NSString*>*)tagsForNode:(id)node {
|
||||
return [NSSet set];
|
||||
}
|
||||
|
||||
- (UIDBounds*)boundsForNode:(id)node {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id<NSObject>)activeChildForNode:(id)node {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (UIImage*)snapshotForNode:(id)node {
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDNodeDescriptor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDUIAccessibilityElementDescriptor
|
||||
: UIDNodeDescriptor<UIAccessibilityElement*>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDUIAccessibilityElementDescriptor.h"
|
||||
#import "UIDBounds.h"
|
||||
#import "UIDSnapshot.h"
|
||||
|
||||
@implementation UIDUIAccessibilityElementDescriptor
|
||||
|
||||
- (UIDBounds*)boundsForNode:(UIAccessibilityElement*)node {
|
||||
return [UIDBounds fromRect:node.accessibilityFrame];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDNodeDescriptor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDUIApplicationDescriptor : UIDNodeDescriptor<UIApplication*>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDUIApplicationDescriptor.h"
|
||||
#import <objc/runtime.h>
|
||||
#import <string>
|
||||
#import <unordered_set>
|
||||
#import "UIDBounds.h"
|
||||
#import "UIDSnapshot.h"
|
||||
|
||||
@implementation UIDUIApplicationDescriptor
|
||||
|
||||
- (NSArray<id<NSObject>>*)childrenOfNode:(UIApplication*)node {
|
||||
static std::unordered_set<std::string> ignoredWindows(
|
||||
{"FBStatusBarTrackingWindow",
|
||||
"FBAccessibilityOverlayWindow",
|
||||
"UITextEffectsWindow"});
|
||||
|
||||
NSMutableArray<UIWindow*>* children = [NSMutableArray new];
|
||||
for (UIWindow* window in node.windows) {
|
||||
if (ignoredWindows.find(class_getName(window.class)) !=
|
||||
ignoredWindows.end()) {
|
||||
continue;
|
||||
}
|
||||
[children addObject:window];
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
- (id<NSObject>)activeChildForNode:(UIApplication*)node {
|
||||
return node.keyWindow;
|
||||
}
|
||||
|
||||
- (UIDBounds*)boundsForNode:(UIApplication*)node {
|
||||
return [UIDBounds fromRect:[UIScreen mainScreen].bounds];
|
||||
}
|
||||
|
||||
- (UIImage*)snapshotForNode:(UIApplication*)node {
|
||||
return UIDApplicationSnapshot(node, [self childrenOfNode:node]);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDChainedDescriptor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDUILabelDescriptor : UIDChainedDescriptor<UILabel*>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDUILabelDescriptor.h"
|
||||
#import "UIDInspectable.h"
|
||||
#import "UIDMetadata.h"
|
||||
#import "UIDMetadataRegister.h"
|
||||
|
||||
@interface UIDUILabelDescriptor () {
|
||||
UIDMetadataId UILabelAttributeId;
|
||||
UIDMetadataId TextAttributeId;
|
||||
UIDMetadataId AttributedTextAttributeId;
|
||||
UIDMetadataId FontAttributeId;
|
||||
UIDMetadataId TextColorAttributeId;
|
||||
UIDMetadataId TextAlignmentAttributeId;
|
||||
UIDMetadataId LineBreakModeAttributeId;
|
||||
UIDMetadataId LineBreakStrategyAttributeId;
|
||||
UIDMetadataId EnabledAttributeId;
|
||||
UIDMetadataId ShowExpansionTextAttributeId;
|
||||
UIDMetadataId AdjustsFontSizeToFitWidthAttributeId;
|
||||
UIDMetadataId AllowsDefaultTightneningForTruncationAttributeId;
|
||||
UIDMetadataId BaselineAdjustmentAttributeId;
|
||||
UIDMetadataId MinScaleFactorAttributeId;
|
||||
UIDMetadataId NumberOfLinesAttributeId;
|
||||
UIDMetadataId HighlightedTextColorAttributeId;
|
||||
UIDMetadataId HighlightedAttributeId;
|
||||
UIDMetadataId ShadowColorAttributeId;
|
||||
UIDMetadataId ShadowOffsetAttributeId;
|
||||
|
||||
NSDictionary* NSTextAlignmentEnum;
|
||||
NSDictionary* NSLineBreakModeEnum;
|
||||
NSDictionary* NSLineBreakStrategyEnum;
|
||||
NSDictionary* UIBaselineAdjustmentEnum;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDUILabelDescriptor
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
NSTextAlignmentEnum = @{
|
||||
@(NSTextAlignmentLeft) : @"LEFT",
|
||||
@(NSTextAlignmentRight) : @"RIGHT",
|
||||
@(NSTextAlignmentCenter) : @"CENTER",
|
||||
@(NSTextAlignmentJustified) : @"JUSTIFIED",
|
||||
@(NSTextAlignmentNatural) : @"NATURAL",
|
||||
};
|
||||
NSLineBreakModeEnum = @{
|
||||
@(NSLineBreakByWordWrapping) : @"WORD WRAPPING",
|
||||
@(NSLineBreakByCharWrapping) : @"CHAR WRAPPING",
|
||||
@(NSLineBreakByClipping) : @"CLIPPING",
|
||||
@(NSLineBreakByTruncatingHead) : @"TRUNCATING HEAD",
|
||||
@(NSLineBreakByTruncatingTail) : @"TRUNCATING TAIL",
|
||||
@(NSLineBreakByTruncatingMiddle) : @"TRUNCATING MIDDLE",
|
||||
};
|
||||
if (@available(iOS 14.0, *)) {
|
||||
NSLineBreakStrategyEnum = @{
|
||||
@(NSLineBreakStrategyNone) : @"NONE",
|
||||
@(NSLineBreakStrategyPushOut) : @"PUSH OUT",
|
||||
@(NSLineBreakStrategyHangulWordPriority) : @"HANGUL WORD PRIORITY",
|
||||
@(NSLineBreakStrategyStandard) : @"STANDARD",
|
||||
};
|
||||
} else {
|
||||
NSLineBreakStrategyEnum = @{
|
||||
@(NSLineBreakStrategyNone) : @"NONE",
|
||||
@(NSLineBreakStrategyPushOut) : @"PUSH OUT",
|
||||
};
|
||||
}
|
||||
UIBaselineAdjustmentEnum = @{
|
||||
@(UIBaselineAdjustmentAlignBaselines) : @"ALIGN BASELINES",
|
||||
@(UIBaselineAdjustmentAlignCenters) : @"ALIGN CENTERS",
|
||||
@(UIBaselineAdjustmentNone) : @"NONE",
|
||||
};
|
||||
|
||||
UILabelAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"UILabel"];
|
||||
TextAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"text"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
AttributedTextAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"attributedText"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
FontAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"font"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
TextColorAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"textColor"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
TextAlignmentAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"textAlignment"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
LineBreakModeAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"lineBreakMode"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
LineBreakStrategyAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"lineBreakStrategy"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
EnabledAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"enabled"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
if (@available(iOS 15.0, macCatalyst 15.0, *)) {
|
||||
ShowExpansionTextAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"showsExpansionTextWhenTruncated"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
}
|
||||
AdjustsFontSizeToFitWidthAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"adjustsFontSizeToFitWidth"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
AllowsDefaultTightneningForTruncationAttributeId =
|
||||
[[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"allowsDefaultTighteningForTruncation"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
BaselineAdjustmentAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"baselineAdjustment"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
MinScaleFactorAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"minimumScaleFactor"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
NumberOfLinesAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"numberOfLines"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
HighlightedTextColorAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"highlightedTextColor"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
HighlightedAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"highligted"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
ShadowColorAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"shadowColor"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
ShadowOffsetAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"shadowOffset"
|
||||
isMutable:false
|
||||
definedBy:UILabelAttributeId];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)aggregateAttributes:(UIDMutableAttributes*)attributes
|
||||
forNode:(UILabel*)node {
|
||||
NSMutableDictionary* labelAttributes = [NSMutableDictionary new];
|
||||
|
||||
[labelAttributes setObject:[UIDInspectableText fromText:node.text]
|
||||
forKey:TextAttributeId];
|
||||
[labelAttributes
|
||||
setObject:[UIDInspectableText fromText:[node.attributedText string]]
|
||||
forKey:AttributedTextAttributeId];
|
||||
[labelAttributes setObject:[UIDInspectableText fromText:node.font.fontName]
|
||||
forKey:FontAttributeId];
|
||||
[labelAttributes setObject:[UIDInspectableColor fromColor:node.textColor]
|
||||
forKey:TextColorAttributeId];
|
||||
[labelAttributes
|
||||
setObject:[UIDInspectableEnum
|
||||
from:NSTextAlignmentEnum[@(node.textAlignment)]]
|
||||
forKey:TextAlignmentAttributeId];
|
||||
[labelAttributes
|
||||
setObject:[UIDInspectableEnum
|
||||
from:NSLineBreakModeEnum[@(node.lineBreakMode)]]
|
||||
forKey:LineBreakModeAttributeId];
|
||||
[labelAttributes setObject:[UIDInspectableBoolean fromBoolean:node.enabled]
|
||||
forKey:EnabledAttributeId];
|
||||
if (@available(iOS 15.0, macCatalyst 15.0, *)) {
|
||||
[labelAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:node.showsExpansionTextWhenTruncated]
|
||||
forKey:ShowExpansionTextAttributeId];
|
||||
}
|
||||
|
||||
[labelAttributes setObject:[UIDInspectableBoolean
|
||||
fromBoolean:node.adjustsFontSizeToFitWidth]
|
||||
forKey:AdjustsFontSizeToFitWidthAttributeId];
|
||||
[labelAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:node.allowsDefaultTighteningForTruncation]
|
||||
forKey:AllowsDefaultTightneningForTruncationAttributeId];
|
||||
[labelAttributes
|
||||
setObject:[UIDInspectableEnum
|
||||
from:UIBaselineAdjustmentEnum[@(node.baselineAdjustment)]]
|
||||
forKey:BaselineAdjustmentAttributeId];
|
||||
[labelAttributes
|
||||
setObject:[UIDInspectableNumber fromCGFloat:node.minimumScaleFactor]
|
||||
forKey:MinScaleFactorAttributeId];
|
||||
[labelAttributes
|
||||
setObject:[UIDInspectableNumber
|
||||
fromNumber:[NSNumber numberWithInt:node.numberOfLines]]
|
||||
forKey:NumberOfLinesAttributeId];
|
||||
[labelAttributes
|
||||
setObject:[UIDInspectableColor fromColor:node.highlightedTextColor]
|
||||
forKey:HighlightedTextColorAttributeId];
|
||||
[labelAttributes
|
||||
setObject:[UIDInspectableBoolean fromBoolean:node.highlighted]
|
||||
forKey:HighlightedAttributeId];
|
||||
[labelAttributes setObject:[UIDInspectableColor fromColor:node.shadowColor]
|
||||
forKey:ShadowColorAttributeId];
|
||||
[labelAttributes setObject:[UIDInspectableSize fromSize:node.shadowOffset]
|
||||
forKey:ShadowOffsetAttributeId];
|
||||
|
||||
[attributes setObject:[UIDInspectableObject fromFields:labelAttributes]
|
||||
forKey:UILabelAttributeId];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDNodeDescriptor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
UINavigationController
|
||||
(https://developer.apple.com/documentation/uikit/uinavigationcontroller?language=objc)
|
||||
Propeties:
|
||||
- viewControllers: the view controllers currently on the navigation stack.
|
||||
- topViewController: last controller pushed on top of the navigation
|
||||
stack.
|
||||
- visibleViewController: the view controller associated with the
|
||||
currently visible view in the navigation stack. View Controller can also be
|
||||
presented instead of pushed. If presented, then it hasn't changed the stack
|
||||
even though its view is visible.
|
||||
*/
|
||||
@interface UIDUINavigationControllerDescriptor
|
||||
: UIDNodeDescriptor<UINavigationController*>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDUINavigationControllerDescriptor.h"
|
||||
|
||||
@implementation UIDUINavigationControllerDescriptor
|
||||
|
||||
- (NSArray<id<NSObject>>*)childrenOfNode:(UINavigationController*)node {
|
||||
return node.viewControllers;
|
||||
}
|
||||
|
||||
- (id<NSObject>)activeChildForNode:(UINavigationController*)node {
|
||||
return node.visibleViewController;
|
||||
}
|
||||
|
||||
- (UIDBounds*)boundsForNode:(UINavigationController*)node {
|
||||
return [UIDBounds fromRect:node.view.bounds];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDNodeDescriptor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
UITabBarController
|
||||
(https://developer.apple.com/documentation/uikit/uitabbarcontroller?language=objc)
|
||||
Properties:
|
||||
- viewControllers: root view controllers displayed by the tab bar user
|
||||
interface.
|
||||
- selectedViewController: the view controller associated with the
|
||||
currently selected tab bar item.
|
||||
*/
|
||||
@interface UIDUITabBarControllerDescriptor
|
||||
: UIDNodeDescriptor<UITabBarController*>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDUITabBarControllerDescriptor.h"
|
||||
|
||||
@implementation UIDUITabBarControllerDescriptor
|
||||
|
||||
- (NSArray<id<NSObject>>*)childrenOfNode:(UITabBarController*)node {
|
||||
return node.viewControllers;
|
||||
}
|
||||
|
||||
- (id<NSObject>)activeChildForNode:(UITabBarController*)node {
|
||||
return node.selectedViewController;
|
||||
}
|
||||
|
||||
- (UIDBounds*)boundsForNode:(UITabBarController*)node {
|
||||
return [UIDBounds fromRect:node.view.bounds];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDNodeDescriptor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDUIViewControllerDescriptor : UIDNodeDescriptor<UIViewController*>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDUIViewControllerDescriptor.h"
|
||||
|
||||
@implementation UIDUIViewControllerDescriptor
|
||||
|
||||
- (NSArray<id<NSObject>>*)childrenOfNode:(UIViewController*)node {
|
||||
if (node.view != nil) {
|
||||
return [NSArray arrayWithObject:node.view];
|
||||
}
|
||||
|
||||
return [NSArray array];
|
||||
}
|
||||
|
||||
- (UIDBounds*)boundsForNode:(UIViewController*)node {
|
||||
CGRect bounds = CGRectMake(
|
||||
0, 0, node.view.bounds.size.width, node.view.bounds.size.height);
|
||||
return [UIDBounds fromRect:bounds];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDChainedDescriptor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDUIViewDescriptor : UIDChainedDescriptor<UIView*>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDUIViewDescriptor.h"
|
||||
#import "UIView+UIDDescriptor.h"
|
||||
|
||||
@implementation UIDUIViewDescriptor
|
||||
|
||||
- (void)aggregateAttributes:(UIDMutableAttributes*)attributes
|
||||
forNode:(UIView*)node {
|
||||
[node UID_aggregateAttributes:attributes];
|
||||
}
|
||||
|
||||
- (NSArray<id<NSObject>>*)childrenOfNode:(UIView*)node {
|
||||
return [node UID_children];
|
||||
}
|
||||
|
||||
- (UIImage*)snapshotForNode:(UIView*)node {
|
||||
return [node UID_snapshot];
|
||||
}
|
||||
|
||||
- (UIDBounds*)boundsForNode:(UIView*)node {
|
||||
return [node UID_bounds];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDChainedDescriptor.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDUIWindowDescriptor : UIDChainedDescriptor<UIWindow*>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDUIWindowDescriptor.h"
|
||||
#import "UIView+UIDDescriptor.h"
|
||||
|
||||
@implementation UIDUIWindowDescriptor
|
||||
|
||||
- (id<NSObject>)activeChildForNode:(UIWindow*)node {
|
||||
return [node UID_activeChild];
|
||||
}
|
||||
|
||||
- (UIDBounds*)boundsForNode:(UIWindow*)node {
|
||||
return [UIDBounds fromRect:node.bounds];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <FlipperKit/SKMacros.h>
|
||||
#import <FlipperKitUIDebuggerPlugin/UIDDescriptor.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FB_LINK_REQUIRE_CATEGORY(UIView_UIDDescriptor)
|
||||
@interface UIView (UIDDescriptor)<UIDDescriptor>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,606 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDInspectable.h"
|
||||
#import "UIDMetadata.h"
|
||||
#import "UIDMetadataRegister.h"
|
||||
#import "UIDSnapshot.h"
|
||||
#import "UIView+UIDDescriptor.h"
|
||||
|
||||
FB_LINKABLE(UIView_UIDDescriptor)
|
||||
@implementation UIView (UIDDescriptor)
|
||||
|
||||
- (NSUInteger)UID_identifier {
|
||||
return [self hash];
|
||||
}
|
||||
|
||||
- (nonnull NSString*)UID_name {
|
||||
return NSStringFromClass([self class]);
|
||||
}
|
||||
|
||||
- (void)UID_aggregateAttributes:(nonnull UIDMutableAttributes*)attributes {
|
||||
static UIDMetadataId UIViewAttributeId;
|
||||
static UIDMetadataId FrameAttributeId;
|
||||
static UIDMetadataId BoundsAttributeId;
|
||||
static UIDMetadataId CenterAttributeId;
|
||||
static UIDMetadataId AnchorPointAttributeId;
|
||||
static UIDMetadataId SafeAreaInsetsAttributeId;
|
||||
static UIDMetadataId ClipsToBoundsAttributeId;
|
||||
static UIDMetadataId HiddenAttributeId;
|
||||
static UIDMetadataId AlphaAttributeId;
|
||||
static UIDMetadataId OpaqueAttributeId;
|
||||
static UIDMetadataId ClearContextBeforeDrawingAttributeId;
|
||||
static UIDMetadataId BackgroundColorAttributeId;
|
||||
static UIDMetadataId TintColorAttributeId;
|
||||
static UIDMetadataId TagAttributeId;
|
||||
|
||||
static UIDMetadataId CALayerAttributeId;
|
||||
static UIDMetadataId CALayerShadowColorAttributeId;
|
||||
static UIDMetadataId CALayerShadowOpacityAttributeId;
|
||||
static UIDMetadataId CALayerShadowRadiusAttributeId;
|
||||
static UIDMetadataId CALayerShadowOffsetAttributeId;
|
||||
static UIDMetadataId CALayerBackgroundColorAttributeId;
|
||||
static UIDMetadataId CALayerBorderColorAttributeId;
|
||||
static UIDMetadataId CALayerBorderWidthAttributeId;
|
||||
static UIDMetadataId CALayerCornerRadiusAttributeId;
|
||||
static UIDMetadataId CALayerMasksToBoundsAttributeId;
|
||||
|
||||
static UIDMetadataId AccessibilityAttributeId;
|
||||
static UIDMetadataId IsAccessibilityElementAttributeId;
|
||||
static UIDMetadataId AccessibilityLabelAttributeId;
|
||||
static UIDMetadataId AccessibilityIdentifierAttributeId;
|
||||
static UIDMetadataId AccessibilityValueAttributeId;
|
||||
static UIDMetadataId AccessibilityHintAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitsAttributeId;
|
||||
static UIDMetadataId AccessibilityViewIsModalAttributeId;
|
||||
static UIDMetadataId ShouldGroupAccessibilityChildrenAttributeId;
|
||||
|
||||
static UIDMetadataId AccessibilityTraitNoneAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitButtonAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitLinkAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitImageAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitSearchFieldAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitKeyboardKeyAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitStaticTextAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitHeaderAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitTabBarAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitSummaryElementAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitSelectedAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitNotEnabledAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitAdjustableAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitAllowsDirectInteractionAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitUpdatesFrequentlyAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitCausesPageTurnAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitPlaysSoundAttributeId;
|
||||
static UIDMetadataId AccessibilityTraitStartsMediaSessionAttributeId;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
UIViewAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"UIView"];
|
||||
FrameAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_LAYOUT
|
||||
name:@"frame"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
BoundsAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_LAYOUT
|
||||
name:@"bounds"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
CenterAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_LAYOUT
|
||||
name:@"center"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
AnchorPointAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_LAYOUT
|
||||
name:@"anchorPoint"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
SafeAreaInsetsAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_LAYOUT
|
||||
name:@"safeAreaInset"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
ClipsToBoundsAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_LAYOUT
|
||||
name:@"clipsToBounds"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
HiddenAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"hidden"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
AlphaAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"alpha"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
OpaqueAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"opaque"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
ClearContextBeforeDrawingAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"clearContextBeforeDrawing"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
BackgroundColorAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"backgroundColor"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
TintColorAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"tintColor"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
|
||||
TagAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"tag"
|
||||
isMutable:false
|
||||
definedBy:UIViewAttributeId];
|
||||
|
||||
CALayerAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"CALayer"];
|
||||
|
||||
CALayerShadowColorAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"shadowColor"
|
||||
isMutable:false
|
||||
definedBy:CALayerAttributeId];
|
||||
CALayerShadowOpacityAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"shadowOpacity"
|
||||
isMutable:false
|
||||
definedBy:CALayerAttributeId];
|
||||
CALayerShadowRadiusAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"shadowRadius"
|
||||
isMutable:false
|
||||
definedBy:CALayerAttributeId];
|
||||
CALayerShadowOffsetAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"shadowOffset"
|
||||
isMutable:false
|
||||
definedBy:CALayerAttributeId];
|
||||
CALayerBackgroundColorAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"shadowBackgroundColor"
|
||||
isMutable:false
|
||||
definedBy:CALayerAttributeId];
|
||||
CALayerBorderColorAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"borderColor"
|
||||
isMutable:false
|
||||
definedBy:CALayerAttributeId];
|
||||
CALayerBorderWidthAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"borderWidth"
|
||||
isMutable:false
|
||||
definedBy:CALayerAttributeId];
|
||||
CALayerCornerRadiusAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"cornerRadius"
|
||||
isMutable:false
|
||||
definedBy:CALayerAttributeId];
|
||||
CALayerMasksToBoundsAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"masksToBounds"
|
||||
isMutable:false
|
||||
definedBy:CALayerAttributeId];
|
||||
|
||||
AccessibilityAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"Accessibility"];
|
||||
|
||||
IsAccessibilityElementAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"isAccessibilityElement"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityAttributeId];
|
||||
AccessibilityLabelAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"accessibilityLabel"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityAttributeId];
|
||||
AccessibilityIdentifierAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"accessibilityIdentifier"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityAttributeId];
|
||||
AccessibilityValueAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"accessibilityValue"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityAttributeId];
|
||||
AccessibilityHintAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"accessibilityHint"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityAttributeId];
|
||||
AccessibilityTraitsAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"accessibilityTraits"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityAttributeId];
|
||||
AccessibilityViewIsModalAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"accessibilityViewIsModal"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityAttributeId];
|
||||
ShouldGroupAccessibilityChildrenAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"shouldGroupAccessibilityChildren"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityAttributeId];
|
||||
|
||||
AccessibilityTraitNoneAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"none"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitButtonAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"button"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitLinkAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"link"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitImageAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"image"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitSearchFieldAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"searchField"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitKeyboardKeyAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"keyboardKey"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitStaticTextAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"staticText"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitHeaderAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"header"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitTabBarAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"tabBar"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitSummaryElementAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"summaryElement"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitSelectedAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"selected"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitNotEnabledAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"notEnabled"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitAdjustableAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"adjustable"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitAllowsDirectInteractionAttributeId =
|
||||
[[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"directInteraction"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitUpdatesFrequentlyAttributeId =
|
||||
[[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"updatedFrequently"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitCausesPageTurnAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"causesPageTurn"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitPlaysSoundAttributeId = [[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"playsSound"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
AccessibilityTraitStartsMediaSessionAttributeId =
|
||||
[[UIDMetadataRegister shared]
|
||||
registerMetadataWithType:UIDEBUGGER_METADATA_TYPE_ATTRIBUTE
|
||||
name:@"startsMediaSession"
|
||||
isMutable:false
|
||||
definedBy:AccessibilityTraitsAttributeId];
|
||||
});
|
||||
|
||||
NSMutableDictionary* viewAttributes = [NSMutableDictionary new];
|
||||
|
||||
[viewAttributes setObject:[UIDInspectableBounds fromRect:self.frame]
|
||||
forKey:FrameAttributeId];
|
||||
[viewAttributes setObject:[UIDInspectableBounds fromRect:self.bounds]
|
||||
forKey:BoundsAttributeId];
|
||||
[viewAttributes setObject:[UIDInspectableCoordinate fromPoint:self.center]
|
||||
forKey:CenterAttributeId];
|
||||
if (@available(iOS 16.0, *)) {
|
||||
[viewAttributes
|
||||
setObject:[UIDInspectableCoordinate fromPoint:self.anchorPoint]
|
||||
forKey:AnchorPointAttributeId];
|
||||
}
|
||||
[viewAttributes
|
||||
setObject:[UIDInspectableEdgeInsets fromUIEdgeInsets:self.safeAreaInsets]
|
||||
forKey:SafeAreaInsetsAttributeId];
|
||||
[viewAttributes
|
||||
setObject:[UIDInspectableBoolean fromBoolean:self.clipsToBounds]
|
||||
forKey:ClipsToBoundsAttributeId];
|
||||
[viewAttributes setObject:[UIDInspectableBoolean fromBoolean:self.isHidden]
|
||||
forKey:HiddenAttributeId];
|
||||
[viewAttributes setObject:[UIDInspectableNumber fromCGFloat:self.alpha]
|
||||
forKey:AlphaAttributeId];
|
||||
[viewAttributes setObject:[UIDInspectableBoolean fromBoolean:self.opaque]
|
||||
forKey:OpaqueAttributeId];
|
||||
[viewAttributes setObject:[UIDInspectableBoolean
|
||||
fromBoolean:self.clearsContextBeforeDrawing]
|
||||
forKey:ClearContextBeforeDrawingAttributeId];
|
||||
[viewAttributes setObject:[UIDInspectableColor fromColor:self.backgroundColor]
|
||||
forKey:BackgroundColorAttributeId];
|
||||
[viewAttributes setObject:[UIDInspectableColor fromColor:self.tintColor]
|
||||
forKey:TintColorAttributeId];
|
||||
[viewAttributes setObject:[UIDInspectableNumber fromNumber:@(self.tag)]
|
||||
forKey:TagAttributeId];
|
||||
|
||||
[attributes setObject:[UIDInspectableObject fromFields:viewAttributes]
|
||||
forKey:UIViewAttributeId];
|
||||
|
||||
NSMutableDictionary* layerAttributes = [NSMutableDictionary new];
|
||||
|
||||
[layerAttributes
|
||||
setObject:[UIDInspectableColor
|
||||
fromColor:[UIColor colorWithCGColor:self.layer.shadowColor]]
|
||||
forKey:CALayerShadowColorAttributeId];
|
||||
[layerAttributes
|
||||
setObject:[UIDInspectableNumber fromCGFloat:self.layer.shadowOpacity]
|
||||
forKey:CALayerShadowOpacityAttributeId];
|
||||
[layerAttributes
|
||||
setObject:[UIDInspectableNumber fromCGFloat:self.layer.shadowRadius]
|
||||
forKey:CALayerShadowRadiusAttributeId];
|
||||
[layerAttributes
|
||||
setObject:[UIDInspectableSize fromSize:self.layer.shadowOffset]
|
||||
forKey:CALayerShadowOffsetAttributeId];
|
||||
[layerAttributes
|
||||
setObject:[UIDInspectableColor
|
||||
fromColor:[UIColor
|
||||
colorWithCGColor:self.layer.backgroundColor]]
|
||||
forKey:CALayerBackgroundColorAttributeId];
|
||||
[layerAttributes
|
||||
setObject:[UIDInspectableColor
|
||||
fromColor:[UIColor colorWithCGColor:self.layer.borderColor]]
|
||||
forKey:CALayerBorderColorAttributeId];
|
||||
[layerAttributes
|
||||
setObject:[UIDInspectableNumber fromCGFloat:self.layer.borderWidth]
|
||||
forKey:CALayerBorderWidthAttributeId];
|
||||
[layerAttributes
|
||||
setObject:[UIDInspectableNumber fromCGFloat:self.layer.cornerRadius]
|
||||
forKey:CALayerCornerRadiusAttributeId];
|
||||
[layerAttributes
|
||||
setObject:[UIDInspectableBoolean fromBoolean:self.layer.masksToBounds]
|
||||
forKey:CALayerMasksToBoundsAttributeId];
|
||||
|
||||
[attributes setObject:[UIDInspectableObject fromFields:layerAttributes]
|
||||
forKey:CALayerAttributeId];
|
||||
|
||||
NSMutableDictionary* accessibilityAttributes = [NSMutableDictionary new];
|
||||
|
||||
[accessibilityAttributes
|
||||
setObject:[UIDInspectableBoolean fromBoolean:self.isAccessibilityElement]
|
||||
forKey:IsAccessibilityElementAttributeId];
|
||||
[accessibilityAttributes
|
||||
setObject:[UIDInspectableText fromText:self.accessibilityLabel]
|
||||
forKey:AccessibilityLabelAttributeId];
|
||||
[accessibilityAttributes
|
||||
setObject:[UIDInspectableText fromText:self.accessibilityIdentifier]
|
||||
forKey:AccessibilityIdentifierAttributeId];
|
||||
[accessibilityAttributes
|
||||
setObject:[UIDInspectableText fromText:self.accessibilityValue]
|
||||
forKey:AccessibilityValueAttributeId];
|
||||
[accessibilityAttributes
|
||||
setObject:[UIDInspectableText fromText:self.accessibilityHint]
|
||||
forKey:AccessibilityHintAttributeId];
|
||||
[accessibilityAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:self.accessibilityViewIsModal]
|
||||
forKey:AccessibilityViewIsModalAttributeId];
|
||||
[accessibilityAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:self.shouldGroupAccessibilityChildren]
|
||||
forKey:ShouldGroupAccessibilityChildrenAttributeId];
|
||||
|
||||
NSMutableDictionary* accessibilityTraitsAttributes =
|
||||
[NSMutableDictionary new];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitNone)]
|
||||
forKey:AccessibilityTraitNoneAttributeId];
|
||||
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitButton)]
|
||||
forKey:AccessibilityTraitButtonAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitLink)]
|
||||
forKey:AccessibilityTraitLinkAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitImage)]
|
||||
forKey:AccessibilityTraitImageAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitSearchField)]
|
||||
forKey:AccessibilityTraitSearchFieldAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitKeyboardKey)]
|
||||
forKey:AccessibilityTraitKeyboardKeyAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitStaticText)]
|
||||
forKey:AccessibilityTraitStaticTextAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitHeader)]
|
||||
forKey:AccessibilityTraitHeaderAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitTabBar)]
|
||||
forKey:AccessibilityTraitTabBarAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitSummaryElement)]
|
||||
forKey:AccessibilityTraitSummaryElementAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitSelected)]
|
||||
forKey:AccessibilityTraitSelectedAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitNotEnabled)]
|
||||
forKey:AccessibilityTraitNotEnabledAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitAdjustable)]
|
||||
forKey:AccessibilityTraitAdjustableAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitAllowsDirectInteraction)]
|
||||
forKey:AccessibilityTraitAllowsDirectInteractionAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitUpdatesFrequently)]
|
||||
forKey:AccessibilityTraitUpdatesFrequentlyAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitCausesPageTurn)]
|
||||
forKey:AccessibilityTraitCausesPageTurnAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitPlaysSound)]
|
||||
forKey:AccessibilityTraitPlaysSoundAttributeId];
|
||||
[accessibilityTraitsAttributes
|
||||
setObject:[UIDInspectableBoolean
|
||||
fromBoolean:(self.accessibilityTraits &
|
||||
UIAccessibilityTraitStartsMediaSession)]
|
||||
forKey:AccessibilityTraitStartsMediaSessionAttributeId];
|
||||
|
||||
[accessibilityAttributes
|
||||
setObject:[UIDInspectableObject fromFields:accessibilityTraitsAttributes]
|
||||
forKey:AccessibilityTraitsAttributeId];
|
||||
|
||||
[attributes
|
||||
setObject:[UIDInspectableObject fromFields:accessibilityAttributes]
|
||||
forKey:AccessibilityAttributeId];
|
||||
}
|
||||
|
||||
- (NSArray<id<NSObject>>*)UID_children {
|
||||
NSMutableArray* children = [NSMutableArray new];
|
||||
|
||||
// Use UIViewControllers for children which responds to a different
|
||||
// view controller than their parent.
|
||||
for (UIView* child in self.subviews) {
|
||||
BOOL isController =
|
||||
[child.nextResponder isKindOfClass:[UIViewController class]];
|
||||
|
||||
if (!child.isHidden) {
|
||||
if (isController && child.nextResponder != self.nextResponder) {
|
||||
[children addObject:child.nextResponder];
|
||||
} else {
|
||||
[children addObject:child];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
In the context of UIView, the active child is defined as the last view in
|
||||
the subviews collection. If said item's next responder is a UIViewController,
|
||||
then return this instead.
|
||||
*/
|
||||
- (id<NSObject>)UID_activeChild {
|
||||
if (self.subviews && self.subviews.count > 0) {
|
||||
UIView* activeChild = [self.subviews lastObject];
|
||||
BOOL isController =
|
||||
[activeChild.nextResponder isKindOfClass:[UIViewController class]];
|
||||
|
||||
if (!activeChild.isHidden) {
|
||||
if (isController && activeChild.nextResponder != self.nextResponder) {
|
||||
return activeChild.nextResponder;
|
||||
}
|
||||
return activeChild;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (UIImage*)UID_snapshot {
|
||||
return UIDViewSnapshot(self);
|
||||
}
|
||||
|
||||
- (UIDBounds*)UID_bounds {
|
||||
if ([self.superview isKindOfClass:[UIScrollView class]]) {
|
||||
UIScrollView* parent = (UIScrollView*)self.superview;
|
||||
|
||||
CGFloat x = self.frame.origin.x - parent.contentOffset.x;
|
||||
CGFloat y = self.frame.origin.y - parent.contentOffset.y;
|
||||
CGFloat width = self.frame.size.width;
|
||||
CGFloat height = self.frame.size.height;
|
||||
|
||||
return [UIDBounds fromRect:CGRectMake(x, y, width, height)];
|
||||
}
|
||||
|
||||
return [UIDBounds fromRect:self.frame];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UIDTraversalMode.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class UIDFrameworkEventMetadata;
|
||||
|
||||
@interface UIDInitEvent : NSObject
|
||||
|
||||
@property(nonatomic) NSUInteger rootId;
|
||||
@property(nonatomic) UIDTraversalMode currentTraversalMode;
|
||||
@property(nonatomic, strong)
|
||||
NSArray<UIDFrameworkEventMetadata*>* frameworkEventMetadata;
|
||||
|
||||
+ (NSString*)name;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDInitEvent.h"
|
||||
|
||||
@implementation UIDInitEvent
|
||||
|
||||
+ (NSString*)name {
|
||||
return @"init";
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class UIDMetadata;
|
||||
|
||||
@interface UIDMetadataUpdateEvent : NSObject
|
||||
|
||||
@property(nonatomic, strong)
|
||||
NSDictionary<NSNumber*, UIDMetadata*>* attributeMetadata;
|
||||
|
||||
+ (NSString*)name;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDMetadataUpdateEvent.h"
|
||||
|
||||
@implementation UIDMetadataUpdateEvent
|
||||
|
||||
+ (NSString*)name {
|
||||
return @"metadataUpdate";
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDPerfStatsEvent : NSObject
|
||||
|
||||
@property(nonatomic) double txId;
|
||||
@property(nonatomic, strong) NSString* observerType;
|
||||
@property(nonatomic) NSUInteger nodesCount;
|
||||
|
||||
@property(nonatomic) long start;
|
||||
@property(nonatomic) long traversalMS;
|
||||
@property(nonatomic) long snapshotMS;
|
||||
@property(nonatomic) long queuingMS;
|
||||
@property(nonatomic) long deferredComputationMS;
|
||||
@property(nonatomic) long serializationMS;
|
||||
@property(nonatomic) long socketMS;
|
||||
@property(nonatomic) long frameworkEventsMS;
|
||||
@property(nonatomic) long payloadSize;
|
||||
@property(nonatomic) NSUInteger eventsCount;
|
||||
@property(nonatomic) NSDictionary<NSString*, NSNumber*>* dynamicMeasures;
|
||||
|
||||
+ (NSString*)name;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDPerfStatsEvent.h"
|
||||
|
||||
@implementation UIDPerfStatsEvent
|
||||
|
||||
+ (NSString*)name {
|
||||
return @"performanceStats";
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDFrameworkEvent.h"
|
||||
#import "UIDNode.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDSubtreeUpdateEvent : NSObject
|
||||
|
||||
@property(nonatomic) double txId;
|
||||
@property(nonatomic, strong) NSString* observerType;
|
||||
@property(nonatomic) NSUInteger rootId;
|
||||
@property(nonatomic, strong) NSArray<UIDNode*>* nodes;
|
||||
@property(nonatomic, strong) UIImage* snapshot;
|
||||
@property(nonatomic, strong) NSArray<UIDFrameworkEvent*>* frameworkEvents;
|
||||
|
||||
+ (NSString*)name;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDSubtreeUpdateEvent.h"
|
||||
|
||||
@implementation UIDSubtreeUpdateEvent
|
||||
|
||||
+ (NSString*)name {
|
||||
return @"subtreeUpdate";
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <FlipperKit/FlipperPlugin.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class FlipperClient;
|
||||
|
||||
@interface FlipperKitUIDebuggerPlugin : NSObject<FlipperPlugin>
|
||||
|
||||
@end
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void FlipperKitUIDebuggerAddPlugin(FlipperClient*);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "FlipperKitUIDebuggerPlugin.h"
|
||||
#import <FlipperKit/FlipperClient.h>
|
||||
#import <FlipperKit/FlipperConnection.h>
|
||||
#import <FlipperKit/FlipperResponder.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "Core/UIDContext.h"
|
||||
|
||||
#import "Descriptors/UIDDescriptorRegister.h"
|
||||
#import "Observer/UIDTreeObserverFactory.h"
|
||||
#import "Observer/UIDTreeObserverManager.h"
|
||||
|
||||
#import "UIDTraversalMode.h"
|
||||
|
||||
@implementation FlipperKitUIDebuggerPlugin {
|
||||
UIDContext* _context;
|
||||
}
|
||||
|
||||
- (instancetype)initWithContext:(UIDContext*)context {
|
||||
if (self = [super init]) {
|
||||
self->_context = context;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
UIDContext* context = [[UIDContext alloc]
|
||||
initWithApplication:[UIApplication sharedApplication]
|
||||
descriptorRegister:[UIDDescriptorRegister defaultRegister]
|
||||
observerFactory:[UIDTreeObserverFactory shared]];
|
||||
return [self initWithContext:context];
|
||||
}
|
||||
|
||||
- (NSString*)identifier {
|
||||
return @"ui-debugger";
|
||||
}
|
||||
|
||||
- (void)didConnect:(id<FlipperConnection>)connection {
|
||||
if (!_context.application) {
|
||||
_context.application = [UIApplication sharedApplication];
|
||||
}
|
||||
|
||||
_context.connection = connection;
|
||||
[[UIDTreeObserverManager shared] startWithContext:_context];
|
||||
|
||||
NSSet<id<UIDConnectionListener>>* connectionListeners =
|
||||
_context.connectionListeners;
|
||||
for (id<UIDConnectionListener> listener in connectionListeners) {
|
||||
[listener onDidConnect];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didDisconnect {
|
||||
_context.connection = nil;
|
||||
[[UIDTreeObserverManager shared] stop];
|
||||
|
||||
NSSet<id<UIDConnectionListener>>* connectionListeners =
|
||||
_context.connectionListeners;
|
||||
for (id<UIDConnectionListener> listener in connectionListeners) {
|
||||
[listener onDidDisconnect];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <FlipperKit/FlipperClient.h>
|
||||
#import "FlipperKitUIDebuggerPlugin.h"
|
||||
#import "UIDContext.h"
|
||||
#import "UIDDescriptorRegister.h"
|
||||
#import "UIDTreeObserverFactory.h"
|
||||
|
||||
@interface FlipperKitUIDebuggerPlugin ()
|
||||
- (instancetype)initWithContext:(UIDContext*)context;
|
||||
@end
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void FlipperKitUIDebuggerAddPlugin(FlipperClient* client) {
|
||||
UIDContext* context = [[UIDContext alloc]
|
||||
initWithApplication:[UIApplication sharedApplication]
|
||||
descriptorRegister:[UIDDescriptorRegister defaultRegister]
|
||||
observerFactory:[UIDTreeObserverFactory shared]];
|
||||
FlipperKitUIDebuggerPlugin* plugin =
|
||||
[[FlipperKitUIDebuggerPlugin alloc] initWithContext:context];
|
||||
|
||||
[client addPlugin:plugin];
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDBounds : NSObject
|
||||
|
||||
@property(nonatomic) NSInteger x;
|
||||
@property(nonatomic) NSInteger y;
|
||||
@property(nonatomic) NSInteger width;
|
||||
@property(nonatomic) NSInteger height;
|
||||
|
||||
- (instancetype)initWithX:(NSInteger)x
|
||||
y:(NSInteger)y
|
||||
width:(NSInteger)width
|
||||
height:(NSInteger)height;
|
||||
|
||||
+ (instancetype)fromRect:(CGRect)rect;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDBounds.h"
|
||||
|
||||
@implementation UIDBounds
|
||||
|
||||
- (instancetype)initWithX:(NSInteger)x
|
||||
y:(NSInteger)y
|
||||
width:(NSInteger)width
|
||||
height:(NSInteger)height {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.x = x;
|
||||
self.y = y;
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromRect:(CGRect)rect {
|
||||
return [[UIDBounds alloc] initWithX:rect.origin.x
|
||||
y:rect.origin.y
|
||||
width:rect.size.width
|
||||
height:rect.size.height];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDEdgeInsets : NSObject
|
||||
|
||||
@property(nonatomic) CGFloat top;
|
||||
@property(nonatomic) CGFloat right;
|
||||
@property(nonatomic) CGFloat bottom;
|
||||
@property(nonatomic) CGFloat left;
|
||||
|
||||
- (instancetype)initWithTop:(CGFloat)top
|
||||
right:(CGFloat)right
|
||||
bottom:(CGFloat)bottom
|
||||
left:(CGFloat)left;
|
||||
|
||||
+ (instancetype)fromUIEdgeInsets:(UIEdgeInsets)edgeInsets;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDEdgeInsets.h"
|
||||
|
||||
@implementation UIDEdgeInsets
|
||||
|
||||
- (instancetype)initWithTop:(CGFloat)top
|
||||
right:(CGFloat)right
|
||||
bottom:(CGFloat)bottom
|
||||
left:(CGFloat)left {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_top = top;
|
||||
_right = right;
|
||||
_bottom = bottom;
|
||||
_left = left;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromUIEdgeInsets:(UIEdgeInsets)edgeInsets {
|
||||
return [[UIDEdgeInsets alloc] initWithTop:edgeInsets.top
|
||||
right:edgeInsets.right
|
||||
bottom:edgeInsets.bottom
|
||||
left:edgeInsets.left];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NSDictionary<NSString*, id>* UIDEventPayload;
|
||||
typedef NSArray<NSString*>* UIDStacktrace;
|
||||
|
||||
@interface UIDFrameworkEvent : NSObject
|
||||
|
||||
@property(nonatomic) NSUInteger nodeIdentifier;
|
||||
@property(nonatomic, strong) NSString* type;
|
||||
@property(nonatomic, strong) NSDate* timestamp;
|
||||
@property(nonatomic, strong) UIDEventPayload payload;
|
||||
@property(nonatomic, strong) UIDStacktrace stacktrace;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDFrameworkEvent.h"
|
||||
|
||||
@implementation UIDFrameworkEvent
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDFrameworkEventMetadata : NSObject
|
||||
|
||||
@property(nonatomic, strong) NSString* type;
|
||||
@property(nonatomic, strong) NSString* documentation;
|
||||
|
||||
+ (instancetype)newWithType:(NSString*)type
|
||||
documentation:(NSString*)documentation;
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDFrameworkEventMetadata.h"
|
||||
|
||||
@implementation UIDFrameworkEventMetadata
|
||||
|
||||
- (instancetype)initWithType:(NSString*)type
|
||||
documentation:(NSString*)documentation {
|
||||
if (self = [super init]) {
|
||||
self->_type = type;
|
||||
self->_documentation = documentation;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)newWithType:(NSString*)type
|
||||
documentation:(NSString*)documentation {
|
||||
return [[self alloc] initWithType:type documentation:documentation];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "UIDFoundation.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDInspectable : NSObject
|
||||
@end
|
||||
|
||||
/**
|
||||
Lazy inspectables can be used to defer materialisation
|
||||
of the inspectable until a later stage, like for example,
|
||||
during serialisation.
|
||||
*/
|
||||
@interface UIDLazyInspectable : UIDInspectable
|
||||
|
||||
- (UIDInspectable*)value;
|
||||
+ (instancetype)from:(UIDInspectable* (^)(void))loader;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIDInspectableValue : UIDInspectable
|
||||
|
||||
+ (instancetype)createWithText:(NSString*)text;
|
||||
+ (instancetype)createWithBoolean:(bool)boolean;
|
||||
+ (instancetype)createWithNumber:(NSNumber*)number;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIDInspectableObject : UIDInspectable
|
||||
|
||||
@property(nonatomic, strong, readonly)
|
||||
NSDictionary<NSNumber*, UIDInspectable*>* fields;
|
||||
|
||||
- (instancetype)initWithFields:
|
||||
(NSDictionary<NSNumber*, UIDInspectable*>*)fields;
|
||||
|
||||
+ (instancetype)fromFields:(NSDictionary<NSNumber*, UIDInspectable*>*)fields;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIDInspectableArray : UIDInspectable
|
||||
|
||||
@property(nonatomic, strong, readonly) NSArray<UIDInspectable*>* items;
|
||||
|
||||
- (instancetype)initWithItems:(NSArray<UIDInspectable*>*)items;
|
||||
|
||||
+ (instancetype)fromItems:(NSArray<UIDInspectable*>*)items;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIDInspectableText : UIDInspectableValue
|
||||
|
||||
@property(nonatomic, strong, readonly) NSString* value;
|
||||
|
||||
- (instancetype)initWithValue:(NSString*)value;
|
||||
|
||||
+ (instancetype)fromText:(NSString*)value;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIDInspectableBoolean : UIDInspectableValue
|
||||
|
||||
@property(nonatomic, readonly) bool value;
|
||||
|
||||
- (instancetype)initWithValue:(bool)value;
|
||||
|
||||
+ (instancetype)fromBoolean:(bool)value;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIDInspectableNumber : UIDInspectableValue
|
||||
|
||||
@property(nonatomic, strong, readonly) NSNumber* value;
|
||||
|
||||
- (instancetype)initWithValue:(NSNumber*)value;
|
||||
|
||||
+ (instancetype)fromNumber:(NSNumber*)value;
|
||||
+ (instancetype)fromCGFloat:(CGFloat)value;
|
||||
|
||||
@end
|
||||
|
||||
@class UIDBounds;
|
||||
@interface UIDInspectableBounds : UIDInspectableValue
|
||||
|
||||
@property(nonatomic, strong, readonly) UIDBounds* value;
|
||||
|
||||
- (instancetype)initWithValue:(UIDBounds*)value;
|
||||
|
||||
+ (instancetype)fromBounds:(UIDBounds*)value;
|
||||
+ (instancetype)fromRect:(CGRect)rect;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIDInspectableCoordinate : UIDInspectableValue
|
||||
|
||||
@property(nonatomic, readonly) CGPoint value;
|
||||
|
||||
- (instancetype)initWithValue:(CGPoint)value;
|
||||
|
||||
+ (instancetype)fromPoint:(CGPoint)value;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIDInspectableSize : UIDInspectableValue
|
||||
|
||||
@property(nonatomic, readonly) CGSize value;
|
||||
|
||||
- (instancetype)initWithValue:(CGSize)value;
|
||||
|
||||
+ (instancetype)fromSize:(CGSize)value;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIDInspectableUnknown : UIDInspectableValue
|
||||
|
||||
@property(nonatomic, readonly) NSString* value;
|
||||
|
||||
- (instancetype)initWithValue:(NSString*)value;
|
||||
|
||||
+ (instancetype)unknown;
|
||||
+ (instancetype)undefined;
|
||||
+ (instancetype)null;
|
||||
|
||||
@end
|
||||
|
||||
@class UIDEdgeInsets;
|
||||
@interface UIDInspectableEdgeInsets : UIDInspectableValue
|
||||
|
||||
@property(nonatomic, readonly) UIDEdgeInsets* value;
|
||||
|
||||
- (instancetype)initWithValue:(UIDEdgeInsets*)value;
|
||||
|
||||
+ (instancetype)fromEdgeInsets:(UIDEdgeInsets*)value;
|
||||
+ (instancetype)fromUIEdgeInsets:(UIEdgeInsets)value;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIDInspectableColor : UIDInspectableValue
|
||||
|
||||
@property(nonatomic, strong, readonly) UIColor* value;
|
||||
|
||||
- (instancetype)initWithValue:(UIColor*)value;
|
||||
|
||||
+ (instancetype)fromColor:(UIColor*)value;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIDInspectableEnum : UIDInspectableValue
|
||||
|
||||
@property(nonatomic, readonly) NSString* value;
|
||||
|
||||
- (instancetype)initWithValue:(NSString*)value;
|
||||
|
||||
+ (instancetype)from:(NSString*)value;
|
||||
|
||||
@end
|
||||
|
||||
typedef NSDictionary<NSNumber*, UIDInspectable*> UIDAttributes;
|
||||
typedef NSMutableDictionary<NSNumber*, UIDInspectable*> UIDMutableAttributes;
|
||||
typedef NSDictionary<NSString*, NSString*> UIDInlineAttributes;
|
||||
typedef NSMutableDictionary<NSString*, NSString*> UIDMutableInlineAttributes;
|
||||
typedef NSDictionary<NSString*, id<UIDFoundation>> UIDGenericAttributes;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDInspectable.h"
|
||||
#import "UIDBounds.h"
|
||||
#import "UIDEdgeInsets.h"
|
||||
|
||||
@implementation UIDInspectable
|
||||
@end
|
||||
|
||||
@interface UIDLazyInspectable () {
|
||||
UIDInspectable* _value;
|
||||
UIDInspectable* (^_loader)(void);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDLazyInspectable
|
||||
- (instancetype)initWithLoader:(UIDInspectable* (^)(void))loader {
|
||||
if (self = [super init]) {
|
||||
self->_value = nil;
|
||||
self->_loader = loader;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UIDInspectable*)value {
|
||||
if (!_value && _loader) {
|
||||
_value = _loader();
|
||||
}
|
||||
return _value;
|
||||
}
|
||||
|
||||
+ (instancetype)from:(UIDInspectable* (^)(void))loader {
|
||||
return [[self alloc] initWithLoader:loader];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableObject
|
||||
|
||||
- (instancetype)initWithFields:
|
||||
(NSDictionary<NSNumber*, UIDInspectable*>*)fields {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_fields = fields;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromFields:(NSDictionary<NSNumber*, UIDInspectable*>*)fields {
|
||||
return [[UIDInspectableObject alloc] initWithFields:fields];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableArray
|
||||
|
||||
- (instancetype)initWithItems:(NSArray<UIDInspectable*>*)items {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_items = items;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromItems:(NSArray<UIDInspectable*>*)items {
|
||||
return [[UIDInspectableArray alloc] initWithItems:items];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableValue
|
||||
|
||||
+ (instancetype)createWithText:(NSString*)text {
|
||||
return [[UIDInspectableText alloc] initWithValue:text];
|
||||
}
|
||||
|
||||
+ (instancetype)createWithBoolean:(bool)boolean {
|
||||
return [[UIDInspectableBoolean alloc] initWithValue:boolean];
|
||||
}
|
||||
|
||||
+ (instancetype)createWithNumber:(NSNumber*)number {
|
||||
return [[UIDInspectableNumber alloc] initWithValue:number];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableText
|
||||
|
||||
- (instancetype)initWithValue:(NSString*)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_value = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromText:(NSString*)value {
|
||||
return [[UIDInspectableText alloc] initWithValue:value];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableBoolean
|
||||
|
||||
- (instancetype)initWithValue:(bool)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_value = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromBoolean:(bool)value {
|
||||
return [[UIDInspectableBoolean alloc] initWithValue:value];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableNumber
|
||||
|
||||
- (instancetype)initWithValue:(NSNumber*)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_value = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromNumber:(NSNumber*)value {
|
||||
return [[UIDInspectableNumber alloc] initWithValue:value];
|
||||
}
|
||||
|
||||
+ (instancetype)fromCGFloat:(CGFloat)value {
|
||||
return [self fromNumber:[NSNumber numberWithFloat:value]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableBounds
|
||||
|
||||
- (instancetype)initWithValue:(UIDBounds*)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_value = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromBounds:(UIDBounds*)bounds {
|
||||
return [[UIDInspectableBounds alloc] initWithValue:bounds];
|
||||
}
|
||||
|
||||
+ (instancetype)fromRect:(CGRect)rect {
|
||||
return [self fromBounds:[UIDBounds fromRect:rect]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableCoordinate
|
||||
|
||||
- (instancetype)initWithValue:(CGPoint)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_value = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromPoint:(CGPoint)value {
|
||||
return [[UIDInspectableCoordinate alloc] initWithValue:value];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableSize
|
||||
|
||||
- (instancetype)initWithValue:(CGSize)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_value = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromSize:(CGSize)value {
|
||||
return [[UIDInspectableSize alloc] initWithValue:value];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableEdgeInsets
|
||||
|
||||
- (instancetype)initWithValue:(UIDEdgeInsets*)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_value = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromEdgeInsets:(UIDEdgeInsets*)value {
|
||||
return [[UIDInspectableEdgeInsets alloc] initWithValue:value];
|
||||
}
|
||||
|
||||
+ (instancetype)fromUIEdgeInsets:(UIEdgeInsets)value {
|
||||
return [self fromEdgeInsets:[UIDEdgeInsets fromUIEdgeInsets:value]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableColor
|
||||
|
||||
- (instancetype)initWithValue:(UIColor*)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_value = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)fromColor:(UIColor*)value {
|
||||
return [[UIDInspectableColor alloc] initWithValue:value];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableUnknown
|
||||
|
||||
- (instancetype)initWithValue:(NSString*)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_value = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)unknown {
|
||||
return [[UIDInspectableUnknown alloc] initWithValue:@"unknown"];
|
||||
}
|
||||
|
||||
+ (instancetype)undefined {
|
||||
return [[UIDInspectableUnknown alloc] initWithValue:@"undefined"];
|
||||
}
|
||||
|
||||
+ (instancetype)null {
|
||||
return [[UIDInspectableUnknown alloc] initWithValue:@"null"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIDInspectableEnum
|
||||
|
||||
- (instancetype)initWithValue:(NSString*)value {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_value = value;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)from:(NSString*)value {
|
||||
return [[UIDInspectableEnum alloc] initWithValue:value ?: @"UNKNOWN"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NSNumber* UIDMetadataId;
|
||||
|
||||
@class UIDInspectableValue;
|
||||
|
||||
/**
|
||||
Represent metadata associated for an attribute. Metadata identifier is a
|
||||
unique identifier used by attributes to refer to its metadata. Type refers to
|
||||
attribute semantics. It can represent: identity, attributes, layout,
|
||||
documentation, or a custom type.
|
||||
*/
|
||||
@interface UIDMetadata : NSObject
|
||||
|
||||
#pragma mark - Included in the wire protocol
|
||||
|
||||
@property(nonatomic, readonly) UIDMetadataId identifier;
|
||||
@property(nonatomic, strong, readonly) NSString* type;
|
||||
@property(nonatomic, strong, readonly) NSString* name;
|
||||
@property(nonatomic, readonly) bool isMutable;
|
||||
@property(nonatomic, readonly, nullable)
|
||||
NSDictionary<NSString*, id>* customAttributes;
|
||||
|
||||
#pragma mark - Not included in the wire protocol
|
||||
|
||||
@property(nonatomic, readonly) UIDMetadataId parent;
|
||||
@property(nonatomic, strong, readonly, nullable)
|
||||
NSSet<UIDInspectableValue*>* possibleValues;
|
||||
@property(nonatomic, strong, readonly, nullable) NSSet<NSString*>* tags;
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (instancetype)
|
||||
initWithIdentifier:(UIDMetadataId)identifier
|
||||
type:(NSString*)type
|
||||
name:(NSString*)name
|
||||
isMutable:(bool)isMutable
|
||||
parent:(UIDMetadataId)parent
|
||||
possibleValues:(nullable NSSet<UIDInspectableValue*>*)possibleValues
|
||||
tags:(nullable NSSet<NSString*>*)tags
|
||||
customAttributes:(nullable NSDictionary<NSString*, id>*)customAttributes;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDMetadata.h"
|
||||
#import "UIDInspectable.h"
|
||||
|
||||
@implementation UIDMetadata
|
||||
|
||||
- (instancetype)initWithIdentifier:(UIDMetadataId)identifier
|
||||
type:(NSString*)type
|
||||
name:(NSString*)name
|
||||
isMutable:(bool)isMutable
|
||||
parent:(UIDMetadataId)parent
|
||||
possibleValues:(NSSet<UIDInspectableValue*>*)possibleValues
|
||||
tags:(NSSet<NSString*>*)tags
|
||||
customAttributes:
|
||||
(nullable NSDictionary<NSString*, id>*)customAttributes {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_identifier = identifier;
|
||||
_type = type;
|
||||
_name = name;
|
||||
_isMutable = isMutable;
|
||||
_parent = parent ?: @0;
|
||||
_possibleValues = possibleValues ?: [NSSet set];
|
||||
_tags = tags ?: [NSSet set];
|
||||
_customAttributes = customAttributes;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UIDBounds.h"
|
||||
#import "UIDInspectable.h"
|
||||
#import "UIDMetadata.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIDNode : NSObject
|
||||
|
||||
@property(nonatomic) NSUInteger identifier;
|
||||
@property(nonatomic, strong) NSString* qualifiedName;
|
||||
@property(nonatomic, strong) NSString* name;
|
||||
@property(nonatomic, strong) UIDBounds* bounds;
|
||||
@property(nonatomic, strong) NSSet<NSString*>* tags;
|
||||
@property(nonatomic, strong) UIDAttributes* attributes;
|
||||
@property(nonatomic, strong) UIDInlineAttributes* inlineAttributes;
|
||||
@property(nonatomic, strong) UIDGenericAttributes* hiddenAttributes;
|
||||
@property(nonatomic, nullable) NSNumber* parent;
|
||||
@property(nonatomic, strong) NSArray<NSNumber*>* children;
|
||||
@property(nonatomic) NSNumber* activeChild;
|
||||
|
||||
- (instancetype)initWithIdentifier:(NSUInteger)identifier
|
||||
qualifiedName:(NSString*)qualifiedName
|
||||
name:(NSString*)name
|
||||
bounds:(UIDBounds*)bounds
|
||||
tags:(NSSet<NSString*>*)tags;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import "UIDNode.h"
|
||||
|
||||
@implementation UIDNode
|
||||
|
||||
- (instancetype)initWithIdentifier:(NSUInteger)identifier
|
||||
qualifiedName:(NSString*)qualifiedName
|
||||
name:(NSString*)name
|
||||
bounds:(UIDBounds*)bounds
|
||||
tags:(NSSet<NSString*>*)tags {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.identifier = identifier;
|
||||
self.qualifiedName = qualifiedName;
|
||||
self.name = name;
|
||||
self.bounds = bounds;
|
||||
self.tags = tags;
|
||||
self.parent = nil;
|
||||
self.children = [NSArray array];
|
||||
self.attributes = [NSDictionary dictionary];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_CLOSED_ENUM(NSInteger, UIDTraversalMode) {
|
||||
UIDTraversalModeViewHierarchy,
|
||||
UIDTraversalModeAccessibilityHierarchy,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
UIDTraversalMode UIDTraversalModeFromString(NSString* string);
|
||||
NSString* NSStringFromUIDTraversalMode(UIDTraversalMode mode);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user