FLEXBundleShortcuts.m 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //
  2. // FLEXBundleShortcuts.m
  3. // FLEX
  4. //
  5. // Created by Tanner Bennett on 12/12/19.
  6. // Copyright © 2020 FLEX Team. All rights reserved.
  7. //
  8. #import "FLEXBundleShortcuts.h"
  9. #import "FLEXShortcut.h"
  10. #import "FLEXAlert.h"
  11. #import "FLEXRuntimeExporter.h"
  12. #import "FLEXTableListViewController.h"
  13. #import "FLEXFileBrowserController.h"
  14. #pragma mark -
  15. @implementation FLEXBundleShortcuts
  16. #pragma mark Overrides
  17. + (instancetype)forObject:(NSBundle *)bundle {
  18. __weak __typeof(self) weakSelf = self;
  19. return [self forObject:bundle additionalRows:@[
  20. [FLEXActionShortcut
  21. title:@"Browse Bundle Directory" subtitle:nil
  22. viewer:^UIViewController *(NSBundle *bundle) {
  23. return [FLEXFileBrowserController path:bundle.bundlePath];
  24. }
  25. accessoryType:^UITableViewCellAccessoryType(NSBundle *bundle) {
  26. return UITableViewCellAccessoryDisclosureIndicator;
  27. }
  28. ],
  29. [FLEXActionShortcut title:@"Browse Bundle as Database…" subtitle:nil
  30. selectionHandler:^(UIViewController *host, NSBundle *bundle) {
  31. __strong __typeof(self) strongSelf = weakSelf;
  32. if (strongSelf) {
  33. [strongSelf promptToExportBundleAsDatabase:bundle host:host];
  34. }
  35. }
  36. accessoryType:^UITableViewCellAccessoryType(NSBundle *bundle) {
  37. return UITableViewCellAccessoryDisclosureIndicator;
  38. }
  39. ],
  40. ]];
  41. }
  42. + (void)promptToExportBundleAsDatabase:(NSBundle *)bundle host:(UIViewController *)host {
  43. [FLEXAlert makeAlert:^(FLEXAlert *make) {
  44. make.title(@"Save As…").message(
  45. @"The database be saved in the Library folder. "
  46. "Depending on the number of classes, it may take "
  47. "10 minutes or more to finish exporting. 20,000 "
  48. "classes takes about 7 minutes."
  49. );
  50. make.configuredTextField(^(UITextField *field) {
  51. field.placeholder = @"FLEXRuntimeExport.objc.db";
  52. field.text = [NSString stringWithFormat:
  53. @"%@.objc.db", bundle.executablePath.lastPathComponent
  54. ];
  55. });
  56. make.button(@"Start").handler(^(NSArray<NSString *> *strings) {
  57. [self browseBundleAsDatabase:bundle host:host name:strings[0]];
  58. });
  59. make.button(@"Cancel").cancelStyle();
  60. } showFrom:host];
  61. }
  62. + (void)browseBundleAsDatabase:(NSBundle *)bundle host:(UIViewController *)host name:(NSString *)name {
  63. NSParameterAssert(name.length);
  64. UIAlertController *progress = [FLEXAlert makeAlert:^(FLEXAlert *make) {
  65. make.title(@"Generating Database");
  66. // Some iOS version glitch out of there is
  67. // no initial message and you add one later
  68. make.message(@"…");
  69. }];
  70. [host presentViewController:progress animated:YES completion:^{
  71. // Generate path to store db
  72. NSString *path = [NSSearchPathForDirectoriesInDomains(
  73. NSLibraryDirectory, NSUserDomainMask, YES
  74. )[0] stringByAppendingPathComponent:name];
  75. progress.message = [path stringByAppendingString:@"\n\nCreating database…"];
  76. // Generate db and show progress
  77. [FLEXRuntimeExporter createRuntimeDatabaseAtPath:path
  78. forImages:@[bundle.executablePath]
  79. progressHandler:^(NSString *status) {
  80. dispatch_async(dispatch_get_main_queue(), ^{
  81. progress.message = [progress.message
  82. stringByAppendingFormat:@"\n%@", status
  83. ];
  84. [progress.view setNeedsLayout];
  85. [progress.view layoutIfNeeded];
  86. });
  87. } completion:^(NSString *error) {
  88. // Display error if any
  89. if (error) {
  90. progress.title = @"Error";
  91. progress.message = error;
  92. [progress addAction:[UIAlertAction
  93. actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]
  94. ];
  95. }
  96. // Browse database
  97. else {
  98. [progress dismissViewControllerAnimated:YES completion:nil];
  99. [host.navigationController pushViewController:[
  100. [FLEXTableListViewController alloc] initWithPath:path
  101. ] animated:YES];
  102. }
  103. }
  104. ];
  105. }];
  106. }
  107. @end