Compare commits
298 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cf1c33a400 | |||
| 4bc797458a | |||
| 09570e3598 | |||
| 89d07a14e1 | |||
| 1bbf8dbea1 | |||
| 343eba92b6 | |||
| d6232baf03 | |||
| 9808b89d6d | |||
| de1cbfae4a | |||
| b036fb18a5 | |||
| c6ed5098cf | |||
| d7283cd22d | |||
| 785e181d75 | |||
| dd66f46a7b | |||
| 55bae8b53e | |||
| 5edca3fdad | |||
| 9bc319a38e | |||
| deac628b06 | |||
| 8e44d88c36 | |||
| 73e4a712e8 | |||
| 9e1f60b2f4 | |||
| 3c385143ee | |||
| e0acf59d06 | |||
| f00af28418 | |||
| 2bd809ae6c | |||
| 003b8f88e8 | |||
| 5e780e6d0c | |||
| 17ea4976c1 | |||
| fbda722f11 | |||
| b351b788d5 | |||
| a195840b67 | |||
| 9b946dda5d | |||
| 806cdc6acb | |||
| aadfc69f01 | |||
| 6e0135d4a0 | |||
| 2599a1eb0d | |||
| c96df6d35c | |||
| fff3059099 | |||
| 4bee6d17bc | |||
| 3d8a12027b | |||
| bc96542856 | |||
| 24526a6a0a | |||
| d33d909fa0 | |||
| 0a9db69419 | |||
| 2db78c3bef | |||
| 1b91bc963e | |||
| 56d90748cb | |||
| 9997721e0a | |||
| bedbd0b8c8 | |||
| cb64c88c59 | |||
| be733c30cb | |||
| e46d26034b | |||
| 3809ece1f9 | |||
| b2410750fd | |||
| 72ccd007b3 | |||
| 4375f1a67f | |||
| 393a43754c | |||
| b56d6f6d33 | |||
| 0d985b504b | |||
| 148890914d | |||
| c734ad16e5 | |||
| ac6301437b | |||
| b45c655ba2 | |||
| 83fe11210e | |||
| e80e3bb5b7 | |||
| 833b8e7534 | |||
| 56e8693c41 | |||
| 49eeb28464 | |||
| a24d752313 | |||
| 643523a779 | |||
| 65744675db | |||
| f994346919 | |||
| a7a8b8e33e | |||
| f254720408 | |||
| e6fd5ed24e | |||
| d13f263492 | |||
| ba36647398 | |||
| 9d97533649 | |||
| 96b13e66b6 | |||
| 9712a4c869 | |||
| 8f9956308f | |||
| 69e88acbee | |||
| 07587986df | |||
| e6641a5f9d | |||
| 111fb6c9e6 | |||
| 995e7eadbe | |||
| ac50a6d36b | |||
| af40ce0909 | |||
| fb2a33876e | |||
| a42efe17a1 | |||
| 4bc2d1c7a9 | |||
| c7ebecfcb3 | |||
| 208f0a31e4 | |||
| 2aeb34a67e | |||
| 39f16bd039 | |||
| eea681d6c5 | |||
| a8768da4b9 | |||
| 4f6fd29d38 | |||
| ba9cb43b6a | |||
| 3af6da8554 | |||
| 6c21395ac8 | |||
| 456fda31cd | |||
| 9fc8735925 | |||
| 9683acbe4f | |||
| 86a1cc9324 | |||
| 88b14b3a92 | |||
| b9cd2682a7 | |||
| 64d1534fae | |||
| 8318902826 | |||
| a7f41fe5fc | |||
| 2983649cdb | |||
| d2e0db8773 | |||
| fd98070166 | |||
| 4a9fd00eda | |||
| 97205fc808 | |||
| 0cffe72a8f | |||
| d5ab2ee916 | |||
| 90c9a48694 | |||
| 0222c682a0 | |||
| 1e6f6ee110 | |||
| 00d6b348f0 | |||
| 5404f37d0f | |||
| 1e539c7129 | |||
| ca1b202949 | |||
| 62220a9a65 | |||
| 02730c6c86 | |||
| 68789fbe1d | |||
| b4261f8647 | |||
| 94bf4eac2a | |||
| bed52392e5 | |||
| c4891840bd | |||
| 9720227ac7 | |||
| 74622aaf10 | |||
| 0cb5ad8453 | |||
| def68eae48 | |||
| ffa658c49b | |||
| 6066de480f | |||
| 0fd7dfa002 | |||
| 60403e614d | |||
| fa7db997bd | |||
| d15e72c681 | |||
| 4f1ff7784d | |||
| 8129a034e3 | |||
| 838db6954b | |||
| 5b3d3af99c | |||
| 2f9f266493 | |||
| 9d94979d08 | |||
| 19b83f4404 | |||
| 2b13378d98 | |||
| 4ae9d41104 | |||
| 1490170eb4 | |||
| cd695ed106 | |||
| 69c1719159 | |||
| 4019518bf5 | |||
| 3fd8e7c77d | |||
| 99c3bcb8c5 | |||
| b587e96e70 | |||
| ef8f0a303e | |||
| cfb1e4caab | |||
| 2411c331cd | |||
| fd4b38f46d | |||
| 269e31894c | |||
| 2f2da50aed | |||
| d87779212c | |||
| 5db6a12c6e | |||
| 6d0f776102 | |||
| 6c83ddc2c7 | |||
| b510d24e13 | |||
| 6cdf2e61dc | |||
| 9b0ed83ff5 | |||
| dbe1b93f48 | |||
| 06444f1576 | |||
| 9bbf1d0d48 | |||
| 0562f15cd0 | |||
| eb63c91481 | |||
| f916174070 | |||
| 60e23e126e | |||
| afeff1b562 | |||
| 5acb33005b | |||
| 3446eff353 | |||
| ad1f1f579e | |||
| e03b5f7e5d | |||
| d010c82dd0 | |||
| 652d03c39a | |||
| 1d39669a52 | |||
| d558ca6852 | |||
| ad32ca0f05 | |||
| 67097982ea | |||
| 1342d3029c | |||
| 62dcef4644 | |||
| 7ee296143e | |||
| c6bac54597 | |||
| 5f7bce64ed | |||
| d2dde55bb1 | |||
| f1a0a5c5e5 | |||
| 0db073459e | |||
| 7c7ed9286f | |||
| aac88dd6c8 | |||
| d7376b75cd | |||
| 5b39b3ed03 | |||
| bbaa85bdbf | |||
| 34e27bc5d9 | |||
| 714307273e | |||
| 5242d3c5a1 | |||
| cf2e94a1d2 | |||
| 800acb4cad | |||
| 368ce64121 | |||
| 05f03090a9 | |||
| a8803781e8 | |||
| 170f74b297 | |||
| 0d0f2a3073 | |||
| d6bddf5199 | |||
| 258ec8697b | |||
| 8f9a6e88ec | |||
| c37270e6ac | |||
| ce10d45c29 | |||
| b2716c4b2e | |||
| ab135ba94e | |||
| bcc04f4113 | |||
| 470b3fa3b3 | |||
| e84dfeae5c | |||
| 44e86e59b7 | |||
| ac6d9cfa3f | |||
| 1a59711760 | |||
| b60ce7a057 | |||
| b4ac210bef | |||
| 9360c58975 | |||
| 43d9a460ce | |||
| 15fee5a8a5 | |||
| fad038392b | |||
| 558d65a0b0 | |||
| 077fca36c0 | |||
| 947769f6f9 | |||
| 7c480c5faf | |||
| fa6c72cb08 | |||
| 9af2926ec1 | |||
| 366a8266bd | |||
| 713fbac54a | |||
| 8198fba689 | |||
| 20e14a36c9 | |||
| 176e98518d | |||
| 31440056c1 | |||
| 6c7b39ed03 | |||
| 96989f7e0c | |||
| 22a23b3b12 | |||
| 90a855a289 | |||
| fd67373995 | |||
| 3b5e095f74 | |||
| c7850df186 | |||
| 6bbcc55cf6 | |||
| e63ea4bbff | |||
| 5a760fb1ac | |||
| e63f2ee3ad | |||
| 46c6dcb7e6 | |||
| bf42bbe27b | |||
| e89fec4b2d | |||
| 715bb92929 | |||
| 109074f98e | |||
| 45fbdb7914 | |||
| cb2e0789d8 | |||
| de1ca783b6 | |||
| 3a9c24b784 | |||
| b57a333fc9 | |||
| 288bf1343e | |||
| a0b1caed54 | |||
| 9282c61183 | |||
| ee6677ee08 | |||
| 3276eb3516 | |||
| a3fa7bbadc | |||
| 637074b354 | |||
| 547bfbaec0 | |||
| 4e1fcf4682 | |||
| 4d50fd2020 | |||
| 2c510c8ca1 | |||
| 8283e2a8e7 | |||
| 3f82631a95 | |||
| d77864494d | |||
| c5ed6d4ece | |||
| 9412f6eccf | |||
| d9aa102e77 | |||
| 6f80476135 | |||
| e18a854a9f | |||
| 0d676e2504 | |||
| fcca09e74a | |||
| 107e44a399 | |||
| e79a3db255 | |||
| bec9ffd981 | |||
| d4070ed9b7 | |||
| 01e4af47e2 | |||
| 220af5c350 | |||
| 15fd16d395 | |||
| af87ea14e0 | |||
| 5c8b334a84 | |||
| d3c3c61ab1 | |||
| c28952f6e9 | |||
| aaf7ffec85 | |||
| 3ef55eac62 | |||
| 515806e194 |
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [NSExceptional]
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report a bug in FLEX
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Environment
|
||||
- Platform+version: **iOS 14** <!--- Change to match your platform and version -->
|
||||
- FLEX version: **9.9.9** <!--- Change to the version of FLEX you're using -->
|
||||
<!--- FLEXing / libFLEX users: please include FLEXing and libFLEX versions separately -->
|
||||
|
||||
### Bug Report
|
||||
|
||||
Here, you can provide a description of the bug. Some tips:
|
||||
|
||||
- Please do not paste an entire crash log. Upload the crash log to something like [ghostbin.co](https://ghostbin.co/) or another paste service. Alternatively, you can cut out the relevant stack trace and paste that inside a ` ```code block``` `
|
||||
- If the bug is more complex than "this button is broken" or a crash, consider including a sample project. For example, if your app's requests aren't showing up in the network history page.
|
||||
- Providing steps to reproduce is always helpful!
|
||||
- If you want to include a screenshot or GIF, consider modifying the default markdown for uploaded images to use this code to make the image smaller on desktop:
|
||||
```
|
||||
<img width="50%" src=your-image-url >
|
||||
```
|
||||
|
||||
This template is a suggestion. You may format your issue however you want, but generally you should at least include your iOS version and FLEX version.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest a new feature for FLEX
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -20,3 +20,6 @@ DerivedData
|
||||
/Example/Pods
|
||||
Podfile.lock
|
||||
IDEWorkspaceChecks.plist
|
||||
*.xcworkspace
|
||||
.build
|
||||
bazel-*
|
||||
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"search.exclude": {
|
||||
"Classes/Headers": true
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
FLEX_PUBLIC_HDRS = glob([
|
||||
"Classes/*.h",
|
||||
"Classes/Manager/*.h",
|
||||
"Classes/Toolbar/*.h",
|
||||
"Classes/Core/**/*.h",
|
||||
"Classes/Utility/Runtime/Objc/**/*.h",
|
||||
"Classes/Utility/Runtime/Objc/*.h",
|
||||
"Classes/ObjectExplorers/**/*.h",
|
||||
"Classes/Editing/**/*.h",
|
||||
"Classes/GlobalStateExplorers/**/*.h",
|
||||
"Classes/Utility/Categories/*.h",
|
||||
], [
|
||||
"**/FLEX.h"
|
||||
], allow_empty = False
|
||||
) + [
|
||||
"Classes/Utility/FLEXMacros.h",
|
||||
"Classes/Utility/FLEXAlert.h",
|
||||
"Classes/Utility/FLEXResources.h",
|
||||
"Classes/Utility/FLEXHeapEnumerator.h"
|
||||
]
|
||||
|
||||
objc_library(
|
||||
name = "FLEX",
|
||||
module_name = "FLEX",
|
||||
hdrs = FLEX_PUBLIC_HDRS,
|
||||
srcs = glob([
|
||||
"Classes/**/*.m",
|
||||
"Classes/**/*.mm",
|
||||
"Classes/**/*.c",
|
||||
"Classes/**/*.h"
|
||||
], FLEX_PUBLIC_HDRS, allow_empty = False),
|
||||
sdk_dylibs = [
|
||||
"libz",
|
||||
"libsqlite3"
|
||||
],
|
||||
sdk_frameworks = [
|
||||
"Foundation",
|
||||
"UIKit",
|
||||
"CoreGraphics",
|
||||
"ImageIO",
|
||||
"QuartzCore",
|
||||
"WebKit",
|
||||
"Security",
|
||||
"SceneKit"
|
||||
],
|
||||
copts = [
|
||||
"-Wno-deprecated-declarations",
|
||||
"-Wno-unsupported-availability-guard"
|
||||
],
|
||||
visibility = ["//visibility:public"]
|
||||
)
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 3/9/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableViewController.h"
|
||||
#import "Classes/Headers/FLEXTableViewController.h"
|
||||
|
||||
#pragma mark - FLEXTableViewFiltering
|
||||
@protocol FLEXTableViewFiltering <FLEXSearchResultsUpdating>
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 3/9/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXFilteringTableViewController.h"
|
||||
#import "FLEXTableViewSection.h"
|
||||
#import "NSArray+FLEX.h"
|
||||
#import "Classes/Headers/FLEXFilteringTableViewController.h"
|
||||
#import "Classes/Headers/FLEXTableViewSection.h"
|
||||
#import "Classes/Utility/Categories/NSArray+FLEX.h"
|
||||
#import "Classes/Utility/FLEXMacros.h"
|
||||
|
||||
@interface FLEXFilteringTableViewController ()
|
||||
|
||||
@@ -73,7 +74,7 @@
|
||||
#pragma mark - Search
|
||||
|
||||
- (void)updateSearchResults:(NSString *)newText {
|
||||
NSArray *(^filter)() = ^NSArray *{
|
||||
NSArray *(^filter)(void) = ^NSArray *{
|
||||
self.filterText = newText;
|
||||
|
||||
// Sections will adjust data based on this property
|
||||
@@ -111,9 +112,18 @@
|
||||
|
||||
- (void)setAllSections:(NSArray<FLEXTableViewSection *> *)allSections {
|
||||
_allSections = allSections.copy;
|
||||
// Only display nonempty sections
|
||||
self.sections = self.nonemptySections;
|
||||
}
|
||||
|
||||
- (void)setSections:(NSArray<FLEXTableViewSection *> *)sections {
|
||||
// Allow sections to reload a portion of the table view at will
|
||||
[sections enumerateObjectsUsingBlock:^(FLEXTableViewSection *s, NSUInteger idx, BOOL *stop) {
|
||||
[s setTable:self.tableView section:idx];
|
||||
}];
|
||||
_sections = sections.copy;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - UITableViewDataSource
|
||||
|
||||
@@ -178,8 +188,6 @@
|
||||
[self.filterDelegate.sections[indexPath.section] didPressInfoButtonAction:indexPath.row](self);
|
||||
}
|
||||
|
||||
#if FLEX_AT_LEAST_IOS13_SDK
|
||||
|
||||
- (UIContextMenuConfiguration *)tableView:(UITableView *)tableView contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point __IOS_AVAILABLE(13.0) {
|
||||
FLEXTableViewSection *section = self.filterDelegate.sections[indexPath.section];
|
||||
NSString *title = [section menuTitleForRow:indexPath.row];
|
||||
@@ -198,6 +206,4 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 1/30/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
@@ -16,4 +16,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@end
|
||||
|
||||
@interface UINavigationController (FLEXObjectExploring)
|
||||
|
||||
/// Push an object explorer view controller onto the navigation stack
|
||||
- (void)pushExplorerForObject:(id)object;
|
||||
/// Push an object explorer view controller onto the navigation stack
|
||||
- (void)pushExplorerForObject:(id)object animated:(BOOL)animated;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 1/30/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXNavigationController.h"
|
||||
#import "FLEXExplorerViewController.h"
|
||||
#import "FLEXTabList.h"
|
||||
#import "Classes/Headers/FLEXNavigationController.h"
|
||||
#import "Classes/ExplorerInterface/FLEXExplorerViewController.h"
|
||||
#import "Classes/Headers/FLEXObjectExplorerFactory.h"
|
||||
#import "Classes/ExplorerInterface/Tabs/FLEXTabList.h"
|
||||
|
||||
@interface UINavigationController (Private) <UIGestureRecognizerDelegate>
|
||||
- (void)_gestureRecognizedInteractiveHide:(UIGestureRecognizer *)sender;
|
||||
@@ -20,6 +21,7 @@
|
||||
@interface FLEXNavigationController ()
|
||||
@property (nonatomic, readonly) BOOL toolbarWasHidden;
|
||||
@property (nonatomic) BOOL waitingToAddTab;
|
||||
@property (nonatomic, readonly) BOOL canShowToolbar;
|
||||
@property (nonatomic) BOOL didSetupPendingDismissButtons;
|
||||
@property (nonatomic) UISwipeGestureRecognizer *navigationBarSwipeGesture;
|
||||
@end
|
||||
@@ -27,7 +29,8 @@
|
||||
@implementation FLEXNavigationController
|
||||
|
||||
+ (instancetype)withRootViewController:(UIViewController *)rootVC {
|
||||
return [[self alloc] initWithRootViewController:rootVC];
|
||||
FLEXNavigationController *nav = [[self alloc] initWithRootViewController:rootVC];
|
||||
return nav;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
@@ -36,10 +39,13 @@
|
||||
self.waitingToAddTab = YES;
|
||||
|
||||
// Add gesture to reveal toolbar if hidden
|
||||
self.navigationBar.userInteractionEnabled = YES;
|
||||
[self.navigationBar addGestureRecognizer:[[UITapGestureRecognizer alloc]
|
||||
UITapGestureRecognizer *navbarTapGesture = [[UITapGestureRecognizer alloc]
|
||||
initWithTarget:self action:@selector(handleNavigationBarTap:)
|
||||
]];
|
||||
];
|
||||
|
||||
// Don't cancel touches to work around bug on versions of iOS prior to 13
|
||||
navbarTapGesture.cancelsTouchesInView = NO;
|
||||
[self.navigationBar addGestureRecognizer:navbarTapGesture];
|
||||
|
||||
// Add gesture to dismiss if not presented with a sheet style
|
||||
if (@available(iOS 13, *)) {
|
||||
@@ -61,6 +67,17 @@
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
if (@available(iOS 15.0, *)) {
|
||||
UISheetPresentationController *presenter = self.sheetPresentationController;
|
||||
presenter.detents = @[
|
||||
UISheetPresentationControllerDetent.mediumDetent,
|
||||
UISheetPresentationControllerDetent.largeDetent,
|
||||
];
|
||||
presenter.prefersScrollingExpandsWhenScrolledToEdge = NO;
|
||||
presenter.selectedDetentIdentifier = UISheetPresentationControllerDetentIdentifierLarge;
|
||||
presenter.largestUndimmedDetentIdentifier = UISheetPresentationControllerDetentIdentifierLarge;
|
||||
}
|
||||
|
||||
if (self.beingPresented && !self.didSetupPendingDismissButtons) {
|
||||
for (UIViewController *vc in self.viewControllers) {
|
||||
[self addNavigationBarItemsToViewController:vc.navigationItem];
|
||||
@@ -89,13 +106,27 @@
|
||||
[self addNavigationBarItemsToViewController:viewController.navigationItem];
|
||||
}
|
||||
|
||||
- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion {
|
||||
// Workaround for UIActivityViewController trying to dismiss us for some reason
|
||||
if (![self.viewControllers.lastObject.presentedViewController isKindOfClass:UIActivityViewController.self]) {
|
||||
[super dismissViewControllerAnimated:flag completion:completion];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dismissAnimated {
|
||||
// Tabs are only closed if the done button is pressed; this
|
||||
// allows you to leave a tab open by dragging down to dismiss
|
||||
[FLEXTabList.sharedList closeTab:self];
|
||||
if ([self.presentingViewController isKindOfClass:[FLEXExplorerViewController class]]) {
|
||||
[FLEXTabList.sharedList closeTab:self];
|
||||
}
|
||||
|
||||
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (BOOL)canShowToolbar {
|
||||
return self.topViewController.toolbarItems.count > 0;
|
||||
}
|
||||
|
||||
- (void)addNavigationBarItemsToViewController:(UINavigationItem *)navigationItem {
|
||||
if (!self.presentingViewController) {
|
||||
return;
|
||||
@@ -145,8 +176,15 @@
|
||||
}
|
||||
|
||||
- (void)handleNavigationBarTap:(UIGestureRecognizer *)sender {
|
||||
// Don't reveal the toolbar if we were just tapping a button
|
||||
CGPoint location = [sender locationInView:self.navigationBar];
|
||||
UIView *hitView = [self.navigationBar hitTest:location withEvent:nil];
|
||||
if ([hitView isKindOfClass:[UIControl class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sender.state == UIGestureRecognizerStateRecognized) {
|
||||
if (self.toolbarHidden) {
|
||||
if (self.toolbarHidden && self.canShowToolbar) {
|
||||
[self setToolbarHidden:NO animated:YES];
|
||||
}
|
||||
}
|
||||
@@ -162,7 +200,7 @@
|
||||
|
||||
- (void)_gestureRecognizedInteractiveHide:(UIPanGestureRecognizer *)sender {
|
||||
if (sender.state == UIGestureRecognizerStateRecognized) {
|
||||
BOOL show = self.topViewController.toolbarItems.count;
|
||||
BOOL show = self.canShowToolbar;
|
||||
CGFloat yTranslation = [sender translationInView:self.view].y;
|
||||
CGFloat yVelocity = [sender velocityInView:self.view].y;
|
||||
if (yVelocity > 2000) {
|
||||
@@ -176,3 +214,18 @@
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UINavigationController (FLEXObjectExploring)
|
||||
|
||||
- (void)pushExplorerForObject:(id)object {
|
||||
[self pushExplorerForObject:object animated:YES];
|
||||
}
|
||||
|
||||
- (void)pushExplorerForObject:(id)object animated:(BOOL)animated {
|
||||
UIViewController *explorer = [FLEXObjectExplorerFactory explorerViewControllerForObject:object];
|
||||
if (explorer) {
|
||||
[self pushViewController:explorer animated:animated];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 7/5/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "FLEXTableView.h"
|
||||
#import "Classes/Headers/FLEXTableView.h"
|
||||
@class FLEXScopeCarousel, FLEXWindow, FLEXTableViewSection;
|
||||
|
||||
typedef CGFloat FLEXDebounceInterval;
|
||||
@@ -67,6 +67,10 @@ extern CGFloat const kFLEXDebounceForExpensiveIO;
|
||||
/// Setting this to YES will make the search bar appear whenever the view appears.
|
||||
/// Otherwise, iOS will only show the search bar when you scroll up.
|
||||
@property (nonatomic) BOOL showSearchBarInitially;
|
||||
/// Defaults to NO.
|
||||
///
|
||||
/// Setting this to YES will make the search bar activate whenever the view appears.
|
||||
@property (nonatomic) BOOL activatesSearchBarAutomatically;
|
||||
|
||||
/// nil unless showsSearchBar is set to YES.
|
||||
///
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 7/5/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableViewController.h"
|
||||
#import "FLEXExplorerViewController.h"
|
||||
#import "FLEXBookmarksViewController.h"
|
||||
#import "FLEXTabsViewController.h"
|
||||
#import "FLEXScopeCarousel.h"
|
||||
#import "FLEXTableView.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXResources.h"
|
||||
#import "UIBarButtonItem+FLEX.h"
|
||||
#import "Classes/Headers/FLEXTableViewController.h"
|
||||
#import "Classes/ExplorerInterface/FLEXExplorerViewController.h"
|
||||
#import "Classes/ExplorerInterface/Bookmarks/FLEXBookmarksViewController.h"
|
||||
#import "Classes/ExplorerInterface/Tabs/FLEXTabsViewController.h"
|
||||
#import "Classes/Core/Views/Carousel/FLEXScopeCarousel.h"
|
||||
#import "Classes/Headers/FLEXTableView.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Utility/FLEXResources.h"
|
||||
#import "Classes/Utility/Categories/UIBarButtonItem+FLEX.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@interface Block : NSObject
|
||||
@@ -50,15 +50,12 @@ CGFloat const kFLEXDebounceForExpensiveIO = 0.5;
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (id)init {
|
||||
#if FLEX_AT_LEAST_IOS13_SDK
|
||||
if (@available(iOS 13.0, *)) {
|
||||
self = [self initWithStyle:UITableViewStyleInsetGrouped];
|
||||
} else {
|
||||
self = [self initWithStyle:UITableViewStyleGrouped];
|
||||
}
|
||||
#else
|
||||
self = [self initWithStyle:UITableViewStyleGrouped];
|
||||
#endif
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -69,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:)]) {
|
||||
@@ -106,11 +103,9 @@ CGFloat const kFLEXDebounceForExpensiveIO = 0.5;
|
||||
|
||||
self.automaticallyShowsSearchBarCancelButton = YES;
|
||||
|
||||
#if FLEX_AT_LEAST_IOS13_SDK
|
||||
if (@available(iOS 13, *)) {
|
||||
self.searchController.automaticallyShowsScopeBar = NO;
|
||||
}
|
||||
#endif
|
||||
|
||||
[self addSearchController:self.searchController];
|
||||
} else {
|
||||
@@ -124,18 +119,15 @@ CGFloat const kFLEXDebounceForExpensiveIO = 0.5;
|
||||
_showsCarousel = showsCarousel;
|
||||
|
||||
if (showsCarousel) {
|
||||
_carousel = ({
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
|
||||
_carousel = ({ weakify(self)
|
||||
|
||||
FLEXScopeCarousel *carousel = [FLEXScopeCarousel new];
|
||||
carousel.selectedIndexChangedAction = ^(NSInteger idx) {
|
||||
__typeof(self) self = weakSelf;
|
||||
carousel.selectedIndexChangedAction = ^(NSInteger idx) { strongify(self);
|
||||
[self.searchDelegate updateSearchResults:self.searchText];
|
||||
};
|
||||
|
||||
// UITableView won't update the header size unless you reset the header view
|
||||
[carousel registerBlockForDynamicTypeChanges:^(FLEXScopeCarousel *carousel) {
|
||||
__typeof(self) self = weakSelf;
|
||||
[carousel registerBlockForDynamicTypeChanges:^(FLEXScopeCarousel *_) { strongify(self);
|
||||
[self layoutTableHeaderIfNeeded];
|
||||
}];
|
||||
|
||||
@@ -173,21 +165,17 @@ CGFloat const kFLEXDebounceForExpensiveIO = 0.5;
|
||||
}
|
||||
|
||||
- (BOOL)automaticallyShowsSearchBarCancelButton {
|
||||
#if FLEX_AT_LEAST_IOS13_SDK
|
||||
if (@available(iOS 13, *)) {
|
||||
return self.searchController.automaticallyShowsCancelButton;
|
||||
}
|
||||
#endif
|
||||
|
||||
return _automaticallyShowsSearchBarCancelButton;
|
||||
}
|
||||
|
||||
- (void)setAutomaticallyShowsSearchBarCancelButton:(BOOL)value {
|
||||
#if FLEX_AT_LEAST_IOS13_SDK
|
||||
if (@available(iOS 13, *)) {
|
||||
self.searchController.automaticallyShowsCancelButton = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
_automaticallyShowsSearchBarCancelButton = value;
|
||||
}
|
||||
@@ -224,10 +212,10 @@ CGFloat const kFLEXDebounceForExpensiveIO = 0.5;
|
||||
|
||||
_shareToolbarItem = FLEXBarButtonItemSystem(Action, self, @selector(shareButtonPressed:));
|
||||
_bookmarksToolbarItem = [UIBarButtonItem
|
||||
itemWithImage:FLEXResources.bookmarksIcon target:self action:@selector(showBookmarks)
|
||||
flex_itemWithImage:FLEXResources.bookmarksIcon target:self action:@selector(showBookmarks)
|
||||
];
|
||||
_openTabsToolbarItem = [UIBarButtonItem
|
||||
itemWithImage:FLEXResources.openTabsIcon target:self action:@selector(showTabSwitcher)
|
||||
flex_itemWithImage:FLEXResources.openTabsIcon target:self action:@selector(showTabSwitcher)
|
||||
];
|
||||
|
||||
self.leftmostToolbarItem = UIBarButtonItem.flex_fixedSpace;
|
||||
@@ -241,7 +229,7 @@ CGFloat const kFLEXDebounceForExpensiveIO = 0.5;
|
||||
self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
|
||||
|
||||
// Toolbar
|
||||
self.navigationController.toolbarHidden = NO;
|
||||
self.navigationController.toolbarHidden = self.toolbarItems.count > 0;
|
||||
self.navigationController.hidesBarsOnSwipe = YES;
|
||||
|
||||
// On iOS 13, the root view controller shows it's search bar no matter what.
|
||||
@@ -259,12 +247,17 @@ CGFloat const kFLEXDebounceForExpensiveIO = 0.5;
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// When going back, make the search bar reappear instead of hiding
|
||||
if (@available(iOS 11.0, *)) {
|
||||
// When going back, make the search bar reappear instead of hiding
|
||||
if ((self.pinSearchBar || self.showSearchBarInitially) && !self.didInitiallyRevealSearchBar) {
|
||||
self.navigationItem.hidesSearchBarWhenScrolling = NO;
|
||||
}
|
||||
}
|
||||
|
||||
// Make the keyboard seem to appear faster
|
||||
if (self.activatesSearchBarAutomatically) {
|
||||
[self makeKeyboardAppearNow];
|
||||
}
|
||||
|
||||
[self setupToolbarItems];
|
||||
}
|
||||
@@ -286,6 +279,17 @@ CGFloat const kFLEXDebounceForExpensiveIO = 0.5;
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
if (self.activatesSearchBarAutomatically) {
|
||||
// Keyboard has appeared, now we call this as we soon present our search bar
|
||||
[self removeDummyTextField];
|
||||
|
||||
// Activate the search bar
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// This doesn't work unless it's wrapped in this dispatch_async call
|
||||
[self.searchController.searchBar becomeFirstResponder];
|
||||
});
|
||||
}
|
||||
|
||||
// We only want to reveal the search bar when the view controller first appears.
|
||||
self.didInitiallyRevealSearchBar = YES;
|
||||
@@ -525,13 +529,37 @@ CGFloat const kFLEXDebounceForExpensiveIO = 0.5;
|
||||
|
||||
#pragma mark - Search Bar
|
||||
|
||||
#pragma mark Faster keyboard
|
||||
|
||||
static UITextField *kDummyTextField = nil;
|
||||
|
||||
/// Make the keyboard appear instantly. We use this to make the
|
||||
/// keyboard appear faster when the search bar is set to appear initially.
|
||||
/// You must call \c -removeDummyTextField before your search bar is to appear.
|
||||
- (void)makeKeyboardAppearNow {
|
||||
if (!kDummyTextField) {
|
||||
kDummyTextField = [UITextField new];
|
||||
kDummyTextField.autocorrectionType = UITextAutocorrectionTypeNo;
|
||||
}
|
||||
|
||||
kDummyTextField.inputAccessoryView = self.searchController.searchBar.inputAccessoryView;
|
||||
[UIApplication.sharedApplication.keyWindow addSubview:kDummyTextField];
|
||||
[kDummyTextField becomeFirstResponder];
|
||||
}
|
||||
|
||||
- (void)removeDummyTextField {
|
||||
if (kDummyTextField.superview) {
|
||||
[kDummyTextField removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark UISearchResultsUpdating
|
||||
|
||||
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
|
||||
[self.debounceTimer invalidate];
|
||||
NSString *text = searchController.searchBar.text;
|
||||
|
||||
void (^updateSearchResults)() = ^{
|
||||
void (^updateSearchResults)(void) = ^{
|
||||
if (self.searchResultsUpdater) {
|
||||
[self.searchResultsUpdater updateSearchResults:text];
|
||||
} else {
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 9/25/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableViewSection.h"
|
||||
#import "Classes/Headers/FLEXTableViewSection.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// A section providing a specific single row.
|
||||
///
|
||||
@@ -16,13 +18,15 @@
|
||||
@interface FLEXSingleRowSection : FLEXTableViewSection
|
||||
|
||||
/// @param reuseIdentifier if nil, kFLEXDefaultCell is used.
|
||||
+ (instancetype)title:(NSString *)sectionTitle
|
||||
reuse:(NSString *)reuseIdentifier
|
||||
+ (instancetype)title:(nullable NSString *)sectionTitle
|
||||
reuse:(nullable NSString *)reuseIdentifier
|
||||
cell:(void(^)(__kindof UITableViewCell *cell))cellConfiguration;
|
||||
|
||||
@property (nonatomic) UIViewController *pushOnSelection;
|
||||
@property (nonatomic) void (^selectionAction)(UIViewController *host);
|
||||
@property (nullable, nonatomic) UIViewController *pushOnSelection;
|
||||
@property (nullable, nonatomic) void (^selectionAction)(UIViewController *host);
|
||||
/// Called to determine whether the single row should display itself or not.
|
||||
@property (nonatomic) BOOL (^filterMatcher)(NSString *filterText);
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 9/25/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXSingleRowSection.h"
|
||||
#import "FLEXTableView.h"
|
||||
#import "Classes/Headers/FLEXSingleRowSection.h"
|
||||
#import "Classes/Headers/FLEXTableView.h"
|
||||
|
||||
@interface FLEXSingleRowSection ()
|
||||
@property (nonatomic, readonly) NSString *reuseIdentifier;
|
||||
@@ -30,6 +30,8 @@
|
||||
- (id)initWithTitle:(NSString *)sectionTitle
|
||||
reuse:(NSString *)reuseIdentifier
|
||||
cell:(void (^)(__kindof UITableViewCell *))cellConfiguration {
|
||||
NSParameterAssert(cellConfiguration);
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_title = sectionTitle;
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 1/29/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "FLEXMacros.h"
|
||||
#import "NSArray+FLEX.h"
|
||||
#import "Classes/Utility/Categories/NSArray+FLEX.h"
|
||||
@class FLEXTableView;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@@ -24,6 +23,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@protected
|
||||
/// Unused by default, use if you want
|
||||
NSString *_title;
|
||||
|
||||
@private
|
||||
__weak UITableView *_tableView;
|
||||
NSInteger _sectionIndex;
|
||||
}
|
||||
|
||||
#pragma mark - Data
|
||||
@@ -57,6 +60,17 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/// \c setFilterText: to call \c super and call \c reloadData.
|
||||
- (void)reloadData;
|
||||
|
||||
/// Like \c reloadData, but optionally reloads the table view section
|
||||
/// associated with this section object, if any. Do not override.
|
||||
/// Do not call outside of the main thread.
|
||||
- (void)reloadData:(BOOL)updateTable;
|
||||
|
||||
/// Provide a table view and section index to allow the section to efficiently reload
|
||||
/// its own section of the table when something changes it. The table reference is
|
||||
/// held weakly, and subclasses cannot access it or the index. Call this method again
|
||||
/// if the section numbers have changed since you last called it.
|
||||
- (void)setTable:(UITableView *)tableView section:(NSInteger)index;
|
||||
|
||||
#pragma mark - Row Selection
|
||||
|
||||
/// Whether the given row should be selectable, such as if tapping the cell
|
||||
@@ -86,7 +100,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (nullable void(^)(__kindof UIViewController *host))didPressInfoButtonAction:(NSInteger)row;
|
||||
|
||||
#pragma mark - Context Menus
|
||||
#if FLEX_AT_LEAST_IOS13_SDK
|
||||
|
||||
/// By default, this is the title of the row.
|
||||
/// @return The title of the context menu, if any.
|
||||
@@ -106,7 +119,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/// should be a description of what will be copied, and the values should be
|
||||
/// the strings to copy. Return an empty string as a value to show a disabled action.
|
||||
- (nullable NSArray<NSString *> *)copyMenuItemsForRow:(NSInteger)row API_AVAILABLE(ios(13.0));
|
||||
#endif
|
||||
|
||||
#pragma mark - Cell Configuration
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 1/29/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableViewSection.h"
|
||||
#import "FLEXTableView.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "UIMenu+FLEX.h"
|
||||
#import "Classes/Headers/FLEXTableViewSection.h"
|
||||
#import "Classes/Headers/FLEXTableView.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Utility/Categories/UIMenu+FLEX.h"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wincomplete-implementation"
|
||||
@@ -22,6 +22,19 @@
|
||||
|
||||
- (void)reloadData { }
|
||||
|
||||
- (void)reloadData:(BOOL)updateTable {
|
||||
[self reloadData];
|
||||
if (updateTable) {
|
||||
NSIndexSet *index = [NSIndexSet indexSetWithIndex:_sectionIndex];
|
||||
[_tableView reloadSections:index withRowAnimation:UITableViewRowAnimationNone];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTable:(UITableView *)tableView section:(NSInteger)index {
|
||||
_tableView = tableView;
|
||||
_sectionIndex = index;
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *,Class> *)cellRegistrationMapping {
|
||||
return nil;
|
||||
}
|
||||
@@ -51,8 +64,6 @@
|
||||
return kFLEXDefaultCell;
|
||||
}
|
||||
|
||||
#if FLEX_AT_LEAST_IOS13_SDK
|
||||
|
||||
- (NSString *)menuTitleForRow:(NSInteger)row {
|
||||
NSString *title = [self titleForRow:row];
|
||||
NSString *subtitle = [self menuSubtitleForRow:row];
|
||||
@@ -68,7 +79,7 @@
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSArray<UIMenuElement *> *)menuItemsForRow:(NSInteger)row sender:(UIViewController *)sender API_AVAILABLE(ios(13)) {
|
||||
- (NSArray<UIMenuElement *> *)menuItemsForRow:(NSInteger)row sender:(UIViewController *)sender API_AVAILABLE(ios(13.0)) {
|
||||
NSArray<NSString *> *copyItems = [self copyMenuItemsForRow:row];
|
||||
NSAssert(copyItems.count % 2 == 0, @"copyMenuItemsForRow: should return an even list");
|
||||
|
||||
@@ -99,13 +110,13 @@
|
||||
}
|
||||
|
||||
UIMenu *copyMenu = [UIMenu
|
||||
inlineMenuWithTitle:@"Copy…"
|
||||
flex_inlineMenuWithTitle:@"Copy…"
|
||||
image:copyIcon
|
||||
children:actions
|
||||
];
|
||||
|
||||
if (collapseMenu) {
|
||||
return @[[copyMenu collapsed]];
|
||||
return @[[copyMenu flex_collapsed]];
|
||||
} else {
|
||||
return @[copyMenu];
|
||||
}
|
||||
@@ -114,8 +125,6 @@
|
||||
return @[];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (NSArray<NSString *> *)copyMenuItemsForRow:(NSInteger)row {
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 7/17/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 7/17/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXCarouselCell.h"
|
||||
#import "FLEXColor.h"
|
||||
#import "UIView+FLEX_Layout.h"
|
||||
#import "Classes/Core/Views/Carousel/FLEXCarouselCell.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
#import "Classes/Utility/Categories/Private/UIView+FLEX_Layout.h"
|
||||
|
||||
@interface FLEXCarouselCell ()
|
||||
@property (nonatomic, readonly) UILabel *titleLabel;
|
||||
@@ -77,7 +77,7 @@
|
||||
self.selectionIndicatorStripe.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
|
||||
UIView *superview = self.contentView;
|
||||
[self.titleLabel pinEdgesToSuperviewWithInsets:UIEdgeInsetsMake(10, 15, 8 + stripeHeight, 15)];
|
||||
[self.titleLabel flex_pinEdgesToSuperviewWithInsets:UIEdgeInsetsMake(10, 15, 8 + stripeHeight, 15)];
|
||||
|
||||
[self.selectionIndicatorStripe.leadingAnchor constraintEqualToAnchor:superview.leadingAnchor].active = YES;
|
||||
[self.selectionIndicatorStripe.bottomAnchor constraintEqualToAnchor:superview.bottomAnchor].active = YES;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 7/17/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 7/17/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXScopeCarousel.h"
|
||||
#import "FLEXCarouselCell.h"
|
||||
#import "FLEXColor.h"
|
||||
#import "UIView+FLEX_Layout.h"
|
||||
#import "Classes/Core/Views/Carousel/FLEXScopeCarousel.h"
|
||||
#import "Classes/Core/Views/Carousel/FLEXCarouselCell.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
#import "Classes/Utility/FLEXMacros.h"
|
||||
#import "Classes/Utility/Categories/Private/UIView+FLEX_Layout.h"
|
||||
|
||||
const CGFloat kCarouselItemSpacing = 0;
|
||||
NSString * const kCarouselCellReuseIdentifier = @"kCarouselCellReuseIdentifier";
|
||||
@@ -72,15 +73,14 @@ NSString * const kCarouselCellReuseIdentifier = @"kCarouselCellReuseIdentifier";
|
||||
self.sizingCell.title = @"NSObject";
|
||||
|
||||
// Dynamic type
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
weakify(self);
|
||||
_dynamicTypeObserver = [NSNotificationCenter.defaultCenter
|
||||
addObserverForName:UIContentSizeCategoryDidChangeNotification
|
||||
object:nil queue:nil usingBlock:^(NSNotification *note) {
|
||||
object:nil queue:nil usingBlock:^(NSNotification *note) { strongify(self)
|
||||
[self.collectionView setNeedsLayout];
|
||||
[self setNeedsUpdateConstraints];
|
||||
|
||||
// Notify observers
|
||||
__typeof(self) self = weakSelf;
|
||||
for (void (^block)(FLEXScopeCarousel *) in self.dynamicTypeHandlers) {
|
||||
block(self);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ NSString * const kCarouselCellReuseIdentifier = @"kCarouselCellReuseIdentifier";
|
||||
- (void)updateConstraints {
|
||||
if (!self.constraintsInstalled) {
|
||||
self.collectionView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
[self.collectionView pinEdgesToSuperview];
|
||||
[self.collectionView flex_pinEdgesToSuperview];
|
||||
|
||||
self.constraintsInstalled = YES;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 12/27/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXMultilineTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXMultilineTableViewCell.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 12/27/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXCodeFontCell.h"
|
||||
#import "UIFont+FLEX.h"
|
||||
#import "Classes/Headers/FLEXCodeFontCell.h"
|
||||
#import "Classes/Utility/Categories/UIFont+FLEX.h"
|
||||
|
||||
@implementation FLEXCodeFontCell
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 1/23/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXTableViewCell.h"
|
||||
|
||||
@interface FLEXKeyValueTableViewCell : FLEXTableViewCell
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 1/23/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXKeyValueTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXKeyValueTableViewCell.h"
|
||||
|
||||
@implementation FLEXKeyValueTableViewCell
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Ryan Olson on 2/13/15.
|
||||
// Copyright (c) 2015 f. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXTableViewCell.h"
|
||||
|
||||
/// A cell with both labels set to be multi-line capable.
|
||||
@interface FLEXMultilineTableViewCell : FLEXTableViewCell
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Ryan Olson on 2/13/15.
|
||||
// Copyright (c) 2015 f. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXMultilineTableViewCell.h"
|
||||
#import "UIView+FLEX_Layout.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "Classes/Headers/FLEXMultilineTableViewCell.h"
|
||||
#import "Classes/Utility/Categories/Private/UIView+FLEX_Layout.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
|
||||
@interface FLEXMultilineTableViewCell ()
|
||||
@property (nonatomic, readonly) UILabel *_titleLabel;
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 4/17/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXTableViewCell.h"
|
||||
|
||||
/// A cell initialized with \c UITableViewCellStyleSubtitle
|
||||
@interface FLEXSubtitleTableViewCell : FLEXTableViewCell
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 4/17/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXSubtitleTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXSubtitleTableViewCell.h"
|
||||
|
||||
@implementation FLEXSubtitleTableViewCell
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 4/17/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 4/17/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableViewCell.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXColor.h"
|
||||
#import "FLEXTableView.h"
|
||||
#import "Classes/Headers/FLEXTableViewCell.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
#import "Classes/Headers/FLEXTableView.h"
|
||||
|
||||
@interface UITableView (Internal)
|
||||
// Exists at least since iOS 5
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 4/17/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 4/17/19.
|
||||
// Copyright © 2019 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableView.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXSubtitleTableViewCell.h"
|
||||
#import "FLEXMultilineTableViewCell.h"
|
||||
#import "FLEXKeyValueTableViewCell.h"
|
||||
#import "FLEXCodeFontCell.h"
|
||||
#import "Classes/Headers/FLEXTableView.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Headers/FLEXSubtitleTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXMultilineTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXKeyValueTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXCodeFontCell.h"
|
||||
|
||||
FLEXTableViewCellReuseIdentifier const kFLEXDefaultCell = @"kFLEXDefaultCell";
|
||||
FLEXTableViewCellReuseIdentifier const kFLEXDetailCell = @"kFLEXDetailCell";
|
||||
@@ -30,29 +30,21 @@ FLEXTableViewCellReuseIdentifier const kFLEXCodeFontCell = @"kFLEXCodeFontCell";
|
||||
@implementation FLEXTableView
|
||||
|
||||
+ (instancetype)flexDefaultTableView {
|
||||
#if FLEX_AT_LEAST_IOS13_SDK
|
||||
if (@available(iOS 13.0, *)) {
|
||||
return [[self alloc] initWithFrame:CGRectZero style:UITableViewStyleInsetGrouped];
|
||||
} else {
|
||||
return [[self alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
|
||||
}
|
||||
#else
|
||||
return [[self alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
+ (id)groupedTableView {
|
||||
#if FLEX_AT_LEAST_IOS13_SDK
|
||||
if (@available(iOS 13.0, *)) {
|
||||
return [[self alloc] initWithFrame:CGRectZero style:UITableViewStyleInsetGrouped];
|
||||
} else {
|
||||
return [[self alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
|
||||
}
|
||||
#else
|
||||
return [[self alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
|
||||
#endif
|
||||
}
|
||||
|
||||
+ (id)plainTableView {
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/30/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
|
||||
@interface FLEXArgumentInputColorView : FLEXArgumentInputView
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/30/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputColorView.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
|
||||
@protocol FLEXColorComponentInputViewDelegate;
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Daniel Rodriguez Troitino on 2/14/15.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
|
||||
@interface FLEXArgumentInputDateView : FLEXArgumentInputView
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Daniel Rodriguez Troitino on 2/14/15.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputDateView.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputDateView.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
|
||||
@interface FLEXArgumentInputDateView ()
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/28/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
|
||||
@interface FLEXArgumentInputFontView : FLEXArgumentInputView
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/28/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputFontView.h"
|
||||
#import "FLEXArgumentInputViewFactory.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "FLEXArgumentInputFontsPickerView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontView.h"
|
||||
#import "Classes/Editing/FLEXArgumentInputViewFactory.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.h"
|
||||
|
||||
@interface FLEXArgumentInputFontView ()
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// Copyright (c) 2014年 f. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputTextView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.h"
|
||||
|
||||
@interface FLEXArgumentInputFontsPickerView : FLEXArgumentInputTextView <UIPickerViewDataSource, UIPickerViewDelegate>
|
||||
@end
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// Copyright (c) 2014年 f. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputFontsPickerView.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontsPickerView.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
|
||||
@interface FLEXArgumentInputFontsPickerView ()
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/18/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputTextView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.h"
|
||||
|
||||
@interface FLEXArgumentInputNotSupportedView : FLEXArgumentInputTextView
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/18/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputNotSupportedView.h"
|
||||
#import "FLEXColor.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputNotSupportedView.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
|
||||
@implementation FLEXArgumentInputNotSupportedView
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/15/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputTextView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.h"
|
||||
|
||||
@interface FLEXArgumentInputNumberView : FLEXArgumentInputTextView
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/15/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputNumberView.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
|
||||
@implementation FLEXArgumentInputNumberView
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/15/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputTextView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.h"
|
||||
|
||||
@interface FLEXArgumentInputObjectView : FLEXArgumentInputTextView
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/15/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputObjectView.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
|
||||
static const CGFloat kSegmentInputMargin = 10;
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/28/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputTextView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.h"
|
||||
|
||||
@interface FLEXArgumentInputStringView : FLEXArgumentInputTextView
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/28/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputStringView.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputStringView.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
|
||||
@implementation FLEXArgumentInputStringView
|
||||
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/16/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
|
||||
@interface FLEXArgumentInputStructView : FLEXArgumentInputView
|
||||
|
||||
/// Enable displaying ivar names for custom struct types
|
||||
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding;
|
||||
|
||||
@end
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/16/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputStructView.h"
|
||||
#import "FLEXArgumentInputViewFactory.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "FLEXTypeEncodingParser.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.h"
|
||||
#import "Classes/Editing/FLEXArgumentInputViewFactory.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
#import "Classes/Utility/Runtime/Objc/FLEXTypeEncodingParser.h"
|
||||
|
||||
@interface FLEXArgumentInputStructView ()
|
||||
|
||||
@@ -19,6 +19,41 @@
|
||||
|
||||
@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) {
|
||||
@@ -181,40 +216,13 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (void)registerFieldNames:(NSArray<NSString *> *)names forTypeEncoding:(NSString *)typeEncoding {
|
||||
NSParameterAssert(typeEncoding); NSParameterAssert(names);
|
||||
structFieldNameRegistrar[typeEncoding] = names;
|
||||
}
|
||||
|
||||
+ (NSArray<NSString *> *)customFieldTitlesForTypeEncoding:(const char *)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;
|
||||
return structFieldNameRegistrar[@(typeEncoding)];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/16/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
|
||||
@interface FLEXArgumentInputSwitchView : FLEXArgumentInputView
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 6/16/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputSwitchView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.h"
|
||||
|
||||
@interface FLEXArgumentInputSwitchView ()
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
|
||||
@interface FLEXArgumentInputTextView : FLEXArgumentInputView <UITextViewDelegate>
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import "FLEXColor.h"
|
||||
#import "FLEXArgumentInputTextView.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputTextView.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
|
||||
@interface FLEXArgumentInputTextView ()
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
self.inputTextView.delegate = self;
|
||||
self.inputTextView.inputAccessoryView = [self createToolBar];
|
||||
if (@available(iOS 11, *)) {
|
||||
self.inputTextView.smartQuotesType = UITextSmartQuotesTypeNo;
|
||||
[self.inputTextView.layer setValue:@YES forKey:@"continuousCorners"];
|
||||
} else {
|
||||
self.inputTextView.layer.borderWidth = 1.f;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 5/30/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 5/30/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXColor.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
|
||||
@interface FLEXArgumentInputView ()
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FLEXArgumentInputSwitchView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.h"
|
||||
|
||||
@interface FLEXArgumentInputViewFactory : NSObject
|
||||
|
||||
@@ -21,4 +21,7 @@
|
||||
/// 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
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
//
|
||||
//
|
||||
|
||||
#import "FLEXArgumentInputViewFactory.h"
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "FLEXArgumentInputObjectView.h"
|
||||
#import "FLEXArgumentInputNumberView.h"
|
||||
#import "FLEXArgumentInputSwitchView.h"
|
||||
#import "FLEXArgumentInputStructView.h"
|
||||
#import "FLEXArgumentInputNotSupportedView.h"
|
||||
#import "FLEXArgumentInputStringView.h"
|
||||
#import "FLEXArgumentInputFontView.h"
|
||||
#import "FLEXArgumentInputColorView.h"
|
||||
#import "FLEXArgumentInputDateView.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "Classes/Editing/FLEXArgumentInputViewFactory.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputObjectView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputNumberView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputSwitchView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputNotSupportedView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputStringView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputFontView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputColorView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputDateView.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
|
||||
@implementation FLEXArgumentInputViewFactory
|
||||
|
||||
@@ -67,4 +67,9 @@
|
||||
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
|
||||
|
||||
@@ -3,15 +3,19 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 5/23/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXFieldEditorViewController.h"
|
||||
#import "Classes/Editing/FLEXFieldEditorViewController.h"
|
||||
|
||||
@interface FLEXDefaultEditorViewController : FLEXFieldEditorViewController
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (id)initWithDefaults:(NSUserDefaults *)defaults key:(NSString *)key;
|
||||
@interface FLEXDefaultEditorViewController : FLEXVariableEditorViewController
|
||||
|
||||
+ (BOOL)canEditDefaultWithValue:(id)currentValue;
|
||||
+ (instancetype)target:(NSUserDefaults *)defaults key:(NSString *)key commitHandler:(void(^_Nullable)(void))onCommit;
|
||||
|
||||
+ (BOOL)canEditDefaultWithValue:(nullable id)currentValue;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -3,35 +3,36 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 5/23/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXDefaultEditorViewController.h"
|
||||
#import "FLEXFieldEditorView.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "FLEXArgumentInputViewFactory.h"
|
||||
#import "Classes/Editing/FLEXDefaultEditorViewController.h"
|
||||
#import "Classes/Editing/FLEXFieldEditorView.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
#import "Classes/Editing/FLEXArgumentInputViewFactory.h"
|
||||
|
||||
@interface FLEXDefaultEditorViewController ()
|
||||
|
||||
@property (nonatomic, readonly) NSUserDefaults *defaults;
|
||||
@property (nonatomic) NSString *key;
|
||||
@property (nonatomic, readonly) NSString *key;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FLEXDefaultEditorViewController
|
||||
|
||||
- (id)initWithDefaults:(NSUserDefaults *)defaults key:(NSString *)key {
|
||||
self = [super initWithTarget:defaults];
|
||||
if (self) {
|
||||
self.key = key;
|
||||
self.title = @"Edit Default";
|
||||
}
|
||||
return self;
|
||||
+ (instancetype)target:(NSUserDefaults *)defaults key:(NSString *)key commitHandler:(void(^_Nullable)(void))onCommit {
|
||||
FLEXDefaultEditorViewController *editor = [self target:defaults data:key commitHandler:onCommit];
|
||||
editor.title = @"Edit Default";
|
||||
return editor;
|
||||
}
|
||||
|
||||
- (NSUserDefaults *)defaults {
|
||||
return [self.target isKindOfClass:[NSUserDefaults class]] ? self.target : nil;
|
||||
return [_target isKindOfClass:[NSUserDefaults class]] ? _target : nil;
|
||||
}
|
||||
|
||||
- (NSString *)key {
|
||||
return _data;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
@@ -50,8 +51,6 @@
|
||||
}
|
||||
|
||||
- (void)actionButtonPressed:(id)sender {
|
||||
[super actionButtonPressed:sender];
|
||||
|
||||
id value = self.firstInputView.inputValue;
|
||||
if (value) {
|
||||
[self.defaults setObject:value forKey:self.key];
|
||||
@@ -59,14 +58,16 @@
|
||||
[self.defaults removeObjectForKey:self.key];
|
||||
}
|
||||
[self.defaults synchronize];
|
||||
|
||||
self.firstInputView.inputValue = [self.defaults objectForKey:self.key];
|
||||
}
|
||||
|
||||
- (void)getterButtonPressed:(id)sender {
|
||||
[super getterButtonPressed:sender];
|
||||
id returnedObject = [self.defaults objectForKey:self.key];
|
||||
[self exploreObjectOrPopViewController:returnedObject];
|
||||
|
||||
// Dismiss keyboard and handle committed changes
|
||||
[super actionButtonPressed:sender];
|
||||
|
||||
// Go back after setting, but not for switches.
|
||||
if (sender) {
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
} else {
|
||||
self.firstInputView.inputValue = [self.defaults objectForKey:self.key];
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)canEditDefaultWithValue:(id)currentValue {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 5/16/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 5/16/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXFieldEditorView.h"
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "Classes/Editing/FLEXFieldEditorView.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
|
||||
@interface FLEXFieldEditorView ()
|
||||
|
||||
@@ -122,7 +123,7 @@
|
||||
}
|
||||
|
||||
+ (UIColor *)dividerColor {
|
||||
return UIColor.lightGrayColor;
|
||||
return FLEXColor.tertiaryBackgroundColor;
|
||||
}
|
||||
|
||||
+ (CGFloat)horizontalPadding {
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 11/22/18.
|
||||
// Copyright © 2018 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXVariableEditorViewController.h"
|
||||
#import "FLEXProperty.h"
|
||||
#import "FLEXIvar.h"
|
||||
#import "Classes/Editing/FLEXVariableEditorViewController.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXProperty.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXIvar.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FLEXFieldEditorViewController : FLEXVariableEditorViewController
|
||||
|
||||
/// @return nil if the property is readonly or if the type is unsupported
|
||||
+ (nullable instancetype)target:(id)target property:(FLEXProperty *)property;
|
||||
+ (nullable instancetype)target:(id)target property:(FLEXProperty *)property commitHandler:(void(^_Nullable)(void))onCommit;
|
||||
/// @return nil if the ivar type is unsupported
|
||||
+ (nullable instancetype)target:(id)target ivar:(FLEXIvar *)ivar;
|
||||
+ (nullable instancetype)target:(id)target ivar:(FLEXIvar *)ivar commitHandler:(void(^_Nullable)(void))onCommit;
|
||||
|
||||
/// Subclasses can change the button title via the \c title property
|
||||
@property (nonatomic, readonly) UIBarButtonItem *getterButton;
|
||||
|
||||
@@ -3,20 +3,22 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 11/22/18.
|
||||
// Copyright © 2018 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXFieldEditorViewController.h"
|
||||
#import "FLEXFieldEditorView.h"
|
||||
#import "FLEXArgumentInputViewFactory.h"
|
||||
#import "FLEXPropertyAttributes.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXColor.h"
|
||||
#import "UIBarButtonItem+FLEX.h"
|
||||
#import "Classes/Editing/FLEXFieldEditorViewController.h"
|
||||
#import "Classes/Editing/FLEXFieldEditorView.h"
|
||||
#import "Classes/Editing/FLEXArgumentInputViewFactory.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXPropertyAttributes.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXMetadataExtras.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
#import "Classes/Utility/Categories/UIBarButtonItem+FLEX.h"
|
||||
|
||||
@interface FLEXFieldEditorViewController () <FLEXArgumentInputViewDelegate>
|
||||
|
||||
@property (nonatomic, readonly) id<FLEXMetadataAuxiliaryInfo> auxiliaryInfoProvider;
|
||||
@property (nonatomic) FLEXProperty *property;
|
||||
@property (nonatomic) FLEXIvar *ivar;
|
||||
|
||||
@@ -30,20 +32,15 @@
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
+ (instancetype)target:(id)target property:(FLEXProperty *)property {
|
||||
id value = [property getValue:target];
|
||||
if (![self canEditProperty:property onObject:target currentValue:value]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
FLEXFieldEditorViewController *editor = [self target:target];
|
||||
+ (instancetype)target:(id)target property:(nonnull FLEXProperty *)property commitHandler:(void(^)(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 {
|
||||
FLEXFieldEditorViewController *editor = [self target:target];
|
||||
+ (instancetype)target:(id)target ivar:(nonnull FLEXIvar *)ivar commitHandler:(void(^)(void))onCommit {
|
||||
FLEXFieldEditorViewController *editor = [self target:target data:ivar commitHandler:onCommit];
|
||||
editor.title = [@"Ivar: " stringByAppendingString:ivar.name];
|
||||
editor.ivar = ivar;
|
||||
return editor;
|
||||
@@ -66,6 +63,8 @@
|
||||
self.toolbarItems = @[
|
||||
UIBarButtonItem.flex_flexibleSpace, self.getterButton, self.actionButton
|
||||
];
|
||||
|
||||
[self registerAuxiliaryInfo];
|
||||
|
||||
// Configure input view
|
||||
self.fieldEditorView.fieldDescription = self.fieldDescription;
|
||||
@@ -86,8 +85,6 @@
|
||||
}
|
||||
|
||||
- (void)actionButtonPressed:(id)sender {
|
||||
[super actionButtonPressed:sender];
|
||||
|
||||
if (self.property) {
|
||||
id userInputObject = self.firstInputView.inputValue;
|
||||
NSArray *arguments = userInputObject ? @[userInputObject] : nil;
|
||||
@@ -103,6 +100,9 @@
|
||||
// this currently could and would assign NSArray to NSMutableArray
|
||||
[self.ivar setValue:self.firstInputView.inputValue onObject:self.target];
|
||||
}
|
||||
|
||||
// Dismiss keyboard and handle committed changes
|
||||
[super actionButtonPressed:sender];
|
||||
|
||||
// Go back after setting, but not for switches.
|
||||
if (sender) {
|
||||
@@ -126,6 +126,17 @@
|
||||
|
||||
#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];
|
||||
@@ -134,6 +145,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (id<FLEXMetadataAuxiliaryInfo>)auxiliaryInfoProvider {
|
||||
return self.ivar ?: self.property;
|
||||
}
|
||||
|
||||
- (const FLEXTypeEncoding *)typeEncoding {
|
||||
if (self.property) {
|
||||
return self.property.attributes.typeEncoding.UTF8String;
|
||||
@@ -150,14 +165,4 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)canEditProperty:(FLEXProperty *)property onObject:(id)object currentValue:(id)value {
|
||||
const FLEXTypeEncoding *typeEncoding = property.attributes.typeEncoding.UTF8String;
|
||||
BOOL canEditType = [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:typeEncoding currentValue:value];
|
||||
return canEditType && [object respondsToSelector:property.likelySetter];
|
||||
}
|
||||
|
||||
+ (BOOL)canEditIvar:(Ivar)ivar currentValue:(id)value {
|
||||
return [FLEXArgumentInputViewFactory canEditFieldWithTypeEncoding:ivar_getTypeEncoding(ivar) currentValue:value];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 5/23/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXVariableEditorViewController.h"
|
||||
#import "FLEXMethod.h"
|
||||
#import "Classes/Editing/FLEXVariableEditorViewController.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXMethod.h"
|
||||
|
||||
@interface FLEXMethodCallingViewController : FLEXVariableEditorViewController
|
||||
|
||||
|
||||
@@ -3,20 +3,20 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 5/23/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXMethodCallingViewController.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "FLEXFieldEditorView.h"
|
||||
#import "FLEXObjectExplorerFactory.h"
|
||||
#import "FLEXObjectExplorerViewController.h"
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "FLEXArgumentInputViewFactory.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "Classes/Editing/FLEXMethodCallingViewController.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
#import "Classes/Editing/FLEXFieldEditorView.h"
|
||||
#import "Classes/Headers/FLEXObjectExplorerFactory.h"
|
||||
#import "Classes/Headers/FLEXObjectExplorerViewController.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
#import "Classes/Editing/FLEXArgumentInputViewFactory.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
|
||||
@interface FLEXMethodCallingViewController ()
|
||||
@property (nonatomic) FLEXMethod *method;
|
||||
@property (nonatomic, readonly) FLEXMethod *method;
|
||||
@end
|
||||
|
||||
@implementation FLEXMethodCallingViewController
|
||||
@@ -28,9 +28,8 @@
|
||||
- (id)initWithTarget:(id)target method:(FLEXMethod *)method {
|
||||
NSParameterAssert(method.isInstanceMethod == !object_isClass(target));
|
||||
|
||||
self = [super initWithTarget:target];
|
||||
self = [super initWithTarget:target data:method commitHandler:nil];
|
||||
if (self) {
|
||||
self.method = method;
|
||||
self.title = method.isInstanceMethod ? @"Method: " : @"Class Method: ";
|
||||
self.title = [self.title stringByAppendingString:method.selectorString];
|
||||
}
|
||||
@@ -72,8 +71,6 @@
|
||||
}
|
||||
|
||||
- (void)actionButtonPressed:(id)sender {
|
||||
[super actionButtonPressed:sender];
|
||||
|
||||
// Gather arguments
|
||||
NSMutableArray *arguments = [NSMutableArray new];
|
||||
for (FLEXArgumentInputView *inputView in self.fieldEditorView.argumentInputViews) {
|
||||
@@ -89,6 +86,9 @@
|
||||
withArguments:arguments
|
||||
error:&error
|
||||
];
|
||||
|
||||
// Dismiss keyboard and handle committed changes
|
||||
[super actionButtonPressed:sender];
|
||||
|
||||
// Display return value or error
|
||||
if (error) {
|
||||
@@ -103,4 +103,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (FLEXMethod *)method {
|
||||
return _data;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 5/16/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
@@ -11,25 +11,45 @@
|
||||
@class FLEXFieldEditorView;
|
||||
@class FLEXArgumentInputView;
|
||||
|
||||
/// Provides a screen for editing or configuring one or more variables.
|
||||
@interface FLEXVariableEditorViewController : UIViewController
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
+ (instancetype)target:(id)target;
|
||||
- (id)initWithTarget:(id)target;
|
||||
/// An abstract screen for editing or configuring one or more variables.
|
||||
/// "Target" is the target of the edit operation, and "data" is the data
|
||||
/// you want to mutate or pass to the target when the action is performed.
|
||||
/// The action may be something like calling a method, setting an ivar, etc.
|
||||
@interface FLEXVariableEditorViewController : UIViewController {
|
||||
@protected
|
||||
id _target;
|
||||
_Nullable id _data;
|
||||
void (^_Nullable _commitHandler)(void);
|
||||
}
|
||||
|
||||
// Convenience accessor since many subclasses only use one input view
|
||||
@property (nonatomic, readonly) FLEXArgumentInputView *firstInputView;
|
||||
/// @param target The target of the operation
|
||||
/// @param data The data associated with the operation
|
||||
/// @param onCommit An action to perform when the data changes
|
||||
+ (instancetype)target:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)(void))onCommit;
|
||||
/// @param target The target of the operation
|
||||
/// @param data The data associated with the operation
|
||||
/// @param onCommit An action to perform when the data changes
|
||||
- (id)initWithTarget:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)(void))onCommit;
|
||||
|
||||
// For subclass use only.
|
||||
@property (nonatomic, readonly) id target;
|
||||
|
||||
/// Convenience accessor since many subclasses only use one input view
|
||||
@property (nonatomic, readonly, nullable) FLEXArgumentInputView *firstInputView;
|
||||
|
||||
@property (nonatomic, readonly) FLEXFieldEditorView *fieldEditorView;
|
||||
/// Subclasses can change the button title via the button's \c title property
|
||||
@property (nonatomic, readonly) UIBarButtonItem *actionButton;
|
||||
|
||||
- (void)actionButtonPressed:(id)sender;
|
||||
/// Subclasses should override to provide "set" functionality.
|
||||
/// The commit handler--if present--is called here.
|
||||
- (void)actionButtonPressed:(nullable id)sender;
|
||||
|
||||
/// Pushes an explorer view controller for the given object
|
||||
/// or pops the current view controller.
|
||||
- (void)exploreObjectOrPopViewController:(id)objectOrNil;
|
||||
- (void)exploreObjectOrPopViewController:(nullable id)objectOrNil;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -3,40 +3,41 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 5/16/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXColor.h"
|
||||
#import "FLEXVariableEditorViewController.h"
|
||||
#import "FLEXFieldEditorView.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXObjectExplorerFactory.h"
|
||||
#import "FLEXArgumentInputView.h"
|
||||
#import "FLEXArgumentInputViewFactory.h"
|
||||
#import "FLEXObjectExplorerViewController.h"
|
||||
#import "UIBarButtonItem+FLEX.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
#import "Classes/Editing/FLEXVariableEditorViewController.h"
|
||||
#import "Classes/Editing/FLEXFieldEditorView.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Headers/FLEXObjectExplorerFactory.h"
|
||||
#import "Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.h"
|
||||
#import "Classes/Editing/FLEXArgumentInputViewFactory.h"
|
||||
#import "Classes/Headers/FLEXObjectExplorerViewController.h"
|
||||
#import "Classes/Utility/Categories/UIBarButtonItem+FLEX.h"
|
||||
|
||||
@interface FLEXVariableEditorViewController () <UIScrollViewDelegate>
|
||||
@property (nonatomic) UIScrollView *scrollView;
|
||||
@property (nonatomic) id target;
|
||||
@end
|
||||
|
||||
@implementation FLEXVariableEditorViewController
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
+ (instancetype)target:(id)target {
|
||||
return [[self alloc] initWithTarget:target];
|
||||
+ (instancetype)target:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)(void))onCommit {
|
||||
return [[self alloc] initWithTarget:target data:data commitHandler:onCommit];
|
||||
}
|
||||
|
||||
- (id)initWithTarget:(id)target {
|
||||
- (id)initWithTarget:(id)target data:(nullable id)data commitHandler:(void(^_Nullable)(void))onCommit {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.target = target;
|
||||
_target = target;
|
||||
_data = data;
|
||||
_commitHandler = onCommit;
|
||||
[NSNotificationCenter.defaultCenter
|
||||
addObserver:self selector:@selector(keyboardDidShow:)
|
||||
name:UIKeyboardDidShowNotification object:nil
|
||||
name:UIKeyboardWillShowNotification object:nil
|
||||
];
|
||||
[NSNotificationCenter.defaultCenter
|
||||
addObserver:self selector:@selector(keyboardWillHide:)
|
||||
@@ -120,6 +121,9 @@
|
||||
- (void)actionButtonPressed:(id)sender {
|
||||
// Subclasses can override
|
||||
[self.fieldEditorView endEditing:YES];
|
||||
if (_commitHandler) {
|
||||
_commitHandler();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)exploreObjectOrPopViewController:(id)objectOrNil {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 2/6/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 2/6/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXBookmarkManager.h"
|
||||
#import "Classes/ExplorerInterface/Bookmarks/FLEXBookmarkManager.h"
|
||||
|
||||
static NSMutableArray *kFLEXBookmarkManagerBookmarks = nil;
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 2/6/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableViewController.h"
|
||||
#import "Classes/Headers/FLEXTableViewController.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 2/6/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXBookmarksViewController.h"
|
||||
#import "FLEXExplorerViewController.h"
|
||||
#import "FLEXNavigationController.h"
|
||||
#import "FLEXObjectExplorerFactory.h"
|
||||
#import "FLEXBookmarkManager.h"
|
||||
#import "UIBarButtonItem+FLEX.h"
|
||||
#import "FLEXColor.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXRuntimeUtility.h"
|
||||
#import "FLEXTableView.h"
|
||||
#import "Classes/ExplorerInterface/Bookmarks/FLEXBookmarksViewController.h"
|
||||
#import "Classes/ExplorerInterface/FLEXExplorerViewController.h"
|
||||
#import "Classes/Headers/FLEXNavigationController.h"
|
||||
#import "Classes/Headers/FLEXObjectExplorerFactory.h"
|
||||
#import "Classes/ExplorerInterface/Bookmarks/FLEXBookmarkManager.h"
|
||||
#import "Classes/Utility/Categories/UIBarButtonItem+FLEX.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Utility/Runtime/FLEXRuntimeUtility.h"
|
||||
#import "Classes/Headers/FLEXTableView.h"
|
||||
|
||||
@interface FLEXBookmarksViewController ()
|
||||
@property (nonatomic, copy) NSArray *bookmarks;
|
||||
@@ -68,10 +68,10 @@
|
||||
- (void)setupEditingBarItems {
|
||||
self.navigationItem.rightBarButtonItem = nil;
|
||||
self.toolbarItems = @[
|
||||
[UIBarButtonItem itemWithTitle:@"Close All" target:self action:@selector(closeAllButtonPressed:)],
|
||||
[UIBarButtonItem flex_itemWithTitle:@"Close All" target:self action:@selector(closeAllButtonPressed:)],
|
||||
UIBarButtonItem.flex_flexibleSpace,
|
||||
// We use a non-system done item because we change its title dynamically
|
||||
[UIBarButtonItem doneStyleitemWithTitle:@"Done" target:self action:@selector(toggleEditing)]
|
||||
[UIBarButtonItem flex_doneStyleitemWithTitle:@"Done" target:self action:@selector(toggleEditing)]
|
||||
];
|
||||
|
||||
self.toolbarItems.firstObject.tintColor = FLEXColor.destructiveColor;
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 4/4/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXExplorerToolbar.h"
|
||||
#import "Classes/Headers/FLEXExplorerToolbar.h"
|
||||
|
||||
@class FLEXWindow;
|
||||
@protocol FLEXExplorerViewControllerDelegate;
|
||||
@@ -21,11 +21,21 @@
|
||||
|
||||
- (BOOL)shouldReceiveTouchAtWindowPoint:(CGPoint)pointInWindowCoordinates;
|
||||
|
||||
/// @brief Used to present (or dismiss) a modal view controller ("tool"), typically triggered by pressing a button in the toolbar.
|
||||
/// @brief Used to present (or dismiss) a modal view controller ("tool"),
|
||||
/// typically triggered by pressing a button in the toolbar.
|
||||
///
|
||||
/// If a tool is already presented, this method simply dismisses it and calls the completion block.
|
||||
/// If no tool is presented, @code future() @endcode is presented and the completion block is called.
|
||||
- (void)toggleToolWithViewControllerProvider:(UINavigationController *(^)(void))future completion:(void(^)(void))completion;
|
||||
- (void)toggleToolWithViewControllerProvider:(UINavigationController *(^)(void))future
|
||||
completion:(void (^)(void))completion;
|
||||
|
||||
/// @brief Used to present (or dismiss) a modal view controller ("tool"),
|
||||
/// typically triggered by pressing a button in the toolbar.
|
||||
///
|
||||
/// If a tool is already presented, this method dismisses it and presents the given tool.
|
||||
/// The completion block is called once the tool has been presented.
|
||||
- (void)presentTool:(UINavigationController *(^)(void))future
|
||||
completion:(void (^)(void))completion;
|
||||
|
||||
// Keyboard shortcut helpers
|
||||
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 4/4/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXExplorerViewController.h"
|
||||
#import "FLEXExplorerToolbarItem.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXWindow.h"
|
||||
#import "FLEXTabList.h"
|
||||
#import "FLEXNavigationController.h"
|
||||
#import "FLEXHierarchyViewController.h"
|
||||
#import "FLEXGlobalsViewController.h"
|
||||
#import "FLEXObjectExplorerViewController.h"
|
||||
#import "FLEXObjectExplorerFactory.h"
|
||||
#import "FLEXNetworkMITMViewController.h"
|
||||
#import "FLEXTabsViewController.h"
|
||||
#import "FLEXWindowManagerController.h"
|
||||
#import "FLEXViewControllersViewController.h"
|
||||
#import "NSUserDefaults+FLEX.h"
|
||||
#import "Classes/ExplorerInterface/FLEXExplorerViewController.h"
|
||||
#import "Classes/Headers/FLEXExplorerToolbarItem.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/ExplorerInterface/FLEXWindow.h"
|
||||
#import "Classes/ExplorerInterface/Tabs/FLEXTabList.h"
|
||||
#import "Classes/Headers/FLEXNavigationController.h"
|
||||
#import "Classes/ViewHierarchy/FLEXHierarchyViewController.h"
|
||||
#import "Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h"
|
||||
#import "Classes/Headers/FLEXObjectExplorerViewController.h"
|
||||
#import "Classes/Headers/FLEXObjectExplorerFactory.h"
|
||||
#import "Classes/Network/FLEXNetworkMITMViewController.h"
|
||||
#import "Classes/ExplorerInterface/Tabs/FLEXTabsViewController.h"
|
||||
#import "Classes/ExplorerInterface/FLEXWindowManagerController.h"
|
||||
#import "Classes/ExplorerInterface/FLEXViewControllersViewController.h"
|
||||
#import "Classes/Utility/Categories/NSUserDefaults+FLEX.h"
|
||||
|
||||
typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
FLEXExplorerModeDefault,
|
||||
@@ -45,6 +45,9 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
/// Only valid while a toolbar drag pan gesture is in progress.
|
||||
@property (nonatomic) CGRect toolbarFrameBeforeDragging;
|
||||
|
||||
/// Only valid while a selected view pan gesture is in progress.
|
||||
@property (nonatomic) CGFloat selectedViewLastPanX;
|
||||
|
||||
/// Borders of all the visible views in the hierarchy at the selection point.
|
||||
/// The keys are NSValues with the corresponding view (nonretained).
|
||||
@property (nonatomic) NSDictionary<NSValue *, UIView *> *outlineViewsForVisibleViews;
|
||||
@@ -58,6 +61,9 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
/// A colored transparent overlay to indicate that the view is selected.
|
||||
@property (nonatomic) UIView *selectedViewOverlay;
|
||||
|
||||
/// Used to actuate changes in view selection on iOS 10+
|
||||
@property (nonatomic, readonly) UISelectionFeedbackGenerator *selectionFBG API_AVAILABLE(ios(10.0));
|
||||
|
||||
/// self.view.window as a \c FLEXWindow
|
||||
@property (nonatomic, readonly) FLEXWindow *window;
|
||||
|
||||
@@ -118,6 +124,19 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
self.movePanGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleMovePan:)];
|
||||
self.movePanGR.enabled = self.currentMode == FLEXExplorerModeMove;
|
||||
[self.view addGestureRecognizer:self.movePanGR];
|
||||
|
||||
// Feedback
|
||||
if (@available(iOS 10.0, *)) {
|
||||
_selectionFBG = [UISelectionFeedbackGenerator new];
|
||||
}
|
||||
|
||||
// Observe keyboard to move self out of the way
|
||||
[NSNotificationCenter.defaultCenter
|
||||
addObserver:self
|
||||
selector:@selector(keyboardShown:)
|
||||
name:UIKeyboardWillShowNotification
|
||||
object:nil
|
||||
];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
@@ -151,7 +170,10 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
|
||||
UIViewController *viewControllerToAsk = [self viewControllerForRotationAndOrientation];
|
||||
UIInterfaceOrientationMask supportedOrientations = FLEXUtility.infoPlistSupportedInterfaceOrientationsMask;
|
||||
if (viewControllerToAsk && ![viewControllerToAsk isKindOfClass:[self class]]) {
|
||||
// We check its class by name because using isKindOfClass will fail for the same class defined
|
||||
// twice in the runtime; and the goal here is to avoid calling -supportedInterfaceOrientations
|
||||
// recursively when I'm inspecting FLEX with itself from a tweak dylib
|
||||
if (viewControllerToAsk && ![NSStringFromClass([viewControllerToAsk class]) hasPrefix:@"FLEX"]) {
|
||||
supportedOrientations = [viewControllerToAsk supportedInterfaceOrientations];
|
||||
}
|
||||
|
||||
@@ -364,6 +386,21 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
return [self.view convertRect:frameInWindow fromView:nil];
|
||||
}
|
||||
|
||||
- (void)keyboardShown:(NSNotification *)notif {
|
||||
CGRect keyboardFrame = [notif.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
||||
CGRect toolbarFrame = self.explorerToolbar.frame;
|
||||
|
||||
if (CGRectGetMinY(keyboardFrame) < CGRectGetMaxY(toolbarFrame)) {
|
||||
toolbarFrame.origin.y = keyboardFrame.origin.y - toolbarFrame.size.height;
|
||||
// Subtract a little more, to ignore accessory input views
|
||||
toolbarFrame.origin.y -= 50;
|
||||
|
||||
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:1 initialSpringVelocity:0.5
|
||||
options:UIViewAnimationOptionCurveEaseOut animations:^{
|
||||
[self updateToolbarPositionWithUnconstrainedFrame:toolbarFrame];
|
||||
} completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Toolbar Buttons
|
||||
|
||||
@@ -392,8 +429,12 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
}
|
||||
|
||||
- (UIWindow *)statusWindow {
|
||||
NSString *statusBarString = [NSString stringWithFormat:@"%@arWindow", @"_statusB"];
|
||||
return [UIApplication.sharedApplication valueForKey:statusBarString];
|
||||
if (!@available(iOS 16, *)) {
|
||||
NSString *statusBarString = [NSString stringWithFormat:@"%@arWindow", @"_statusB"];
|
||||
return [UIApplication.sharedApplication valueForKey:statusBarString];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)recentButtonTapped:(FLEXExplorerToolbarItem *)sender {
|
||||
@@ -425,7 +466,11 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
toolbar.moveItem.selected = self.currentMode == FLEXExplorerModeMove;
|
||||
|
||||
// Recent only enabled when we have a last active tab
|
||||
toolbar.recentItem.enabled = FLEXTabList.sharedList.activeTab != nil;
|
||||
if (!self.presentedViewController) {
|
||||
toolbar.recentItem.enabled = FLEXTabList.sharedList.activeTab != nil;
|
||||
} else {
|
||||
toolbar.recentItem.enabled = NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -449,17 +494,12 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
initWithTarget:self action:@selector(handleToolbarDetailsTapGesture:)
|
||||
];
|
||||
[toolbar.selectedViewDescriptionContainer addGestureRecognizer:self.detailsTapGR];
|
||||
|
||||
// Swipe gestures for selecting deeper / higher views at a point
|
||||
UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc]
|
||||
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]
|
||||
initWithTarget:self action:@selector(handleChangeViewAtPointGesture:)
|
||||
];
|
||||
UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc]
|
||||
initWithTarget:self action:@selector(handleChangeViewAtPointGesture:)
|
||||
];
|
||||
leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
|
||||
rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;
|
||||
[toolbar.selectedViewDescriptionContainer addGestureRecognizer:leftSwipe];
|
||||
[toolbar.selectedViewDescriptionContainer addGestureRecognizer:rightSwipe];
|
||||
[toolbar.selectedViewDescriptionContainer addGestureRecognizer:panGesture];
|
||||
|
||||
// Long press gesture to present tabs manager
|
||||
[toolbar.globalsItem addGestureRecognizer:[[UILongPressGestureRecognizer alloc]
|
||||
@@ -598,19 +638,54 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleChangeViewAtPointGesture:(UISwipeGestureRecognizer *)sender {
|
||||
- (void)handleChangeViewAtPointGesture:(UIPanGestureRecognizer *)sender {
|
||||
NSInteger max = self.viewsAtTapPoint.count - 1;
|
||||
NSInteger currentIdx = [self.viewsAtTapPoint indexOfObject:self.selectedView];
|
||||
switch (sender.direction) {
|
||||
case UISwipeGestureRecognizerDirectionLeft:
|
||||
self.selectedView = self.viewsAtTapPoint[MIN(max, currentIdx + 1)];
|
||||
break;
|
||||
case UISwipeGestureRecognizerDirectionRight:
|
||||
self.selectedView = self.viewsAtTapPoint[MAX(0, currentIdx - 1)];
|
||||
CGFloat locationX = [sender locationInView:self.view].x;
|
||||
|
||||
// Track the pan gesture: every N points we move along the X axis,
|
||||
// actuate some haptic feedback and move up or down the hierarchy.
|
||||
// We only store the "last" location when we've met the threshold.
|
||||
// We only change the view and actuate feedback if the view selection
|
||||
// changes; that is, as long as we don't go outside or under the array.
|
||||
switch (sender.state) {
|
||||
case UIGestureRecognizerStateBegan: {
|
||||
self.selectedViewLastPanX = locationX;
|
||||
break;
|
||||
}
|
||||
case UIGestureRecognizerStateChanged: {
|
||||
static CGFloat kNextLevelThreshold = 20.f;
|
||||
CGFloat lastX = self.selectedViewLastPanX;
|
||||
NSInteger newSelection = currentIdx;
|
||||
|
||||
// Left, go down the hierarchy
|
||||
if (locationX < lastX && (lastX - locationX) >= kNextLevelThreshold) {
|
||||
// Choose a new view index up to the max index
|
||||
newSelection = MIN(max, currentIdx + 1);
|
||||
self.selectedViewLastPanX = locationX;
|
||||
}
|
||||
// Right, go up the hierarchy
|
||||
else if (lastX < locationX && (locationX - lastX) >= kNextLevelThreshold) {
|
||||
// Choose a new view index down to the min index
|
||||
newSelection = MAX(0, currentIdx - 1);
|
||||
self.selectedViewLastPanX = locationX;
|
||||
}
|
||||
|
||||
if (currentIdx != newSelection) {
|
||||
self.selectedView = self.viewsAtTapPoint[newSelection];
|
||||
[self actuateSelectionChangedFeedback];
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)actuateSelectionChangedFeedback {
|
||||
if (@available(iOS 10.0, *)) {
|
||||
[self.selectionFBG selectionChanged];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -777,31 +852,34 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
#pragma mark - Touch Handling
|
||||
|
||||
- (BOOL)shouldReceiveTouchAtWindowPoint:(CGPoint)pointInWindowCoordinates {
|
||||
BOOL shouldReceiveTouch = NO;
|
||||
|
||||
CGPoint pointInLocalCoordinates = [self.view convertPoint:pointInWindowCoordinates fromView:nil];
|
||||
|
||||
// Always if it's on the toolbar
|
||||
if (CGRectContainsPoint(self.explorerToolbar.frame, pointInLocalCoordinates)) {
|
||||
shouldReceiveTouch = YES;
|
||||
// If we have a modal presented, is it in the modal?
|
||||
if (self.presentedViewController) {
|
||||
UIView *presentedView = self.presentedViewController.view;
|
||||
CGPoint pipvc = [presentedView convertPoint:pointInLocalCoordinates fromView:self.view];
|
||||
UIView *hit = [presentedView hitTest:pipvc withEvent:nil];
|
||||
if (hit != nil) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
// Always if we're in selection mode
|
||||
if (!shouldReceiveTouch && self.currentMode == FLEXExplorerModeSelect) {
|
||||
shouldReceiveTouch = YES;
|
||||
if (self.currentMode == FLEXExplorerModeSelect) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Always in move mode too
|
||||
if (!shouldReceiveTouch && self.currentMode == FLEXExplorerModeMove) {
|
||||
shouldReceiveTouch = YES;
|
||||
if (self.currentMode == FLEXExplorerModeMove) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Always if we have a modal presented
|
||||
if (!shouldReceiveTouch && self.presentedViewController) {
|
||||
shouldReceiveTouch = YES;
|
||||
// Always if it's on the toolbar
|
||||
if (CGRectContainsPoint(self.explorerToolbar.frame, pointInLocalCoordinates)) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
return shouldReceiveTouch;
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
@@ -847,8 +925,14 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
// up in case we start replacing them again in the future
|
||||
self.appMenuItems = UIMenuController.sharedMenuController.menuItems;
|
||||
|
||||
[self updateButtonStates];
|
||||
|
||||
// Show the view controller
|
||||
[super presentViewController:toPresent animated:animated completion:completion];
|
||||
[super presentViewController:toPresent animated:animated completion:^{
|
||||
[self updateButtonStates];
|
||||
|
||||
if (completion) completion();
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)dismissViewControllerAnimated:(BOOL)animated completion:(void (^)(void))completion {
|
||||
@@ -869,23 +953,40 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
|
||||
[self updateButtonStates];
|
||||
|
||||
[super dismissViewControllerAnimated:animated completion:completion];
|
||||
[super dismissViewControllerAnimated:animated completion:^{
|
||||
[self updateButtonStates];
|
||||
|
||||
if (completion) completion();
|
||||
}];
|
||||
}
|
||||
|
||||
- (BOOL)wantsWindowToBecomeKey
|
||||
{
|
||||
- (BOOL)wantsWindowToBecomeKey {
|
||||
return self.window.previousKeyWindow != nil;
|
||||
}
|
||||
|
||||
- (void)toggleToolWithViewControllerProvider:(UINavigationController *(^)(void))future
|
||||
completion:(void(^)(void))completion {
|
||||
completion:(void (^)(void))completion {
|
||||
if (self.presentedViewController) {
|
||||
// We do NOT want to present the future; this is
|
||||
// a convenience method for toggling the SAME TOOL
|
||||
[self dismissViewControllerAnimated:YES completion:completion];
|
||||
} else if (future) {
|
||||
[self presentViewController:future() animated:YES completion:completion];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)presentTool:(UINavigationController *(^)(void))future
|
||||
completion:(void (^)(void))completion {
|
||||
if (self.presentedViewController) {
|
||||
// If a tool is already presented, dismiss it first
|
||||
[self dismissViewControllerAnimated:YES completion:^{
|
||||
[self presentViewController:future() animated:YES completion:completion];
|
||||
}];
|
||||
} else if (future) {
|
||||
[self presentViewController:future() animated:YES completion:completion];
|
||||
}
|
||||
}
|
||||
|
||||
- (FLEXWindow *)window {
|
||||
return (id)self.view.window;
|
||||
}
|
||||
@@ -924,11 +1025,7 @@ typedef NS_ENUM(NSUInteger, FLEXExplorerMode) {
|
||||
} else {
|
||||
return [FLEXHierarchyViewController delegate:self];
|
||||
}
|
||||
} completion:^{
|
||||
if (completion) {
|
||||
completion();
|
||||
}
|
||||
}];
|
||||
} completion:completion];
|
||||
}
|
||||
|
||||
- (void)toggleMenuTool {
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 2/13/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXFilteringTableViewController.h"
|
||||
#import "Classes/Headers/FLEXFilteringTableViewController.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner Bennett on 2/13/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXViewControllersViewController.h"
|
||||
#import "FLEXObjectExplorerFactory.h"
|
||||
#import "FLEXMutableListSection.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "Classes/ExplorerInterface/FLEXViewControllersViewController.h"
|
||||
#import "Classes/Headers/FLEXObjectExplorerFactory.h"
|
||||
#import "Classes/Headers/FLEXMutableListSection.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
|
||||
@interface FLEXViewControllersViewController ()
|
||||
@property (nonatomic, readonly) FLEXMutableListSection *section;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 4/13/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 4/13/14.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXWindow.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "Classes/ExplorerInterface/FLEXWindow.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@implementation FLEXWindow
|
||||
@@ -18,18 +18,13 @@
|
||||
// Some apps have windows at UIWindowLevelStatusBar + n.
|
||||
// If we make the window level too high, we block out UIAlertViews.
|
||||
// There's a balance between staying above the app's windows and staying below alerts.
|
||||
// UIWindowLevelStatusBar + 100 seems to hit that balance.
|
||||
self.windowLevel = UIWindowLevelStatusBar + 100.0;
|
||||
self.windowLevel = UIWindowLevelAlert - 1;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
|
||||
BOOL pointInside = NO;
|
||||
if ([self.eventDelegate shouldHandleTouchAtPoint:point]) {
|
||||
pointInside = [super pointInside:point withEvent:event];
|
||||
}
|
||||
return pointInside;
|
||||
return [self.eventDelegate shouldHandleTouchAtPoint:point];
|
||||
}
|
||||
|
||||
- (BOOL)shouldAffectStatusBarAppearance {
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 2/6/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableViewController.h"
|
||||
#import "Classes/Headers/FLEXTableViewController.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 2/6/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXWindowManagerController.h"
|
||||
#import "FLEXManager+Private.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXObjectExplorerFactory.h"
|
||||
#import "Classes/ExplorerInterface/FLEXWindowManagerController.h"
|
||||
#import "Classes/Manager/Private/FLEXManager+Private.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Headers/FLEXObjectExplorerFactory.h"
|
||||
|
||||
@interface FLEXWindowManagerController ()
|
||||
@property (nonatomic) UIWindow *keyWindow;
|
||||
@@ -72,7 +72,7 @@
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)showRevertOrDismissAlert:(void(^)())revertBlock {
|
||||
- (void)showRevertOrDismissAlert:(void(^)(void))revertBlock {
|
||||
[self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES];
|
||||
[self reloadData];
|
||||
[self.tableView reloadData];
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 2/1/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 2/1/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTabList.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "Classes/ExplorerInterface/Tabs/FLEXTabList.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
|
||||
@interface FLEXTabList () {
|
||||
NSMutableArray *_openTabs;
|
||||
@@ -80,10 +80,20 @@
|
||||
|
||||
- (void)closeTab:(UINavigationController *)tab {
|
||||
NSParameterAssert(tab);
|
||||
NSParameterAssert([self.openTabs containsObject:tab]);
|
||||
NSInteger idx = [self.openTabs indexOfObject:tab];
|
||||
if (idx != NSNotFound) {
|
||||
[self closeTabAtIndex:idx];
|
||||
}
|
||||
|
||||
[self closeTabAtIndex:idx];
|
||||
// Not sure how this is possible, but it happens sometimes
|
||||
if (self.activeTab == tab) {
|
||||
[self chooseNewActiveTab];
|
||||
}
|
||||
|
||||
// It is possible for an object explorer to form a retain cycle
|
||||
// with its own navigation controller; clearing the view controllers
|
||||
// manually when closing a tab breaks the cycle
|
||||
tab.viewControllers = @[];
|
||||
}
|
||||
|
||||
- (void)closeTabAtIndex:(NSInteger)idx {
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 2/4/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTableViewController.h"
|
||||
#import "Classes/Headers/FLEXTableViewController.h"
|
||||
|
||||
@interface FLEXTabsViewController : FLEXTableViewController
|
||||
|
||||
|
||||
@@ -3,20 +3,20 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 2/4/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXTabsViewController.h"
|
||||
#import "FLEXNavigationController.h"
|
||||
#import "FLEXTabList.h"
|
||||
#import "FLEXBookmarkManager.h"
|
||||
#import "FLEXTableView.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import "FLEXColor.h"
|
||||
#import "UIBarButtonItem+FLEX.h"
|
||||
#import "FLEXExplorerViewController.h"
|
||||
#import "FLEXGlobalsViewController.h"
|
||||
#import "FLEXBookmarksViewController.h"
|
||||
#import "Classes/ExplorerInterface/Tabs/FLEXTabsViewController.h"
|
||||
#import "Classes/Headers/FLEXNavigationController.h"
|
||||
#import "Classes/ExplorerInterface/Tabs/FLEXTabList.h"
|
||||
#import "Classes/ExplorerInterface/Bookmarks/FLEXBookmarkManager.h"
|
||||
#import "Classes/Headers/FLEXTableView.h"
|
||||
#import "Classes/Utility/FLEXUtility.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
#import "Classes/Utility/Categories/UIBarButtonItem+FLEX.h"
|
||||
#import "Classes/ExplorerInterface/FLEXExplorerViewController.h"
|
||||
#import "Classes/GlobalStateExplorers/Globals/FLEXGlobalsViewController.h"
|
||||
#import "Classes/ExplorerInterface/Bookmarks/FLEXBookmarksViewController.h"
|
||||
|
||||
@interface FLEXTabsViewController ()
|
||||
@property (nonatomic, copy) NSArray<UINavigationController *> *openTabs;
|
||||
@@ -121,12 +121,12 @@
|
||||
- (void)setupEditingBarItems {
|
||||
self.navigationItem.rightBarButtonItem = nil;
|
||||
self.toolbarItems = @[
|
||||
[UIBarButtonItem itemWithTitle:@"Close All" target:self action:@selector(closeAllButtonPressed:)],
|
||||
[UIBarButtonItem flex_itemWithTitle:@"Close All" target:self action:@selector(closeAllButtonPressed:)],
|
||||
UIBarButtonItem.flex_flexibleSpace,
|
||||
[UIBarButtonItem disabledSystemItem:UIBarButtonSystemItemAdd],
|
||||
[UIBarButtonItem flex_disabledSystemItem:UIBarButtonSystemItemAdd],
|
||||
UIBarButtonItem.flex_flexibleSpace,
|
||||
// We use a non-system done item because we change its title dynamically
|
||||
[UIBarButtonItem doneStyleitemWithTitle:@"Done" target:self action:@selector(toggleEditing)]
|
||||
[UIBarButtonItem flex_doneStyleitemWithTitle:@"Done" target:self action:@selector(toggleEditing)]
|
||||
];
|
||||
|
||||
self.toolbarItems.firstObject.tintColor = FLEXColor.destructiveColor;
|
||||
|
||||
+13
-19
@@ -3,25 +3,19 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 3/12/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Classes/Utility/Categories/UIBarButtonItem+FLEX.h"
|
||||
#import "Classes/Utility/Categories/CALayer+FLEX.h"
|
||||
#import "Classes/Utility/Categories/UIFont+FLEX.h"
|
||||
#import "Classes/Utility/Categories/UIGestureRecognizer+Blocks.h"
|
||||
#import "Classes/Utility/Categories/UIPasteboard+FLEX.h"
|
||||
#import "Classes/Utility/Categories/UIMenu+FLEX.h"
|
||||
#import "Classes/Utility/Categories/UITextField+Range.h"
|
||||
|
||||
|
||||
#import <FLEX/UIBarButtonItem+FLEX.h>
|
||||
#import <FLEX/CALayer+FLEX.h>
|
||||
#import <FLEX/UIFont+FLEX.h>
|
||||
#import <FLEX/UIGestureRecognizer+Blocks.h>
|
||||
#import <FLEX/UIView+FLEX_Layout.h>
|
||||
#import <FLEX/UIPasteboard+FLEX.h>
|
||||
#import <FLEX/UIMenu+FLEX.h>
|
||||
#import <FLEX/UITextField+Range.h>
|
||||
|
||||
#import <FLEX/NSObject+FLEX_Reflection.h>
|
||||
#import <FLEX/NSArray+FLEX.h>
|
||||
#import <FLEX/NSDictionary+ObjcRuntime.h>
|
||||
#import <FLEX/NSString+ObjcRuntime.h>
|
||||
#import <FLEX/NSString+FLEX.h>
|
||||
#import <FLEX/NSUserDefaults+FLEX.h>
|
||||
#import <FLEX/NSMapTable+FLEX_Subscripting.h>
|
||||
#import <FLEX/NSTimer+FLEX.h>
|
||||
#import "Classes/Utility/Categories/NSObject+FLEX_Reflection.h"
|
||||
#import "Classes/Utility/Categories/NSArray+FLEX.h"
|
||||
#import "Classes/Utility/Categories/NSUserDefaults+FLEX.h"
|
||||
#import "Classes/Utility/Categories/NSTimer+FLEX.h"
|
||||
#import "Classes/Utility/Categories/NSDateFormatter+FLEX.h"
|
||||
|
||||
+12
-13
@@ -3,21 +3,20 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 3/11/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <FLEX/FLEXFilteringTableViewController.h>
|
||||
#import <FLEX/FLEXNavigationController.h>
|
||||
#import <FLEX/FLEXTableViewController.h>
|
||||
#import <FLEX/FLEXTableView.h>
|
||||
#import "Classes/Headers/FLEXFilteringTableViewController.h"
|
||||
#import "Classes/Headers/FLEXNavigationController.h"
|
||||
#import "Classes/Headers/FLEXTableViewController.h"
|
||||
#import "Classes/Headers/FLEXTableView.h"
|
||||
|
||||
#import <FLEX/FLEXSingleRowSection.h>
|
||||
#import <FLEX/FLEXTableViewSection.h>
|
||||
#import "Classes/Headers/FLEXSingleRowSection.h"
|
||||
#import "Classes/Headers/FLEXTableViewSection.h"
|
||||
|
||||
#import <FLEX/FLEXCodeFontCell.h>
|
||||
#import <FLEX/FLEXSubtitleTableViewCell.h>
|
||||
#import <FLEX/FLEXTableViewCell.h>
|
||||
#import <FLEX/FLEXMultilineTableViewCell.h>
|
||||
#import <FLEX/FLEXKeyValueTableViewCell.h>
|
||||
#import "Classes/Headers/FLEXCodeFontCell.h"
|
||||
#import "Classes/Headers/FLEXSubtitleTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXMultilineTableViewCell.h"
|
||||
#import "Classes/Headers/FLEXKeyValueTableViewCell.h"
|
||||
|
||||
#import <FLEX/FLEXScopeCarousel.h>
|
||||
|
||||
@@ -3,28 +3,20 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 3/11/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <FLEX/FLEXObjectExplorerFactory.h>
|
||||
#import <FLEX/FLEXObjectExplorerViewController.h>
|
||||
#import "Classes/Headers/FLEXObjectExplorerFactory.h"
|
||||
#import "Classes/Headers/FLEXObjectExplorerViewController.h"
|
||||
|
||||
#import <FLEX/FLEXObjectExplorer.h>
|
||||
#import "Classes/Headers/FLEXObjectExplorer.h"
|
||||
|
||||
#import <FLEX/FLEXShortcut.h>
|
||||
#import <FLEX/FLEXShortcutsFactory+Defaults.h>
|
||||
#import <FLEX/FLEXShortcutsSection.h>
|
||||
#import <FLEX/FLEXBlockShortcuts.h>
|
||||
#import <FLEX/FLEXBundleShortcuts.h>
|
||||
#import <FLEX/FLEXClassShortcuts.h>
|
||||
#import <FLEX/FLEXImageShortcuts.h>
|
||||
#import <FLEX/FLEXLayerShortcuts.h>
|
||||
#import <FLEX/FLEXViewControllerShortcuts.h>
|
||||
#import <FLEX/FLEXViewShortcuts.h>
|
||||
#import "Classes/Headers/FLEXShortcut.h"
|
||||
#import "Classes/Headers/FLEXShortcutsSection.h"
|
||||
|
||||
#import <FLEX/FLEXCollectionContentSection.h>
|
||||
#import <FLEX/FLEXColorPreviewSection.h>
|
||||
#import <FLEX/FLEXDefaultsContentSection.h>
|
||||
#import <FLEX/FLEXMetadataSection.h>
|
||||
#import <FLEX/FLEXMutableListSection.h>
|
||||
#import <FLEX/FLEXObjectInfoSection.h>
|
||||
#import "Classes/Headers/FLEXCollectionContentSection.h"
|
||||
#import "Classes/Headers/FLEXColorPreviewSection.h"
|
||||
#import "Classes/Headers/FLEXDefaultsContentSection.h"
|
||||
#import "Classes/Headers/FLEXMetadataSection.h"
|
||||
#import "Classes/Headers/FLEXMutableListSection.h"
|
||||
#import "Classes/Headers/FLEXObjectInfoSection.h"
|
||||
|
||||
+18
-16
@@ -3,23 +3,25 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 3/11/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <FLEX/FLEXObjcInternal.h>
|
||||
#import <FLEX/FLEXRuntimeSafety.h>
|
||||
#import <FLEX/FLEXBlockDescription.h>
|
||||
#import <FLEX/FLEXTypeEncodingParser.h>
|
||||
#import "Classes/Utility/Runtime/Objc/FLEXObjcInternal.h"
|
||||
#import "Classes/Utility/Runtime/Objc/FLEXSwiftInternal.h"
|
||||
#import "Classes/Utility/Runtime/Objc/FLEXRuntimeSafety.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXBlockDescription.h"
|
||||
#import "Classes/Utility/Runtime/Objc/FLEXTypeEncodingParser.h"
|
||||
|
||||
#import <FLEX/FLEXMirror.h>
|
||||
#import <FLEX/FLEXProtocol.h>
|
||||
#import <FLEX/FLEXProperty.h>
|
||||
#import <FLEX/FLEXIvar.h>
|
||||
#import <FLEX/FLEXMethodBase.h>
|
||||
#import <FLEX/FLEXMethod.h>
|
||||
#import <FLEX/FLEXPropertyAttributes.h>
|
||||
#import <FLEX/FLEXRuntime+Compare.h>
|
||||
#import <FLEX/FLEXRuntime+UIKitHelpers.h>
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXMirror.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXProtocol.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXProperty.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXIvar.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXMethodBase.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXMethod.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXPropertyAttributes.h"
|
||||
#import "Classes/Utility/Categories/FLEXRuntime+Compare.h"
|
||||
#import "Classes/Utility/Categories/FLEXRuntime+UIKitHelpers.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXMetadataExtras.h"
|
||||
|
||||
#import <FLEX/FLEXProtocolBuilder.h>
|
||||
#import <FLEX/FLEXClassBuilder.h>
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXProtocolBuilder.h"
|
||||
#import "Classes/Utility/Runtime/Objc/Reflection/FLEXClassBuilder.h"
|
||||
|
||||
+15
-14
@@ -4,22 +4,23 @@
|
||||
//
|
||||
// Created by Eric Horacek on 7/18/15.
|
||||
// Modified by Tanner Bennett on 3/12/20.
|
||||
// Copyright (c) 2020 Flipboard. All rights reserved.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <FLEX/FLEXManager.h>
|
||||
#import <FLEX/FLEXManager+Extensibility.h>
|
||||
#import <FLEX/FLEXManager+Networking.h>
|
||||
#import "Classes/Headers/FLEXManager.h"
|
||||
#import "Classes/Headers/FLEXManager+Extensibility.h"
|
||||
#import "Classes/Headers/FLEXManager+Networking.h"
|
||||
|
||||
#import <FLEX/FLEXExplorerToolbar.h>
|
||||
#import <FLEX/FLEXExplorerToolbarItem.h>
|
||||
#import <FLEX/FLEXGlobalsEntry.h>
|
||||
#import "Classes/Headers/FLEXExplorerToolbar.h"
|
||||
#import "Classes/Headers/FLEXExplorerToolbarItem.h"
|
||||
#import "Classes/GlobalStateExplorers/Globals/FLEXGlobalsEntry.h"
|
||||
|
||||
#import <FLEX/FLEX-Core.h>
|
||||
#import <FLEX/FLEX-Runtime.h>
|
||||
#import <FLEX/FLEX-Categories.h>
|
||||
#import <FLEX/FLEX-ObjectExploring.h>
|
||||
#import "Classes/Headers/FLEX-Core.h"
|
||||
#import "Classes/Headers/FLEX-Runtime.h"
|
||||
#import "Classes/Headers/FLEX-Categories.h"
|
||||
#import "Classes/Headers/FLEX-ObjectExploring.h"
|
||||
|
||||
#import <FLEX/FLEXMacros.h>
|
||||
#import <FLEX/FLEXAlert.h>
|
||||
#import <FLEX/FLEXResources.h>
|
||||
#import "Classes/Utility/FLEXMacros.h"
|
||||
#import "Classes/Utility/FLEXAlert.h"
|
||||
#import "Classes/Utility/FLEXResources.h"
|
||||
#import "Classes/Utility/FLEXHeapEnumerator.h"
|
||||
|
||||
@@ -8,12 +8,21 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class FLEXDBQueryRowCell;
|
||||
|
||||
extern NSString * const kFLEXDBQueryRowCellReuse;
|
||||
|
||||
@protocol FLEXDBQueryRowCellLayoutSource <NSObject>
|
||||
|
||||
- (CGFloat)dbQueryRowCell:(FLEXDBQueryRowCell *)dbQueryRowCell minXForColumn:(NSUInteger)column;
|
||||
- (CGFloat)dbQueryRowCell:(FLEXDBQueryRowCell *)dbQueryRowCell widthForColumn:(NSUInteger)column;
|
||||
|
||||
@end
|
||||
|
||||
@interface FLEXDBQueryRowCell : UITableViewCell
|
||||
|
||||
/// An array of NSString, NSNumber, or NSData objects
|
||||
@property (nonatomic) NSArray *data;
|
||||
@property (nonatomic, weak) id<FLEXDBQueryRowCellLayoutSource> layoutSource;
|
||||
|
||||
@end
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
// Copyright © 2015年 f. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXDBQueryRowCell.h"
|
||||
#import "FLEXMultiColumnTableView.h"
|
||||
#import "NSArray+FLEX.h"
|
||||
#import "UIFont+FLEX.h"
|
||||
#import "FLEXColor.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXDBQueryRowCell.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.h"
|
||||
#import "Classes/Utility/Categories/NSArray+FLEX.h"
|
||||
#import "Classes/Utility/Categories/UIFont+FLEX.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
|
||||
NSString * const kFLEXDBQueryRowCellReuse = @"kFLEXDBQueryRowCellReuse";
|
||||
|
||||
@@ -63,11 +63,12 @@ NSString * const kFLEXDBQueryRowCellReuse = @"kFLEXDBQueryRowCellReuse";
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
|
||||
CGFloat width = self.contentView.frame.size.width / self.labels.count;
|
||||
CGFloat height = self.contentView.frame.size.height;
|
||||
|
||||
[self.labels flex_forEach:^(UILabel *label, NSUInteger i) {
|
||||
label.frame = CGRectMake(width * i + 5, 0, (width - 10), height);
|
||||
CGFloat width = [self.layoutSource dbQueryRowCell:self widthForColumn:i];
|
||||
CGFloat minX = [self.layoutSource dbQueryRowCell:self minXForColumn:i];
|
||||
label.frame = CGRectMake(minX + 5, 0, (width - 10), height);
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// which Flying Meat Inc. licenses this file to you.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FLEXSQLResult.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXSQLResult.h"
|
||||
|
||||
/// Conformers should automatically open and close the database
|
||||
@protocol FLEXDatabaseManager <NSObject>
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
@optional
|
||||
|
||||
- (NSArray<NSString *> *)queryRowIDsInTable:(NSString *)tableName;
|
||||
- (FLEXSQLResult *)executeStatement:(NSString *)SQLStatement;
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "FLEXTableColumnHeader.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableColumnHeader.h"
|
||||
|
||||
@class FLEXMultiColumnTableView;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
- (NSString *)rowTitle:(NSInteger)row;
|
||||
- (NSArray<NSString *> *)contentForRow:(NSInteger)row;
|
||||
|
||||
- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView widthForContentCellInColumn:(NSInteger)column;
|
||||
- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView minWidthForContentCellInColumn:(NSInteger)column;
|
||||
- (CGFloat)multiColumnTableView:(FLEXMultiColumnTableView *)tableView heightForContentCellInRow:(NSInteger)row;
|
||||
- (CGFloat)heightForTopHeaderInTableView:(FLEXMultiColumnTableView *)tableView;
|
||||
- (CGFloat)widthForLeftHeaderInTableView:(FLEXMultiColumnTableView *)tableView;
|
||||
|
||||
@@ -6,13 +6,15 @@
|
||||
// Copyright © 2015年 Peng Tao. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXMultiColumnTableView.h"
|
||||
#import "FLEXDBQueryRowCell.h"
|
||||
#import "FLEXTableLeftCell.h"
|
||||
#import "FLEXColor.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXMultiColumnTableView.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXDBQueryRowCell.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXTableLeftCell.h"
|
||||
#import "Classes/Utility/Categories/NSArray+FLEX.h"
|
||||
#import "Classes/Utility/FLEXColor.h"
|
||||
|
||||
@interface FLEXMultiColumnTableView () <
|
||||
UITableViewDataSource, UITableViewDelegate, UIScrollViewDelegate
|
||||
UITableViewDataSource, UITableViewDelegate,
|
||||
UIScrollViewDelegate, FLEXDBQueryRowCellLayoutSource
|
||||
>
|
||||
|
||||
@property (nonatomic) UIScrollView *contentScrollView;
|
||||
@@ -21,12 +23,12 @@
|
||||
@property (nonatomic) UITableView *contentTableView;
|
||||
@property (nonatomic) UIView *leftHeader;
|
||||
|
||||
@property (nonatomic) NSArray<UIView *> *headerViews;
|
||||
|
||||
/// \c NSNotFound if no column selected
|
||||
@property (nonatomic) NSInteger sortColumn;
|
||||
@property (nonatomic) FLEXTableColumnHeaderSortType sortType;
|
||||
|
||||
@property (nonatomic) NSArray *rowData;
|
||||
|
||||
@property (nonatomic, readonly) NSInteger numberOfColumns;
|
||||
@property (nonatomic, readonly) NSInteger numberOfRows;
|
||||
@property (nonatomic, readonly) CGFloat topHeaderHeight;
|
||||
@@ -71,9 +73,9 @@ static const CGFloat kColumnMargin = 1;
|
||||
}
|
||||
|
||||
CGFloat contentWidth = 0.0;
|
||||
NSInteger rowsCount = self.numberOfColumns;
|
||||
for (int i = 0; i < rowsCount; i++) {
|
||||
contentWidth += [self contentWidthForColumn:i];
|
||||
NSInteger columnsCount = self.numberOfColumns;
|
||||
for (int i = 0; i < columnsCount; i++) {
|
||||
contentWidth += CGRectGetWidth(self.headerViews[i].bounds);
|
||||
}
|
||||
|
||||
CGFloat contentHeight = height - topheaderHeight - topInsets;
|
||||
@@ -147,26 +149,30 @@ static const CGFloat kColumnMargin = 1;
|
||||
#pragma mark - Data
|
||||
|
||||
- (void)reloadData {
|
||||
[self loadHeaderData];
|
||||
[self loadLeftViewData];
|
||||
[self loadContentData];
|
||||
[self loadHeaderData];
|
||||
}
|
||||
|
||||
- (void)loadHeaderData {
|
||||
// Remove existing headers, if any
|
||||
for (UIView *subview in self.headerScrollView.subviews) {
|
||||
for (UIView *subview in self.headerViews) {
|
||||
[subview removeFromSuperview];
|
||||
}
|
||||
|
||||
CGFloat xOffset = 0.0;
|
||||
for (NSInteger column = 0; column < self.numberOfColumns; column++) {
|
||||
CGFloat width = [self contentWidthForColumn:column] + self.columnMargin;
|
||||
|
||||
FLEXTableColumnHeader *header = [[FLEXTableColumnHeader alloc]
|
||||
initWithFrame:CGRectMake(xOffset, 0, width, self.topHeaderHeight - 1)
|
||||
];
|
||||
__block CGFloat xOffset = 0;
|
||||
|
||||
self.headerViews = [NSArray flex_forEachUpTo:self.numberOfColumns map:^id(NSUInteger column) {
|
||||
FLEXTableColumnHeader *header = [FLEXTableColumnHeader new];
|
||||
header.titleLabel.text = [self columnTitle:column];
|
||||
|
||||
CGSize fittingSize = CGSizeMake(CGFLOAT_MAX, self.topHeaderHeight - 1);
|
||||
CGFloat width = self.columnMargin + MAX(
|
||||
[self minContentWidthForColumn:column],
|
||||
[header sizeThatFits:fittingSize].width
|
||||
);
|
||||
header.frame = CGRectMake(xOffset, 0, width, self.topHeaderHeight - 1);
|
||||
|
||||
if (column == self.sortColumn) {
|
||||
header.sortType = self.sortType;
|
||||
}
|
||||
@@ -178,21 +184,22 @@ static const CGFloat kColumnMargin = 1;
|
||||
[header addGestureRecognizer:gesture];
|
||||
header.userInteractionEnabled = YES;
|
||||
|
||||
[self.headerScrollView addSubview:header];
|
||||
xOffset += width;
|
||||
}
|
||||
[self.headerScrollView addSubview:header];
|
||||
return header;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)contentHeaderTap:(UIGestureRecognizer *)gesture {
|
||||
NSInteger newSortColumn = [self.headerScrollView.subviews indexOfObject:gesture.view];
|
||||
NSInteger newSortColumn = [self.headerViews indexOfObject:gesture.view];
|
||||
FLEXTableColumnHeaderSortType newType = FLEXNextTableColumnHeaderSortType(self.sortType);
|
||||
|
||||
// Reset old header
|
||||
FLEXTableColumnHeader *oldHeader = (id)self.headerScrollView.subviews[self.sortColumn];
|
||||
FLEXTableColumnHeader *oldHeader = (id)self.headerViews[self.sortColumn];
|
||||
oldHeader.sortType = FLEXTableColumnHeaderSortTypeNone;
|
||||
|
||||
// Update new header
|
||||
FLEXTableColumnHeader *newHeader = (id)self.headerScrollView.subviews[newSortColumn];
|
||||
FLEXTableColumnHeader *newHeader = (id)self.headerViews[newSortColumn];
|
||||
newHeader.sortType = newType;
|
||||
|
||||
// Update self
|
||||
@@ -227,13 +234,13 @@ static const CGFloat kColumnMargin = 1;
|
||||
}
|
||||
// Right side table view for data
|
||||
else {
|
||||
self.rowData = [self.dataSource contentForRow:indexPath.row];
|
||||
FLEXDBQueryRowCell *cell = [tableView
|
||||
dequeueReusableCellWithIdentifier:kFLEXDBQueryRowCellReuse forIndexPath:indexPath
|
||||
];
|
||||
|
||||
cell.contentView.backgroundColor = backgroundColor;
|
||||
cell.data = [self.dataSource contentForRow:indexPath.row];
|
||||
cell.layoutSource = self;
|
||||
NSAssert(cell.data.count == self.numberOfColumns, @"Count of data provided was incorrect");
|
||||
return cell;
|
||||
}
|
||||
@@ -280,6 +287,17 @@ static const CGFloat kColumnMargin = 1;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark FLEXDBQueryRowCellLayoutSource
|
||||
|
||||
- (CGFloat)dbQueryRowCell:(FLEXDBQueryRowCell *)dbQueryRowCell minXForColumn:(NSUInteger)column {
|
||||
return CGRectGetMinX(self.headerViews[column].frame);
|
||||
}
|
||||
|
||||
- (CGFloat)dbQueryRowCell:(FLEXDBQueryRowCell *)dbQueryRowCell widthForColumn:(NSUInteger)column {
|
||||
return CGRectGetWidth(self.headerViews[column].bounds);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark DataSource Accessor
|
||||
|
||||
- (NSInteger)numberOfRows {
|
||||
@@ -298,8 +316,8 @@ static const CGFloat kColumnMargin = 1;
|
||||
return [self.dataSource rowTitle:row];
|
||||
}
|
||||
|
||||
- (CGFloat)contentWidthForColumn:(NSInteger)column {
|
||||
return [self.dataSource multiColumnTableView:self widthForContentCellInColumn:column];
|
||||
- (CGFloat)minContentWidthForColumn:(NSInteger)column {
|
||||
return [self.dataSource multiColumnTableView:self minWidthForContentCellInColumn:column];
|
||||
}
|
||||
|
||||
- (CGFloat)contentHeightForRow:(NSInteger)row {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FLEXDatabaseManager.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXDatabaseManager.h"
|
||||
|
||||
@interface FLEXRealmDatabaseManager : NSObject <FLEXDatabaseManager>
|
||||
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
// Copyright © 2016 Realm. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXRealmDatabaseManager.h"
|
||||
#import "NSArray+FLEX.h"
|
||||
#import "FLEXSQLResult.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDatabaseManager.h"
|
||||
#import "Classes/Utility/Categories/NSArray+FLEX.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXSQLResult.h"
|
||||
|
||||
#if __has_include(<Realm/Realm.h>)
|
||||
#import <Realm/Realm.h>
|
||||
#import <Realm/RLMRealm_Dynamic.h>
|
||||
#else
|
||||
#import "FLEXRealmDefines.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXRealmDefines.h"
|
||||
#endif
|
||||
|
||||
@interface FLEXRealmDatabaseManager ()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 3/3/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
// FLEX
|
||||
//
|
||||
// Created by Tanner on 3/3/20.
|
||||
// Copyright © 2020 Flipboard. All rights reserved.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXSQLResult.h"
|
||||
#import "NSArray+FLEX.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXSQLResult.h"
|
||||
#import "Classes/Utility/Categories/NSArray+FLEX.h"
|
||||
|
||||
@implementation FLEXSQLResult
|
||||
@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];
|
||||
}
|
||||
|
||||
- (id)initWithmessage:(NSString *)message columns:(NSArray *)columns rows:(NSArray<NSArray *> *)rows {
|
||||
- (instancetype)initWithMessage:(NSString *)message columns:(NSArray<NSString *> *)columns rows:(NSArray<NSArray<NSString *> *> *)rows {
|
||||
NSParameterAssert(message || (columns && rows));
|
||||
NSParameterAssert(columns.count == rows.firstObject.count);
|
||||
NSParameterAssert(rows.count == 0 || columns.count == rows.firstObject.count);
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
// which Flying Meat Inc. licenses this file to you.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FLEXDatabaseManager.h"
|
||||
#import "FLEXSQLResult.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXDatabaseManager.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXSQLResult.h"
|
||||
|
||||
@interface FLEXSQLiteDatabaseManager : NSObject <FLEXDatabaseManager>
|
||||
|
||||
|
||||
@@ -6,13 +6,16 @@
|
||||
// Copyright © 2015年 Peng Tao. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXSQLiteDatabaseManager.h"
|
||||
#import "FLEXManager.h"
|
||||
#import "NSArray+FLEX.h"
|
||||
#import "FLEXRuntimeConstants.h"
|
||||
#import "Classes/GlobalStateExplorers/DatabaseBrowser/FLEXSQLiteDatabaseManager.h"
|
||||
#import "Classes/Headers/FLEXManager.h"
|
||||
#import "Classes/Utility/Categories/NSArray+FLEX.h"
|
||||
#import "Classes/Utility/Runtime/Objc/FLEXRuntimeConstants.h"
|
||||
#import <sqlite3.h>
|
||||
|
||||
static NSString * const QUERY_TABLENAMES = @"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
|
||||
#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");
|
||||
|
||||
@interface FLEXSQLiteDatabaseManager ()
|
||||
@property (nonatomic) sqlite3 *db;
|
||||
@@ -30,7 +33,7 @@ static NSString * const QUERY_TABLENAMES = @"SELECT name FROM sqlite_master WHER
|
||||
- (instancetype)initWithPath:(NSString *)path {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.path = path;;
|
||||
self.path = path;
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -107,16 +110,36 @@ static NSString * const QUERY_TABLENAMES = @"SELECT name FROM sqlite_master WHER
|
||||
- (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"];
|
||||
}] ?: @[];
|
||||
}
|
||||
|
||||
- (NSArray<NSArray *> *)queryAllDataInTable:(NSString *)tableName {
|
||||
return [self executeStatement:[@"SELECT * FROM "
|
||||
stringByAppendingString:tableName
|
||||
]].rows ?: @[];
|
||||
NSString *command = [NSString stringWithFormat:@"SELECT * FROM \"%@\"", tableName];
|
||||
return [self executeStatement:command].rows ?: @[];
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)queryRowIDsInTable:(NSString *)tableName {
|
||||
NSString *command = [NSString stringWithFormat:QUERY_ROWIDS, tableName];
|
||||
NSArray<NSArray<NSString *> *> *data = [self executeStatement:command].rows ?: @[];
|
||||
|
||||
return [data flex_mapped:^id(NSArray<NSString *> *obj, NSUInteger idx) {
|
||||
return obj.firstObject;
|
||||
}];
|
||||
}
|
||||
|
||||
- (FLEXSQLResult *)executeStatement:(NSString *)sql {
|
||||
@@ -138,7 +161,7 @@ static NSString * const QUERY_TABLENAMES = @"SELECT name FROM sqlite_master WHER
|
||||
return self.lastResult;
|
||||
}
|
||||
|
||||
// Grab columns
|
||||
// Grab columns (columnCount will be 0 for insert/update/delete)
|
||||
int columnCount = sqlite3_column_count(pstmt);
|
||||
NSArray<NSString *> *columns = [NSArray flex_forEachUpTo:columnCount map:^id(NSUInteger i) {
|
||||
return @(sqlite3_column_name(pstmt, (int)i));
|
||||
@@ -156,8 +179,9 @@ static NSString * const QUERY_TABLENAMES = @"SELECT name FROM sqlite_master WHER
|
||||
}
|
||||
|
||||
if (status == SQLITE_DONE) {
|
||||
if (rows.count) {
|
||||
// We selected some rows
|
||||
// columnCount will be 0 for insert/update/delete
|
||||
if (rows.count || columnCount > 0) {
|
||||
// We executed a SELECT query
|
||||
result = _lastResult = [FLEXSQLResult columns:columns rows:rows];
|
||||
} else {
|
||||
// We executed a query like INSERT, UDPATE, or DELETE
|
||||
@@ -257,7 +281,7 @@ static NSString * const QUERY_TABLENAMES = @"SELECT name FROM sqlite_master WHER
|
||||
- (FLEXSQLResult *)errorResult:(NSString *)description {
|
||||
const char *error = sqlite3_errmsg(_db);
|
||||
NSString *message = error ? @(error) : [NSString
|
||||
stringWithFormat:@"(%@: empty error", description
|
||||
stringWithFormat:@"(%@: empty error)", description
|
||||
];
|
||||
|
||||
return [FLEXSQLResult error:message];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user