Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9db1b544df | |||
| b58629b8ea | |||
| adeb22af15 | |||
| 6ab183e109 | |||
| 034f401cb4 | |||
| da1958def5 |
@@ -20,4 +20,3 @@ DerivedData
|
||||
/Example/Pods
|
||||
Podfile.lock
|
||||
IDEWorkspaceChecks.plist
|
||||
*.xcworkspace
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
}
|
||||
|
||||
- (BOOL)canShowToolbar {
|
||||
return self.topViewController.toolbarItems.count > 0;
|
||||
return self.topViewController.toolbarItems.count;
|
||||
}
|
||||
|
||||
- (void)addNavigationBarItemsToViewController:(UINavigationItem *)navigationItem {
|
||||
|
||||
@@ -66,9 +66,9 @@ CGFloat const kFLEXDebounceForExpensiveIO = 0.5;
|
||||
_searchBarDebounceInterval = kFLEXDebounceFast;
|
||||
_showSearchBarInitially = YES;
|
||||
_style = style;
|
||||
_manuallyDeactivateSearchOnDisappear = (
|
||||
NSProcessInfo.processInfo.operatingSystemVersion.majorVersion < 11
|
||||
);
|
||||
_manuallyDeactivateSearchOnDisappear = ({
|
||||
NSProcessInfo.processInfo.operatingSystemVersion.majorVersion < 11;
|
||||
});
|
||||
|
||||
// We will be our own search delegate if we implement this method
|
||||
if ([self respondsToSelector:@selector(updateSearchResults:)]) {
|
||||
|
||||
@@ -10,7 +10,4 @@
|
||||
|
||||
@interface FLEXArgumentInputStructView : FLEXArgumentInputView
|
||||
|
||||
/// Enable displaying ivar names for custom struct types
|
||||
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding;
|
||||
|
||||
@end
|
||||
|
||||
@@ -19,41 +19,6 @@
|
||||
|
||||
@implementation FLEXArgumentInputStructView
|
||||
|
||||
static NSMutableDictionary<NSString *, NSArray<NSString *> *> *structFieldNameRegistrar = nil;
|
||||
+ (void)initialize {
|
||||
if (self == [FLEXArgumentInputStructView class]) {
|
||||
structFieldNameRegistrar = [NSMutableDictionary new];
|
||||
[self registerDefaultFieldNames];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)registerDefaultFieldNames {
|
||||
NSDictionary *defaults = @{
|
||||
@(@encode(CGRect)): @[@"CGPoint origin", @"CGSize size"],
|
||||
@(@encode(CGPoint)): @[@"CGFloat x", @"CGFloat y"],
|
||||
@(@encode(CGSize)): @[@"CGFloat width", @"CGFloat height"],
|
||||
@(@encode(CGVector)): @[@"CGFloat dx", @"CGFloat dy"],
|
||||
@(@encode(UIEdgeInsets)): @[@"CGFloat top", @"CGFloat left", @"CGFloat bottom", @"CGFloat right"],
|
||||
@(@encode(UIOffset)): @[@"CGFloat horizontal", @"CGFloat vertical"],
|
||||
@(@encode(NSRange)): @[@"NSUInteger location", @"NSUInteger length"],
|
||||
@(@encode(CATransform3D)): @[@"CGFloat m11", @"CGFloat m12", @"CGFloat m13", @"CGFloat m14",
|
||||
@"CGFloat m21", @"CGFloat m22", @"CGFloat m23", @"CGFloat m24",
|
||||
@"CGFloat m31", @"CGFloat m32", @"CGFloat m33", @"CGFloat m34",
|
||||
@"CGFloat m41", @"CGFloat m42", @"CGFloat m43", @"CGFloat m44"],
|
||||
@(@encode(CGAffineTransform)): @[@"CGFloat a", @"CGFloat b",
|
||||
@"CGFloat c", @"CGFloat d",
|
||||
@"CGFloat tx", @"CGFloat ty"],
|
||||
};
|
||||
|
||||
[structFieldNameRegistrar addEntriesFromDictionary:defaults];
|
||||
|
||||
if (@available(iOS 11.0, *)) {
|
||||
structFieldNameRegistrar[@(@encode(NSDirectionalEdgeInsets))] = @[
|
||||
@"CGFloat top", @"CGFloat leading", @"CGFloat bottom", @"CGFloat trailing"
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)initWithArgumentTypeEncoding:(const char *)typeEncoding {
|
||||
self = [super initWithArgumentTypeEncoding:typeEncoding];
|
||||
if (self) {
|
||||
@@ -216,13 +181,40 @@ static NSMutableDictionary<NSString *, NSArray<NSString *> *> *structFieldNameRe
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding {
|
||||
NSParameterAssert(typeEncoding); NSParameterAssert(names);
|
||||
structFieldNameRegistrar[typeEncoding] = names;
|
||||
}
|
||||
|
||||
+ (NSArray<NSString *> *)customFieldTitlesForTypeEncoding:(const char *)typeEncoding {
|
||||
return structFieldNameRegistrar[@(typeEncoding)];
|
||||
NSArray<NSString *> *customTitles = nil;
|
||||
if (strcmp(typeEncoding, @encode(CGRect)) == 0) {
|
||||
customTitles = @[@"CGPoint origin", @"CGSize size"];
|
||||
} else if (strcmp(typeEncoding, @encode(CGPoint)) == 0) {
|
||||
customTitles = @[@"CGFloat x", @"CGFloat y"];
|
||||
} else if (strcmp(typeEncoding, @encode(CGSize)) == 0) {
|
||||
customTitles = @[@"CGFloat width", @"CGFloat height"];
|
||||
} else if (strcmp(typeEncoding, @encode(CGVector)) == 0) {
|
||||
customTitles = @[@"CGFloat dx", @"CGFloat dy"];
|
||||
} else if (strcmp(typeEncoding, @encode(UIEdgeInsets)) == 0) {
|
||||
customTitles = @[@"CGFloat top", @"CGFloat left", @"CGFloat bottom", @"CGFloat right"];
|
||||
} else if (strcmp(typeEncoding, @encode(UIOffset)) == 0) {
|
||||
customTitles = @[@"CGFloat horizontal", @"CGFloat vertical"];
|
||||
} else if (strcmp(typeEncoding, @encode(NSRange)) == 0) {
|
||||
customTitles = @[@"NSUInteger location", @"NSUInteger length"];
|
||||
} else if (strcmp(typeEncoding, @encode(CATransform3D)) == 0) {
|
||||
customTitles = @[@"CGFloat m11", @"CGFloat m12", @"CGFloat m13", @"CGFloat m14",
|
||||
@"CGFloat m21", @"CGFloat m22", @"CGFloat m23", @"CGFloat m24",
|
||||
@"CGFloat m31", @"CGFloat m32", @"CGFloat m33", @"CGFloat m34",
|
||||
@"CGFloat m41", @"CGFloat m42", @"CGFloat m43", @"CGFloat m44"];
|
||||
} else if (strcmp(typeEncoding, @encode(CGAffineTransform)) == 0) {
|
||||
customTitles = @[@"CGFloat a", @"CGFloat b",
|
||||
@"CGFloat c", @"CGFloat d",
|
||||
@"CGFloat tx", @"CGFloat ty"];
|
||||
} else {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
if (strcmp(typeEncoding, @encode(NSDirectionalEdgeInsets)) == 0) {
|
||||
customTitles = @[@"CGFloat top", @"CGFloat leading",
|
||||
@"CGFloat bottom", @"CGFloat trailing"];
|
||||
}
|
||||
}
|
||||
}
|
||||
return customTitles;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -21,7 +21,4 @@
|
||||
/// Useful when deciding whether to edit or explore a property, ivar, or NSUserDefaults value.
|
||||
+ (BOOL)canEditFieldWithTypeEncoding:(const char *)typeEncoding currentValue:(id)currentValue;
|
||||
|
||||
/// Enable displaying ivar names for custom struct types
|
||||
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding;
|
||||
|
||||
@end
|
||||
|
||||
@@ -67,9 +67,4 @@
|
||||
return [self argumentInputViewSubclassForTypeEncoding:typeEncoding currentValue:currentValue] != nil;
|
||||
}
|
||||
|
||||
/// Enable displaying ivar names for custom struct types
|
||||
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding {
|
||||
[FLEXArgumentInputStructView registerFieldNames:names forTypeEncoding:typeEncoding];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#import "FLEXFieldEditorView.h"
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXColor.h"
|
||||
|
||||
@interface FLEXFieldEditorView ()
|
||||
|
||||
@@ -123,7 +122,7 @@
|
||||
}
|
||||
|
||||
+ (UIColor *)dividerColor {
|
||||
return FLEXColor.tertiaryBackgroundColor;
|
||||
return UIColor.lightGrayColor;
|
||||
}
|
||||
|
||||
+ (CGFloat)horizontalPadding {
|
||||
|
||||
@@ -11,14 +11,12 @@
|
||||
#import "FLEXArgumentInputViewFactory.h"
|
||||
#import "FLEXPropertyAttributes.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "FLEXMetadataExtras.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXColor.h"
|
||||
#import "UIBarButtonItem+FLEX.h"
|
||||
|
||||
@interface FLEXFieldEditorViewController () <FLEXArgumentInputViewDelegate>
|
||||
|
||||
@property (nonatomic, readonly) id<FLEXMetadataAuxiliaryInfo> auxiliaryInfoProvider;
|
||||
@property (nonatomic) FLEXProperty *property;
|
||||
@property (nonatomic) FLEXIvar *ivar;
|
||||
|
||||
@@ -32,14 +30,14 @@
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
+ (instancetype)target:(id)target property:(nonnull FLEXProperty *)property commitHandler:(void(^)(void))onCommit {
|
||||
+ (instancetype)target:(id)target property:(nonnull FLEXProperty *)property commitHandler:(void(^_Nullable)(void))onCommit {
|
||||
FLEXFieldEditorViewController *editor = [self target:target data:property commitHandler:onCommit];
|
||||
editor.title = [@"Property: " stringByAppendingString:property.name];
|
||||
editor.property = property;
|
||||
return editor;
|
||||
}
|
||||
|
||||
+ (instancetype)target:(id)target ivar:(nonnull FLEXIvar *)ivar commitHandler:(void(^)(void))onCommit {
|
||||
+ (instancetype)target:(id)target ivar:(nonnull FLEXIvar *)ivar commitHandler:(void(^_Nullable)(void))onCommit {
|
||||
FLEXFieldEditorViewController *editor = [self target:target data:ivar commitHandler:onCommit];
|
||||
editor.title = [@"Ivar: " stringByAppendingString:ivar.name];
|
||||
editor.ivar = ivar;
|
||||
@@ -63,8 +61,6 @@
|
||||
self.toolbarItems = @[
|
||||
UIBarButtonItem.flex_flexibleSpace, self.getterButton, self.actionButton
|
||||
];
|
||||
|
||||
[self registerAuxiliaryInfo];
|
||||
|
||||
// Configure input view
|
||||
self.fieldEditorView.fieldDescription = self.fieldDescription;
|
||||
@@ -126,17 +122,6 @@
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)registerAuxiliaryInfo {
|
||||
// This is how Reflex will get Swift struct field names into the editor at runtime
|
||||
NSDictionary<NSString *, NSArray *> *labels = [self.auxiliaryInfoProvider
|
||||
auxiliaryInfoForKey:FLEXAuxiliarynfoKeyFieldLabels
|
||||
];
|
||||
|
||||
for (NSString *type in labels) {
|
||||
[FLEXArgumentInputViewFactory registerFieldNames:labels[type] forTypeEncoding:type];
|
||||
}
|
||||
}
|
||||
|
||||
- (id)currentValue {
|
||||
if (self.property) {
|
||||
return [self.property getValue:self.target];
|
||||
@@ -145,10 +130,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (id<FLEXMetadataAuxiliaryInfo>)auxiliaryInfoProvider {
|
||||
return self.ivar ?: self.property;
|
||||
}
|
||||
|
||||
- (const FLEXTypeEncoding *)typeEncoding {
|
||||
if (self.property) {
|
||||
return self.property.attributes.typeEncoding.UTF8String;
|
||||
|
||||
+13
-11
@@ -6,15 +6,17 @@
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UIBarButtonItem+FLEX.h"
|
||||
#import "CALayer+FLEX.h"
|
||||
#import "UIFont+FLEX.h"
|
||||
#import "UIGestureRecognizer+Blocks.h"
|
||||
#import "UIPasteboard+FLEX.h"
|
||||
#import "UIMenu+FLEX.h"
|
||||
#import "UITextField+Range.h"
|
||||
|
||||
#import "NSObject+FLEX_Reflection.h"
|
||||
#import "NSArray+FLEX.h"
|
||||
#import "NSUserDefaults+FLEX.h"
|
||||
#import "NSTimer+FLEX.h"
|
||||
|
||||
#import <UIBarButtonItem+FLEX.h>
|
||||
#import <CALayer+FLEX.h>
|
||||
#import <UIFont+FLEX.h>
|
||||
#import <UIGestureRecognizer+Blocks.h>
|
||||
#import <UIPasteboard+FLEX.h>
|
||||
#import <UIMenu+FLEX.h>
|
||||
#import <UITextField+Range.h>
|
||||
|
||||
#import <NSObject+FLEX_Reflection.h>
|
||||
#import <NSArray+FLEX.h>
|
||||
#import <NSUserDefaults+FLEX.h>
|
||||
#import <NSTimer+FLEX.h>
|
||||
|
||||
+11
-11
@@ -6,17 +6,17 @@
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXFilteringTableViewController.h"
|
||||
#import "FLEXNavigationController.h"
|
||||
#import "FLEXTableViewController.h"
|
||||
#import "FLEXTableView.h"
|
||||
#import <FLEXFilteringTableViewController.h>
|
||||
#import <FLEXNavigationController.h>
|
||||
#import <FLEXTableViewController.h>
|
||||
#import <FLEXTableView.h>
|
||||
|
||||
#import "FLEXSingleRowSection.h"
|
||||
#import "FLEXTableViewSection.h"
|
||||
#import <FLEXSingleRowSection.h>
|
||||
#import <FLEXTableViewSection.h>
|
||||
|
||||
#import "FLEXCodeFontCell.h"
|
||||
#import "FLEXSubtitleTableViewCell.h"
|
||||
#import "FLEXTableViewCell.h"
|
||||
#import "FLEXMultilineTableViewCell.h"
|
||||
#import "FLEXKeyValueTableViewCell.h"
|
||||
#import <FLEXCodeFontCell.h>
|
||||
#import <FLEXSubtitleTableViewCell.h>
|
||||
#import <FLEXTableViewCell.h>
|
||||
#import <FLEXMultilineTableViewCell.h>
|
||||
#import <FLEXKeyValueTableViewCell.h>
|
||||
|
||||
|
||||
@@ -6,17 +6,17 @@
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXObjectExplorerFactory.h"
|
||||
#import "FLEXObjectExplorerViewController.h"
|
||||
#import <FLEXObjectExplorerFactory.h>
|
||||
#import <FLEXObjectExplorerViewController.h>
|
||||
|
||||
#import "FLEXObjectExplorer.h"
|
||||
#import <FLEXObjectExplorer.h>
|
||||
|
||||
#import "FLEXShortcut.h"
|
||||
#import "FLEXShortcutsSection.h"
|
||||
#import <FLEXShortcut.h>
|
||||
#import <FLEXShortcutsSection.h>
|
||||
|
||||
#import "FLEXCollectionContentSection.h"
|
||||
#import "FLEXColorPreviewSection.h"
|
||||
#import "FLEXDefaultsContentSection.h"
|
||||
#import "FLEXMetadataSection.h"
|
||||
#import "FLEXMutableListSection.h"
|
||||
#import "FLEXObjectInfoSection.h"
|
||||
#import <FLEXCollectionContentSection.h>
|
||||
#import <FLEXColorPreviewSection.h>
|
||||
#import <FLEXDefaultsContentSection.h>
|
||||
#import <FLEXMetadataSection.h>
|
||||
#import <FLEXMutableListSection.h>
|
||||
#import <FLEXObjectInfoSection.h>
|
||||
|
||||
+16
-17
@@ -6,22 +6,21 @@
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXObjcInternal.h"
|
||||
#import "FLEXSwiftInternal.h"
|
||||
#import "FLEXRuntimeSafety.h"
|
||||
#import "FLEXBlockDescription.h"
|
||||
#import "FLEXTypeEncodingParser.h"
|
||||
#import <FLEXObjcInternal.h>
|
||||
#import <FLEXSwiftInternal.h>
|
||||
#import <FLEXRuntimeSafety.h>
|
||||
#import <FLEXBlockDescription.h>
|
||||
#import <FLEXTypeEncodingParser.h>
|
||||
|
||||
#import "FLEXMirror.h"
|
||||
#import "FLEXProtocol.h"
|
||||
#import "FLEXProperty.h"
|
||||
#import "FLEXIvar.h"
|
||||
#import "FLEXMethodBase.h"
|
||||
#import "FLEXMethod.h"
|
||||
#import "FLEXPropertyAttributes.h"
|
||||
#import "FLEXRuntime+Compare.h"
|
||||
#import "FLEXRuntime+UIKitHelpers.h"
|
||||
#import "FLEXMetadataExtras.h"
|
||||
#import <FLEXMirror.h>
|
||||
#import <FLEXProtocol.h>
|
||||
#import <FLEXProperty.h>
|
||||
#import <FLEXIvar.h>
|
||||
#import <FLEXMethodBase.h>
|
||||
#import <FLEXMethod.h>
|
||||
#import <FLEXPropertyAttributes.h>
|
||||
#import <FLEXRuntime+Compare.h>
|
||||
#import <FLEXRuntime+UIKitHelpers.h>
|
||||
|
||||
#import "FLEXProtocolBuilder.h"
|
||||
#import "FLEXClassBuilder.h"
|
||||
#import <FLEXProtocolBuilder.h>
|
||||
#import <FLEXClassBuilder.h>
|
||||
|
||||
+13
-13
@@ -7,19 +7,19 @@
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXManager.h"
|
||||
#import "FLEXManager+Extensibility.h"
|
||||
#import "FLEXManager+Networking.h"
|
||||
#import <FLEXManager.h>
|
||||
#import <FLEXManager+Extensibility.h>
|
||||
#import <FLEXManager+Networking.h>
|
||||
|
||||
#import "FLEXExplorerToolbar.h"
|
||||
#import "FLEXExplorerToolbarItem.h"
|
||||
#import "FLEXGlobalsEntry.h"
|
||||
#import <FLEXExplorerToolbar.h>
|
||||
#import <FLEXExplorerToolbarItem.h>
|
||||
#import <FLEXGlobalsEntry.h>
|
||||
|
||||
#import "FLEX-Core.h"
|
||||
#import "FLEX-Runtime.h"
|
||||
#import "FLEX-Categories.h"
|
||||
#import "FLEX-ObjectExploring.h"
|
||||
#import <FLEX-Core.h>
|
||||
#import <FLEX-Runtime.h>
|
||||
#import <FLEX-Categories.h>
|
||||
#import <FLEX-ObjectExploring.h>
|
||||
|
||||
#import "FLEXMacros.h"
|
||||
#import "FLEXAlert.h"
|
||||
#import "FLEXResources.h"
|
||||
#import <FLEXMacros.h>
|
||||
#import <FLEXAlert.h>
|
||||
#import <FLEXResources.h>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
@synthesize keyedRows = _keyedRows;
|
||||
|
||||
+ (instancetype)message:(NSString *)message {
|
||||
return [[self alloc] initWithMessage:message columns:nil rows:nil];
|
||||
return [[self alloc] initWithmessage:message columns:nil rows:nil];
|
||||
}
|
||||
|
||||
+ (instancetype)error:(NSString *)message {
|
||||
@@ -23,12 +23,12 @@
|
||||
}
|
||||
|
||||
+ (instancetype)columns:(NSArray<NSString *> *)columnNames rows:(NSArray<NSArray<NSString *> *> *)rowData {
|
||||
return [[self alloc] initWithMessage:nil columns:columnNames rows:rowData];
|
||||
return [[self alloc] initWithmessage:nil columns:columnNames rows:rowData];
|
||||
}
|
||||
|
||||
- (instancetype)initWithMessage:(NSString *)message columns:(NSArray<NSString *> *)columns rows:(NSArray<NSArray<NSString *> *> *)rows {
|
||||
- (id)initWithmessage:(NSString *)message columns:(NSArray *)columns rows:(NSArray<NSArray *> *)rows {
|
||||
NSParameterAssert(message || (columns && rows));
|
||||
NSParameterAssert(rows.count == 0 || columns.count == rows.firstObject.count);
|
||||
NSParameterAssert(columns.count == rows.firstObject.count);
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
@@ -12,10 +12,7 @@
|
||||
#import "FLEXRuntimeConstants.h"
|
||||
#import <sqlite3.h>
|
||||
|
||||
#define kQuery(name, str) static NSString * const QUERY_##name = str
|
||||
|
||||
kQuery(TABLENAMES, @"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name");
|
||||
kQuery(ROWIDS, @"SELECT rowid FROM \"%@\" ORDER BY rowid ASC");
|
||||
static NSString * const QUERY_TABLENAMES = @"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
|
||||
|
||||
@interface FLEXSQLiteDatabaseManager ()
|
||||
@property (nonatomic) sqlite3 *db;
|
||||
@@ -110,19 +107,7 @@ kQuery(ROWIDS, @"SELECT rowid FROM \"%@\" ORDER BY rowid ASC");
|
||||
- (NSArray<NSString *> *)queryAllColumnsOfTable:(NSString *)tableName {
|
||||
NSString *sql = [NSString stringWithFormat:@"PRAGMA table_info('%@')",tableName];
|
||||
FLEXSQLResult *results = [self executeStatement:sql];
|
||||
|
||||
// https://github.com/FLEXTool/FLEX/issues/554
|
||||
if (!results.keyedRows.count) {
|
||||
sql = [NSString stringWithFormat:@"SELECT * FROM pragma_table_info('%@')", tableName];
|
||||
results = [self executeStatement:sql];
|
||||
|
||||
// Fallback to empty query
|
||||
if (!results.keyedRows.count) {
|
||||
sql = [NSString stringWithFormat:@"SELECT * FROM \"%@\" where 0=1", tableName];
|
||||
return [self executeStatement:sql].columns ?: @[];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return [results.keyedRows flex_mapped:^id(NSDictionary *column, NSUInteger idx) {
|
||||
return column[@"name"];
|
||||
}] ?: @[];
|
||||
@@ -134,7 +119,7 @@ kQuery(ROWIDS, @"SELECT rowid FROM \"%@\" ORDER BY rowid ASC");
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)queryRowIDsInTable:(NSString *)tableName {
|
||||
NSString *command = [NSString stringWithFormat:QUERY_ROWIDS, tableName];
|
||||
NSString *command = [NSString stringWithFormat:@"SELECT rowid FROM \"%@\"", tableName];
|
||||
NSArray<NSArray<NSString *> *> *data = [self executeStatement:command].rows ?: @[];
|
||||
|
||||
return [data flex_mapped:^id(NSArray<NSString *> *obj, NSUInteger idx) {
|
||||
@@ -161,7 +146,7 @@ kQuery(ROWIDS, @"SELECT rowid FROM \"%@\" ORDER BY rowid ASC");
|
||||
return self.lastResult;
|
||||
}
|
||||
|
||||
// Grab columns (columnCount will be 0 for insert/update/delete)
|
||||
// Grab columns
|
||||
int columnCount = sqlite3_column_count(pstmt);
|
||||
NSArray<NSString *> *columns = [NSArray flex_forEachUpTo:columnCount map:^id(NSUInteger i) {
|
||||
return @(sqlite3_column_name(pstmt, (int)i));
|
||||
@@ -179,9 +164,8 @@ kQuery(ROWIDS, @"SELECT rowid FROM \"%@\" ORDER BY rowid ASC");
|
||||
}
|
||||
|
||||
if (status == SQLITE_DONE) {
|
||||
// columnCount will be 0 for insert/update/delete
|
||||
if (rows.count || columnCount > 0) {
|
||||
// We executed a SELECT query
|
||||
if (rows.count) {
|
||||
// We selected some rows
|
||||
result = _lastResult = [FLEXSQLResult columns:columns rows:rows];
|
||||
} else {
|
||||
// We executed a query like INSERT, UDPATE, or DELETE
|
||||
|
||||
@@ -13,23 +13,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FLEXTableContentViewController : UIViewController
|
||||
|
||||
/// Display a mutable table with the given columns, rows, and name.
|
||||
///
|
||||
/// @param columnNames self explanatory.
|
||||
/// @param rowData an array of rows, where each row is an array of column data.
|
||||
/// @param rowIDs an array of stringy row IDs. Required for deleting rows.
|
||||
/// @param tableName an optional name of the table being viewed, if any. Enables adding rows.
|
||||
/// Display a table with the given columns, rows, and name.
|
||||
/// @param databaseManager an optional manager to allow modifying the table.
|
||||
/// Required for deleting rows. Required for adding rows if \c tableName is supplied.
|
||||
+ (instancetype)columns:(NSArray<NSString *> *)columnNames
|
||||
rows:(NSArray<NSArray<NSString *> *> *)rowData
|
||||
rowIDs:(NSArray<NSString *> *)rowIDs
|
||||
rowIDs:(nullable NSArray<NSString *> *)rowIds
|
||||
tableName:(NSString *)tableName
|
||||
database:(id<FLEXDatabaseManager>)databaseManager;
|
||||
|
||||
/// Display an immutable table with the given columns and rows.
|
||||
+ (instancetype)columns:(NSArray<NSString *> *)columnNames
|
||||
rows:(NSArray<NSArray<NSString *> *> *)rowData;
|
||||
database:(nullable id<FLEXDatabaseManager>)databaseManager;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
//
|
||||
|
||||
#import "FLEXTableContentViewController.h"
|
||||
#import "FLEXTableRowDataViewController.h"
|
||||
#import "FLEXMultiColumnTableView.h"
|
||||
#import "FLEXWebViewController.h"
|
||||
#import "FLEXUtility.h"
|
||||
@@ -22,8 +21,6 @@
|
||||
@property (nonatomic, nullable) NSMutableArray<NSString *> *rowIDs;
|
||||
@property (nonatomic, readonly, nullable) id<FLEXDatabaseManager> databaseManager;
|
||||
|
||||
@property (nonatomic, readonly) BOOL canRefresh;
|
||||
|
||||
@property (nonatomic) FLEXMultiColumnTableView *multiColumnView;
|
||||
@end
|
||||
|
||||
@@ -31,43 +28,16 @@
|
||||
|
||||
+ (instancetype)columns:(NSArray<NSString *> *)columnNames
|
||||
rows:(NSArray<NSArray<NSString *> *> *)rowData
|
||||
rowIDs:(NSArray<NSString *> *)rowIDs
|
||||
rowIDs:(nullable NSArray<NSString *> *)rowIDs
|
||||
tableName:(NSString *)tableName
|
||||
database:(id<FLEXDatabaseManager>)databaseManager {
|
||||
return [[self alloc]
|
||||
initWithColumns:columnNames
|
||||
rows:rowData
|
||||
rowIDs:rowIDs
|
||||
tableName:tableName
|
||||
database:databaseManager
|
||||
];
|
||||
}
|
||||
|
||||
+ (instancetype)columns:(NSArray<NSString *> *)cols
|
||||
rows:(NSArray<NSArray<NSString *> *> *)rowData {
|
||||
return [[self alloc] initWithColumns:cols rows:rowData rowIDs:nil tableName:nil database:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithColumns:(NSArray<NSString *> *)columnNames
|
||||
rows:(NSArray<NSArray<NSString *> *> *)rowData
|
||||
rowIDs:(nullable NSArray<NSString *> *)rowIDs
|
||||
tableName:(nullable NSString *)tableName
|
||||
database:(nullable id<FLEXDatabaseManager>)databaseManager {
|
||||
// Must supply all optional parameters as one, or none
|
||||
BOOL all = rowIDs && tableName && databaseManager;
|
||||
BOOL none = !rowIDs && !tableName && !databaseManager;
|
||||
NSParameterAssert(all || none);
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self->_columns = columnNames.copy;
|
||||
self->_rows = rowData.mutableCopy;
|
||||
self->_rowIDs = rowIDs.mutableCopy;
|
||||
self->_tableName = tableName.copy;
|
||||
self->_databaseManager = databaseManager;
|
||||
}
|
||||
|
||||
return self;
|
||||
database:(nullable id<FLEXDatabaseManager>)databaseManager {
|
||||
FLEXTableContentViewController *controller = [self new];
|
||||
controller->_columns = columnNames.copy;
|
||||
controller->_rows = rowData.mutableCopy;
|
||||
controller->_rowIDs = rowIDs.mutableCopy;
|
||||
controller->_tableName = tableName.copy;
|
||||
controller->_databaseManager = databaseManager;
|
||||
return controller;
|
||||
}
|
||||
|
||||
- (void)loadView {
|
||||
@@ -79,6 +49,7 @@
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
self.title = self.tableName;
|
||||
self.edgesForExtendedLayout = UIRectEdgeNone;
|
||||
[self.multiColumnView reloadData];
|
||||
[self setupToolbarItems];
|
||||
}
|
||||
@@ -96,10 +67,6 @@
|
||||
return _multiColumnView;
|
||||
}
|
||||
|
||||
- (BOOL)canRefresh {
|
||||
return self.databaseManager && self.tableName;
|
||||
}
|
||||
|
||||
#pragma mark MultiColumnTableView DataSource
|
||||
|
||||
- (NSInteger)numberOfColumnsInTableView:(FLEXMultiColumnTableView *)tableView {
|
||||
@@ -155,10 +122,6 @@
|
||||
return [NSString stringWithFormat:@"%@:\n%@", self.columns[idx], field];
|
||||
}];
|
||||
|
||||
NSArray<NSString *> *values = [self.rows[row] flex_mapped:^id(NSString *value, NSUInteger idx) {
|
||||
return [NSString stringWithFormat:@"'%@'", value];
|
||||
}];
|
||||
|
||||
[FLEXAlert makeAlert:^(FLEXAlert *make) {
|
||||
make.title([@"Row " stringByAppendingString:@(row).stringValue]);
|
||||
NSString *message = [fields componentsJoinedByString:@"\n\n"];
|
||||
@@ -166,19 +129,10 @@
|
||||
make.button(@"Copy").handler(^(NSArray<NSString *> *strings) {
|
||||
UIPasteboard.generalPasteboard.string = message;
|
||||
});
|
||||
make.button(@"Copy as CSV").handler(^(NSArray<NSString *> *strings) {
|
||||
UIPasteboard.generalPasteboard.string = [values componentsJoinedByString:@", "];
|
||||
});
|
||||
make.button(@"Focus on Row").handler(^(NSArray<NSString *> *strings) {
|
||||
UIViewController *focusedRow = [FLEXTableRowDataViewController
|
||||
rows:[NSDictionary dictionaryWithObjects:self.rows[row] forKeys:self.columns]
|
||||
];
|
||||
[self.navigationController pushViewController:focusedRow animated:YES];
|
||||
});
|
||||
|
||||
// Option to delete row
|
||||
BOOL hasRowID = self.rows.count && row < self.rows.count;
|
||||
if (hasRowID && self.canRefresh) {
|
||||
if (hasRowID) {
|
||||
make.button(@"Delete").destructiveStyle().handler(^(NSArray<NSString *> *strings) {
|
||||
NSString *deleteRow = [NSString stringWithFormat:
|
||||
@"DELETE FROM %@ WHERE rowid = %@",
|
||||
@@ -188,7 +142,9 @@
|
||||
[self executeStatementAndShowResult:deleteRow completion:^(BOOL success) {
|
||||
// Remove deleted row and reload view
|
||||
if (success) {
|
||||
[self reloadTableDataFromDB];
|
||||
[self.rowIDs removeObjectAtIndex:row];
|
||||
[self.rows removeObjectAtIndex:row];
|
||||
[self.multiColumnView reloadData];
|
||||
}
|
||||
}];
|
||||
});
|
||||
@@ -260,24 +216,14 @@
|
||||
return;
|
||||
}
|
||||
|
||||
UIBarButtonItem *trashButton = FLEXBarButtonItemSystem(Trash, self, @selector(trashPressed));
|
||||
UIBarButtonItem *addButton = FLEXBarButtonItemSystem(Add, self, @selector(addPressed));
|
||||
|
||||
// Only allow adding rows or deleting rows if we have a table name
|
||||
trashButton.enabled = self.canRefresh;
|
||||
addButton.enabled = self.canRefresh;
|
||||
|
||||
self.toolbarItems = @[
|
||||
UIBarButtonItem.flex_flexibleSpace,
|
||||
addButton,
|
||||
UIBarButtonItem.flex_flexibleSpace,
|
||||
[trashButton flex_withTintColor:UIColor.redColor],
|
||||
UIBarButtonItem *trashButton = [FLEXBarButtonItemSystem(Trash, self, @selector(trashPressed))
|
||||
flex_withTintColor:UIColor.redColor
|
||||
];
|
||||
trashButton.enabled = self.databaseManager && self.rows.count;
|
||||
self.toolbarItems = @[UIBarButtonItem.flex_flexibleSpace, trashButton];
|
||||
}
|
||||
|
||||
- (void)trashPressed {
|
||||
NSParameterAssert(self.tableName);
|
||||
|
||||
[FLEXAlert makeAlert:^(FLEXAlert *make) {
|
||||
make.title(@"Delete All Rows");
|
||||
make.message(@"All rows in this table will be permanently deleted.\nDo you want to proceed?");
|
||||
@@ -295,35 +241,9 @@
|
||||
} showFrom:self];
|
||||
}
|
||||
|
||||
- (void)addPressed {
|
||||
NSParameterAssert(self.tableName);
|
||||
|
||||
[FLEXAlert makeAlert:^(FLEXAlert *make) {
|
||||
make.title(@"Add a New Row");
|
||||
make.message(@"Comma separate values to use in an INSERT statement.\n\n");
|
||||
make.message(@"INSERT INTO [table] VALUES (your_input)");
|
||||
make.textField(@"5, 'John Smith', 14,...");
|
||||
make.button(@"Insert").handler(^(NSArray<NSString *> *strings) {
|
||||
NSString *statement = [NSString stringWithFormat:
|
||||
@"INSERT INTO %@ VALUES (%@)", self.tableName, strings[0]
|
||||
];
|
||||
|
||||
[self executeStatementAndShowResult:statement completion:^(BOOL success) {
|
||||
if (success) {
|
||||
[self reloadTableDataFromDB];
|
||||
}
|
||||
}];
|
||||
});
|
||||
make.button(@"Cancel").cancelStyle();
|
||||
} showFrom:self];
|
||||
}
|
||||
|
||||
#pragma mark - Helpers
|
||||
|
||||
- (void)executeStatementAndShowResult:(NSString *)statement
|
||||
completion:(void (^_Nullable)(BOOL success))completion {
|
||||
NSParameterAssert(self.databaseManager);
|
||||
|
||||
- (void)executeStatementAndShowResult:(NSString *)statement completion:(void (^_Nullable)(BOOL success))completion {
|
||||
FLEXSQLResult *result = [self.databaseManager executeStatement:statement];
|
||||
|
||||
[FLEXAlert makeAlert:^(FLEXAlert *make) {
|
||||
@@ -340,20 +260,5 @@
|
||||
} showFrom:self];
|
||||
}
|
||||
|
||||
- (void)reloadTableDataFromDB {
|
||||
if (!self.canRefresh) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray<NSArray *> *rows = [self.databaseManager queryAllDataInTable:self.tableName];
|
||||
NSArray<NSString *> *rowIDs = nil;
|
||||
if ([self.databaseManager respondsToSelector:@selector(queryRowIDsInTable:)]) {
|
||||
rowIDs = [self.databaseManager queryRowIDsInTable:self.tableName];
|
||||
}
|
||||
|
||||
self.rows = rows.mutableCopy;
|
||||
self.rowIDs = rowIDs.mutableCopy;
|
||||
[self.multiColumnView reloadData];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
[FLEXAlert showAlert:@"Message" message:result.message from:self];
|
||||
} else {
|
||||
UIViewController *resultsScreen = [FLEXTableContentViewController
|
||||
columns:result.columns rows:result.rows
|
||||
columns:result.columns rows:result.rows rowIDs:nil tableName:@"" database:nil
|
||||
];
|
||||
|
||||
[self.navigationController pushViewController:resultsScreen animated:YES];
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
//
|
||||
// FLEXTableRowDataViewController.h
|
||||
// FLEX
|
||||
//
|
||||
// Created by Chaoshuai Lu on 7/8/20.
|
||||
//
|
||||
|
||||
#import "FLEXFilteringTableViewController.h"
|
||||
|
||||
@interface FLEXTableRowDataViewController : FLEXFilteringTableViewController
|
||||
|
||||
+ (instancetype)rows:(NSDictionary<NSString *, id> *)rowData;
|
||||
|
||||
@end
|
||||
@@ -1,54 +0,0 @@
|
||||
//
|
||||
// FLEXTableRowDataViewController.m
|
||||
// FLEX
|
||||
//
|
||||
// Created by Chaoshuai Lu on 7/8/20.
|
||||
//
|
||||
|
||||
#import "FLEXTableRowDataViewController.h"
|
||||
#import "FLEXMutableListSection.h"
|
||||
#import "FLEXAlert.h"
|
||||
|
||||
@interface FLEXTableRowDataViewController ()
|
||||
@property (nonatomic) NSDictionary<NSString *, NSString *> *rowsByColumn;
|
||||
@end
|
||||
|
||||
@implementation FLEXTableRowDataViewController
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
+ (instancetype)rows:(NSDictionary<NSString *, id> *)rowData {
|
||||
FLEXTableRowDataViewController *controller = [self new];
|
||||
controller.rowsByColumn = rowData;
|
||||
return controller;
|
||||
}
|
||||
|
||||
#pragma mark - Overrides
|
||||
|
||||
- (NSArray<FLEXTableViewSection *> *)makeSections {
|
||||
NSDictionary<NSString *, NSString *> *rowsByColumn = self.rowsByColumn;
|
||||
|
||||
FLEXMutableListSection<NSString *> *section = [FLEXMutableListSection list:self.rowsByColumn.allKeys
|
||||
cellConfiguration:^(UITableViewCell *cell, NSString *column, NSInteger row) {
|
||||
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
||||
cell.textLabel.text = column;
|
||||
cell.detailTextLabel.text = rowsByColumn[column].description;
|
||||
} filterMatcher:^BOOL(NSString *filterText, NSString *column) {
|
||||
return [column localizedCaseInsensitiveContainsString:filterText] ||
|
||||
[rowsByColumn[column] localizedCaseInsensitiveContainsString:filterText];
|
||||
}
|
||||
];
|
||||
|
||||
section.selectionHandler = ^(UIViewController *host, NSString *column) {
|
||||
UIPasteboard.generalPasteboard.string = rowsByColumn[column].description;
|
||||
[FLEXAlert makeAlert:^(FLEXAlert *make) {
|
||||
make.title(@"Column Copied to Clipboard");
|
||||
make.message(rowsByColumn[column].description);
|
||||
make.button(@"Dismiss").cancelStyle();
|
||||
} showFrom:host];
|
||||
};
|
||||
|
||||
return @[section];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -213,7 +213,7 @@ typedef NS_ENUM(NSUInteger, FLEXObjectReferenceSection) {
|
||||
}];
|
||||
}
|
||||
|
||||
- (FLEXMutableListSection *)makeSection:(NSArray *)rows title:(NSString *)title {
|
||||
- (FLEXMutableListSection *)makeSection:(NSArray *)rows title:(NSString *)title { weakify(self)
|
||||
FLEXMutableListSection *section = [FLEXMutableListSection list:rows
|
||||
cellConfiguration:^(FLEXTableViewCell *cell, FLEXObjectRef *ref, NSInteger row) {
|
||||
cell.textLabel.text = ref.reference;
|
||||
@@ -228,8 +228,8 @@ typedef NS_ENUM(NSUInteger, FLEXObjectReferenceSection) {
|
||||
}
|
||||
];
|
||||
|
||||
section.selectionHandler = ^(UIViewController *host, FLEXObjectRef *ref) {
|
||||
[host.navigationController pushViewController:[
|
||||
section.selectionHandler = ^(UIViewController *host, FLEXObjectRef *ref) { strongify(self)
|
||||
[self.navigationController pushViewController:[
|
||||
FLEXObjectExplorerFactory explorerViewControllerForObject:ref.object
|
||||
] animated:YES];
|
||||
};
|
||||
|
||||
@@ -38,26 +38,9 @@
|
||||
self = [self initWithNibName:nil bundle:nil];
|
||||
if (self) {
|
||||
self.originalText = text;
|
||||
|
||||
NSString *html = @"<head><style>:root{ color-scheme: light dark; }</style>"
|
||||
"<meta name='viewport' content='initial-scale=1.0'></head><body><pre>%@</pre></body>";
|
||||
|
||||
// Loading message for when input text takes a long time to escape
|
||||
NSString *loadingMessage = [NSString stringWithFormat:html, @"Loading..."];
|
||||
[self.webView loadHTMLString:loadingMessage baseURL:nil];
|
||||
|
||||
// Escape HTML on a background thread
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
NSString *escapedText = [FLEXUtility stringByEscapingHTMLEntitiesInString:text];
|
||||
NSString *htmlString = [NSString stringWithFormat:html, escapedText];
|
||||
|
||||
// Update webview on the main thread
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.webView loadHTMLString:htmlString baseURL:nil];
|
||||
});
|
||||
});
|
||||
NSString *htmlString = [NSString stringWithFormat:@"<head><style>:root{ color-scheme: light dark; }</style><meta name='viewport' content='initial-scale=1.0'></head><body><pre>%@</pre></body>", [FLEXUtility stringByEscapingHTMLEntitiesInString:text]];
|
||||
[self.webView loadHTMLString:htmlString baseURL:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -67,10 +50,16 @@
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:url];
|
||||
[self.webView loadRequest:request];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
// WKWebView's delegate is assigned so we need to clear it manually.
|
||||
if (_webView.navigationDelegate == self) {
|
||||
_webView.navigationDelegate = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
@@ -79,9 +68,7 @@
|
||||
self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
|
||||
if (self.originalText.length > 0) {
|
||||
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]
|
||||
initWithTitle:@"Copy" style:UIBarButtonItemStylePlain target:self action:@selector(copyButtonTapped:)
|
||||
];
|
||||
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Copy" style:UIBarButtonItemStylePlain target:self action:@selector(copyButtonTapped:)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,23 +79,20 @@
|
||||
|
||||
#pragma mark - WKWebView Delegate
|
||||
|
||||
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
|
||||
decisionHandler:(void (^)(WKNavigationActionPolicy))handler {
|
||||
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
|
||||
WKNavigationActionPolicy policy = WKNavigationActionPolicyCancel;
|
||||
if (navigationAction.navigationType == WKNavigationTypeOther) {
|
||||
// Allow the initial load
|
||||
policy = WKNavigationActionPolicyAllow;
|
||||
} else {
|
||||
// For clicked links, push another web view controller onto the navigation stack
|
||||
// so that hitting the back button works as expected.
|
||||
// For clicked links, push another web view controller onto the navigation stack so that hitting the back button works as expected.
|
||||
// Don't allow the current web view to handle the navigation.
|
||||
NSURLRequest *request = navigationAction.request;
|
||||
FLEXWebViewController *webVC = [[[self class] alloc] initWithURL:request.URL];
|
||||
webVC.title = request.URL.absoluteString;
|
||||
FLEXWebViewController *webVC = [[[self class] alloc] initWithURL:[request URL]];
|
||||
webVC.title = [[request URL] absoluteString];
|
||||
[self.navigationController pushViewController:webVC animated:YES];
|
||||
}
|
||||
|
||||
handler(policy);
|
||||
decisionHandler(policy);
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +101,7 @@
|
||||
+ (BOOL)supportsPathExtension:(NSString *)extension {
|
||||
BOOL supported = NO;
|
||||
NSSet<NSString *> *supportedExtensions = [self webViewSupportedPathExtensions];
|
||||
if ([supportedExtensions containsObject:extension.lowercaseString]) {
|
||||
if ([supportedExtensions containsObject:[extension lowercaseString]]) {
|
||||
supported = YES;
|
||||
}
|
||||
return supported;
|
||||
@@ -129,14 +113,11 @@
|
||||
dispatch_once(&onceToken, ^{
|
||||
// Note that this is not exhaustive, but all these extensions should work well in the web view.
|
||||
// See https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html#//apple_ref/doc/uid/TP40006482-SW7
|
||||
pathExtensions = [NSSet<NSString *> setWithArray:@[
|
||||
@"jpg", @"jpeg", @"png", @"gif", @"pdf", @"svg", @"tiff", @"3gp", @"3gpp", @"3g2",
|
||||
@"3gp2", @"aiff", @"aif", @"aifc", @"cdda", @"amr", @"mp3", @"swa", @"mp4", @"mpeg",
|
||||
@"mpg", @"mp3", @"wav", @"bwf", @"m4a", @"m4b", @"m4p", @"mov", @"qt", @"mqv", @"m4v"
|
||||
]];
|
||||
pathExtensions = [NSSet<NSString *> setWithArray:@[@"jpg", @"jpeg", @"png", @"gif", @"pdf", @"svg", @"tiff", @"3gp", @"3gpp", @"3g2",
|
||||
@"3gp2", @"aiff", @"aif", @"aifc", @"cdda", @"amr", @"mp3", @"swa", @"mp4", @"mpeg",
|
||||
@"mpg", @"mp3", @"wav", @"bwf", @"m4a", @"m4b", @"m4p", @"mov", @"qt", @"mqv", @"m4v"]];
|
||||
|
||||
});
|
||||
|
||||
return pathExtensions;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ static BOOL my_os_log_shim_enabled(void *addr) {
|
||||
[super viewDidLoad];
|
||||
|
||||
self.showsSearchBar = YES;
|
||||
self.pinSearchBar = YES;
|
||||
self.showSearchBarInitially = NO;
|
||||
|
||||
weakify(self)
|
||||
id logHandler = ^(NSArray<FLEXSystemLogMessage *> *newMessages) { strongify(self)
|
||||
@@ -175,15 +175,9 @@ static BOOL my_os_log_shim_enabled(void *addr) {
|
||||
[self.logMessages mutate:^(NSMutableArray *list) {
|
||||
[list addObjectsFromArray:newMessages];
|
||||
}];
|
||||
|
||||
// Re-filter messages to filter against new messages
|
||||
if (self.filterText.length) {
|
||||
[self updateSearchResults:self.filterText];
|
||||
}
|
||||
|
||||
// "Follow" the log as new messages stream in if we were previously near the bottom.
|
||||
UITableView *tv = self.tableView;
|
||||
BOOL wasNearBottom = tv.contentOffset.y >= tv.contentSize.height - tv.frame.size.height - 100.0;
|
||||
BOOL wasNearBottom = self.tableView.contentOffset.y >= self.tableView.contentSize.height - self.tableView.frame.size.height - 100.0;
|
||||
[self reloadData];
|
||||
if (wasNearBottom) {
|
||||
[self scrollToLastRow];
|
||||
@@ -193,8 +187,8 @@ static BOOL my_os_log_shim_enabled(void *addr) {
|
||||
- (void)scrollToLastRow {
|
||||
NSInteger numberOfRows = [self.tableView numberOfRowsInSection:0];
|
||||
if (numberOfRows > 0) {
|
||||
NSIndexPath *last = [NSIndexPath indexPathForRow:numberOfRows - 1 inSection:0];
|
||||
[self.tableView scrollToRowAtIndexPath:last atScrollPosition:UITableViewScrollPositionBottom animated:YES];
|
||||
NSIndexPath *lastIndexPath = [NSIndexPath indexPathForRow:numberOfRows - 1 inSection:0];
|
||||
[self.tableView scrollToRowAtIndexPath:lastIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../Classes/Utility/Runtime/Objc/Reflection/FLEXMetadataExtras.h
|
||||
@@ -0,0 +1,8 @@
|
||||
module FLEX {
|
||||
umbrella header "FLEX.h"
|
||||
|
||||
link "flex"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
@@ -52,11 +52,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/// Removes all registered global entries.
|
||||
- (void)clearGlobalEntries;
|
||||
|
||||
#pragma mark - Editing
|
||||
|
||||
/// Enable displaying ivar names for custom struct types
|
||||
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding;
|
||||
|
||||
#pragma mark - Simulator Shortcuts
|
||||
|
||||
/// Simulator keyboard shortcuts are enabled by default.
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#import "FLEXNetworkMITMViewController.h"
|
||||
#import "FLEXKeyboardHelpViewController.h"
|
||||
#import "FLEXFileBrowserController.h"
|
||||
#import "FLEXArgumentInputStructView.h"
|
||||
#import "FLEXUtility.h"
|
||||
|
||||
@interface FLEXManager (ExtensibilityPrivate)
|
||||
@@ -76,13 +75,6 @@
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Editing
|
||||
|
||||
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding {
|
||||
[FLEXArgumentInputStructView registerFieldNames:names forTypeEncoding:typeEncoding];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Simulator Shortcuts
|
||||
|
||||
- (void)registerSimulatorShortcutWithKey:(NSString *)key modifiers:(UIKeyModifierFlags)modifiers action:(dispatch_block_t)action description:(NSString *)description {
|
||||
|
||||
@@ -1,303 +0,0 @@
|
||||
//
|
||||
// FLEXFirebaseTransaction.m
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 12/24/21.
|
||||
//
|
||||
|
||||
#import "FLEXNetworkTransaction.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import <dlfcn.h>
|
||||
#include <string>
|
||||
|
||||
typedef std::string (*ReturnsString)(void *);
|
||||
|
||||
@implementation FLEXFirebaseSetDataInfo
|
||||
|
||||
+ (instancetype)data:(NSDictionary *)data merge:(NSNumber *)merge mergeFields:(NSArray *)mergeFields {
|
||||
NSParameterAssert(data);
|
||||
NSParameterAssert(merge || mergeFields);
|
||||
|
||||
FLEXFirebaseSetDataInfo *info = [self new];
|
||||
info->_documentData = data;
|
||||
info->_merge = merge;
|
||||
info->_mergeFields = mergeFields;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static NSString *FLEXStringFromFIRRequestType(FLEXFIRRequestType type) {
|
||||
switch (type) {
|
||||
case FLEXFIRRequestTypeNotFirebase:
|
||||
return @"not firebase";
|
||||
case FLEXFIRRequestTypeFetchQuery:
|
||||
return @"query fetch";
|
||||
case FLEXFIRRequestTypeFetchDocument:
|
||||
return @"document fetch";
|
||||
case FLEXFIRRequestTypeSetData:
|
||||
return @"set data";
|
||||
case FLEXFIRRequestTypeUpdateData:
|
||||
return @"update data";
|
||||
case FLEXFIRRequestTypeAddDocument:
|
||||
return @"create";
|
||||
case FLEXFIRRequestTypeDeleteDocument:
|
||||
return @"delete";
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
static FLEXFIRTransactionDirection FIRDirectionFromRequestType(FLEXFIRRequestType type) {
|
||||
switch (type) {
|
||||
case FLEXFIRRequestTypeNotFirebase:
|
||||
return FLEXFIRTransactionDirectionNone;
|
||||
case FLEXFIRRequestTypeFetchQuery:
|
||||
case FLEXFIRRequestTypeFetchDocument:
|
||||
return FLEXFIRTransactionDirectionPull;
|
||||
case FLEXFIRRequestTypeSetData:
|
||||
case FLEXFIRRequestTypeUpdateData:
|
||||
case FLEXFIRRequestTypeAddDocument:
|
||||
case FLEXFIRRequestTypeDeleteDocument:
|
||||
return FLEXFIRTransactionDirectionPush;
|
||||
}
|
||||
|
||||
return FLEXFIRTransactionDirectionNone;
|
||||
}
|
||||
|
||||
@interface FLEXFirebaseTransaction ()
|
||||
@property (nonatomic) id extraData;
|
||||
@property (nonatomic, readonly) NSString *queryDescription;
|
||||
@end
|
||||
|
||||
@implementation FLEXFirebaseTransaction
|
||||
@synthesize queryDescription = _queryDescription;
|
||||
|
||||
+ (instancetype)initiator:(id)initiator requestType:(FLEXFIRRequestType)type extraData:(id)data {
|
||||
FLEXFirebaseTransaction *fire = [FLEXFirebaseTransaction withStartTime:NSDate.date];
|
||||
fire->_direction = FIRDirectionFromRequestType(type);
|
||||
fire->_initiator = initiator;
|
||||
fire->_requestType = type;
|
||||
fire->_extraData = data;
|
||||
return fire;
|
||||
}
|
||||
|
||||
+ (instancetype)queryFetch:(FIRQuery *)initiator {
|
||||
return [self initiator:initiator requestType:FLEXFIRRequestTypeFetchQuery extraData:nil];
|
||||
}
|
||||
|
||||
+ (instancetype)documentFetch:(FIRDocumentReference *)initiator {
|
||||
return [self initiator:initiator requestType:FLEXFIRRequestTypeFetchDocument extraData:nil];
|
||||
}
|
||||
|
||||
+ (instancetype)setData:(FIRDocumentReference *)initiator data:(NSDictionary *)data
|
||||
merge:(NSNumber *)merge mergeFields:(NSArray *)mergeFields {
|
||||
|
||||
FLEXFirebaseSetDataInfo *info = [FLEXFirebaseSetDataInfo data:data merge:merge mergeFields:mergeFields];
|
||||
return [self initiator:initiator requestType:FLEXFIRRequestTypeSetData extraData:info];
|
||||
}
|
||||
|
||||
+ (instancetype)updateData:(FIRDocumentReference *)initiator data:(NSDictionary *)data {
|
||||
return [self initiator:initiator requestType:FLEXFIRRequestTypeUpdateData extraData:data];
|
||||
}
|
||||
|
||||
+ (instancetype)addDocument:(FIRCollectionReference *)initiator document:(FIRDocumentReference *)doc {
|
||||
return [self initiator:initiator requestType:FLEXFIRRequestTypeAddDocument extraData:doc];
|
||||
}
|
||||
|
||||
+ (instancetype)deleteDocument:(FIRDocumentReference *)initiator {
|
||||
return [self initiator:initiator requestType:FLEXFIRRequestTypeDeleteDocument extraData:nil];
|
||||
}
|
||||
|
||||
- (NSString *)queryDescription {
|
||||
if (_queryDescription) {
|
||||
return _queryDescription;
|
||||
}
|
||||
|
||||
// Grab C++ symbol to describe FIRQuery.query
|
||||
static ReturnsString firebase_firestore_core_query_tostring = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
// Is Firebase available?
|
||||
if (NSClassFromString(@"FIRDocumentReference")) {
|
||||
firebase_firestore_core_query_tostring = (ReturnsString)dlsym(
|
||||
RTLD_DEFAULT, "_ZNK8firebase9firestore4core5Query8ToStringEv"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
if (!firebase_firestore_core_query_tostring) {
|
||||
return @"nil";
|
||||
}
|
||||
|
||||
FIRQuery *query = self.initiator_query;
|
||||
if (!query) return nil;
|
||||
|
||||
void *core_query = query.query;
|
||||
std::string description = firebase_firestore_core_query_tostring(core_query);
|
||||
|
||||
// Query strings are like 'Query(canonical_id=...)' so I remove the leading part, and the ()
|
||||
NSString *prefix = @"Query(canonical_id=";
|
||||
NSString *desc = @(description.c_str());
|
||||
desc = [desc stringByReplacingOccurrencesOfString:prefix withString:@""];
|
||||
desc = [desc stringByReplacingCharactersInRange:NSMakeRange(desc.length-1, 1) withString:@""];
|
||||
|
||||
_queryDescription = desc;
|
||||
return _queryDescription;
|
||||
}
|
||||
|
||||
- (FIRDocumentReference *)initiator_doc {
|
||||
if ([_initiator isKindOfClass:cFIRDocumentReference]) {
|
||||
return _initiator;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
- (FIRQuery *)initiator_query {
|
||||
if ([_initiator isKindOfClass:cFIRQuery]) {
|
||||
return _initiator;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (FIRCollectionReference *)initiator_collection {
|
||||
if ([_initiator isKindOfClass:cFIRCollectionReference]) {
|
||||
return _initiator;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (FLEXFirebaseSetDataInfo *)setDataInfo {
|
||||
if (self.requestType == FLEXFIRRequestTypeSetData) {
|
||||
return self.extraData;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSDictionary *)updateData {
|
||||
if (self.requestType == FLEXFIRRequestTypeUpdateData) {
|
||||
return self.extraData;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSString *)path {
|
||||
switch (self.direction) {
|
||||
case FLEXFIRTransactionDirectionNone:
|
||||
return nil;
|
||||
case FLEXFIRTransactionDirectionPush:
|
||||
case FLEXFIRTransactionDirectionPull: {
|
||||
switch (self.requestType) {
|
||||
case FLEXFIRRequestTypeNotFirebase:
|
||||
@throw NSInternalInconsistencyException;
|
||||
|
||||
case FLEXFIRRequestTypeFetchQuery:
|
||||
case FLEXFIRRequestTypeAddDocument:
|
||||
return self.initiator_collection.path ?: self.queryDescription;
|
||||
case FLEXFIRRequestTypeFetchDocument:
|
||||
case FLEXFIRRequestTypeSetData:
|
||||
case FLEXFIRRequestTypeUpdateData:
|
||||
case FLEXFIRRequestTypeDeleteDocument:
|
||||
return self.initiator_doc.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSString *)primaryDescription {
|
||||
if (!_primaryDescription) {
|
||||
_primaryDescription = self.path.lastPathComponent;
|
||||
}
|
||||
|
||||
return _primaryDescription;
|
||||
}
|
||||
|
||||
- (NSString *)secondaryDescription {
|
||||
if (!_secondaryDescription) {
|
||||
_secondaryDescription = self.path.stringByDeletingLastPathComponent;
|
||||
}
|
||||
|
||||
return _secondaryDescription;
|
||||
}
|
||||
|
||||
- (NSString *)tertiaryDescription {
|
||||
if (!_tertiaryDescription) {
|
||||
NSMutableArray<NSString *> *detailComponents = [NSMutableArray new];
|
||||
|
||||
NSString *timestamp = [self timestampStringFromRequestDate:self.startTime];
|
||||
if (timestamp.length > 0) {
|
||||
[detailComponents addObject:timestamp];
|
||||
}
|
||||
|
||||
[detailComponents addObject:self.direction == FLEXFIRTransactionDirectionPush ?
|
||||
@"Push ↑" : @"Pull ↓"
|
||||
];
|
||||
|
||||
if (self.direction == FLEXFIRTransactionDirectionPush) {
|
||||
[detailComponents addObjectsFromArray:@[FLEXStringFromFIRRequestType(self.requestType)]];
|
||||
}
|
||||
|
||||
if (self.state == FLEXNetworkTransactionStateFinished || self.state == FLEXNetworkTransactionStateFailed) {
|
||||
if (self.direction == FLEXFIRTransactionDirectionPull) {
|
||||
NSString *docCount = [NSString stringWithFormat:@"%@ document(s)", @(self.documents.count)];
|
||||
[detailComponents addObjectsFromArray:@[docCount]];
|
||||
}
|
||||
} else {
|
||||
// Unstarted, Awaiting Response, Receiving Data, etc.
|
||||
NSString *state = [self.class readableStringFromTransactionState:self.state];
|
||||
[detailComponents addObject:state];
|
||||
}
|
||||
|
||||
_tertiaryDescription = [detailComponents componentsJoinedByString:@" ・ "];
|
||||
}
|
||||
|
||||
return _tertiaryDescription;
|
||||
}
|
||||
|
||||
- (NSString *)copyString {
|
||||
return self.path;
|
||||
}
|
||||
|
||||
- (BOOL)matchesQuery:(NSString *)filterString {
|
||||
if ([self.path localizedCaseInsensitiveContainsString:filterString]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
BOOL isPull = self.direction == FLEXFIRTransactionDirectionPull;
|
||||
BOOL isPush = self.direction == FLEXFIRTransactionDirectionPush;
|
||||
|
||||
// Allow filtering for push or pull directly
|
||||
if (isPull && [filterString localizedCaseInsensitiveCompare:@"pull"] == NSOrderedSame) {
|
||||
return YES;
|
||||
}
|
||||
if (isPush && [filterString localizedCaseInsensitiveCompare:@"push"] == NSOrderedSame) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
//- (NSString *)responseString {
|
||||
// if (!_responseString) {
|
||||
// _responseString = [NSString stringWithUTF8String:(char *)self.response.bytes];
|
||||
// }
|
||||
//
|
||||
// return _responseString;
|
||||
//}
|
||||
//
|
||||
//- (NSDictionary *)responseObject {
|
||||
// if (!_responseObject) {
|
||||
// _responseObject = [NSJSONSerialization JSONObjectWithData:self.response options:0 error:nil];
|
||||
// }
|
||||
//
|
||||
// return _responseObject;
|
||||
//}
|
||||
|
||||
@end
|
||||
@@ -13,21 +13,22 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
+ (instancetype)dataSourceWithProvider:(NSArray<TransactionType> *(^)(void))future;
|
||||
|
||||
/// Whether or not the data in \c transactions and \c bytesReceived are actually filtered yet or not
|
||||
@property (nonatomic, readonly) BOOL isFiltered;
|
||||
|
||||
/// The content of this array is filtered to match the input of \c filter:completion:
|
||||
@property (nonatomic, readonly) NSArray<TransactionType> *transactions;
|
||||
@property (nonatomic, readonly) NSArray<TransactionType> *allTransactions;
|
||||
/// Equal to \c allTransactions if not filtered
|
||||
@property (nonatomic, readonly) NSArray<TransactionType> *filteredTransactions;
|
||||
|
||||
/// The content of this array is filtered to match the input of \c filter:completion:
|
||||
/// Use this instead of either of the other two as it updates based on whether we have a filter or not
|
||||
@property (nonatomic) NSInteger bytesReceived;
|
||||
@property (nonatomic) NSInteger totalBytesReceived;
|
||||
/// Equal to \c totalBytesReceived if not filtered
|
||||
@property (nonatomic) NSInteger filteredBytesReceived;
|
||||
|
||||
- (void)reloadByteCounts;
|
||||
- (void)reloadData:(void (^_Nullable)(FLEXMITMDataSource *dataSource))completion;
|
||||
- (void)filter:(NSString *)searchString completion:(void(^_Nullable)(FLEXMITMDataSource *dataSource))completion;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -24,8 +24,12 @@
|
||||
return ds;
|
||||
}
|
||||
|
||||
- (BOOL)isFiltered {
|
||||
return self.filterString.length > 0;
|
||||
- (NSArray *)transactions {
|
||||
return _filteredTransactions;
|
||||
}
|
||||
|
||||
- (NSInteger)bytesReceived {
|
||||
return _filteredBytesReceived;
|
||||
}
|
||||
|
||||
- (void)reloadByteCounts {
|
||||
@@ -45,9 +49,8 @@
|
||||
self.filteredTransactions = self.allTransactions;
|
||||
if (completion) completion(self);
|
||||
} else {
|
||||
NSArray<FLEXNetworkTransaction *> *allTransactions = self.allTransactions.copy;
|
||||
[self onBackgroundQueue:^NSArray *{
|
||||
return [allTransactions flex_filtered:^BOOL(FLEXNetworkTransaction *entry, NSUInteger idx) {
|
||||
return [self.allTransactions flex_filtered:^BOOL(FLEXNetworkTransaction *entry, NSUInteger idx) {
|
||||
return [entry matchesQuery:searchString];
|
||||
}];
|
||||
} thenOnMainQueue:^(NSArray *filteredNetworkTransactions) {
|
||||
@@ -60,20 +63,15 @@
|
||||
}
|
||||
|
||||
- (void)setAllTransactions:(NSArray *)transactions {
|
||||
_allTransactions = transactions.copy;
|
||||
_allTransactions = transactions;
|
||||
[self updateBytesReceived];
|
||||
}
|
||||
|
||||
/// This is really just a semantic setter for \c _transactions
|
||||
- (void)setFilteredTransactions:(NSArray *)filteredTransactions {
|
||||
_transactions = filteredTransactions.copy;
|
||||
_filteredTransactions = filteredTransactions;
|
||||
[self updateFilteredBytesReceived];
|
||||
}
|
||||
|
||||
- (void)setTransactions:(NSArray *)transactions {
|
||||
self.filteredTransactions = transactions;
|
||||
}
|
||||
|
||||
- (void)updateBytesReceived {
|
||||
NSInteger bytesReceived = 0;
|
||||
for (FLEXNetworkTransaction *transaction in self.transactions) {
|
||||
@@ -85,11 +83,11 @@
|
||||
|
||||
- (void)updateFilteredBytesReceived {
|
||||
NSInteger filteredBytesReceived = 0;
|
||||
for (FLEXNetworkTransaction *transaction in self.transactions) {
|
||||
for (FLEXNetworkTransaction *transaction in self.filteredTransactions) {
|
||||
filteredBytesReceived += transaction.receivedDataLength;
|
||||
}
|
||||
|
||||
self.bytesReceived = filteredBytesReceived;
|
||||
self.filteredBytesReceived = filteredBytesReceived;
|
||||
}
|
||||
|
||||
- (void)onBackgroundQueue:(NSArray *(^)(void))backgroundBlock thenOnMainQueue:(void(^)(NSArray *))mainBlock {
|
||||
|
||||
@@ -21,14 +21,9 @@
|
||||
#import "FLEXWebViewController.h"
|
||||
#import "UIBarButtonItem+FLEX.h"
|
||||
#import "FLEXResources.h"
|
||||
#import "NSUserDefaults+FLEX.h"
|
||||
|
||||
#define kFirebaseAvailable NSClassFromString(@"FIRDocumentReference")
|
||||
#define kWebsocketsAvailable @available(iOS 13.0, *)
|
||||
|
||||
typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
FLEXNetworkObserverModeFirebase = 0,
|
||||
FLEXNetworkObserverModeREST,
|
||||
typedef NS_ENUM(NSUInteger, FLEXNetworkObserverMode) {
|
||||
FLEXNetworkObserverModeREST = 0,
|
||||
FLEXNetworkObserverModeWebsockets,
|
||||
};
|
||||
|
||||
@@ -37,12 +32,11 @@ typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
@property (nonatomic) BOOL updateInProgress;
|
||||
@property (nonatomic) BOOL pendingReload;
|
||||
|
||||
@property (nonatomic) FLEXNetworkObserverMode mode;
|
||||
@property (nonatomic, readonly) FLEXNetworkObserverMode mode;
|
||||
|
||||
@property (nonatomic, readonly) FLEXMITMDataSource<FLEXNetworkTransaction *> *dataSource;
|
||||
@property (nonatomic, readonly) FLEXMITMDataSource<FLEXHTTPTransaction *> *HTTPDataSource;
|
||||
@property (nonatomic, readonly) FLEXMITMDataSource<FLEXWebsocketTransaction *> *websocketDataSource;
|
||||
@property (nonatomic, readonly) FLEXMITMDataSource<FLEXFirebaseTransaction *> *firebaseDataSource;
|
||||
|
||||
@end
|
||||
|
||||
@@ -58,33 +52,20 @@ typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
[super viewDidLoad];
|
||||
|
||||
self.showsSearchBar = YES;
|
||||
self.pinSearchBar = YES;
|
||||
self.showSearchBarInitially = NO;
|
||||
NSMutableArray *scopeTitles = [NSMutableArray arrayWithObject:@"REST"];
|
||||
|
||||
_HTTPDataSource = [FLEXMITMDataSource dataSourceWithProvider:^NSArray * {
|
||||
return FLEXNetworkRecorder.defaultRecorder.HTTPTransactions;
|
||||
}];
|
||||
|
||||
if (kFirebaseAvailable) {
|
||||
_firebaseDataSource = [FLEXMITMDataSource dataSourceWithProvider:^NSArray * {
|
||||
return FLEXNetworkRecorder.defaultRecorder.firebaseTransactions;
|
||||
}];
|
||||
[scopeTitles insertObject:@"Firebase" atIndex:0]; // First space
|
||||
}
|
||||
|
||||
if (kWebsocketsAvailable) {
|
||||
[scopeTitles addObject:@"Websockets"]; // Last space
|
||||
|
||||
if (@available(iOS 13.0, *)) {
|
||||
self.searchController.searchBar.showsScopeBar = YES;
|
||||
self.searchController.searchBar.scopeButtonTitles = @[@"REST", @"Websockets"];
|
||||
_websocketDataSource = [FLEXMITMDataSource dataSourceWithProvider:^NSArray * {
|
||||
return FLEXNetworkRecorder.defaultRecorder.websocketTransactions;
|
||||
}];
|
||||
}
|
||||
|
||||
// Scopes will only be shown if we have either firebase or websockets available
|
||||
self.searchController.searchBar.showsScopeBar = scopeTitles.count > 1;
|
||||
self.searchController.searchBar.scopeButtonTitles = scopeTitles;
|
||||
self.mode = NSUserDefaults.standardUserDefaults.flex_lastNetworkObserverMode;
|
||||
|
||||
[self addToolbarItems:@[
|
||||
[UIBarButtonItem
|
||||
flex_itemWithImage:FLEXResources.gearIcon
|
||||
@@ -161,23 +142,12 @@ typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
|
||||
- (void)trashButtonTapped:(UIBarButtonItem *)sender {
|
||||
[FLEXAlert makeSheet:^(FLEXAlert *make) {
|
||||
BOOL clearAll = !self.dataSource.isFiltered;
|
||||
if (!clearAll) {
|
||||
make.title(@"Clear Filtered Requests?");
|
||||
make.message(@"This will only remove the requests matching your search string on this screen.");
|
||||
} else {
|
||||
make.title(@"Clear All Recorded Requests?");
|
||||
make.message(@"This cannot be undone.");
|
||||
}
|
||||
make.title(@"Clear All Recorded Requests?");
|
||||
make.message(@"This cannot be undone.");
|
||||
|
||||
make.button(@"Cancel").cancelStyle();
|
||||
make.button(@"Clear").destructiveStyle().handler(^(NSArray *strings) {
|
||||
if (clearAll) {
|
||||
[FLEXNetworkRecorder.defaultRecorder clearRecordedActivity];
|
||||
} else {
|
||||
FLEXNetworkTransactionKind kind = (FLEXNetworkTransactionKind)self.mode;
|
||||
[FLEXNetworkRecorder.defaultRecorder clearRecordedActivity:kind matching:self.searchText];
|
||||
}
|
||||
make.button(@"Clear All").destructiveStyle().handler(^(NSArray *strings) {
|
||||
[FLEXNetworkRecorder.defaultRecorder clearRecordedActivity];
|
||||
});
|
||||
} showFrom:self source:sender];
|
||||
}
|
||||
@@ -190,72 +160,7 @@ typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
#pragma mark Transactions
|
||||
|
||||
- (FLEXNetworkObserverMode)mode {
|
||||
FLEXNetworkObserverMode mode = self.searchController.searchBar.selectedScopeButtonIndex;
|
||||
switch (mode) {
|
||||
case FLEXNetworkObserverModeFirebase:
|
||||
if (kFirebaseAvailable) {
|
||||
return FLEXNetworkObserverModeFirebase;
|
||||
}
|
||||
|
||||
return FLEXNetworkObserverModeREST;
|
||||
case FLEXNetworkObserverModeREST:
|
||||
if (kFirebaseAvailable) {
|
||||
return FLEXNetworkObserverModeREST;
|
||||
}
|
||||
|
||||
return FLEXNetworkObserverModeWebsockets;
|
||||
case FLEXNetworkObserverModeWebsockets:
|
||||
return FLEXNetworkObserverModeWebsockets;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setMode:(FLEXNetworkObserverMode)mode {
|
||||
// The segmentd control will have different appearances based on which APIs
|
||||
// are available. For example, when only Websockets is available:
|
||||
//
|
||||
// 0 1
|
||||
// ┌───────────────────────────┬────────────────────────────┐
|
||||
// │ REST │ Websockets │
|
||||
// └───────────────────────────┴────────────────────────────┘
|
||||
//
|
||||
// And when both Firebase and Websockets are available:
|
||||
//
|
||||
// 0 1 2
|
||||
// ┌──────────────────┬──────────────────┬──────────────────┐
|
||||
// │ Firebase │ REST │ Websockets │
|
||||
// └──────────────────┴──────────────────┴──────────────────┘
|
||||
//
|
||||
// As a result, we need to adjust the input mode variable accordingly
|
||||
// before we actually set it. When we try to set it to Firebase but
|
||||
// Firebase is not available, we don't do anything, because when Firebase
|
||||
// is unavailable, FLEXNetworkObserverModeFirebase represents the same index
|
||||
// as REST would without Firebase. For each of the others, we subtract 1
|
||||
// from them for every relevant API that is unavailable. So for Websockets,
|
||||
// if it is unavailable, we subtract 1 and it becomes FLEXNetworkObserverModeREST.
|
||||
// And if Firebase is also unavailable, we subtract 1 again.
|
||||
|
||||
switch (mode) {
|
||||
case FLEXNetworkObserverModeFirebase:
|
||||
// Will default to REST if Firebase is unavailable
|
||||
break;
|
||||
case FLEXNetworkObserverModeREST:
|
||||
// Firebase will become REST when Firebase is unavailable
|
||||
if (!kFirebaseAvailable) {
|
||||
mode--;
|
||||
}
|
||||
break;
|
||||
case FLEXNetworkObserverModeWebsockets:
|
||||
// Default to REST if Websockets are unavailable
|
||||
if (!kWebsocketsAvailable) {
|
||||
mode--;
|
||||
}
|
||||
// Firebase will become REST when Firebase is unavailable
|
||||
if (!kFirebaseAvailable) {
|
||||
mode--;
|
||||
}
|
||||
}
|
||||
|
||||
self.searchController.searchBar.selectedScopeButtonIndex = mode;
|
||||
return self.searchController.searchBar.selectedScopeButtonIndex;
|
||||
}
|
||||
|
||||
- (FLEXMITMDataSource<FLEXNetworkTransaction *> *)dataSource {
|
||||
@@ -264,8 +169,9 @@ typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
return self.HTTPDataSource;
|
||||
case FLEXNetworkObserverModeWebsockets:
|
||||
return self.websocketDataSource;
|
||||
case FLEXNetworkObserverModeFirebase:
|
||||
return self.firebaseDataSource;
|
||||
|
||||
default:
|
||||
@throw NSInternalInconsistencyException;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +184,6 @@ typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
|
||||
[self.HTTPDataSource reloadData:completion];
|
||||
[self.websocketDataSource reloadData:completion];
|
||||
[self.firebaseDataSource reloadData:completion];
|
||||
}
|
||||
|
||||
|
||||
@@ -294,21 +199,20 @@ typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
}
|
||||
|
||||
- (NSString *)headerText {
|
||||
long long bytesReceived = self.dataSource.bytesReceived;
|
||||
NSInteger totalRequests = self.dataSource.transactions.count;
|
||||
long long bytesReceived = 0;
|
||||
NSInteger totalRequests = 0;
|
||||
if (self.searchController.isActive) {
|
||||
bytesReceived = self.dataSource.filteredBytesReceived;
|
||||
totalRequests = self.dataSource.transactions.count;
|
||||
} else {
|
||||
bytesReceived = self.dataSource.bytesReceived;
|
||||
totalRequests = self.dataSource.transactions.count;
|
||||
}
|
||||
|
||||
NSString *byteCountText = [NSByteCountFormatter
|
||||
stringFromByteCount:bytesReceived countStyle:NSByteCountFormatterCountStyleBinary
|
||||
];
|
||||
NSString *requestsText = totalRequests == 1 ? @"Request" : @"Requests";
|
||||
|
||||
// Exclude byte count from Firebase
|
||||
if (self.mode == FLEXNetworkObserverModeFirebase) {
|
||||
return [NSString stringWithFormat:@"%@ %@",
|
||||
@(totalRequests), requestsText
|
||||
];
|
||||
}
|
||||
|
||||
return [NSString stringWithFormat:@"%@ %@ (%@ received)",
|
||||
@(totalRequests), requestsText, byteCountText
|
||||
];
|
||||
@@ -428,7 +332,6 @@ typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
- (void)handleTransactionUpdatedNotification:(NSNotification *)notification {
|
||||
[self.HTTPDataSource reloadByteCounts];
|
||||
[self.websocketDataSource reloadByteCounts];
|
||||
// Don't need to reload Firebase here
|
||||
|
||||
FLEXNetworkTransaction *transaction = notification.userInfo[kFLEXNetworkRecorderUserInfoTransactionKey];
|
||||
|
||||
@@ -518,13 +421,9 @@ typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FLEXNetworkObserverModeFirebase: {
|
||||
FLEXFirebaseTransaction *transaction = [self firebaseTransactionAtIndexPath:indexPath];
|
||||
// id obj = transaction.documents.count == 1 ? transaction.documents.firstObject : transaction.documents;
|
||||
UIViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:transaction];
|
||||
[self.navigationController pushViewController:explorer animated:YES];
|
||||
}
|
||||
|
||||
default:
|
||||
@throw NSInternalInconsistencyException;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,9 +500,6 @@ typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
return self.websocketDataSource.transactions[indexPath.row];
|
||||
}
|
||||
|
||||
- (FLEXFirebaseTransaction *)firebaseTransactionAtIndexPath:(NSIndexPath *)indexPath {
|
||||
return self.firebaseDataSource.transactions[indexPath.row];
|
||||
}
|
||||
|
||||
#pragma mark - Search Bar
|
||||
|
||||
@@ -616,14 +512,11 @@ typedef NS_ENUM(NSInteger, FLEXNetworkObserverMode) {
|
||||
|
||||
[self.HTTPDataSource filter:searchString completion:callback];
|
||||
[self.websocketDataSource filter:searchString completion:callback];
|
||||
[self.firebaseDataSource filter:searchString completion:callback];
|
||||
}
|
||||
|
||||
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)newScope {
|
||||
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope {
|
||||
[self updateFirstSectionHeader];
|
||||
[self.tableView reloadData];
|
||||
|
||||
NSUserDefaults.standardUserDefaults.flex_lastNetworkObserverMode = self.mode;
|
||||
}
|
||||
|
||||
- (void)willDismissSearchController:(UISearchController *)searchController {
|
||||
|
||||
@@ -14,14 +14,7 @@ extern NSString *const kFLEXNetworkRecorderTransactionUpdatedNotification;
|
||||
extern NSString *const kFLEXNetworkRecorderUserInfoTransactionKey;
|
||||
extern NSString *const kFLEXNetworkRecorderTransactionsClearedNotification;
|
||||
|
||||
@class FLEXNetworkTransaction, FLEXHTTPTransaction, FLEXWebsocketTransaction, FLEXFirebaseTransaction;
|
||||
@class FIRQuery, FIRDocumentReference, FIRCollectionReference, FIRDocumentSnapshot, FIRQuerySnapshot;
|
||||
|
||||
typedef NS_ENUM(NSUInteger, FLEXNetworkTransactionKind) {
|
||||
FLEXNetworkTransactionKindFirebase = 0,
|
||||
FLEXNetworkTransactionKindREST,
|
||||
FLEXNetworkTransactionKindWebsockets,
|
||||
};
|
||||
@class FLEXNetworkTransaction, FLEXHTTPTransaction, FLEXWebsocketTransaction;
|
||||
|
||||
@interface FLEXNetworkRecorder : NSObject
|
||||
|
||||
@@ -50,8 +43,6 @@ typedef NS_ENUM(NSUInteger, FLEXNetworkTransactionKind) {
|
||||
@property (nonatomic, readonly) NSArray<FLEXHTTPTransaction *> *HTTPTransactions;
|
||||
/// Array of FLEXWebsocketTransaction objects ordered by start time with the newest first.
|
||||
@property (nonatomic, readonly) NSArray<FLEXWebsocketTransaction *> *websocketTransactions API_AVAILABLE(ios(13.0));
|
||||
/// Array of FLEXFirebaseTransaction objects ordered by start time with the newest first.
|
||||
@property (nonatomic, readonly) NSArray<FLEXFirebaseTransaction *> *firebaseTransactions;
|
||||
|
||||
/// The full response data IFF it hasn't been purged due to memory pressure.
|
||||
- (NSData *)cachedResponseBodyForTransaction:(FLEXHTTPTransaction *)transaction;
|
||||
@@ -59,9 +50,6 @@ typedef NS_ENUM(NSUInteger, FLEXNetworkTransactionKind) {
|
||||
/// Dumps all network transactions and cached response bodies.
|
||||
- (void)clearRecordedActivity;
|
||||
|
||||
/// Clear only transactions matching the given query.
|
||||
- (void)clearRecordedActivity:(FLEXNetworkTransactionKind)kind matching:(NSString *)query;
|
||||
|
||||
|
||||
#pragma mark Recording network activity
|
||||
|
||||
@@ -94,29 +82,4 @@ typedef NS_ENUM(NSUInteger, FLEXNetworkTransactionKind) {
|
||||
- (void)recordWebsocketMessageReceived:(NSURLSessionWebSocketMessage *)message
|
||||
task:(NSURLSessionWebSocketTask *)task API_AVAILABLE(ios(13.0));
|
||||
|
||||
- (void)recordFIRQueryWillFetch:(FIRQuery *)query withTransactionID:(NSString *)transactionID;
|
||||
- (void)recordFIRDocumentWillFetch:(FIRDocumentReference *)document withTransactionID:(NSString *)transactionID;
|
||||
|
||||
- (void)recordFIRQueryDidFetch:(FIRQuerySnapshot *)response error:(NSError *)error
|
||||
transactionID:(NSString *)transactionID;
|
||||
- (void)recordFIRDocumentDidFetch:(FIRDocumentSnapshot *)response error:(NSError *)error
|
||||
transactionID:(NSString *)transactionID;
|
||||
|
||||
- (void)recordFIRWillSetData:(FIRDocumentReference *)doc
|
||||
data:(NSDictionary *)documentData
|
||||
merge:(NSNumber *)yesorno
|
||||
mergeFields:(NSArray *)fields
|
||||
transactionID:(NSString *)transactionID;
|
||||
- (void)recordFIRWillUpdateData:(FIRDocumentReference *)doc fields:(NSDictionary *)fields
|
||||
transactionID:(NSString *)transactionID;
|
||||
- (void)recordFIRWillDeleteDocument:(FIRDocumentReference *)doc transactionID:(NSString *)transactionID;
|
||||
- (void)recordFIRWillAddDocument:(FIRCollectionReference *)initiator
|
||||
document:(FIRDocumentReference *)doc
|
||||
transactionID:(NSString *)transactionID;
|
||||
|
||||
- (void)recordFIRDidSetData:(NSError *)error transactionID:(NSString *)transactionID;
|
||||
- (void)recordFIRDidUpdateData:(NSError *)error transactionID:(NSString *)transactionID;
|
||||
- (void)recordFIRDidDeleteDocument:(NSError *)error transactionID:(NSString *)transactionID;
|
||||
- (void)recordFIRDidAddDocument:(NSError *)error transactionID:(NSString *)transactionID;
|
||||
|
||||
@end
|
||||
|
||||
@@ -24,10 +24,9 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
@interface FLEXNetworkRecorder ()
|
||||
|
||||
@property (nonatomic) OSCache *restCache;
|
||||
@property (atomic) NSMutableArray<FLEXHTTPTransaction *> *orderedHTTPTransactions;
|
||||
@property (atomic) NSMutableArray<FLEXWebsocketTransaction *> *orderedWSTransactions;
|
||||
@property (atomic) NSMutableArray<FLEXFirebaseTransaction *> *orderedFirebaseTransactions;
|
||||
@property (atomic) NSMutableDictionary<NSString *, __kindof FLEXNetworkTransaction *> *requestIDsToTransactions;
|
||||
@property (nonatomic) NSMutableArray<FLEXHTTPTransaction *> *orderedHTTPTransactions;
|
||||
@property (nonatomic) NSMutableArray<FLEXWebsocketTransaction *> *orderedWSTransactions;
|
||||
@property (nonatomic) NSMutableDictionary<NSString *, FLEXHTTPTransaction *> *requestIDsToHTTPTransactions;
|
||||
@property (nonatomic) dispatch_queue_t queue;
|
||||
|
||||
@end
|
||||
@@ -48,8 +47,7 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
|
||||
self.orderedWSTransactions = [NSMutableArray new];
|
||||
self.orderedHTTPTransactions = [NSMutableArray new];
|
||||
self.orderedFirebaseTransactions = [NSMutableArray new];
|
||||
self.requestIDsToTransactions = [NSMutableDictionary new];
|
||||
self.requestIDsToHTTPTransactions = [NSMutableDictionary new];
|
||||
self.hostDenylist = NSUserDefaults.standardUserDefaults.flex_networkHostDenylist.mutableCopy;
|
||||
|
||||
// Serial queue used because we use mutable objects that are not thread safe
|
||||
@@ -91,10 +89,6 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
return self.orderedWSTransactions.copy;
|
||||
}
|
||||
|
||||
- (NSArray<FLEXFirebaseTransaction *> *)firebaseTransactions {
|
||||
return self.orderedFirebaseTransactions.copy;
|
||||
}
|
||||
|
||||
- (NSData *)cachedResponseBodyForTransaction:(FLEXHTTPTransaction *)transaction {
|
||||
return [self.restCache objectForKey:transaction.requestID];
|
||||
}
|
||||
@@ -104,45 +98,7 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
[self.restCache removeAllObjects];
|
||||
[self.orderedWSTransactions removeAllObjects];
|
||||
[self.orderedHTTPTransactions removeAllObjects];
|
||||
[self.orderedFirebaseTransactions removeAllObjects];
|
||||
[self.requestIDsToTransactions removeAllObjects];
|
||||
|
||||
[self notify:kFLEXNetworkRecorderTransactionsClearedNotification transaction:nil];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)clearRecordedActivity:(FLEXNetworkTransactionKind)kind matching:(NSString *)query {
|
||||
dispatch_async(self.queue, ^{
|
||||
switch (kind) {
|
||||
case FLEXNetworkTransactionKindFirebase: {
|
||||
[self.orderedFirebaseTransactions flex_filter:^BOOL(FLEXFirebaseTransaction *obj, NSUInteger idx) {
|
||||
return ![obj matchesQuery:query];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case FLEXNetworkTransactionKindREST: {
|
||||
NSArray<FLEXHTTPTransaction *> *toRemove;
|
||||
toRemove = [self.orderedHTTPTransactions flex_filtered:^BOOL(FLEXHTTPTransaction *obj, NSUInteger idx) {
|
||||
return [obj matchesQuery:query];
|
||||
}];
|
||||
|
||||
// Remove from cache
|
||||
for (FLEXHTTPTransaction *t in toRemove) {
|
||||
[self.restCache removeObjectForKey:t.requestID];
|
||||
}
|
||||
|
||||
// Remove from list
|
||||
[self.orderedHTTPTransactions removeObjectsInArray:toRemove];
|
||||
|
||||
break;
|
||||
}
|
||||
case FLEXNetworkTransactionKindWebsockets: {
|
||||
[self.orderedWSTransactions flex_filter:^BOOL(FLEXWebsocketTransaction *obj, NSUInteger idx) {
|
||||
return ![obj matchesQuery:query];
|
||||
}];
|
||||
break;
|
||||
}
|
||||
}
|
||||
[self.requestIDsToHTTPTransactions removeAllObjects];
|
||||
|
||||
[self notify:kFLEXNetworkRecorderTransactionsClearedNotification transaction:nil];
|
||||
});
|
||||
@@ -188,10 +144,10 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
[self recordLoadingFinishedWithRequestID:requestID responseBody:nil];
|
||||
}
|
||||
|
||||
// A redirect is always a new request
|
||||
dispatch_async(self.queue, ^{
|
||||
[self.orderedHTTPTransactions insertObject:transaction atIndex:0];
|
||||
self.requestIDsToTransactions[requestID] = transaction;
|
||||
[self.requestIDsToHTTPTransactions setObject:transaction forKey:requestID];
|
||||
transaction.transactionState = FLEXNetworkTransactionStateAwaitingResponse;
|
||||
|
||||
[self postNewTransactionNotificationWithTransaction:transaction];
|
||||
});
|
||||
@@ -202,13 +158,13 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
NSDate *responseDate = [NSDate date];
|
||||
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXHTTPTransaction *transaction = self.requestIDsToTransactions[requestID];
|
||||
FLEXHTTPTransaction *transaction = self.requestIDsToHTTPTransactions[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
transaction.response = response;
|
||||
transaction.state = FLEXNetworkTransactionStateReceivingData;
|
||||
transaction.transactionState = FLEXNetworkTransactionStateReceivingData;
|
||||
transaction.latency = -[transaction.startTime timeIntervalSinceDate:responseDate];
|
||||
|
||||
[self postUpdateNotificationForTransaction:transaction];
|
||||
@@ -217,7 +173,7 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
|
||||
- (void)recordDataReceivedWithRequestID:(NSString *)requestID dataLength:(int64_t)dataLength {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXHTTPTransaction *transaction = self.requestIDsToTransactions[requestID];
|
||||
FLEXHTTPTransaction *transaction = self.requestIDsToHTTPTransactions[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
@@ -231,12 +187,12 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
NSDate *finishedDate = [NSDate date];
|
||||
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXHTTPTransaction *transaction = self.requestIDsToTransactions[requestID];
|
||||
FLEXHTTPTransaction *transaction = self.requestIDsToHTTPTransactions[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
transaction.state = FLEXNetworkTransactionStateFinished;
|
||||
transaction.transactionState = FLEXNetworkTransactionStateFinished;
|
||||
transaction.duration = -[transaction.startTime timeIntervalSinceDate:finishedDate];
|
||||
|
||||
BOOL shouldCache = responseBody.length > 0;
|
||||
@@ -290,12 +246,12 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
|
||||
- (void)recordLoadingFailedWithRequestID:(NSString *)requestID error:(NSError *)error {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXHTTPTransaction *transaction = self.requestIDsToTransactions[requestID];
|
||||
FLEXHTTPTransaction *transaction = self.requestIDsToHTTPTransactions[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
transaction.state = FLEXNetworkTransactionStateFailed;
|
||||
transaction.transactionState = FLEXNetworkTransactionStateFailed;
|
||||
transaction.duration = -[transaction.startTime timeIntervalSinceNow];
|
||||
transaction.error = error;
|
||||
|
||||
@@ -305,7 +261,7 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
|
||||
- (void)recordMechanism:(NSString *)mechanism forRequestID:(NSString *)requestID {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXHTTPTransaction *transaction = self.requestIDsToTransactions[requestID];
|
||||
FLEXHTTPTransaction *transaction = self.requestIDsToHTTPTransactions[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
@@ -323,7 +279,7 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
withMessage:message task:task direction:FLEXWebsocketOutgoing
|
||||
];
|
||||
|
||||
[self.orderedWSTransactions insertObject:send atIndex:0];
|
||||
[self.orderedWSTransactions addObject:send];
|
||||
[self postNewTransactionNotificationWithTransaction:send];
|
||||
});
|
||||
}
|
||||
@@ -334,7 +290,7 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
return t.message == message;
|
||||
}];
|
||||
send.error = error;
|
||||
send.state = error ? FLEXNetworkTransactionStateFailed : FLEXNetworkTransactionStateFinished;
|
||||
send.transactionState = error ? FLEXNetworkTransactionStateFailed : FLEXNetworkTransactionStateFinished;
|
||||
|
||||
[self postUpdateNotificationForTransaction:send];
|
||||
});
|
||||
@@ -346,137 +302,12 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
withMessage:message task:task direction:FLEXWebsocketIncoming
|
||||
];
|
||||
|
||||
[self.orderedWSTransactions insertObject:receive atIndex:0];
|
||||
[self.orderedWSTransactions addObject:receive];
|
||||
[self postNewTransactionNotificationWithTransaction:receive];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Firebase, Reading
|
||||
|
||||
- (void)recordFIRQueryWillFetch:(FIRQuery *)query withTransactionID:(NSString *)transactionID {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction queryFetch:query];
|
||||
self.requestIDsToTransactions[transactionID] = transaction;
|
||||
[self postNewTransactionNotificationWithTransaction:transaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)recordFIRDocumentWillFetch:(FIRDocumentReference *)document withTransactionID:(NSString *)transactionID {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction documentFetch:document];
|
||||
self.requestIDsToTransactions[transactionID] = transaction;
|
||||
[self postNewTransactionNotificationWithTransaction:transaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)recordFIRQueryDidFetch:(FIRQuerySnapshot *)response error:(NSError *)error transactionID:(NSString *)transactionID {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXFirebaseTransaction *transaction = self.requestIDsToTransactions[transactionID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
transaction.error = error;
|
||||
transaction.documents = response.documents;
|
||||
transaction.state = FLEXNetworkTransactionStateFinished;
|
||||
[self.orderedFirebaseTransactions insertObject:transaction atIndex:0];
|
||||
|
||||
[self postUpdateNotificationForTransaction:transaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)recordFIRDocumentDidFetch:(FIRDocumentSnapshot *)response error:(NSError *)error transactionID:(NSString *)transactionID {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXFirebaseTransaction *transaction = self.requestIDsToTransactions[transactionID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
transaction.error = error;
|
||||
transaction.documents = response ? @[response] : @[];
|
||||
transaction.state = FLEXNetworkTransactionStateFinished;
|
||||
[self.orderedFirebaseTransactions insertObject:transaction atIndex:0];
|
||||
|
||||
[self postUpdateNotificationForTransaction:transaction];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark Firebase, Writing
|
||||
|
||||
- (void)recordFIRWillSetData:(FIRDocumentReference *)doc
|
||||
data:(NSDictionary *)documentData
|
||||
merge:(NSNumber *)yesorno
|
||||
mergeFields:(NSArray *)fields
|
||||
transactionID:(NSString *)transactionID {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction
|
||||
setData:doc data:documentData merge:yesorno mergeFields:fields
|
||||
];
|
||||
self.requestIDsToTransactions[transactionID] = transaction;
|
||||
[self postNewTransactionNotificationWithTransaction:transaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)recordFIRWillUpdateData:(FIRDocumentReference *)doc fields:(NSDictionary *)fields
|
||||
transactionID:(NSString *)transactionID {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction updateData:doc data:fields];
|
||||
self.requestIDsToTransactions[transactionID] = transaction;
|
||||
[self postNewTransactionNotificationWithTransaction:transaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)recordFIRWillDeleteDocument:(FIRDocumentReference *)doc transactionID:(NSString *)transactionID {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction deleteDocument:doc];
|
||||
self.requestIDsToTransactions[transactionID] = transaction;
|
||||
[self postNewTransactionNotificationWithTransaction:transaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)recordFIRWillAddDocument:(FIRCollectionReference *)initiator document:(FIRDocumentReference *)doc
|
||||
transactionID:(NSString *)transactionID {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXFirebaseTransaction *transaction = [FLEXFirebaseTransaction
|
||||
addDocument:initiator document:doc
|
||||
];
|
||||
self.requestIDsToTransactions[transactionID] = transaction;
|
||||
[self postNewTransactionNotificationWithTransaction:transaction];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)recordFIRDidSetData:(NSError *)error transactionID:(NSString *)transactionID {
|
||||
[self firebaseTransaction:transactionID didUpdate:error];
|
||||
}
|
||||
|
||||
- (void)recordFIRDidUpdateData:(NSError *)error transactionID:(NSString *)transactionID {
|
||||
[self firebaseTransaction:transactionID didUpdate:error];
|
||||
}
|
||||
|
||||
- (void)recordFIRDidDeleteDocument:(NSError *)error transactionID:(NSString *)transactionID {
|
||||
[self firebaseTransaction:transactionID didUpdate:error];
|
||||
}
|
||||
|
||||
- (void)recordFIRDidAddDocument:(NSError *)error transactionID:(NSString *)transactionID {
|
||||
[self firebaseTransaction:transactionID didUpdate:error];
|
||||
}
|
||||
|
||||
- (void)firebaseTransaction:(NSString *)transactionID didUpdate:(NSError *)error {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXFirebaseTransaction *transaction = self.requestIDsToTransactions[transactionID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
transaction.error = error;
|
||||
transaction.state = FLEXNetworkTransactionStateFinished;
|
||||
[self.orderedFirebaseTransactions insertObject:transaction atIndex:0];
|
||||
|
||||
[self postUpdateNotificationForTransaction:transaction];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Notification Posting
|
||||
#pragma mark Notification Posting
|
||||
|
||||
- (void)postNewTransactionNotificationWithTransaction:(FLEXNetworkTransaction *)transaction {
|
||||
[self notify:kFLEXNetworkRecorderNewTransactionNotification transaction:transaction];
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "Firestore.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UIKit/UIKit.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, FLEXNetworkTransactionState) {
|
||||
FLEXNetworkTransactionStateUnstarted = -1,
|
||||
/// This is the default; it's usually nonsense for a request to be marked as "unstarted"
|
||||
FLEXNetworkTransactionStateAwaitingResponse = 0,
|
||||
FLEXNetworkTransactionStateUnstarted,
|
||||
FLEXNetworkTransactionStateAwaitingResponse,
|
||||
FLEXNetworkTransactionStateReceivingData,
|
||||
FLEXNetworkTransactionStateFinished,
|
||||
FLEXNetworkTransactionStateFailed
|
||||
@@ -25,13 +24,7 @@ typedef NS_ENUM(NSUInteger, FLEXWebsocketMessageDirection) {
|
||||
|
||||
/// The shared base class for all types of network transactions.
|
||||
/// Subclasses should implement the descriptions and details properties, and assign a thumbnail.
|
||||
@interface FLEXNetworkTransaction : NSObject {
|
||||
@protected
|
||||
|
||||
NSString *_primaryDescription;
|
||||
NSString *_secondaryDescription;
|
||||
NSString *_tertiaryDescription;
|
||||
}
|
||||
@interface FLEXNetworkTransaction : NSObject
|
||||
|
||||
+ (instancetype)withStartTime:(NSDate *)startTime;
|
||||
|
||||
@@ -42,7 +35,7 @@ typedef NS_ENUM(NSUInteger, FLEXWebsocketMessageDirection) {
|
||||
@property (nonatomic, readonly) BOOL displayAsError;
|
||||
@property (nonatomic, readonly) NSDate *startTime;
|
||||
|
||||
@property (nonatomic) FLEXNetworkTransactionState state;
|
||||
@property (nonatomic) FLEXNetworkTransactionState transactionState;
|
||||
@property (nonatomic) int64_t receivedDataLength;
|
||||
/// A small thumbnail to preview the type of/the response
|
||||
@property (nonatomic) UIImage *thumbnail;
|
||||
@@ -55,15 +48,15 @@ typedef NS_ENUM(NSUInteger, FLEXWebsocketMessageDirection) {
|
||||
/// Minor details to display at the bottom of the cell, such as a timestamp, HTTP method, or status.
|
||||
@property (nonatomic, readonly) NSString *tertiaryDescription;
|
||||
|
||||
/// Subclasses should implement for when the transaction is complete
|
||||
@property (nonatomic, readonly) NSArray<NSString *> *details;
|
||||
|
||||
/// The string to copy when the user selects the "copy" action
|
||||
@property (nonatomic, readonly) NSString *copyString;
|
||||
|
||||
/// Whether or not this request should show up when the user searches for a given string
|
||||
- (BOOL)matchesQuery:(NSString *)filterString;
|
||||
|
||||
/// For internal use
|
||||
- (NSString *)timestampStringFromRequestDate:(NSDate *)date;
|
||||
|
||||
@end
|
||||
|
||||
/// The shared base class for all NSURL-API-related transactions.
|
||||
@@ -73,8 +66,6 @@ typedef NS_ENUM(NSUInteger, FLEXWebsocketMessageDirection) {
|
||||
+ (instancetype)withRequest:(NSURLRequest *)request startTime:(NSDate *)startTime;
|
||||
|
||||
@property (nonatomic, readonly) NSURLRequest *request;
|
||||
/// Subclasses should implement for when the transaction is complete
|
||||
@property (nonatomic, readonly) NSArray<NSString *> *details;
|
||||
|
||||
@end
|
||||
|
||||
@@ -114,65 +105,3 @@ typedef NS_ENUM(NSUInteger, FLEXWebsocketMessageDirection) {
|
||||
@property (nonatomic, readonly) int64_t dataLength API_AVAILABLE(ios(13.0));
|
||||
|
||||
@end
|
||||
|
||||
|
||||
typedef NS_ENUM(NSUInteger, FLEXFIRTransactionDirection) {
|
||||
FLEXFIRTransactionDirectionNone,
|
||||
FLEXFIRTransactionDirectionPush,
|
||||
FLEXFIRTransactionDirectionPull,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, FLEXFIRRequestType) {
|
||||
FLEXFIRRequestTypeNotFirebase,
|
||||
FLEXFIRRequestTypeFetchQuery,
|
||||
FLEXFIRRequestTypeFetchDocument,
|
||||
FLEXFIRRequestTypeSetData,
|
||||
FLEXFIRRequestTypeUpdateData,
|
||||
FLEXFIRRequestTypeAddDocument,
|
||||
FLEXFIRRequestTypeDeleteDocument,
|
||||
};
|
||||
|
||||
@interface FLEXFirebaseSetDataInfo : NSObject
|
||||
/// The data that was set
|
||||
@property (nonatomic, readonly) NSDictionary *documentData;
|
||||
/// \c nil if \c mergeFields is populated
|
||||
@property (nonatomic, readonly) NSNumber *merge;
|
||||
/// \c nil if \c merge is populated
|
||||
@property (nonatomic, readonly) NSArray *mergeFields;
|
||||
@end
|
||||
|
||||
@interface FLEXFirebaseTransaction : FLEXNetworkTransaction
|
||||
|
||||
+ (instancetype)queryFetch:(FIRQuery *)initiator;
|
||||
+ (instancetype)documentFetch:(FIRDocumentReference *)initiator;
|
||||
+ (instancetype)setData:(FIRDocumentReference *)initiator
|
||||
data:(NSDictionary *)data
|
||||
merge:(NSNumber *)merge
|
||||
mergeFields:(NSArray *)mergeFields;
|
||||
+ (instancetype)updateData:(FIRDocumentReference *)initiator data:(NSDictionary *)data;
|
||||
+ (instancetype)addDocument:(FIRCollectionReference *)initiator document:(FIRDocumentReference *)doc;
|
||||
+ (instancetype)deleteDocument:(FIRDocumentReference *)initiator;
|
||||
|
||||
@property (nonatomic, readonly) FLEXFIRTransactionDirection direction;
|
||||
@property (nonatomic, readonly) FLEXFIRRequestType requestType;
|
||||
|
||||
@property (nonatomic, readonly) id initiator;
|
||||
@property (nonatomic, readonly) FIRQuery *initiator_query;
|
||||
@property (nonatomic, readonly) FIRDocumentReference *initiator_doc;
|
||||
@property (nonatomic, readonly) FIRCollectionReference *initiator_collection;
|
||||
|
||||
/// Only used for fetch types
|
||||
@property (nonatomic, copy) NSArray<FIRDocumentSnapshot *> *documents;
|
||||
/// Only used for the "set data" type
|
||||
@property (nonatomic, readonly) FLEXFirebaseSetDataInfo *setDataInfo;
|
||||
/// Only used for the "update data" type
|
||||
@property (nonatomic, readonly) NSDictionary *updateData;
|
||||
/// Only used for the "add document" type
|
||||
@property (nonatomic, readonly) FIRDocumentReference *addedDocument;
|
||||
|
||||
@property (nonatomic, readonly) NSString *path;
|
||||
|
||||
//@property (nonatomic, readonly) NSString *responseString;
|
||||
//@property (nonatomic, readonly) NSDictionary *responseObject;
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,6 +10,16 @@
|
||||
#import "FLEXResources.h"
|
||||
#import "FLEXUtility.h"
|
||||
|
||||
@interface FLEXNetworkTransaction () {
|
||||
@protected
|
||||
|
||||
NSString *_primaryDescription;
|
||||
NSString *_secondaryDescription;
|
||||
NSString *_tertiaryDescription;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FLEXNetworkTransaction
|
||||
|
||||
+ (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state {
|
||||
@@ -44,23 +54,6 @@
|
||||
return transaction;
|
||||
}
|
||||
|
||||
- (NSString *)timestampStringFromRequestDate:(NSDate *)date {
|
||||
static NSDateFormatter *dateFormatter = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
dateFormatter = [NSDateFormatter new];
|
||||
dateFormatter.dateFormat = @"HH:mm:ss";
|
||||
});
|
||||
|
||||
return [dateFormatter stringFromDate:date];
|
||||
}
|
||||
|
||||
- (void)setState:(FLEXNetworkTransactionState)transactionState {
|
||||
_state = transactionState;
|
||||
// Reset bottom description
|
||||
_tertiaryDescription = nil;
|
||||
}
|
||||
|
||||
- (BOOL)displayAsError {
|
||||
return _error != nil;
|
||||
}
|
||||
@@ -88,6 +81,17 @@
|
||||
return transaction;
|
||||
}
|
||||
|
||||
- (NSString *)timestampStringFromRequestDate:(NSDate *)date {
|
||||
static NSDateFormatter *dateFormatter = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
dateFormatter = [NSDateFormatter new];
|
||||
dateFormatter.dateFormat = @"HH:mm:ss";
|
||||
});
|
||||
|
||||
return [dateFormatter stringFromDate:date];
|
||||
}
|
||||
|
||||
- (NSString *)primaryDescription {
|
||||
if (!_primaryDescription) {
|
||||
NSString *name = self.request.URL.lastPathComponent;
|
||||
@@ -138,11 +142,11 @@
|
||||
[detailComponents addObject:httpMethod];
|
||||
}
|
||||
|
||||
if (self.state == FLEXNetworkTransactionStateFinished || self.state == FLEXNetworkTransactionStateFailed) {
|
||||
if (self.transactionState == FLEXNetworkTransactionStateFinished || self.transactionState == FLEXNetworkTransactionStateFailed) {
|
||||
[detailComponents addObjectsFromArray:self.details];
|
||||
} else {
|
||||
// Unstarted, Awaiting Response, Receiving Data, etc.
|
||||
NSString *state = [self.class readableStringFromTransactionState:self.state];
|
||||
NSString *state = [self.class readableStringFromTransactionState:self.transactionState];
|
||||
[detailComponents addObject:state];
|
||||
}
|
||||
|
||||
@@ -152,6 +156,12 @@
|
||||
return _tertiaryDescription;
|
||||
}
|
||||
|
||||
- (void)setTransactionState:(FLEXNetworkTransactionState)transactionState {
|
||||
super.transactionState = transactionState;
|
||||
// Reset bottom description
|
||||
_tertiaryDescription = nil;
|
||||
}
|
||||
|
||||
- (NSString *)copyString {
|
||||
return self.request.URL.absoluteString;
|
||||
}
|
||||
@@ -251,7 +261,7 @@
|
||||
// Populate receivedDataLength
|
||||
if (direction == FLEXWebsocketIncoming) {
|
||||
wst.receivedDataLength = wst.dataLength;
|
||||
wst.state = FLEXNetworkTransactionStateFinished;
|
||||
wst.transactionState = FLEXNetworkTransactionStateFinished;
|
||||
}
|
||||
|
||||
// Populate thumbnail image
|
||||
|
||||
@@ -37,7 +37,6 @@ NSString * const kFLEXNetworkTransactionCellIdentifier = @"kFLEXNetworkTransacti
|
||||
self.pathLabel = [UILabel new];
|
||||
self.pathLabel.font = UIFont.flex_defaultTableCellFont;
|
||||
self.pathLabel.textColor = [UIColor colorWithWhite:0.4 alpha:1.0];
|
||||
self.pathLabel.lineBreakMode = NSLineBreakByTruncatingMiddle;
|
||||
[self.contentView addSubview:self.pathLabel];
|
||||
|
||||
self.thumbnailImageView = [UIImageView new];
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
//
|
||||
// Firestore.h
|
||||
// Pods
|
||||
//
|
||||
// Created by Tanner Bennett on 10/13/21.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#pragma mark - Forward Declarations
|
||||
|
||||
@class FIRQuery;
|
||||
@class FIRQuerySnapshot;
|
||||
@class FIRDocumentReference;
|
||||
@class FIRDocumentSnapshot;
|
||||
@class FIRQueryDocumentSnapshot;
|
||||
@class FIRCollectionReference;
|
||||
@class FIRFirestore;
|
||||
@protocol FIRListenerRegistration;
|
||||
|
||||
#define cFIRQuery objc_getClass("FIRQuery")
|
||||
#define cFIRCollectionReference objc_getClass("FIRCollectionReference")
|
||||
#define cFIRDocumentReference objc_getClass("FIRDocumentReference")
|
||||
|
||||
typedef void (^FIRDocumentSnapshotBlock)(FIRDocumentSnapshot *_Nullable snapshot,
|
||||
NSError *_Nullable error);
|
||||
typedef void (^FIRQuerySnapshotBlock)(FIRQuerySnapshot *_Nullable snapshot,
|
||||
NSError *_Nullable error);
|
||||
|
||||
typedef NS_ENUM(NSUInteger, FIRFirestoreSource) {
|
||||
FIRFirestoreSourceDefault,
|
||||
FIRFirestoreSourceServer,
|
||||
FIRFirestoreSourceCache
|
||||
} NS_SWIFT_NAME(FirestoreSource);
|
||||
|
||||
#pragma mark - Query
|
||||
@interface FIRQuery : NSObject
|
||||
|
||||
- (id)init __attribute__((unavailable()));
|
||||
|
||||
@property(nonatomic, readonly) FIRFirestore *firestore;
|
||||
@property(nonatomic, readonly) void *query;
|
||||
|
||||
- (void)getDocumentsWithCompletion:(FIRQuerySnapshotBlock)completion
|
||||
NS_SWIFT_NAME(getDocuments(completion:));
|
||||
- (void)getDocumentsWithSource:(FIRFirestoreSource)source
|
||||
completion:(FIRQuerySnapshotBlock)completion
|
||||
NS_SWIFT_NAME(getDocuments(source:completion:));
|
||||
|
||||
@end
|
||||
|
||||
|
||||
typedef void (^FIRDocumentSnapshotBlock)(FIRDocumentSnapshot *_Nullable snapshot,
|
||||
NSError *_Nullable error);
|
||||
|
||||
#pragma mark - DocumentReference
|
||||
NS_SWIFT_NAME(DocumentReference)
|
||||
@interface FIRDocumentReference : NSObject
|
||||
|
||||
- (instancetype)init __attribute__((unavailable));
|
||||
|
||||
@property(nonatomic, readonly) NSString *documentID;
|
||||
@property(nonatomic, readonly) FIRCollectionReference *parent;
|
||||
@property(nonatomic, readonly) FIRFirestore *firestore;
|
||||
@property(nonatomic, readonly) NSString *path;
|
||||
|
||||
- (FIRCollectionReference *)collectionWithPath:(NSString *)collectionPath
|
||||
NS_SWIFT_NAME(collection(_:));
|
||||
|
||||
#pragma mark Writing Data
|
||||
|
||||
- (void)setData:(NSDictionary<NSString *, id> *)documentData;
|
||||
- (void)setData:(NSDictionary<NSString *, id> *)documentData merge:(BOOL)merge;
|
||||
- (void)setData:(NSDictionary<NSString *, id> *)documentData mergeFields:(NSArray<id> *)mergeFields;
|
||||
- (void)setData:(NSDictionary<NSString *, id> *)documentData
|
||||
completion:(nullable void (^)(NSError *_Nullable error))completion;
|
||||
- (void)setData:(NSDictionary<NSString *, id> *)documentData
|
||||
merge:(BOOL)merge
|
||||
completion:(nullable void (^)(NSError *_Nullable error))completion;
|
||||
- (void)setData:(NSDictionary<NSString *, id> *)documentData
|
||||
mergeFields:(NSArray<id> *)mergeFields
|
||||
completion:(nullable void (^)(NSError *_Nullable error))completion;
|
||||
|
||||
- (void)updateData:(NSDictionary<id, id> *)fields;
|
||||
- (void)updateData:(NSDictionary<id, id> *)fields
|
||||
completion:(nullable void (^)(NSError *_Nullable error))completion;
|
||||
|
||||
- (void)deleteDocument NS_SWIFT_NAME(delete());
|
||||
- (void)deleteDocumentWithCompletion:(nullable void (^)(NSError *_Nullable error))completion
|
||||
NS_SWIFT_NAME(delete(completion:));
|
||||
|
||||
#pragma mark Retrieving Data
|
||||
|
||||
- (void)getDocumentWithCompletion:(FIRDocumentSnapshotBlock)completion
|
||||
NS_SWIFT_NAME(getDocument(completion:));
|
||||
- (void)getDocumentWithSource:(FIRFirestoreSource)source
|
||||
completion:(FIRDocumentSnapshotBlock)completion
|
||||
NS_SWIFT_NAME(getDocument(source:completion:));
|
||||
|
||||
- (id<FIRListenerRegistration>)addSnapshotListener:(FIRDocumentSnapshotBlock)listener
|
||||
NS_SWIFT_NAME(addSnapshotListener(_:));
|
||||
- (id<FIRListenerRegistration>)addSnapshotListenerWithIncludeMetadataChanges:(BOOL)includeMetadataChanges
|
||||
listener:(FIRDocumentSnapshotBlock)listener
|
||||
NS_SWIFT_NAME(addSnapshotListener(includeMetadataChanges:listener:));
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark - CollectionReference
|
||||
NS_SWIFT_NAME(CollectionReference)
|
||||
@interface FIRCollectionReference : FIRQuery
|
||||
|
||||
- (id)init __attribute__((unavailable()));
|
||||
|
||||
@property(nonatomic, readonly) NSString *collectionID;
|
||||
@property(nonatomic, nullable, readonly) FIRDocumentReference *parent;
|
||||
@property(nonatomic, readonly) NSString *path;
|
||||
|
||||
- (FIRDocumentReference *)documentWithAutoID NS_SWIFT_NAME(document());
|
||||
- (FIRDocumentReference *)documentWithPath:(NSString *)documentPath NS_SWIFT_NAME(document(_:));
|
||||
- (FIRDocumentReference *)addDocumentWithData:(NSDictionary<NSString *, id> *)data
|
||||
NS_SWIFT_NAME(addDocument(data:));
|
||||
- (FIRDocumentReference *)addDocumentWithData:(NSDictionary<NSString *, id> *)data
|
||||
completion:(nullable void (^)(NSError *_Nullable error))completion
|
||||
NS_SWIFT_NAME(addDocument(data:completion:));
|
||||
@end
|
||||
|
||||
#pragma mark - QuerySnapshot
|
||||
NS_SWIFT_NAME(QuerySnapshot)
|
||||
@interface FIRQuerySnapshot : NSObject
|
||||
|
||||
- (id)init __attribute__((unavailable()));
|
||||
|
||||
@property(nonatomic, readonly) FIRQuery *query;
|
||||
@property(nonatomic, readonly, getter=isEmpty) BOOL empty;
|
||||
@property(nonatomic, readonly) NSInteger count;
|
||||
@property(nonatomic, readonly) NSArray<FIRQueryDocumentSnapshot *> *documents;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - DocumentSnapshot
|
||||
NS_SWIFT_NAME(DocumentSnapshot)
|
||||
@interface FIRDocumentSnapshot : NSObject
|
||||
|
||||
- (instancetype)init __attribute__((unavailable()));
|
||||
|
||||
@property(nonatomic, readonly) BOOL exists;
|
||||
@property(nonatomic, readonly) FIRDocumentReference *reference;
|
||||
@property(nonatomic, copy, readonly) NSString *documentID;
|
||||
|
||||
@property(nonatomic, readonly, nullable) NSDictionary<NSString *, id> *data;
|
||||
|
||||
- (nullable id)valueForField:(id)field NS_SWIFT_NAME(get(_:));
|
||||
- (nullable id)objectForKeyedSubscript:(id)key;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - QueryDocumentSnapshot
|
||||
NS_SWIFT_NAME(QueryDocumentSnapshot)
|
||||
@interface FIRQueryDocumentSnapshot : FIRDocumentSnapshot
|
||||
|
||||
- (instancetype)init __attribute__((unavailable()));
|
||||
|
||||
@property(nonatomic, readonly) NSDictionary<NSString *, id> *data;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
|
||||
#if defined(__clang__)
|
||||
#if __has_feature(objc_arc)
|
||||
#define _LOGOS_SELF_TYPE_NORMAL __unsafe_unretained
|
||||
#define _LOGOS_SELF_TYPE_INIT __attribute__((ns_consumed))
|
||||
#define _LOGOS_SELF_CONST const
|
||||
#define _LOGOS_RETURN_RETAINED __attribute__((ns_returns_retained))
|
||||
#else
|
||||
#define _LOGOS_SELF_TYPE_NORMAL
|
||||
#define _LOGOS_SELF_TYPE_INIT
|
||||
#define _LOGOS_SELF_CONST
|
||||
#define _LOGOS_RETURN_RETAINED
|
||||
#endif
|
||||
#else
|
||||
#define _LOGOS_SELF_TYPE_NORMAL
|
||||
#define _LOGOS_SELF_TYPE_INIT
|
||||
#define _LOGOS_SELF_CONST
|
||||
#define _LOGOS_RETURN_RETAINED
|
||||
#endif
|
||||
@@ -21,7 +21,6 @@
|
||||
#import "NSUserDefaults+FLEX.h"
|
||||
#import "NSObject+FLEX_Reflection.h"
|
||||
#import "FLEXMethod.h"
|
||||
#import "Firestore.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import <objc/message.h>
|
||||
@@ -102,7 +101,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id<NSUR
|
||||
if (enabled) {
|
||||
// Inject if needed. This injection is protected with a dispatch_once, so we're ok calling it multiple times.
|
||||
// By doing the injection lazily, we keep the impact of the tool lower when this feature isn't enabled.
|
||||
[self setNetworkMonitorHooks];
|
||||
[self injectIntoAllNSURLThings];
|
||||
}
|
||||
|
||||
if (previouslyEnabled != enabled) {
|
||||
@@ -115,13 +114,10 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id<NSUR
|
||||
}
|
||||
|
||||
+ (void)load {
|
||||
// We don't want to do the swizzling from +load because not all the
|
||||
// delegate classes we want to hook may be loaded at this point.
|
||||
// However, Firebase classes will definitely be loaded by now,
|
||||
// so we can definitely hook those sooner if need be.
|
||||
// We don't want to do the swizzling from +load because not all the classes may be loaded at this point.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ([self isEnabled]) {
|
||||
[self setNetworkMonitorHooks];
|
||||
[self injectIntoAllNSURLThings];
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -170,285 +166,7 @@ didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask delegate:(id<NSUR
|
||||
objc_setAssociatedObject(object, key, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
#pragma mark - Hooking
|
||||
|
||||
static void (*_logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$)(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, FIRDocumentSnapshotBlock);
|
||||
static void _logos_method$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, FIRDocumentSnapshotBlock);
|
||||
static void (*_logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$)(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRQuery * _LOGOS_SELF_CONST, SEL, FIRQuerySnapshotBlock);
|
||||
static void _logos_method$_ungrouped$FIRQuery$getDocumentsWithCompletion$(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRQuery * _LOGOS_SELF_CONST, SEL, FIRQuerySnapshotBlock);
|
||||
|
||||
static void (*_logos_orig$_ungrouped$FIRDocumentReference$setData$merge$completion$)(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, NSDictionary *, BOOL, void (^)(NSError *));
|
||||
static void (*_logos_orig$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$)(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, NSDictionary *, NSArray *, void (^)(NSError *));
|
||||
static void (*_logos_orig$_ungrouped$FIRDocumentReference$updateData$completion$)(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, NSDictionary *, void (^)(NSError *));
|
||||
static void (*_logos_orig$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$)(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, void (^)(NSError *));
|
||||
|
||||
static void _logos_register_hook(Class _class, SEL _cmd, IMP _new, IMP *_old) {
|
||||
unsigned int _count, _i;
|
||||
Class _searchedClass = _class;
|
||||
Method *_methods;
|
||||
while (_searchedClass) {
|
||||
_methods = class_copyMethodList(_searchedClass, &_count);
|
||||
for (_i = 0; _i < _count; _i++) {
|
||||
if (method_getName(_methods[_i]) == _cmd) {
|
||||
if (_class == _searchedClass) {
|
||||
*_old = method_getImplementation(_methods[_i]);
|
||||
*_old = class_replaceMethod(_class, _cmd, _new, method_getTypeEncoding(_methods[_i]));
|
||||
} else {
|
||||
class_addMethod(_class, _cmd, _new, method_getTypeEncoding(_methods[_i]));
|
||||
}
|
||||
free(_methods);
|
||||
return;
|
||||
}
|
||||
}
|
||||
free(_methods);
|
||||
_searchedClass = class_getSuperclass(_searchedClass);
|
||||
}
|
||||
}
|
||||
|
||||
static Class _logos_superclass$_ungrouped$FIRDocumentReference;
|
||||
static void (*_logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$)(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST, SEL, FIRDocumentSnapshotBlock);
|
||||
static Class _logos_superclass$_ungrouped$FIRQuery;
|
||||
static void (*_logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$)(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRQuery * _LOGOS_SELF_CONST, SEL, FIRQuerySnapshotBlock);
|
||||
static Class _logos_superclass$_ungrouped$FIRCollectionReference;
|
||||
static FIRDocumentReference * (*_logos_orig$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$)(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRCollectionReference * _LOGOS_SELF_CONST, SEL, NSDictionary *, void (^)(NSError *error));
|
||||
|
||||
#pragma mark Firebase, Reading Data
|
||||
|
||||
static void _logos_method$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST self, SEL _cmd, FIRDocumentSnapshotBlock completion) {
|
||||
|
||||
// Generate transaction ID
|
||||
NSString *requestID = [FLEXNetworkObserver nextRequestID];
|
||||
|
||||
// Record transaction start
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRDocumentWillFetch:self withTransactionID:requestID];
|
||||
// Hook callback
|
||||
FIRDocumentSnapshotBlock orig = completion;
|
||||
completion = ^(FIRDocumentSnapshot *document, NSError *error) {
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRDocumentDidFetch:document error:error transactionID:requestID];
|
||||
orig(document, error);
|
||||
};
|
||||
|
||||
// Forward invocation
|
||||
(_logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$ ? _logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$ : (__typeof__(_logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRDocumentReference, @selector(getDocumentWithCompletion:)))(self, _cmd, completion);
|
||||
}
|
||||
|
||||
static void _logos_method$_ungrouped$FIRQuery$getDocumentsWithCompletion$(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRQuery * _LOGOS_SELF_CONST self, SEL _cmd, FIRQuerySnapshotBlock completion) {
|
||||
|
||||
// Generate transaction ID
|
||||
NSString *requestID = [FLEXNetworkObserver nextRequestID];
|
||||
|
||||
// Record transaction start
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRQueryWillFetch:self withTransactionID:requestID];
|
||||
// Hook callback
|
||||
FIRQuerySnapshotBlock orig = completion;
|
||||
completion = ^(FIRQuerySnapshot *query, NSError *error) {
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRQueryDidFetch:query error:error transactionID:requestID];
|
||||
orig(query, error);
|
||||
};
|
||||
|
||||
// Forward invocation
|
||||
(_logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$ ? _logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$ : (__typeof__(_logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRQuery, @selector(getDocumentsWithCompletion:)))(self, _cmd, completion);
|
||||
}
|
||||
|
||||
#pragma mark Firebase, Writing Data
|
||||
|
||||
static void _logos_method$_ungrouped$FIRDocumentReference$setData$merge$completion$(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST __unused self,
|
||||
SEL __unused _cmd, NSDictionary<NSString *, id> * documentData, BOOL merge, void (^completion)(NSError *)) {
|
||||
|
||||
// Generate transaction ID
|
||||
NSString *requestID = [FLEXNetworkObserver nextRequestID];
|
||||
|
||||
// Record transaction start
|
||||
[FLEXNetworkRecorder.defaultRecorder
|
||||
recordFIRWillSetData:self
|
||||
data:documentData
|
||||
merge:@(merge)
|
||||
mergeFields:nil
|
||||
transactionID:requestID
|
||||
];
|
||||
|
||||
// Hook callback
|
||||
void (^orig)(NSError *) = completion;
|
||||
completion = ^(NSError *error) {
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRDidSetData:error transactionID:requestID];
|
||||
orig(error);
|
||||
};
|
||||
|
||||
// Forward invocation
|
||||
(_logos_orig$_ungrouped$FIRDocumentReference$setData$merge$completion$ ? _logos_orig$_ungrouped$FIRDocumentReference$setData$merge$completion$ : (__typeof__(_logos_orig$_ungrouped$FIRDocumentReference$setData$merge$completion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRDocumentReference, @selector(setData:merge:completion:)))(self, _cmd, documentData, merge, completion);
|
||||
}
|
||||
|
||||
static void _logos_method$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST __unused self,
|
||||
SEL __unused _cmd, NSDictionary<NSString *, id> * documentData,
|
||||
NSArray * mergeFields, void (^completion)(NSError *)) {
|
||||
|
||||
// Generate transaction ID
|
||||
NSString *requestID = [FLEXNetworkObserver nextRequestID];
|
||||
|
||||
// Record transaction start
|
||||
[FLEXNetworkRecorder.defaultRecorder
|
||||
recordFIRWillSetData:self
|
||||
data:documentData
|
||||
merge:nil
|
||||
mergeFields:mergeFields
|
||||
transactionID:requestID
|
||||
];
|
||||
|
||||
// Hook callback
|
||||
void (^orig)(NSError *) = completion;
|
||||
completion = ^(NSError *error) {
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRDidSetData:error transactionID:requestID];
|
||||
orig(error);
|
||||
};
|
||||
|
||||
// Forward invocation
|
||||
(_logos_orig$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$ ? _logos_orig$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$ : (__typeof__(_logos_orig$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRDocumentReference, @selector(setData:mergeFields:completion:)))(self, _cmd, documentData, mergeFields, completion);
|
||||
}
|
||||
|
||||
static void _logos_method$_ungrouped$FIRDocumentReference$updateData$completion$(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST __unused self,
|
||||
SEL __unused _cmd, NSDictionary<id, id> * fields, void (^completion)(NSError *)) {
|
||||
|
||||
// Generate transaction ID
|
||||
NSString *requestID = [FLEXNetworkObserver nextRequestID];
|
||||
|
||||
// Record transaction start
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRWillUpdateData:self fields:fields transactionID:requestID];
|
||||
// Hook callback
|
||||
void (^orig)(NSError *) = completion;
|
||||
completion = ^(NSError *error) {
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRDidUpdateData:error transactionID:requestID];
|
||||
orig(error);
|
||||
};
|
||||
|
||||
// Forward invocation
|
||||
(_logos_orig$_ungrouped$FIRDocumentReference$updateData$completion$ ? _logos_orig$_ungrouped$FIRDocumentReference$updateData$completion$ : (__typeof__(_logos_orig$_ungrouped$FIRDocumentReference$updateData$completion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRDocumentReference, @selector(updateData:completion:)))(self, _cmd, fields, completion);
|
||||
}
|
||||
|
||||
static void _logos_method$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRDocumentReference * _LOGOS_SELF_CONST __unused self,
|
||||
SEL __unused _cmd, void (^completion)(NSError *)) {
|
||||
|
||||
// Generate transaction ID
|
||||
NSString *requestID = [FLEXNetworkObserver nextRequestID];
|
||||
|
||||
// Record transaction start
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRWillDeleteDocument:self transactionID:requestID];
|
||||
// Hook callback
|
||||
void (^orig)(NSError *) = completion;
|
||||
completion = ^(NSError *error) {
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRDidDeleteDocument:error transactionID:requestID];
|
||||
orig(error);
|
||||
};
|
||||
|
||||
// Forward invocation
|
||||
(_logos_orig$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$ ? _logos_orig$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$ : (__typeof__(_logos_orig$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRDocumentReference, @selector(deleteDocumentWithCompletion:)))(self, _cmd, completion);
|
||||
}
|
||||
|
||||
static FIRDocumentReference * _logos_method$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$(
|
||||
_LOGOS_SELF_TYPE_NORMAL FIRCollectionReference * _LOGOS_SELF_CONST __unused self,
|
||||
SEL __unused _cmd, NSDictionary<NSString *, id> * data, void (^completion)(NSError *error)) {
|
||||
|
||||
// Generate transaction ID
|
||||
NSString *requestID = [FLEXNetworkObserver nextRequestID];
|
||||
|
||||
// Hook callback
|
||||
void (^orig)(NSError *) = completion;
|
||||
completion = ^(NSError *error) {
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRDidAddDocument:error transactionID:requestID];
|
||||
orig(error);
|
||||
};
|
||||
|
||||
// Forward invocation
|
||||
FIRDocumentReference *ret = (_logos_orig$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$ ? _logos_orig$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$ : (__typeof__(_logos_orig$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$))class_getMethodImplementation(_logos_superclass$_ungrouped$FIRCollectionReference, @selector(addDocumentWithData:completion:)))(self, _cmd, data, completion);
|
||||
|
||||
// Record transaction start
|
||||
[FLEXNetworkRecorder.defaultRecorder recordFIRWillAddDocument:self document:ret transactionID:requestID];
|
||||
|
||||
// Return
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ (void)setNetworkMonitorHooks {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
[self hookFirebaseThings];
|
||||
[self injectIntoAllNSURLThings];
|
||||
});
|
||||
}
|
||||
|
||||
+ (void)hookFirebaseThings {
|
||||
Class _logos_class$_ungrouped$FIRDocumentReference = objc_getClass("FIRDocumentReference");
|
||||
_logos_superclass$_ungrouped$FIRDocumentReference = class_getSuperclass(_logos_class$_ungrouped$FIRDocumentReference);
|
||||
Class _logos_class$_ungrouped$FIRQuery = objc_getClass("FIRQuery");
|
||||
_logos_superclass$_ungrouped$FIRQuery = class_getSuperclass(_logos_class$_ungrouped$FIRQuery);
|
||||
Class _logos_class$_ungrouped$FIRCollectionReference = objc_getClass("FIRCollectionReference");
|
||||
_logos_superclass$_ungrouped$FIRCollectionReference = class_getSuperclass(_logos_class$_ungrouped$FIRCollectionReference);
|
||||
|
||||
// Reading //
|
||||
|
||||
_logos_register_hook(
|
||||
_logos_class$_ungrouped$FIRDocumentReference,
|
||||
@selector(getDocumentWithCompletion:),
|
||||
(IMP)&_logos_method$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$,
|
||||
(IMP *)&_logos_orig$_ungrouped$FIRDocumentReference$getDocumentWithCompletion$
|
||||
);
|
||||
|
||||
_logos_register_hook(
|
||||
_logos_class$_ungrouped$FIRQuery,
|
||||
@selector(getDocumentsWithCompletion:),
|
||||
(IMP)&_logos_method$_ungrouped$FIRQuery$getDocumentsWithCompletion$,
|
||||
(IMP *)&_logos_orig$_ungrouped$FIRQuery$getDocumentsWithCompletion$
|
||||
);
|
||||
|
||||
// Writing //
|
||||
|
||||
_logos_register_hook(
|
||||
_logos_class$_ungrouped$FIRDocumentReference,
|
||||
@selector(setData:merge:completion:),
|
||||
(IMP)&_logos_method$_ungrouped$FIRDocumentReference$setData$merge$completion$,
|
||||
(IMP *)&_logos_orig$_ungrouped$FIRDocumentReference$setData$merge$completion$
|
||||
);
|
||||
_logos_register_hook(
|
||||
_logos_class$_ungrouped$FIRDocumentReference,
|
||||
@selector(setData:mergeFields:completion:),
|
||||
(IMP)&_logos_method$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$,
|
||||
(IMP *)&_logos_orig$_ungrouped$FIRDocumentReference$setData$mergeFields$completion$
|
||||
);
|
||||
_logos_register_hook(
|
||||
_logos_class$_ungrouped$FIRDocumentReference,
|
||||
@selector(updateData:completion:),
|
||||
(IMP)&_logos_method$_ungrouped$FIRDocumentReference$updateData$completion$,
|
||||
(IMP *)&_logos_orig$_ungrouped$FIRDocumentReference$updateData$completion$
|
||||
);
|
||||
_logos_register_hook(
|
||||
_logos_class$_ungrouped$FIRDocumentReference,
|
||||
@selector(deleteDocumentWithCompletion:),
|
||||
(IMP)&_logos_method$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$,
|
||||
(IMP *)&_logos_orig$_ungrouped$FIRDocumentReference$deleteDocumentWithCompletion$
|
||||
);
|
||||
_logos_register_hook(
|
||||
_logos_class$_ungrouped$FIRCollectionReference,
|
||||
@selector(addDocumentWithData:completion:),
|
||||
(IMP)&_logos_method$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$,
|
||||
(IMP *)&_logos_orig$_ungrouped$FIRCollectionReference$addDocumentWithData$completion$
|
||||
);
|
||||
}
|
||||
#pragma mark - Delegate Injection
|
||||
|
||||
+ (void)injectIntoAllNSURLThings {
|
||||
// Only allow swizzling once.
|
||||
|
||||
@@ -72,21 +72,23 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id<FLEXMirror>)mirrorForClass:(Class)cls {
|
||||
- (id<FLEXMirror>)initialMirror {
|
||||
static Class FLEXSwiftMirror = nil;
|
||||
|
||||
id obj = _object;
|
||||
|
||||
// Should we use Reflex?
|
||||
if (FLEXIsSwiftObjectOrClass(cls) && FLEXObjectExplorer.reflexAvailable) {
|
||||
if (FLEXIsSwiftObjectOrClass(obj) && FLEXObjectExplorer.reflexAvailable) {
|
||||
// Initialize FLEXSwiftMirror class if needed
|
||||
if (!FLEXSwiftMirror) {
|
||||
FLEXSwiftMirror = NSClassFromString(@"FLEXSwiftMirror");
|
||||
}
|
||||
|
||||
return [(id<FLEXMirror>)[FLEXSwiftMirror alloc] initWithSubject:cls];
|
||||
return [(id<FLEXMirror>)[FLEXSwiftMirror alloc] initWithSubject:obj];
|
||||
}
|
||||
|
||||
// No; not swift object, or Reflex unavailable
|
||||
return [FLEXMirror reflect:cls];
|
||||
return [FLEXMirror reflect:obj];
|
||||
}
|
||||
|
||||
|
||||
@@ -176,9 +178,9 @@
|
||||
Class superclass = nil;
|
||||
NSInteger count = self.classHierarchyClasses.count;
|
||||
NSInteger rootIdx = count - 1;
|
||||
id<FLEXMirror> mirror = self.initialMirror;
|
||||
for (NSInteger i = 0; i < count; i++) {
|
||||
Class cls = self.classHierarchyClasses[i];
|
||||
id<FLEXMirror> mirror = [self mirrorForClass:cls];
|
||||
superclass = (i < rootIdx) ? self.classHierarchyClasses[i+1] : nil;
|
||||
|
||||
[allProperties addObject:[self
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
if (!self.filterText.length) {
|
||||
self.metadata = self.allMetadata;
|
||||
} else {
|
||||
self.metadata = [self.allMetadata flex_filtered:^BOOL(id<FLEXRuntimeMetadata> obj, NSUInteger idx) {
|
||||
self.metadata = [self.allMetadata flex_filtered:^BOOL(FLEXProperty *obj, NSUInteger idx) {
|
||||
return [obj.description localizedCaseInsensitiveContainsString:self.filterText];
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ typedef void (^FLEXMutableListCellForElement)(__kindof UITableViewCell *cell, id
|
||||
|
||||
/// By default, rows are not selectable. If you want rows
|
||||
/// to be selectable, provide a selection handler here.
|
||||
@property (nonatomic, copy) void (^selectionHandler)(__kindof UIViewController *host, ObjectType element);
|
||||
@property (nonatomic, copy) void (^selectionHandler)(__kindof UIViewController *host, id element);
|
||||
|
||||
/// The objects representing all possible rows in the section.
|
||||
@property (nonatomic) NSArray<ObjectType> *list;
|
||||
|
||||
@@ -77,8 +77,7 @@
|
||||
@"frame", @"bounds", @"center", @"transform",
|
||||
@"backgroundColor", @"alpha", @"opaque", @"hidden",
|
||||
@"clipsToBounds", @"userInteractionEnabled", @"layer",
|
||||
@"superview", @"subviews",
|
||||
@"accessibilityIdentifier", @"accessibilityLabel"
|
||||
@"superview", @"subviews"
|
||||
]).forClass(UIView.class);
|
||||
|
||||
// UILabel
|
||||
@@ -87,8 +86,7 @@
|
||||
@"textColor", @"textAlignment", @"numberOfLines",
|
||||
@"lineBreakMode", @"enabled", @"backgroundColor",
|
||||
@"alpha", @"hidden", @"preferredMaxLayoutWidth",
|
||||
@"superview", @"subviews",
|
||||
@"accessibilityIdentifier", @"accessibilityLabel"
|
||||
@"superview", @"subviews"
|
||||
]).forClass(UILabel.class);
|
||||
|
||||
// UIWindow
|
||||
@@ -113,16 +111,14 @@
|
||||
self.append.ivars(ivars).methods(methods).properties(@[
|
||||
@"enabled", @"allTargets", @"frame",
|
||||
@"backgroundColor", @"hidden", @"clipsToBounds",
|
||||
@"userInteractionEnabled", @"superview", @"subviews",
|
||||
@"accessibilityIdentifier", @"accessibilityLabel"
|
||||
@"userInteractionEnabled", @"superview", @"subviews"
|
||||
]).forClass(UIControl.class);
|
||||
|
||||
// UIButton
|
||||
self.append.ivars(ivars).properties(@[
|
||||
@"titleLabel", @"font", @"imageView", @"tintColor",
|
||||
@"currentTitle", @"currentImage", @"enabled", @"frame",
|
||||
@"superview", @"subviews",
|
||||
@"accessibilityIdentifier", @"accessibilityLabel"
|
||||
@"superview", @"subviews"
|
||||
]).forClass(UIButton.class);
|
||||
|
||||
// UIImageView
|
||||
@@ -130,7 +126,6 @@
|
||||
@"image", @"animationImages", @"frame", @"bounds", @"center",
|
||||
@"transform", @"alpha", @"hidden", @"clipsToBounds",
|
||||
@"userInteractionEnabled", @"layer", @"superview", @"subviews",
|
||||
@"accessibilityIdentifier", @"accessibilityLabel"
|
||||
]).forClass(UIImageView.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -165,10 +165,10 @@
|
||||
|
||||
// Generate all (sub)titles from shortcuts
|
||||
if (self.allShortcuts) {
|
||||
self.allTitles = [self.allShortcuts flex_mapped:^id(id<FLEXShortcut> s, NSUInteger idx) {
|
||||
self.allTitles = [self.allShortcuts flex_mapped:^id(FLEXShortcut *s, NSUInteger idx) {
|
||||
return [s titleWith:self.object];
|
||||
}];
|
||||
self.allSubtitles = [self.allShortcuts flex_mapped:^id(id<FLEXShortcut> s, NSUInteger idx) {
|
||||
self.allSubtitles = [self.allShortcuts flex_mapped:^id(FLEXShortcut *s, NSUInteger idx) {
|
||||
return [s subtitleWith:self.object] ?: @"";
|
||||
}];
|
||||
}
|
||||
@@ -188,7 +188,7 @@
|
||||
- (BOOL)canSelectRow:(NSInteger)row {
|
||||
UITableViewCellAccessoryType type = [self.shortcuts[row] accessoryTypeWith:self.object];
|
||||
BOOL hasDisclosure = NO;
|
||||
hasDisclosure |= type == UITableViewCellAccessoryDisclosureIndicator;
|
||||
hasDisclosure |= type == UITableViewCellAccessoryDisclosureIndicator;
|
||||
hasDisclosure |= type == UITableViewCellAccessoryDetailDisclosureButton;
|
||||
return hasDisclosure;
|
||||
}
|
||||
|
||||
@@ -35,9 +35,6 @@ extern NSString * const kFLEXDefaultsRegisterJSONExplorerKey;
|
||||
/// Whether or not to register the object explorer as a JSON viewer on launch
|
||||
@property (nonatomic) BOOL flex_registerDictionaryJSONViewerOnLaunch;
|
||||
|
||||
/// The last selected screen in the network observer
|
||||
@property (nonatomic) NSInteger flex_lastNetworkObserverMode;
|
||||
|
||||
/// Disable os_log and re-enable ASL. May break Console.app output.
|
||||
@property (nonatomic) BOOL flex_disableOSLog;
|
||||
@property (nonatomic) BOOL flex_cacheOSLogMessages;
|
||||
|
||||
@@ -16,7 +16,6 @@ NSString * const kFLEXDefaultsHidePrivateMethodsKey = @"com.flipboard.FLEX.hide_
|
||||
NSString * const kFLEXDefaultsShowMethodOverridesKey = @"com.flipboard.FLEX.show_method_overrides";
|
||||
NSString * const kFLEXDefaultsHideVariablePreviewsKey = @"com.flipboard.FLEX.hide_variable_previews";
|
||||
NSString * const kFLEXDefaultsNetworkObserverEnabledKey = @"com.flex.FLEXNetworkObserver.enableOnLaunch";
|
||||
NSString * const kFLEXDefaultsNetworkObserverLastModeKey = @"com.flex.FLEXNetworkObserver.lastMode";
|
||||
NSString * const kFLEXDefaultsNetworkHostDenylistKey = @"com.flipboard.FLEX.network_host_denylist";
|
||||
NSString * const kFLEXDefaultsDisableOSLogForceASLKey = @"com.flipboard.FLEX.try_disable_os_log";
|
||||
NSString * const kFLEXDefaultsRegisterJSONExplorerKey = @"com.flipboard.FLEX.view_json_as_object";
|
||||
@@ -93,14 +92,6 @@ NSString * const kFLEXDefaultsRegisterJSONExplorerKey = @"com.flipboard.FLEX.vie
|
||||
[self setBool:enable forKey:kFLEXDefaultsRegisterJSONExplorerKey];
|
||||
}
|
||||
|
||||
- (NSInteger)flex_lastNetworkObserverMode {
|
||||
return [self integerForKey:kFLEXDefaultsNetworkObserverLastModeKey];
|
||||
}
|
||||
|
||||
- (void)setFlex_lastNetworkObserverMode:(NSInteger)mode {
|
||||
[self setInteger:mode forKey:kFLEXDefaultsNetworkObserverLastModeKey];
|
||||
}
|
||||
|
||||
#pragma mark System Log
|
||||
|
||||
- (BOOL)flex_disableOSLog {
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
+ (SEL)swizzledSelectorForSelector:(SEL)selector;
|
||||
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls;
|
||||
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)cls withBlock:(id)block swizzledSelector:(SEL)swizzledSelector;
|
||||
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)class withBlock:(id)block swizzledSelector:(SEL)swizzledSelector;
|
||||
+ (void)replaceImplementationOfSelector:(SEL)selector withSelector:(SEL)swizzledSelector forClass:(Class)cls withMethodDescription:(struct objc_method_description)methodDescription implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock;
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
//
|
||||
// FLEXMetadataExtras.h
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 4/26/22.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FLEXMethodBase.h"
|
||||
#import "FLEXProperty.h"
|
||||
#import "FLEXIvar.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// A dictionary mapping type encoding strings to an array of field titles
|
||||
extern NSString * const FLEXAuxiliarynfoKeyFieldLabels;
|
||||
|
||||
@protocol FLEXMetadataAuxiliaryInfo <NSObject>
|
||||
|
||||
/// Used to supply arbitrary additional data that need not be exposed by their own properties
|
||||
- (nullable id)auxiliaryInfoForKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
@interface FLEXMethodBase (Auxiliary) <FLEXMetadataAuxiliaryInfo> @end
|
||||
@interface FLEXProperty (Auxiliary) <FLEXMetadataAuxiliaryInfo> @end
|
||||
@interface FLEXIvar (Auxiliary) <FLEXMetadataAuxiliaryInfo> @end
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -1,22 +0,0 @@
|
||||
//
|
||||
// FLEXMetadataExtras.m
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 4/26/22.
|
||||
//
|
||||
|
||||
#import "FLEXMetadataExtras.h"
|
||||
|
||||
NSString * const FLEXAuxiliarynfoKeyFieldLabels = @"FLEXAuxiliarynfoKeyFieldLabels";
|
||||
|
||||
@implementation FLEXMethodBase (Auxiliary)
|
||||
- (id)auxiliaryInfoForKey:(NSString *)key { return nil; }
|
||||
@end
|
||||
|
||||
@implementation FLEXProperty (Auxiliary)
|
||||
- (id)auxiliaryInfoForKey:(NSString *)key { return nil; }
|
||||
@end
|
||||
|
||||
@implementation FLEXIvar (Auxiliary)
|
||||
- (id)auxiliaryInfoForKey:(NSString *)key { return nil; }
|
||||
@end
|
||||
@@ -175,6 +175,7 @@
|
||||
92E1E1EECA3F2533E1B8BF35 /* Pods-FLEXample.debug.xcconfig */,
|
||||
BE1780244AEC542DDB894B08 /* Pods-FLEXample.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -431,7 +432,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"FLEXample/Supporting Files/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = S6N2F22V2Z;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = "FLEXample/Supporting Files/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
@@ -456,7 +457,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"FLEXample/Supporting Files/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DEVELOPMENT_TEAM = S6N2F22V2Z;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = "FLEXample/Supporting Files/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
C386D705241AA61600699085 /* music_library_schema.jpg in Resources */ = {isa = PBXBuildFile; fileRef = C386D703241AA61600699085 /* music_library_schema.jpg */; };
|
||||
C386D70B241AA67800699085 /* Dog.m in Sources */ = {isa = PBXBuildFile; fileRef = C386D709241AA67800699085 /* Dog.m */; };
|
||||
C386D70C241AA67800699085 /* Owner.m in Sources */ = {isa = PBXBuildFile; fileRef = C386D70A241AA67800699085 /* Owner.m */; };
|
||||
C38D96EC2818F306008709D0 /* Reflex in Frameworks */ = {isa = PBXBuildFile; productRef = C38D96EB2818F306008709D0 /* Reflex */; };
|
||||
C3A67856241AB8AD005A4681 /* MiscNetworkRequests.m in Sources */ = {isa = PBXBuildFile; fileRef = C3A67855241AB8AD005A4681 /* MiscNetworkRequests.m */; };
|
||||
C3A67858241ADDF7005A4681 /* Commit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3A67857241ADDF7005A4681 /* Commit.swift */; };
|
||||
C3B3760025B8CDA300AD43AB /* Person.m in Sources */ = {isa = PBXBuildFile; fileRef = C3B375FF25B8CDA300AD43AB /* Person.m */; };
|
||||
C3F86CD72740ED2600E094BF /* Reflex in Frameworks */ = {isa = PBXBuildFile; productRef = C3F86CD62740ED2600E094BF /* Reflex */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -62,7 +62,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C38D96EC2818F306008709D0 /* Reflex in Frameworks */,
|
||||
C3F86CD72740ED2600E094BF /* Reflex in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -183,7 +183,7 @@
|
||||
);
|
||||
name = FLEXample;
|
||||
packageProductDependencies = (
|
||||
C38D96EB2818F306008709D0 /* Reflex */,
|
||||
C3F86CD62740ED2600E094BF /* Reflex */,
|
||||
);
|
||||
productName = FLEXample;
|
||||
productReference = C386D6CC2419975A00699085 /* FLEXample.app */;
|
||||
@@ -215,7 +215,7 @@
|
||||
);
|
||||
mainGroup = C386D6C32419975A00699085;
|
||||
packageReferences = (
|
||||
C38D96EA2818F306008709D0 /* XCRemoteSwiftPackageReference "Reflex" */,
|
||||
C3F86CD52740ED2600E094BF /* XCRemoteSwiftPackageReference "Reflex" */,
|
||||
);
|
||||
productRefGroup = C386D6CD2419975A00699085 /* Products */;
|
||||
projectDirPath = "";
|
||||
@@ -462,7 +462,7 @@
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
C38D96EA2818F306008709D0 /* XCRemoteSwiftPackageReference "Reflex" */ = {
|
||||
C3F86CD52740ED2600E094BF /* XCRemoteSwiftPackageReference "Reflex" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "file:///Users/tanner/Repos/Reflex";
|
||||
requirement = {
|
||||
@@ -473,9 +473,9 @@
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
C38D96EB2818F306008709D0 /* Reflex */ = {
|
||||
C3F86CD62740ED2600E094BF /* Reflex */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = C38D96EA2818F306008709D0 /* XCRemoteSwiftPackageReference "Reflex" */;
|
||||
package = C3F86CD52740ED2600E094BF /* XCRemoteSwiftPackageReference "Reflex" */;
|
||||
productName = Reflex;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
|
||||
@@ -44,8 +44,8 @@ public class CommitIdentity: NSObject, Codable {
|
||||
}
|
||||
}
|
||||
|
||||
//@objcMembers
|
||||
public struct CommitDetails: Codable {
|
||||
@objcMembers
|
||||
public class CommitDetails: NSObject, Codable {
|
||||
public let message: String
|
||||
public let url: String
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
self.navigationItem.rightBarButtonItem = [UIBarButtonItem
|
||||
flex_itemWithTitle:@"FLEX" target:FLEXManager.sharedManager action:@selector(toggleExplorer)
|
||||
];
|
||||
self.navigationItem.rightBarButtonItem.accessibilityIdentifier = @"toggle-explorer";
|
||||
|
||||
// Load and process commits
|
||||
NSString *commitsURL = @"https://api.github.com/repos/Flipboard/FLEX/commits";
|
||||
|
||||
+1
-5
@@ -36,11 +36,7 @@ Pod::Spec.new do |spec|
|
||||
spec.frameworks = [ "Foundation", "UIKit", "CoreGraphics", "ImageIO", "QuartzCore", "WebKit", "Security", "SceneKit" ]
|
||||
spec.libraries = [ "z", "sqlite3" ]
|
||||
spec.requires_arc = true
|
||||
spec.library = 'stdc++'
|
||||
spec.xcconfig = {
|
||||
'CLANG_CXX_LANGUAGE_STANDARD' => 'gnu++11',
|
||||
}
|
||||
spec.compiler_flags = "-Wno-unsupported-availability-guard", "-Wno-deprecated-declarations"
|
||||
spec.compiler_flags = "-Wno-unsupported-availability-guard"
|
||||
spec.public_header_files = [ "Classes/*.h", "Classes/Manager/*.h", "Classes/Toolbar/*.h",
|
||||
"Classes/Core/Controllers/*.h", "Classes/Core/Views/*.h",
|
||||
"Classes/Core/Views/Cells/*.h", "Classes/Core/*.h",
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
03ED813D24B7D91200831CA0 /* FLEXTableRowDataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 03ED813B24B7D91200831CA0 /* FLEXTableRowDataViewController.m */; };
|
||||
03ED813E24B7D91200831CA0 /* FLEXTableRowDataViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 03ED813C24B7D91200831CA0 /* FLEXTableRowDataViewController.h */; };
|
||||
04F1CA191C137CF1000A52B0 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 04F1CA181C137CF1000A52B0 /* LICENSE */; };
|
||||
1C27A8B91F0E5A0400F0D02D /* FLEXTestsMethodsList.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C27A8B81F0E5A0400F0D02D /* FLEXTestsMethodsList.m */; };
|
||||
1C27A8BB1F0E5A0400F0D02D /* FLEX.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4C941F1B5B20570088C3F2 /* FLEX.framework */; };
|
||||
@@ -141,7 +139,6 @@
|
||||
94AAF0381BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 94AAF0361BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
94AAF0391BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 94AAF0371BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m */; };
|
||||
94AAF03A1BAF2F0300DE8760 /* FLEXKeyboardShortcutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 942DCD821BAE0AD300DB5DC2 /* FLEXKeyboardShortcutManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
A42069CF2809377F00EBCAEA /* FLEXFirebaseTransaction.mm in Sources */ = {isa = PBXBuildFile; fileRef = A42069CE2809377F00EBCAEA /* FLEXFirebaseTransaction.mm */; };
|
||||
C301994A2409B38A00759E8E /* CALayer+FLEX.h in Headers */ = {isa = PBXBuildFile; fileRef = C30199482409B38A00759E8E /* CALayer+FLEX.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C301994B2409B38A00759E8E /* CALayer+FLEX.m in Sources */ = {isa = PBXBuildFile; fileRef = C30199492409B38A00759E8E /* CALayer+FLEX.m */; };
|
||||
C309B82F223ED64400B228EC /* FLEXLogController.h in Headers */ = {isa = PBXBuildFile; fileRef = C309B82D223ED64400B228EC /* FLEXLogController.h */; };
|
||||
@@ -163,7 +160,7 @@
|
||||
C313854923F5F7D50046E63C /* flex_fishhook.h in Headers */ = {isa = PBXBuildFile; fileRef = C313854723F5F7D50046E63C /* flex_fishhook.h */; };
|
||||
C31C4A6923342A2200C35F12 /* FLEXMetadataSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C31C4A6723342A2200C35F12 /* FLEXMetadataSection.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C31C4A6A23342A2200C35F12 /* FLEXMetadataSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C31C4A6823342A2200C35F12 /* FLEXMetadataSection.m */; };
|
||||
C31D93E423E38CBE005517BF /* FLEXBlockShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C31D93E223E38CBE005517BF /* FLEXBlockShortcuts.h */; };
|
||||
C31D93E423E38CBE005517BF /* FLEXBlockShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C31D93E223E38CBE005517BF /* FLEXBlockShortcuts.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C31D93E523E38CBE005517BF /* FLEXBlockShortcuts.m in Sources */ = {isa = PBXBuildFile; fileRef = C31D93E323E38CBE005517BF /* FLEXBlockShortcuts.m */; };
|
||||
C31D93E823E38E97005517BF /* FLEXBlockDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = C31D93E623E38E97005517BF /* FLEXBlockDescription.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C31D93E923E38E97005517BF /* FLEXBlockDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = C31D93E723E38E97005517BF /* FLEXBlockDescription.m */; };
|
||||
@@ -184,11 +181,11 @@
|
||||
C3490E20233BDD73002AE200 /* FLEXSingleRowSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C3490E1E233BDD73002AE200 /* FLEXSingleRowSection.m */; };
|
||||
C34C9BDD23A7F2740031CA3E /* FLEXRuntime+UIKitHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = C34C9BDB23A7F2740031CA3E /* FLEXRuntime+UIKitHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C34C9BDE23A7F2740031CA3E /* FLEXRuntime+UIKitHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = C34C9BDC23A7F2740031CA3E /* FLEXRuntime+UIKitHelpers.m */; };
|
||||
C34D4EB023A2ABD900C1F903 /* FLEXLayerShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C34D4EAE23A2ABD900C1F903 /* FLEXLayerShortcuts.h */; };
|
||||
C34D4EB023A2ABD900C1F903 /* FLEXLayerShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C34D4EAE23A2ABD900C1F903 /* FLEXLayerShortcuts.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C34D4EB123A2ABD900C1F903 /* FLEXLayerShortcuts.m in Sources */ = {isa = PBXBuildFile; fileRef = C34D4EAF23A2ABD900C1F903 /* FLEXLayerShortcuts.m */; };
|
||||
C34D4EB423A2AF2A00C1F903 /* FLEXColorPreviewSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C34D4EB223A2AF2A00C1F903 /* FLEXColorPreviewSection.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C34D4EB523A2AF2A00C1F903 /* FLEXColorPreviewSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C34D4EB323A2AF2A00C1F903 /* FLEXColorPreviewSection.m */; };
|
||||
C34D4EB823A2B17900C1F903 /* FLEXBundleShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C34D4EB623A2B17900C1F903 /* FLEXBundleShortcuts.h */; };
|
||||
C34D4EB823A2B17900C1F903 /* FLEXBundleShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C34D4EB623A2B17900C1F903 /* FLEXBundleShortcuts.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C34D4EB923A2B17900C1F903 /* FLEXBundleShortcuts.m in Sources */ = {isa = PBXBuildFile; fileRef = C34D4EB723A2B17900C1F903 /* FLEXBundleShortcuts.m */; };
|
||||
C34EE30821CB23CC00BD3A7C /* FLEXOSLogController.h in Headers */ = {isa = PBXBuildFile; fileRef = C34EE30621CB23CC00BD3A7C /* FLEXOSLogController.h */; };
|
||||
C3511B9122D7C99E0057BAB7 /* FLEXGlobalsSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C3511B8F22D7C99E0057BAB7 /* FLEXGlobalsSection.h */; };
|
||||
@@ -236,7 +233,6 @@
|
||||
C36FBFDC230F3B98008D95D5 /* FLEXIvar.m in Sources */ = {isa = PBXBuildFile; fileRef = C36FBFCA230F3B98008D95D5 /* FLEXIvar.m */; };
|
||||
C37A0C93218BAC9600848CA7 /* FLEXObjcInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = C37A0C91218BAC9600848CA7 /* FLEXObjcInternal.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C37A0C94218BAC9600848CA7 /* FLEXObjcInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = C37A0C92218BAC9600848CA7 /* FLEXObjcInternal.mm */; };
|
||||
C381FDC3271CCB0500401081 /* Firestore.h in Headers */ = {isa = PBXBuildFile; fileRef = C381FDC2271CCB0500401081 /* Firestore.h */; };
|
||||
C383C3B923B6A62A007A321B /* FLEXRuntimeSafety.h in Headers */ = {isa = PBXBuildFile; fileRef = C383C3B723B6A62A007A321B /* FLEXRuntimeSafety.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C383C3BA23B6A62A007A321B /* FLEXRuntimeSafety.m in Sources */ = {isa = PBXBuildFile; fileRef = C383C3B823B6A62A007A321B /* FLEXRuntimeSafety.m */; };
|
||||
C383C3BD23B6B398007A321B /* UITextField+Range.m in Sources */ = {isa = PBXBuildFile; fileRef = C383C3BB23B6B398007A321B /* UITextField+Range.m */; };
|
||||
@@ -264,12 +260,10 @@
|
||||
C387C87B22DFCD6A00750E58 /* FLEXCarouselCell.m in Sources */ = {isa = PBXBuildFile; fileRef = C387C87922DFCD6A00750E58 /* FLEXCarouselCell.m */; };
|
||||
C387C88322E0D24A00750E58 /* UIView+FLEX_Layout.h in Headers */ = {isa = PBXBuildFile; fileRef = C387C88122E0D24A00750E58 /* UIView+FLEX_Layout.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
C387C88422E0D24A00750E58 /* UIView+FLEX_Layout.m in Sources */ = {isa = PBXBuildFile; fileRef = C387C88222E0D24A00750E58 /* UIView+FLEX_Layout.m */; };
|
||||
C38D970228190C93008709D0 /* FLEXMetadataExtras.m in Sources */ = {isa = PBXBuildFile; fileRef = C38D970028190C93008709D0 /* FLEXMetadataExtras.m */; };
|
||||
C38D970328190C93008709D0 /* FLEXMetadataExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = C38D970128190C93008709D0 /* FLEXMetadataExtras.h */; };
|
||||
C38DF0EA22CFE4370077B4AD /* FLEXTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = C38DF0E822CFE4370077B4AD /* FLEXTableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C38DF0EB22CFE4370077B4AD /* FLEXTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C38DF0E922CFE4370077B4AD /* FLEXTableViewController.m */; };
|
||||
C38EF26223A2FCD20047A7EC /* FLEXViewControllerShortcuts.m in Sources */ = {isa = PBXBuildFile; fileRef = C38EF26023A2FCD20047A7EC /* FLEXViewControllerShortcuts.m */; };
|
||||
C38EF26323A2FCD20047A7EC /* FLEXViewControllerShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C38EF26123A2FCD20047A7EC /* FLEXViewControllerShortcuts.h */; };
|
||||
C38EF26323A2FCD20047A7EC /* FLEXViewControllerShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C38EF26123A2FCD20047A7EC /* FLEXViewControllerShortcuts.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C38F3F31230C958F004E3731 /* FLEXAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = C38F3F2F230C958F004E3731 /* FLEXAlert.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C38F3F32230C958F004E3731 /* FLEXAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = C38F3F30230C958F004E3731 /* FLEXAlert.m */; };
|
||||
C397E318240EC98F0091E4EC /* FLEXSQLResult.h in Headers */ = {isa = PBXBuildFile; fileRef = C397E316240EC98F0091E4EC /* FLEXSQLResult.h */; };
|
||||
@@ -301,9 +295,9 @@
|
||||
C398627623AD79B7007E6793 /* NSString+FLEX.h in Headers */ = {isa = PBXBuildFile; fileRef = C398627423AD79B6007E6793 /* NSString+FLEX.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
C398627723AD79B7007E6793 /* NSString+FLEX.m in Sources */ = {isa = PBXBuildFile; fileRef = C398627523AD79B7007E6793 /* NSString+FLEX.m */; };
|
||||
C398682523AC359600E9E391 /* FLEXShortcutsFactory+Defaults.m in Sources */ = {isa = PBXBuildFile; fileRef = C398682323AC359600E9E391 /* FLEXShortcutsFactory+Defaults.m */; };
|
||||
C398682623AC359600E9E391 /* FLEXShortcutsFactory+Defaults.h in Headers */ = {isa = PBXBuildFile; fileRef = C398682423AC359600E9E391 /* FLEXShortcutsFactory+Defaults.h */; };
|
||||
C398682623AC359600E9E391 /* FLEXShortcutsFactory+Defaults.h in Headers */ = {isa = PBXBuildFile; fileRef = C398682423AC359600E9E391 /* FLEXShortcutsFactory+Defaults.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C398682823AC36EC00E9E391 /* FLEXViewShortcuts.m in Sources */ = {isa = PBXBuildFile; fileRef = C3F527C4231891F6009CBA07 /* FLEXViewShortcuts.m */; };
|
||||
C398682923AC370100E9E391 /* FLEXViewShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F527C3231891F6009CBA07 /* FLEXViewShortcuts.h */; };
|
||||
C398682923AC370100E9E391 /* FLEXViewShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F527C3231891F6009CBA07 /* FLEXViewShortcuts.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C39EADC923F37B89005618BE /* FLEXTypeEncodingParser.m in Sources */ = {isa = PBXBuildFile; fileRef = C3854DF123F36C9E00FCD1E2 /* FLEXTypeEncodingParser.m */; };
|
||||
C39ED92822D63F3200B5773A /* FLEXAddressExplorerCoordinator.h in Headers */ = {isa = PBXBuildFile; fileRef = C39ED92622D63F3200B5773A /* FLEXAddressExplorerCoordinator.h */; };
|
||||
C39ED92922D63F3200B5773A /* FLEXAddressExplorerCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = C39ED92722D63F3200B5773A /* FLEXAddressExplorerCoordinator.m */; };
|
||||
@@ -341,7 +335,7 @@
|
||||
C3E5DA02231700EE00E655DB /* FLEXObjectInfoSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C3E5DA00231700EE00E655DB /* FLEXObjectInfoSection.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C3EB6F8D242E9C83006EA386 /* FLEXRuntimeExporter.m in Sources */ = {isa = PBXBuildFile; fileRef = C3EB6F8B242E9C83006EA386 /* FLEXRuntimeExporter.m */; };
|
||||
C3EB6F8E242E9C83006EA386 /* FLEXRuntimeExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = C3EB6F8C242E9C83006EA386 /* FLEXRuntimeExporter.h */; };
|
||||
C3EE76BF22DFC63600EC0AA0 /* FLEXScopeCarousel.h in Headers */ = {isa = PBXBuildFile; fileRef = C3EE76BD22DFC63600EC0AA0 /* FLEXScopeCarousel.h */; };
|
||||
C3EE76BF22DFC63600EC0AA0 /* FLEXScopeCarousel.h in Headers */ = {isa = PBXBuildFile; fileRef = C3EE76BD22DFC63600EC0AA0 /* FLEXScopeCarousel.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C3EE76C022DFC63600EC0AA0 /* FLEXScopeCarousel.m in Sources */ = {isa = PBXBuildFile; fileRef = C3EE76BE22DFC63600EC0AA0 /* FLEXScopeCarousel.m */; };
|
||||
C3F31D3D2267D883003C991A /* FLEXSubtitleTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F31D342267D883003C991A /* FLEXSubtitleTableViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C3F31D3E2267D883003C991A /* FLEXTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F31D352267D883003C991A /* FLEXTableViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -353,11 +347,11 @@
|
||||
C3F31D442267D883003C991A /* FLEXTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = C3F31D3C2267D883003C991A /* FLEXTableView.m */; };
|
||||
C3F527BD2318603F009CBA07 /* FLEXShortcutsSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F527BB2318603F009CBA07 /* FLEXShortcutsSection.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C3F527BE2318603F009CBA07 /* FLEXShortcutsSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C3F527BC2318603F009CBA07 /* FLEXShortcutsSection.m */; };
|
||||
C3F527C12318670F009CBA07 /* FLEXImageShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F527BF2318670F009CBA07 /* FLEXImageShortcuts.h */; };
|
||||
C3F527C12318670F009CBA07 /* FLEXImageShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F527BF2318670F009CBA07 /* FLEXImageShortcuts.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C3F527C22318670F009CBA07 /* FLEXImageShortcuts.m in Sources */ = {isa = PBXBuildFile; fileRef = C3F527C02318670F009CBA07 /* FLEXImageShortcuts.m */; };
|
||||
C3F646C1239EAA8F00D4A011 /* UIPasteboard+FLEX.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F646BF239EAA8F00D4A011 /* UIPasteboard+FLEX.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C3F646C2239EAA8F00D4A011 /* UIPasteboard+FLEX.m in Sources */ = {isa = PBXBuildFile; fileRef = C3F646C0239EAA8F00D4A011 /* UIPasteboard+FLEX.m */; };
|
||||
C3F646F223A045DB00D4A011 /* FLEXClassShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F646F023A045DB00D4A011 /* FLEXClassShortcuts.h */; };
|
||||
C3F646F223A045DB00D4A011 /* FLEXClassShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F646F023A045DB00D4A011 /* FLEXClassShortcuts.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C3F646F323A045DB00D4A011 /* FLEXClassShortcuts.m in Sources */ = {isa = PBXBuildFile; fileRef = C3F646F123A045DB00D4A011 /* FLEXClassShortcuts.m */; };
|
||||
C3F646F623A04A7500D4A011 /* FLEXShortcut.h in Headers */ = {isa = PBXBuildFile; fileRef = C3F646F423A04A7500D4A011 /* FLEXShortcut.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
C3F646F723A04A7500D4A011 /* FLEXShortcut.m in Sources */ = {isa = PBXBuildFile; fileRef = C3F646F523A04A7500D4A011 /* FLEXShortcut.m */; };
|
||||
@@ -380,8 +374,6 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
03ED813B24B7D91200831CA0 /* FLEXTableRowDataViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXTableRowDataViewController.m; sourceTree = "<group>"; };
|
||||
03ED813C24B7D91200831CA0 /* FLEXTableRowDataViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXTableRowDataViewController.h; sourceTree = "<group>"; };
|
||||
04F1CA181C137CF1000A52B0 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
|
||||
1C27A8B61F0E5A0300F0D02D /* FLEXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FLEXTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1C27A8B81F0E5A0400F0D02D /* FLEXTestsMethodsList.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXTestsMethodsList.m; sourceTree = "<group>"; };
|
||||
@@ -521,7 +513,6 @@
|
||||
94A515241C4CA2080063292F /* FLEXExplorerToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FLEXExplorerToolbarItem.m; path = Classes/Toolbar/FLEXExplorerToolbarItem.m; sourceTree = SOURCE_ROOT; };
|
||||
94AAF0361BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXKeyboardHelpViewController.h; sourceTree = "<group>"; };
|
||||
94AAF0371BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXKeyboardHelpViewController.m; sourceTree = "<group>"; };
|
||||
A42069CE2809377F00EBCAEA /* FLEXFirebaseTransaction.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FLEXFirebaseTransaction.mm; sourceTree = "<group>"; };
|
||||
C30199482409B38A00759E8E /* CALayer+FLEX.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CALayer+FLEX.h"; sourceTree = "<group>"; };
|
||||
C30199492409B38A00759E8E /* CALayer+FLEX.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CALayer+FLEX.m"; sourceTree = "<group>"; };
|
||||
C309B82D223ED64400B228EC /* FLEXLogController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXLogController.h; sourceTree = "<group>"; };
|
||||
@@ -619,7 +610,6 @@
|
||||
C36FBFCA230F3B98008D95D5 /* FLEXIvar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXIvar.m; sourceTree = "<group>"; };
|
||||
C37A0C91218BAC9600848CA7 /* FLEXObjcInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXObjcInternal.h; sourceTree = "<group>"; };
|
||||
C37A0C92218BAC9600848CA7 /* FLEXObjcInternal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FLEXObjcInternal.mm; sourceTree = "<group>"; };
|
||||
C381FDC2271CCB0500401081 /* Firestore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Firestore.h; sourceTree = "<group>"; };
|
||||
C383C3B723B6A62A007A321B /* FLEXRuntimeSafety.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXRuntimeSafety.h; sourceTree = "<group>"; };
|
||||
C383C3B823B6A62A007A321B /* FLEXRuntimeSafety.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXRuntimeSafety.m; sourceTree = "<group>"; };
|
||||
C383C3BB23B6B398007A321B /* UITextField+Range.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITextField+Range.m"; sourceTree = "<group>"; };
|
||||
@@ -646,8 +636,6 @@
|
||||
C387C87922DFCD6A00750E58 /* FLEXCarouselCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXCarouselCell.m; sourceTree = "<group>"; };
|
||||
C387C88122E0D24A00750E58 /* UIView+FLEX_Layout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+FLEX_Layout.h"; sourceTree = "<group>"; };
|
||||
C387C88222E0D24A00750E58 /* UIView+FLEX_Layout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+FLEX_Layout.m"; sourceTree = "<group>"; };
|
||||
C38D970028190C93008709D0 /* FLEXMetadataExtras.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXMetadataExtras.m; sourceTree = "<group>"; };
|
||||
C38D970128190C93008709D0 /* FLEXMetadataExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXMetadataExtras.h; sourceTree = "<group>"; };
|
||||
C38DF0E822CFE4370077B4AD /* FLEXTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXTableViewController.h; sourceTree = "<group>"; };
|
||||
C38DF0E922CFE4370077B4AD /* FLEXTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXTableViewController.m; sourceTree = "<group>"; };
|
||||
C38EF26023A2FCD20047A7EC /* FLEXViewControllerShortcuts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXViewControllerShortcuts.m; sourceTree = "<group>"; };
|
||||
@@ -990,7 +978,6 @@
|
||||
3A4C94B41B5B21410088C3F2 /* Network */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C381FDC2271CCB0500401081 /* Firestore.h */,
|
||||
3A4C94B51B5B21410088C3F2 /* FLEXNetworkMITMViewController.h */,
|
||||
3A4C94B61B5B21410088C3F2 /* FLEXNetworkMITMViewController.m */,
|
||||
3A4C94B71B5B21410088C3F2 /* FLEXNetworkRecorder.h */,
|
||||
@@ -999,7 +986,6 @@
|
||||
3A4C94BA1B5B21410088C3F2 /* FLEXNetworkSettingsController.m */,
|
||||
3A4C94BB1B5B21410088C3F2 /* FLEXNetworkTransaction.h */,
|
||||
3A4C94BC1B5B21410088C3F2 /* FLEXNetworkTransaction.m */,
|
||||
A42069CE2809377F00EBCAEA /* FLEXFirebaseTransaction.mm */,
|
||||
C35DAD7E2709140700AA95E6 /* FLEXHTTPTransactionDetailController.h */,
|
||||
C35DAD7F2709140700AA95E6 /* FLEXHTTPTransactionDetailController.m */,
|
||||
C35DAD8C2709143000AA95E6 /* FLEXMITMDataSource.h */,
|
||||
@@ -1069,8 +1055,6 @@
|
||||
779B1ECB1C0C4D7C001F5E49 /* FLEXTableLeftCell.m */,
|
||||
779B1ECC1C0C4D7C001F5E49 /* FLEXTableListViewController.h */,
|
||||
779B1ECD1C0C4D7C001F5E49 /* FLEXTableListViewController.m */,
|
||||
03ED813C24B7D91200831CA0 /* FLEXTableRowDataViewController.h */,
|
||||
03ED813B24B7D91200831CA0 /* FLEXTableRowDataViewController.m */,
|
||||
04F1CA181C137CF1000A52B0 /* LICENSE */,
|
||||
);
|
||||
path = DatabaseBrowser;
|
||||
@@ -1286,8 +1270,6 @@
|
||||
C36FBFC7230F3B98008D95D5 /* FLEXProtocolBuilder.m */,
|
||||
C36FBFC9230F3B98008D95D5 /* FLEXClassBuilder.h */,
|
||||
C36FBFBF230F3B98008D95D5 /* FLEXClassBuilder.m */,
|
||||
C38D970128190C93008709D0 /* FLEXMetadataExtras.h */,
|
||||
C38D970028190C93008709D0 /* FLEXMetadataExtras.m */,
|
||||
);
|
||||
path = Reflection;
|
||||
sourceTree = "<group>";
|
||||
@@ -1508,13 +1490,11 @@
|
||||
3A4C94ED1B5B21410088C3F2 /* FLEXArgumentInputColorView.h in Headers */,
|
||||
C3A9424523C641C1006871A3 /* SceneKit+Snapshot.h in Headers */,
|
||||
3A4C94EB1B5B21410088C3F2 /* FLEXImagePreviewViewController.h in Headers */,
|
||||
C38D970328190C93008709D0 /* FLEXMetadataExtras.h in Headers */,
|
||||
C34D4EB823A2B17900C1F903 /* FLEXBundleShortcuts.h in Headers */,
|
||||
C3694DC223EA147F006625D7 /* UIBarButtonItem+FLEX.h in Headers */,
|
||||
C38F3F31230C958F004E3731 /* FLEXAlert.h in Headers */,
|
||||
C398624D23AD6C67007E6793 /* FLEXKeyPathSearchController.h in Headers */,
|
||||
3A4C95381B5B21410088C3F2 /* FLEXNetworkRecorder.h in Headers */,
|
||||
C381FDC3271CCB0500401081 /* Firestore.h in Headers */,
|
||||
3A4C94251B5B20570088C3F2 /* FLEX.h in Headers */,
|
||||
C383C3C523B6BB81007A321B /* FLEXCodeFontCell.h in Headers */,
|
||||
C3F527C12318670F009CBA07 /* FLEXImageShortcuts.h in Headers */,
|
||||
@@ -1530,7 +1510,6 @@
|
||||
3A4C95301B5B21410088C3F2 /* FLEXSystemLogMessage.h in Headers */,
|
||||
C398625523AD6C67007E6793 /* FLEXObjcRuntimeViewController.h in Headers */,
|
||||
C3E5DA02231700EE00E655DB /* FLEXObjectInfoSection.h in Headers */,
|
||||
03ED813E24B7D91200831CA0 /* FLEXTableRowDataViewController.h in Headers */,
|
||||
C34D4EB023A2ABD900C1F903 /* FLEXLayerShortcuts.h in Headers */,
|
||||
C3F646F623A04A7500D4A011 /* FLEXShortcut.h in Headers */,
|
||||
C3531B9D23E69BB200A184AD /* FLEXManager+Networking.h in Headers */,
|
||||
@@ -1834,7 +1813,6 @@
|
||||
94AAF0391BAF2E1F00DE8760 /* FLEXKeyboardHelpViewController.m in Sources */,
|
||||
C398624E23AD6C67007E6793 /* FLEXRuntimeKeyPath.m in Sources */,
|
||||
C3694DC323EA147F006625D7 /* UIBarButtonItem+FLEX.m in Sources */,
|
||||
C38D970228190C93008709D0 /* FLEXMetadataExtras.m in Sources */,
|
||||
C36FBFD4230F3B98008D95D5 /* FLEXProtocol.m in Sources */,
|
||||
C34D4EB123A2ABD900C1F903 /* FLEXLayerShortcuts.m in Sources */,
|
||||
C38F3F32230C958F004E3731 /* FLEXAlert.m in Sources */,
|
||||
@@ -1881,7 +1859,6 @@
|
||||
3A4C95411B5B21410088C3F2 /* FLEXNetworkTransactionCell.m in Sources */,
|
||||
C3DFCD952416BC6500BB7084 /* FLEXFilteringTableViewController.m in Sources */,
|
||||
C3F527BE2318603F009CBA07 /* FLEXShortcutsSection.m in Sources */,
|
||||
A42069CF2809377F00EBCAEA /* FLEXFirebaseTransaction.mm in Sources */,
|
||||
3A4C94D61B5B21410088C3F2 /* FLEXObjectExplorerViewController.m in Sources */,
|
||||
C383C3BD23B6B398007A321B /* UITextField+Range.m in Sources */,
|
||||
3A4C94DE1B5B21410088C3F2 /* FLEXHeapEnumerator.m in Sources */,
|
||||
@@ -1914,7 +1891,6 @@
|
||||
779B1ED31C0C4D7C001F5E49 /* FLEXTableColumnHeader.m in Sources */,
|
||||
C30D2963261FAE9E00D89649 /* FLEXNSStringShortcuts.m in Sources */,
|
||||
C37A0C94218BAC9600848CA7 /* FLEXObjcInternal.mm in Sources */,
|
||||
03ED813D24B7D91200831CA0 /* FLEXTableRowDataViewController.m in Sources */,
|
||||
C31D93E523E38CBE005517BF /* FLEXBlockShortcuts.m in Sources */,
|
||||
C312A13123ECB5D300E38049 /* FLEXBookmarkManager.m in Sources */,
|
||||
C34D4EB523A2AF2A00C1F903 /* FLEXColorPreviewSection.m in Sources */,
|
||||
@@ -2154,7 +2130,7 @@
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
INFOPLIST_FILE = Classes/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
INSTALL_PATH = "@rpath";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.flipboard.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
@@ -2190,7 +2166,7 @@
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
INFOPLIST_FILE = Classes/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
INSTALL_PATH = "@rpath";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.flipboard.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
|
||||
Reference in New Issue
Block a user