diff --git a/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m b/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m index 46d886ca18..4b69c8b3c7 100644 --- a/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m +++ b/Classes/ObjectExplorers/FLEXObjectExplorerFactory.m @@ -11,6 +11,7 @@ #import "FLEXClassShortcuts.h" #import "FLEXViewShortcuts.h" #import "FLEXViewControllerShortcuts.h" +#import "FLEXUIAppShortcuts.h" #import "FLEXImageShortcuts.h" #import "FLEXLayerShortcuts.h" #import "FLEXColorPreviewSection.h" @@ -35,6 +36,7 @@ + (void)initialize { ClassKey(NSOrderedSet) : [FLEXCollectionContentSection class], ClassKey(NSUserDefaults) : [FLEXDefaultsContentSection class], ClassKey(UIViewController) : [FLEXViewControllerShortcuts class], + ClassKey(UIApplication) : [FLEXUIAppShortcuts class], ClassKey(UIView) : [FLEXViewShortcuts class], ClassKey(UIImage) : [FLEXImageShortcuts class], ClassKey(CALayer) : [FLEXLayerShortcuts class], diff --git a/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.h b/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.h index a1e4dc926f..58aa86c854 100644 --- a/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.h +++ b/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.h @@ -8,6 +8,8 @@ #import "FLEXShortcutsSection.h" +@interface FLEXShortcutsFactory (UIApplication) @end + @interface FLEXShortcutsFactory (Views) @end @interface FLEXShortcutsFactory (ViewControllers) @end diff --git a/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.m b/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.m index 264f636909..208547435e 100644 --- a/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.m +++ b/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.m @@ -11,6 +11,25 @@ #import "FLEXRuntimeUtility.h" #import "NSObject+FLEX_Reflection.h" +#pragma mark - UIApplication + +@implementation FLEXShortcutsFactory (UIApplication) + ++ (void)load { FLEX_EXIT_IF_TESTING() + self.append.classProperties(@[@"sharedApplication"]).forClass(UIApplication.flex_metaclass); + self.append.properties(@[ + @"delegate", @"keyWindow", @"windows" + ]).forClass(UIApplication.class); + + if (@available(iOS 13, *)) { + self.append.properties(@[ + @"connectedScenes", @"openSessions", @"supportsMultipleScenes" + ]).forClass(UIApplication.class); + } +} + +@end + #pragma mark - Views @implementation FLEXShortcutsFactory (Views) @@ -135,7 +154,7 @@ + (void)load { FLEX_EXIT_IF_TESTING() ]).forClass(UIImage.class); if (@available(iOS 13, *)) { - self.append.properties(@[@"symbolImage"]); + self.append.properties(@[@"symbolImage"]).forClass(UIImage.class); } } @@ -237,24 +256,6 @@ + (void)load { FLEX_EXIT_IF_TESTING() self.append.classProperties(@[ @"defaultTimeZone", @"systemTimeZone", @"localTimeZone" ]).forClass(NSTimeZone.class); - - -// self.append.<#type#>(@[@"<#value#>"]).forClass(NSURLSession.class); -// -// -// self.append.<#type#>(@[@"<#value#>"]).forClass(NSURLSession.class); -// -// -// self.append.<#type#>(@[@"<#value#>"]).forClass(NSURLSession.class); -// -// -// self.append.<#type#>(@[@"<#value#>"]).forClass(NSURLSession.class); -// -// -// self.append.<#type#>(@[@"<#value#>"]).forClass(NSURLSession.class); -// -// -// self.append.<#type#>(@[@"<#value#>"]).forClass(NSURLSession.class); } @end diff --git a/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.h b/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.h index 6084cda719..7af82231c2 100644 --- a/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.h +++ b/Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsSection.h @@ -59,6 +59,8 @@ /// Subclasses \e may override this to hide the disclosure indicator /// for some rows. It is shown for all rows by default, unless /// you initialize it with \c forObject:rowTitles:rowSubtitles: +/// +/// When you hide the disclosure indicator, the row is not selectable. - (UITableViewCellAccessoryType)accessoryTypeForRow:(NSInteger)row; /// The number of lines for the title and subtitle labels. Defaults to 1. diff --git a/Classes/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.h b/Classes/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.h new file mode 100644 index 0000000000..7ea053da12 --- /dev/null +++ b/Classes/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.h @@ -0,0 +1,13 @@ +// +// FLEXUIAppShortcuts.h +// FLEX +// +// Created by Tanner on 5/25/20. +// Copyright © 2020 Flipboard. All rights reserved. +// + +#import "FLEXShortcutsSection.h" + +@interface FLEXUIAppShortcuts : FLEXShortcutsSection + +@end diff --git a/Classes/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.m b/Classes/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.m new file mode 100644 index 0000000000..5612f954c8 --- /dev/null +++ b/Classes/ObjectExplorers/Sections/Shortcuts/FLEXUIAppShortcuts.m @@ -0,0 +1,77 @@ +// +// FLEXUIAppShortcuts.m +// FLEX +// +// Created by Tanner on 5/25/20. +// Copyright © 2020 Flipboard. All rights reserved. +// + +#import "FLEXUIAppShortcuts.h" +#import "FLEXRuntimeUtility.h" +#import "FLEXShortcut.h" +#import "FLEXAlert.h" + +@implementation FLEXUIAppShortcuts + +#pragma mark - Overrides + ++ (instancetype)forObject:(UIApplication *)application { + return [self forObject:application additionalRows:@[ + [FLEXActionShortcut title:@"Open URL…" + subtitle:^NSString *(UIViewController *controller) { + return nil; + } + selectionHandler:^void(UIViewController *host, UIApplication *app) { + [FLEXAlert makeAlert:^(FLEXAlert *make) { + make.title(@"Open URL"); + make.message( + @"This will call openURL: or openURL:options:completion: " + "with the string below. 'Open if Universal' will only open " + "the URL if it is a registered Universal Link." + ); + + make.textField(@"twitter://user?id=12345"); + make.button(@"Open").handler(^(NSArray *strings) { + [self openURL:strings[0] inApp:app onlyIfUniveral:NO host:host]; + }); + make.button(@"Open if Universal").handler(^(NSArray *strings) { + [self openURL:strings[0] inApp:app onlyIfUniveral:YES host:host]; + }); + make.button(@"Cancel").cancelStyle(); + } showFrom:host]; + } + accessoryType:^UITableViewCellAccessoryType(UIViewController *controller) { + return UITableViewCellAccessoryDisclosureIndicator; + } + ] + ]]; +} + ++ (void)openURL:(NSString *)urlString + inApp:(UIApplication *)app + onlyIfUniveral:(BOOL)universalOnly + host:(UIViewController *)host { + NSURL *url = [NSURL URLWithString:urlString]; + + if (url) { + if (@available(iOS 10, *)) { + [app openURL:url options:@{ + UIApplicationOpenURLOptionUniversalLinksOnly: @(universalOnly) + } completionHandler:^(BOOL success) { + if (!success) { + [FLEXAlert showAlert:@"No Universal Link Handler" + message:@"No installed application is registered to handle this link." + from:host + ]; + } + }]; + } else { + [app openURL:url]; + } + } else { + [FLEXAlert showAlert:@"Error" message:@"Invalid URL" from:host]; + } +} + +@end + diff --git a/FLEX.xcodeproj/project.pbxproj b/FLEX.xcodeproj/project.pbxproj index 67859e2e04..7ef9595856 100644 --- a/FLEX.xcodeproj/project.pbxproj +++ b/FLEX.xcodeproj/project.pbxproj @@ -164,6 +164,8 @@ C32A195F231732E800EB02AC /* FLEXCollectionContentSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C32A195D231732E800EB02AC /* FLEXCollectionContentSection.m */; }; C32A19622317378C00EB02AC /* FLEXDefaultsContentSection.h in Headers */ = {isa = PBXBuildFile; fileRef = C32A19602317378C00EB02AC /* FLEXDefaultsContentSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; C32A19632317378C00EB02AC /* FLEXDefaultsContentSection.m in Sources */ = {isa = PBXBuildFile; fileRef = C32A19612317378C00EB02AC /* FLEXDefaultsContentSection.m */; }; + C32F3A18247C6B3E0063542D /* FLEXUIAppShortcuts.h in Headers */ = {isa = PBXBuildFile; fileRef = C32F3A16247C6B3E0063542D /* FLEXUIAppShortcuts.h */; }; + C32F3A19247C6B3E0063542D /* FLEXUIAppShortcuts.m in Sources */ = {isa = PBXBuildFile; fileRef = C32F3A17247C6B3E0063542D /* FLEXUIAppShortcuts.m */; }; C33C825B23159EAF00DD2451 /* FLEXTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C33C825A23159EAF00DD2451 /* FLEXTests.m */; }; C33C825E2316DC8600DD2451 /* FLEXObjectExplorer.h in Headers */ = {isa = PBXBuildFile; fileRef = C33C825C2316DC8600DD2451 /* FLEXObjectExplorer.h */; settings = {ATTRIBUTES = (Public, ); }; }; C33C825F2316DC8600DD2451 /* FLEXObjectExplorer.m in Sources */ = {isa = PBXBuildFile; fileRef = C33C825D2316DC8600DD2451 /* FLEXObjectExplorer.m */; }; @@ -523,6 +525,8 @@ C32A195D231732E800EB02AC /* FLEXCollectionContentSection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXCollectionContentSection.m; sourceTree = ""; }; C32A19602317378C00EB02AC /* FLEXDefaultsContentSection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXDefaultsContentSection.h; sourceTree = ""; }; C32A19612317378C00EB02AC /* FLEXDefaultsContentSection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXDefaultsContentSection.m; sourceTree = ""; }; + C32F3A16247C6B3E0063542D /* FLEXUIAppShortcuts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FLEXUIAppShortcuts.h; sourceTree = ""; }; + C32F3A17247C6B3E0063542D /* FLEXUIAppShortcuts.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXUIAppShortcuts.m; sourceTree = ""; }; C33C825A23159EAF00DD2451 /* FLEXTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXTests.m; sourceTree = ""; }; C33C825C2316DC8600DD2451 /* FLEXObjectExplorer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FLEXObjectExplorer.h; path = Classes/ObjectExplorers/FLEXObjectExplorer.h; sourceTree = SOURCE_ROOT; }; C33C825D2316DC8600DD2451 /* FLEXObjectExplorer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FLEXObjectExplorer.m; path = Classes/ObjectExplorers/FLEXObjectExplorer.m; sourceTree = SOURCE_ROOT; }; @@ -1363,6 +1367,8 @@ C34D4EB723A2B17900C1F903 /* FLEXBundleShortcuts.m */, C38EF26123A2FCD20047A7EC /* FLEXViewControllerShortcuts.h */, C38EF26023A2FCD20047A7EC /* FLEXViewControllerShortcuts.m */, + C32F3A16247C6B3E0063542D /* FLEXUIAppShortcuts.h */, + C32F3A17247C6B3E0063542D /* FLEXUIAppShortcuts.m */, C31D93E223E38CBE005517BF /* FLEXBlockShortcuts.h */, C31D93E323E38CBE005517BF /* FLEXBlockShortcuts.m */, ); @@ -1489,6 +1495,7 @@ C3BFD070233C23ED0015FB82 /* NSArray+FLEX.h in Headers */, C398682923AC370100E9E391 /* FLEXViewShortcuts.h in Headers */, C3474C4023DA496400466532 /* FLEXKeyValueTableViewCell.h in Headers */, + C32F3A18247C6B3E0063542D /* FLEXUIAppShortcuts.h in Headers */, 779B1ED61C0C4D7C001F5E49 /* FLEXTableContentViewController.h in Headers */, C3DFCDB82418336D00BB7084 /* NSUserDefaults+FLEX.h in Headers */, 3A4C95221B5B21410088C3F2 /* FLEXFileBrowserSearchOperation.h in Headers */, @@ -1755,6 +1762,7 @@ 3A4C94CE1B5B21410088C3F2 /* FLEXGlobalsEntry.m in Sources */, C398625223AD6C67007E6793 /* FLEXKeyPathSearchController.m in Sources */, C3E5D9FE2316E83700E655DB /* FLEXRuntime+Compare.m in Sources */, + C32F3A19247C6B3E0063542D /* FLEXUIAppShortcuts.m in Sources */, 71E1C2192307FBB800F5032A /* FLEXKeychainQuery.m in Sources */, C398627323AD7951007E6793 /* UIGestureRecognizer+Blocks.m in Sources */, C3F646F723A04A7500D4A011 /* FLEXShortcut.m in Sources */,