├── deb ├── obj │ ├── .stamp │ ├── customft │ │ └── .stamp │ ├── CustomFT.dylib │ └── kCustomFT.bundle │ │ ├── reboot@2x.png │ │ ├── reboot@3x.png │ │ ├── powerOff@2x.png │ │ ├── powerOff@3x.png │ │ ├── respring@2x.png │ │ ├── respring@3x.png │ │ ├── safeMode@2x.png │ │ └── safeMode@3x.png └── customft │ └── obj │ ├── .stamp │ └── CustomFT.bundle │ ├── CustomFT │ ├── CustomFT@3x.jpg │ ├── CustomFT.plist │ └── Info.plist ├── theos ├── customft ├── theos ├── Resources │ ├── CustomFT@3x.jpg │ ├── CustomFT.plist │ └── Info.plist ├── BTOOptionsViewController.h ├── entry.plist ├── Makefile ├── BTOActionSearchViewController.h ├── BTOAddShortCutViewController.h ├── BTOShortCutManager.h ├── BTOOptionsViewController.m ├── BTOActionSearchViewController.m ├── CustomFT.mm ├── BTOShortCutManager.m └── BTOAddShortCutViewController.m ├── Resources ├── reboot@2x.png ├── reboot@3x.png ├── powerOff@2x.png ├── powerOff@3x.png ├── respring@2x.png ├── respring@3x.png ├── safeMode@2x.png └── safeMode@3x.png ├── traverse ├── Resources │ ├── Traverse@3x.jpg │ ├── Info.plist │ └── TROptions.plist ├── TRPreferencesController.mm ├── entry.plist └── Makefile ├── CustomFT.plist ├── entitlements.xml ├── README.md ├── control ├── Makefile ├── LICENSE ├── LICENSE.md ├── ControlCenter.xm ├── HeaderFiles.h ├── Applications.xm └── Tweak.xm /deb/obj/.stamp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /theos: -------------------------------------------------------------------------------- 1 | /opt/theos -------------------------------------------------------------------------------- /deb/customft/obj/.stamp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /deb/obj/customft/.stamp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /customft/theos: -------------------------------------------------------------------------------- 1 | /opt/theos -------------------------------------------------------------------------------- /Resources/reboot@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/Resources/reboot@2x.png -------------------------------------------------------------------------------- /Resources/reboot@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/Resources/reboot@3x.png -------------------------------------------------------------------------------- /deb/obj/CustomFT.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/deb/obj/CustomFT.dylib -------------------------------------------------------------------------------- /Resources/powerOff@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/Resources/powerOff@2x.png -------------------------------------------------------------------------------- /Resources/powerOff@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/Resources/powerOff@3x.png -------------------------------------------------------------------------------- /Resources/respring@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/Resources/respring@2x.png -------------------------------------------------------------------------------- /Resources/respring@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/Resources/respring@3x.png -------------------------------------------------------------------------------- /Resources/safeMode@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/Resources/safeMode@2x.png -------------------------------------------------------------------------------- /Resources/safeMode@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/Resources/safeMode@3x.png -------------------------------------------------------------------------------- /customft/Resources/CustomFT@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/customft/Resources/CustomFT@3x.jpg -------------------------------------------------------------------------------- /traverse/Resources/Traverse@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/traverse/Resources/Traverse@3x.jpg -------------------------------------------------------------------------------- /deb/obj/kCustomFT.bundle/reboot@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/deb/obj/kCustomFT.bundle/reboot@2x.png -------------------------------------------------------------------------------- /deb/obj/kCustomFT.bundle/reboot@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/deb/obj/kCustomFT.bundle/reboot@3x.png -------------------------------------------------------------------------------- /CustomFT.plist: -------------------------------------------------------------------------------- 1 | { 2 | Filter = { 3 | Bundles = ( 4 | "com.apple.UIKit", 5 | "com.apple.springboard", 6 | ); 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /deb/customft/obj/CustomFT.bundle/CustomFT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/deb/customft/obj/CustomFT.bundle/CustomFT -------------------------------------------------------------------------------- /deb/obj/kCustomFT.bundle/powerOff@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/deb/obj/kCustomFT.bundle/powerOff@2x.png -------------------------------------------------------------------------------- /deb/obj/kCustomFT.bundle/powerOff@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/deb/obj/kCustomFT.bundle/powerOff@3x.png -------------------------------------------------------------------------------- /deb/obj/kCustomFT.bundle/respring@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/deb/obj/kCustomFT.bundle/respring@2x.png -------------------------------------------------------------------------------- /deb/obj/kCustomFT.bundle/respring@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/deb/obj/kCustomFT.bundle/respring@3x.png -------------------------------------------------------------------------------- /deb/obj/kCustomFT.bundle/safeMode@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/deb/obj/kCustomFT.bundle/safeMode@2x.png -------------------------------------------------------------------------------- /deb/obj/kCustomFT.bundle/safeMode@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/deb/obj/kCustomFT.bundle/safeMode@3x.png -------------------------------------------------------------------------------- /deb/customft/obj/CustomFT.bundle/CustomFT@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bolencki13/Traverse/HEAD/deb/customft/obj/CustomFT.bundle/CustomFT@3x.jpg -------------------------------------------------------------------------------- /customft/BTOOptionsViewController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface BTOOptionsViewController : UIViewController { 4 | NSUserDefaults *prefs; 5 | UIView *holder; 6 | } 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /customft/entry.plist: -------------------------------------------------------------------------------- 1 | { 2 | entry = { 3 | bundle = CustomFT; 4 | cell = PSLinkCell; 5 | detail = "CustomFTListController"; 6 | icon = "CustomFT.jpg"; 7 | isController = 1; 8 | label = Traverse; 9 | }; 10 | } -------------------------------------------------------------------------------- /entitlements.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.backboard.client 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Traverse Jailbreak Tweak 2 | 3 | Cydia Link: 4 | http://cydia.saurik.com/package/com.bolencki13.customft/ 5 | 6 | * version 1.2.0-4 7 | * Activator action support 8 | * Shellscript action support 9 | * UI Fixes 10 | * Settings improvements 11 | * Bug Fixes 12 | * version 1.1.0-6 13 | * Initial Commit -------------------------------------------------------------------------------- /traverse/TRPreferencesController.mm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #include 4 | 5 | @interface TRPreferencesController : TRRootViewController 6 | 7 | @end 8 | 9 | @implementation TRPreferencesController 10 | - (void)viewDidLoad { 11 | [super viewDidLoad]; 12 | 13 | 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.bolencki13.customft 2 | Name: Traverse 3 | Depends: mobilesubstrate, com.bolencki13.libTraverse 4 | Version: 1.3.2 5 | Architecture: iphoneos-arm 6 | Description: Create custom 3D actions for apps 7 | Maintainer: Brian Olencki 8 | Author: Brian Olencki 9 | Section: Tweaks 10 | Depiction: http://cydia.bolencki13.com/repo/depictions/?p=com.bolencki13.customft -------------------------------------------------------------------------------- /traverse/entry.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | entry 6 | 7 | bundle 8 | traverse 9 | cell 10 | PSLinkCell 11 | detail 12 | TRPreferencesController 13 | icon 14 | Traverse.jpg 15 | isController 16 | 17 | label 18 | Traverse 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /customft/Makefile: -------------------------------------------------------------------------------- 1 | GO_EASY_ON_ME = 1 2 | export THEOS_BUILD_DIR = deb 3 | ARCHS = armv7 arm64 4 | TARGET_CFLAGS = -fobjc-arc 5 | 6 | include theos/makefiles/common.mk 7 | 8 | BUNDLE_NAME = CustomFT 9 | CustomFT_FILES = CustomFT.mm $(wildcard *.m) 10 | CustomFT_INSTALL_PATH = /Library/PreferenceBundles 11 | CustomFT_FRAMEWORKS = UIKit SafariServices 12 | CustomFT_PRIVATE_FRAMEWORKS = Preferences 13 | 14 | include $(THEOS_MAKE_PATH)/bundle.mk 15 | 16 | internal-stage:: 17 | $(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences$(ECHO_END) 18 | $(ECHO_NOTHING)cp entry.plist $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences/CustomFT.plist$(ECHO_END) 19 | -------------------------------------------------------------------------------- /traverse/Makefile: -------------------------------------------------------------------------------- 1 | GO_EASY_ON_ME = 1 2 | ARCHS = armv7 arm64 3 | SDKVERSION = 9.2 4 | 5 | include $(THEOS)/makefiles/common.mk 6 | 7 | BUNDLE_NAME = traverse 8 | traverse_FILES = $(wildcard *.mm) 9 | traverse_INSTALL_PATH = /Library/PreferenceBundles 10 | traverse_FRAMEWORKS = UIKit 11 | traverse_PRIVATE_FRAMEWORKS = Preferences 12 | traverse_CFLAGS = -fobjc-arc 13 | traverse_LIBRARIES = Traverse 14 | 15 | include $(THEOS_MAKE_PATH)/bundle.mk 16 | 17 | internal-stage:: 18 | $(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences$(ECHO_END) 19 | $(ECHO_NOTHING)cp entry.plist $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences/traverse.plist$(ECHO_END) 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GO_EASY_ON_ME = 1 2 | ARCHS = armv7 arm64 3 | SDKVERSION = 9.2 4 | 5 | include $(THEOS)/makefiles/common.mk 6 | 7 | TWEAK_NAME = CustomFT 8 | CustomFT_FILES = Applications.xm ControlCenter.xm 9 | CustomFT_FRAMEWORKS = UIKit CoreGraphics AudioToolbox 10 | CustomFT_PRIVATE_FRAMEWORKS = SpringBoardServices Preferences 11 | CustomFT_CFLAGS = -fobjc-arc 12 | CustomFT_LIBRARIES = Traverse 13 | 14 | BUNDLE_NAME = kCustomFT 15 | kCustomFT_INSTALL_PATH = /Library/Application Support/CustomFT 16 | 17 | include $(THEOS)/makefiles/bundle.mk 18 | include $(THEOS_MAKE_PATH)/tweak.mk 19 | 20 | after-install:: 21 | install.exec "killall -9 SpringBoard" 22 | SUBPROJECTS += traverse 23 | include $(THEOS_MAKE_PATH)/aggregate.mk 24 | -------------------------------------------------------------------------------- /customft/BTOActionSearchViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTOActionSearchViewController.h 3 | // test 4 | // 5 | // Created by Brian Olencki on 11/8/15. 6 | // Copyright © 2015 bolencki13. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface PSViewController () 13 | - (void)viewDidLoad; 14 | - (UIView*)view; 15 | - (void)presentViewController:(id)arg1 animated:(BOOL)arg2 completion:(/*^block*/id)arg3 ; 16 | @end 17 | @interface BTOActionSearchViewController : PSViewController { 18 | NSMutableArray *aryTableView; 19 | UITableView *tblActions; 20 | UIRefreshControl *refreshControl; 21 | 22 | NSString *urlString; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /customft/Resources/CustomFT.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Action Page 12 | 13 | 14 | cell 15 | PSLinkCell 16 | isController 17 | 1 18 | label 19 | FT App List 20 | icon 21 | services.png 22 | detail 23 | CustomFTListController 24 | 25 | 26 | title 27 | CustomFT 28 | 29 | 30 | -------------------------------------------------------------------------------- /deb/customft/obj/CustomFT.bundle/CustomFT.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Action Page 12 | 13 | 14 | cell 15 | PSLinkCell 16 | isController 17 | 1 18 | label 19 | FT App List 20 | icon 21 | services.png 22 | detail 23 | CustomFTListController 24 | 25 | 26 | title 27 | CustomFT 28 | 29 | 30 | -------------------------------------------------------------------------------- /traverse/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | traverse 9 | CFBundleIdentifier 10 | com.bolencki13.customft 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | NSPrincipalClass 22 | TRPreferencesController 23 | 24 | 25 | -------------------------------------------------------------------------------- /customft/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | CustomFT 9 | CFBundleIdentifier 10 | com.bolencki13.customft 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | DTPlatformName 22 | iphoneos 23 | MinimumOSVersion 24 | 3.0 25 | NSPrincipalClass 26 | CustomFTListController 27 | 28 | 29 | -------------------------------------------------------------------------------- /deb/customft/obj/CustomFT.bundle/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | CustomFT 9 | CFBundleIdentifier 10 | com.bolencki13.customft 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | DTPlatformName 22 | iphoneos 23 | MinimumOSVersion 24 | 3.0 25 | NSPrincipalClass 26 | CustomFTListController 27 | 28 | 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010-2015 Google, Inc. http://angularjs.org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010-2015 Google, Inc. http://angularjs.org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /customft/BTOAddShortCutViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTOAddShortCutViewController.h 3 | // test 4 | // 5 | // Created by Brian Olencki on 10/17/15. 6 | // Copyright © 2015 bolencki13. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BTOShortCutManager.h" 11 | 12 | @interface BTOInputView : UIView { 13 | UISegmentedControl *_segmentedControl; 14 | UITextField *_txtURLScheme; 15 | UITextField *txtSchellScript; 16 | 17 | NSString *activatorAction; 18 | } 19 | @property (nonatomic, retain) UISegmentedControl *segmentedControl; 20 | @property (nonatomic, retain) UITextField *txtURLScheme; 21 | - (NSString*)getURL; 22 | @end 23 | @interface BTOAddShortCutViewController : UIViewController { 24 | UITextField *_txtTitle; 25 | UITextField *_txtSubTitle; 26 | UITextField *_txtBundleID; 27 | BTOInputView *viewInput; 28 | NSString *pickedImage; 29 | 30 | NSArray *aryIcons; 31 | UIPickerView *pickerView; 32 | NSInteger _iconNumber; 33 | } 34 | @property (retain, nonatomic) UITextField *txtTitle; 35 | @property (retain, nonatomic) UITextField *txtSubTitle; 36 | @property (retain, nonatomic) UITextField *txtBundleID; 37 | @property (nonatomic) NSInteger iconNumber; 38 | - (void)setIconNumber:(NSInteger)iconNumber; 39 | - (void)setURLText:(NSString*)text; 40 | @end 41 | -------------------------------------------------------------------------------- /customft/BTOShortCutManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // BTOShortCutManager.h 3 | // test 4 | // 5 | // Created by Brian Olencki on 10/17/15. 6 | // Copyright © 2015 bolencki13. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define SCREEN ([UIScreen mainScreen].bounds) 12 | 13 | @protocol BTOShortCutManagerDelegate 14 | - (void)performActionForBundleID:(NSString*)bundleID withTitle:(NSString*)title; 15 | @end 16 | 17 | @interface BTOShortCutManager : NSObject { 18 | NSUserDefaults *prefs; 19 | 20 | id _delegate; 21 | } 22 | @property (nonatomic, assign) id delegate; 23 | + (BTOShortCutManager*)sharedInstance; 24 | - (NSDictionary*)getShortCuts; 25 | - (void)deleteShortCutWithBundleID:(NSString*)bundleID; 26 | - (void)addShortCutWithTitle:(NSString *)title withSubTitle:(NSString *)subTitle withBundleID:(NSString *)bundleID withURL:(NSString*)url withIcon:(NSInteger)iconNumber withImage:(NSString*)image; 27 | - (NSArray*)shortCutsForAppWithBundleID:(NSString*)bundleID; 28 | - (NSString*)getURLSchemeForBundleID:(NSString*)bundleID withTitle:(NSString*)title; 29 | - (BOOL)containsBundleID:(NSString*)bundleID; 30 | - (UIApplicationShortcutIconType)iconTypeForNumber:(NSInteger)number; 31 | - (UIImage*)customImageForBundleID:(NSString*)bundleID withTitle:(NSString*)title; 32 | - (NSArray*)itemForBundleID:(NSString*)bundleID withTitle:(NSString*)title; 33 | @end 34 | -------------------------------------------------------------------------------- /traverse/Resources/TROptions.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | 9 | cell 10 | PSGroupCell 11 | footerText 12 | Change the blur style of the menus 13 | 14 | 15 | cell 16 | PSSegmentCell 17 | default 18 | 1 19 | defaults 20 | com.bolencki13.customft 21 | detail 22 | PSListItemsController 23 | key 24 | blur 25 | validTitles 26 | 27 | Extra Light 28 | Light 29 | Dark 30 | 31 | validValues 32 | 33 | 0 34 | 1 35 | 2 36 | 37 | 38 | 39 | 40 | cell 41 | PSGroupCell 42 | footerText 43 | Show an 'Add Action' item within the menu. Allows adding of actions right from springboard 44 | 45 | 46 | 47 | cell 48 | PSSwitchCell 49 | default 50 | 51 | defaults 52 | com.bolencki13.customft 53 | key 54 | addMenu 55 | label 56 | 'Add Action' Item 57 | 58 | 59 | 60 | cell 61 | PSGroupCell 62 | footerText 63 | Only show the 'Add Action' item when there are no other shorcut items present. This can help remove clutter and actions being cut off by the screen 64 | 65 | 66 | 67 | cell 68 | PSSwitchCell 69 | default 70 | 71 | defaults 72 | com.bolencki13.customft 73 | key 74 | addNotEvery 75 | label 76 | Restrict 'Add Action' 77 | 78 | 79 | 80 | cell 81 | PSGroupCell 82 | footerText 83 | Example URL Schemes. For more options, check TraverseDB.com 84 | 85 | 86 | cell 87 | PSButtonCell 88 | label 89 | URL Scheme Exmaple #1 90 | action 91 | showExample1 92 | 93 | 94 | cell 95 | PSButtonCell 96 | label 97 | URL Scheme Exmaple #2 98 | action 99 | showExample2 100 | 101 | 102 | 103 | cell 104 | PSGroupCell 105 | footerText 106 | Traverse © bolencki13 2015-2016 107 | 108 | 109 | 110 | title 111 | Options 112 | 113 | 114 | -------------------------------------------------------------------------------- /ControlCenter.xm: -------------------------------------------------------------------------------- 1 | #import "HeaderFiles.h" 2 | #import 3 | #include 4 | 5 | @interface SBControlCenterController : UIViewController 6 | + (id)sharedInstance; 7 | - (BOOL)isVisible; 8 | @end 9 | 10 | @interface SBApplicationShortcutMenu () 11 | - (id)my_shortcutItemsToDisplay; 12 | @end 13 | 14 | 15 | %hook SBApplicationShortcutMenu 16 | + (void)initialize { 17 | static dispatch_once_t onceToken; 18 | dispatch_once(&onceToken, ^{ 19 | Class myClass = [self class]; 20 | 21 | SEL originalSelector = @selector(_shortcutItemsToDisplay); 22 | SEL swizzledSelector = @selector(my_shortcutItemsToDisplay); 23 | 24 | Method originalMethod = class_getInstanceMethod(myClass, originalSelector); 25 | Method swizzledMethod = class_getInstanceMethod(myClass, swizzledSelector); 26 | 27 | BOOL didAddMethod = class_addMethod(myClass, 28 | originalSelector, 29 | method_getImplementation(swizzledMethod), 30 | method_getTypeEncoding(swizzledMethod)); 31 | 32 | if (didAddMethod) { 33 | class_replaceMethod(myClass, 34 | swizzledSelector, 35 | method_getImplementation(originalMethod), 36 | method_getTypeEncoding(originalMethod)); 37 | } else { 38 | method_exchangeImplementations(originalMethod, swizzledMethod); 39 | } 40 | HBLogDebug(@"Swizzling '-(id)_shortcutItemsToDisplay;'"); 41 | }); 42 | } 43 | - (id)initWithFrame:(struct CGRect)arg1 application:(id)arg2 iconView:(id)arg3 interactionProgress:(id)arg4 orientation:(long long)arg5 { 44 | self = %orig; 45 | 46 | if ([((SBIconView*)arg3).superview isKindOfClass:NSClassFromString(@"SBControlCenterButton")]) { 47 | 48 | } 49 | return self; 50 | } 51 | %new 52 | - (id)my_shortcutItemsToDisplay { 53 | HBLogDebug(@"Calling swizzled method for '-(id)_shortcutItemsToDisplay;'"); 54 | NSMutableArray *objects = [[self my_shortcutItemsToDisplay] mutableCopy]; 55 | 56 | if ([[NSClassFromString(@"SBControlCenterController") sharedInstance] isVisible] != YES || self.application.bundleIdentifier == nil) { 57 | return objects; 58 | } 59 | 60 | // NSArray *aryObjects; 61 | // NSUserDefaults *prefs = [[NSUserDefaults alloc] initWithSuiteName:@"com.bolencki13.customft"]; 62 | // if ([prefs integerForKey:@"CCActionType"] == 0) { 63 | // aryObjects = [[TRShortCutManager sharedInstance] shortCutsForAppWithBundleID:bundleID withType:TRShortCutTypeControlCenter]; 64 | // } else if ([prefs integerForKey:@"CCActionType"] == 1) { 65 | // aryObjects = [[TRShortCutManager sharedInstance] shortCutsForAppWithBundleID:bundleID withType:TRShortCutTypeSpringboard]; 66 | // } else { 67 | // aryObjects = [[TRShortCutManager sharedInstance] shortCutsForAppWithBundleID:bundleID withType:TRShortCutTypeAll]; 68 | // } 69 | 70 | NSUserDefaults *prefs = [[NSUserDefaults alloc] initWithSuiteName:@"com.bolencki13.customft"]; 71 | if ([prefs boolForKey:@"addMenu"] == YES) { 72 | if ([prefs boolForKey:@"addNotEvery"] == NO) { 73 | SBSApplicationShortcutItem *newAction = [[SBSApplicationShortcutItem alloc] init]; 74 | [newAction setIcon:[[SBSApplicationShortcutSystemIcon alloc] initWithType:UIApplicationShortcutIconTypeAdd]]; 75 | [newAction setLocalizedTitle:@"New"]; 76 | [newAction setLocalizedSubtitle:@"Add New Action"]; 77 | [newAction setType:@"com.bolencki13.customft-newAction"]; 78 | [objects addObject:newAction]; 79 | } else if ([prefs boolForKey:@"addNotEvery"] == YES && [objects count] == 0) { 80 | SBSApplicationShortcutItem *newAction = [[SBSApplicationShortcutItem alloc] init]; 81 | [newAction setIcon:[[SBSApplicationShortcutSystemIcon alloc] initWithType:UIApplicationShortcutIconTypeAdd]]; 82 | [newAction setLocalizedTitle:@"New"]; 83 | [newAction setLocalizedSubtitle:@"Add New Action"]; 84 | [newAction setType:@"com.bolencki13.customft-newAction"]; 85 | [objects addObject:newAction]; 86 | } 87 | } 88 | return objects; 89 | } 90 | %end 91 | -------------------------------------------------------------------------------- /HeaderFiles.h: -------------------------------------------------------------------------------- 1 | #import 2 | #include 3 | #import 4 | 5 | #define NSLog(FORMAT, ...) NSLog(@"[%@]: %@",@"Traverse" , [NSString stringWithFormat:FORMAT, ##__VA_ARGS__]) 6 | 7 | @interface UIVisualEffectView(Private) 8 | - (void)_setEffect:(id)arg1; 9 | @end 10 | 11 | @interface SBApplicationShortcutMenuItemView : UIView 12 | @property(retain, nonatomic) UIApplicationShortcutItem *shortcutItem; // @synthesize shortcutItem=_shortcutItem; 13 | - (UIImage *)invertImage:(UIImage *)image; 14 | @end 15 | 16 | @interface SBIconView : UIView 17 | + (CGSize)defaultIconImageSize; 18 | + (CGSize)defaultIconSize; 19 | @end 20 | @interface SBFolderIconView : SBIconView 21 | - (void)setIcon:(id)arg1; 22 | - (id)_folderIconImageView; 23 | @end 24 | 25 | @class SBApplicationShortcutMenu; 26 | @interface SBIconController : UIViewController 27 | @property(retain, nonatomic) SBApplicationShortcutMenu *presentedShortcutMenu; 28 | + (id)sharedInstance; 29 | - (void)_handleShortcutMenuPeek:(id)arg1; 30 | - (void)_revealMenuForIconView:(id)arg1 presentImmediately:(_Bool)arg2; 31 | @end 32 | 33 | 34 | @interface SBApplicationController : NSObject 35 | + (id)sharedInstance; 36 | - (id)applicationWithBundleIdentifier:(id)arg1; 37 | - (id)runningApplications; 38 | - (id)allApplications; 39 | - (id)allBundleIdentifiers; 40 | @end 41 | @interface SBApplicationShortcutStoreManager : NSObject 42 | + (id)sharedManager; 43 | - (void)saveSynchronously; 44 | - (void)setShortcutItems:(id)arg1 forBundleIdentifier:(id)arg2; 45 | - (id)shortcutItemsForBundleIdentifier:(NSString*)arg1; 46 | - (id)init; 47 | @end 48 | @interface SBApplication : NSObject 49 | @property(copy, nonatomic) NSArray *staticShortcutItems; 50 | - (NSString*)bundleIdentifier; 51 | - (id)urlScheme; 52 | @end; 53 | 54 | @class SBApplicationShortcutItem; 55 | // @protocol SBApplicationShortcutMenuDelegate 56 | // - (void)applicationShortcutMenu:(SBApplicationShortcutMenu *)arg1 launchApplicationWithIconView:(SBIconView *)arg2; 57 | // - (void)applicationShortcutMenu:(SBApplicationShortcutMenu *)arg1 startEditingForIconView:(SBIconView *)arg2; 58 | // - (void)applicationShortcutMenu:(SBApplicationShortcutMenu *)arg1 activateShortcutItem:(SBApplicationShortcutItem *)arg2 index:(long long)arg3; 59 | // 60 | // @optional 61 | // - (void)applicationShortcutMenuDidPresent:(SBApplicationShortcutMenu *)arg1; 62 | // - (void)applicationShortcutMenuDidDismiss:(SBApplicationShortcutMenu *)arg1; 63 | // @end 64 | @interface SBApplicationShortcutMenu : UIView 65 | @property (nonatomic, assign) BOOL isCC; 66 | @property(retain, nonatomic) SBApplication *application; 67 | - (id)initWithFrame:(CGRect)arg1 application:(id)arg2 iconView:(id)arg3 interactionProgress:(id)arg4 orientation:(long long)arg5; 68 | - (void)_setupViews; 69 | - (void)_peekWithContentFraction:(double)arg1 smoothedBlurFraction:(double)arg2; 70 | - (void)dismissAnimated:(_Bool)arg1 completionHandler:(id)arg2; 71 | - (id)_shortcutItemsToDisplay; 72 | @end 73 | @interface SpringBoard : UIApplication 74 | - (void)reboot; 75 | - (void)powerDown; 76 | - (void)applicationOpenURL:(id)arg1; 77 | - (_Bool)launchApplicationWithIdentifier:(id)arg1 suspended:(_Bool)arg2; 78 | - (void)_rotateView:(id)arg1 toOrientation:(long long)arg2; 79 | - (void)wipeDeviceNow; 80 | @end 81 | @interface SBApplicationShortcutMenuContentView : UIView 82 | - (void)_presentForFraction:(double)arg1; 83 | @end 84 | 85 | @interface UIApplicationShortcutIcon() 86 | @end 87 | @interface SBSApplicationShortcutIcon : NSObject 88 | @end 89 | @interface SBSApplicationShortcutItem : NSObject 90 | - (void)setIcon:(id)arg1; 91 | - (void)setLocalizedSubtitle:(id)arg1; 92 | - (void)setLocalizedTitle:(id)arg1; 93 | - (void)setType:(id)arg1; 94 | @end 95 | @interface SBSApplicationShortcutSystemIcon : SBSApplicationShortcutIcon 96 | - (id)initWithType:(UIApplicationShortcutIconType)arg1; 97 | @end 98 | @interface SBSApplicationShortcutCustomImageIcon : SBSApplicationShortcutIcon 99 | - (id)initWithImagePNGData:(id)arg1; 100 | @end 101 | @interface SBSApplicationShortcutContactIcon : SBSApplicationShortcutIcon 102 | -(instancetype)initWithContactIdentifier:(NSString *)contactIdentifier; 103 | -(instancetype)initWithFirstName:(NSString*)firstName lastName:(NSString*)lastName; 104 | -(instancetype)initWithFirstName:(NSString*)firstName lastName:(NSString*)lastName imageData:(NSData*)imageData; 105 | @end 106 | -------------------------------------------------------------------------------- /customft/BTOOptionsViewController.m: -------------------------------------------------------------------------------- 1 | #import "BTOOptionsViewController.h" 2 | 3 | #define SCREEN ([UIScreen mainScreen].bounds) 4 | 5 | @implementation BTOOptionsViewController 6 | - (void)viewDidLoad { 7 | [super viewDidLoad]; 8 | self.view.backgroundColor = [UIColor whiteColor]; 9 | 10 | UIButton *btnBack = [UIButton buttonWithType:UIButtonTypeSystem]; 11 | [btnBack addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; 12 | [btnBack setFrame:CGRectMake(10, 20, 50, 50)]; 13 | [btnBack setTitle:@"Back" forState:UIControlStateNormal]; 14 | [self.view addSubview:btnBack]; 15 | 16 | prefs = [[NSUserDefaults alloc] initWithSuiteName:@"com.bolencki13.customft"]; 17 | [prefs registerDefaults:@{ 18 | @"blur" : @1, 19 | @"addMenu" : @YES, 20 | @"addNotEvery" : @NO 21 | }]; 22 | 23 | UILabel *lblTitleBlur = [[UILabel alloc] initWithFrame:CGRectMake(10, 70, 100, 30)]; 24 | lblTitleBlur.text = @"Blur Color:"; 25 | [self.view addSubview:lblTitleBlur]; 26 | 27 | UISegmentedControl *sgcBlurStyle = [[UISegmentedControl alloc] initWithItems:@[@"Extra Light",@"Light",@"Dark"]]; 28 | sgcBlurStyle.frame = CGRectMake(10, 100, [UIScreen mainScreen].bounds.size.width-20, 50); 29 | [sgcBlurStyle addTarget:self action:@selector(updateBlur:) forControlEvents: UIControlEventValueChanged]; 30 | sgcBlurStyle.selectedSegmentIndex = [prefs integerForKey:@"blur"]; 31 | [self.view addSubview:sgcBlurStyle]; 32 | 33 | UIButton *btnExample1 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 34 | [btnExample1 addTarget:self action:@selector(showExample:) forControlEvents:UIControlEventTouchUpInside]; 35 | [btnExample1 setFrame:CGRectMake(20, 160, [UIScreen mainScreen].bounds.size.width/2-45, 50)]; 36 | [btnExample1 setTitle:@"URLScheme ex1" forState:UIControlStateNormal]; 37 | [btnExample1 setTag:1]; 38 | [self.view addSubview:btnExample1]; 39 | 40 | UIButton *btnExample2 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 41 | [btnExample2 addTarget:self action:@selector(showExample:) forControlEvents:UIControlEventTouchUpInside]; 42 | [btnExample2 setFrame:CGRectMake(SCREEN.size.width/2+5, 160, SCREEN.size.width/2-45, 50)]; 43 | [btnExample2 setTitle:@"URLScheme ex2" forState:UIControlStateNormal]; 44 | [btnExample2 setTag:2]; 45 | [self.view addSubview:btnExample2]; 46 | 47 | holder = [[UIView alloc] initWithFrame:CGRectMake(0, 220, SCREEN.size.width, 105)]; 48 | [self.view addSubview:holder]; 49 | UILabel *lblTitle = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, SCREEN.size.width-75, 50)]; 50 | lblTitle.text = @"Show Add Action"; 51 | [holder addSubview:lblTitle]; 52 | UISwitch *swcMaster = [[UISwitch alloc] initWithFrame:CGRectMake(SCREEN.size.width-70, 10, 65, 50)]; 53 | [swcMaster addTarget:self action:@selector(handleSwitch:) forControlEvents:UIControlEventValueChanged]; 54 | [swcMaster setOn:[prefs boolForKey:@"addMenu"] animated:YES]; 55 | swcMaster.tag = 0; 56 | [holder addSubview:swcMaster]; 57 | UIView *viewSubmenu = [[UIView alloc] initWithFrame:CGRectMake(0, 55, SCREEN.size.width, 50)]; 58 | viewSubmenu.tag = 13; 59 | [holder addSubview:viewSubmenu]; 60 | UILabel *lblSubTitle = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, SCREEN.size.width-75, 50)]; 61 | lblSubTitle.text = @"Only when no other action"; 62 | [viewSubmenu addSubview:lblSubTitle]; 63 | UISwitch *swcSub = [[UISwitch alloc] initWithFrame:CGRectMake(SCREEN.size.width-70, 10, 65, 50)]; 64 | [swcSub addTarget:self action:@selector(handleSwitch:) forControlEvents:UIControlEventValueChanged]; 65 | swcSub.tag = 1; 66 | [swcSub setOn:[prefs boolForKey:@"addNotEvery"] animated:YES]; 67 | [viewSubmenu addSubview:swcSub]; 68 | [self setSubMenuForState:swcMaster.isOn]; 69 | } 70 | - (void)back { 71 | [self dismissViewControllerAnimated:YES completion:nil]; 72 | } 73 | 74 | - (void)updateBlur:(UISegmentedControl*)sender { 75 | [prefs setInteger:sender.selectedSegmentIndex forKey:@"blur"]; 76 | } 77 | - (void)showExample:(UIButton*)sender { 78 | if (sender.tag == 1) { 79 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://iphonedevwiki.net/index.php/NSURL"]]; 80 | } else { 81 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://wiki.akosma.com/IPhone_URL_Schemes"]]; 82 | } 83 | } 84 | - (void)handleSwitch:(UISwitch*)sender { 85 | if (sender.tag == 0) { 86 | [prefs setBool:sender.isOn forKey:@"addMenu"]; 87 | [self setSubMenuForState:sender.isOn]; 88 | } else if (sender.tag == 1) { 89 | [prefs setBool:sender.isOn forKey:@"addNotEvery"]; 90 | } 91 | } 92 | - (void)setSubMenuForState:(BOOL)state { 93 | if (state == NO) { 94 | ((UIView*)[holder viewWithTag:13]).alpha = 0.5; 95 | ((UIView*)[holder viewWithTag:13]).userInteractionEnabled = NO; 96 | } else { 97 | ((UIView*)[holder viewWithTag:13]).alpha = 1.0; 98 | ((UIView*)[holder viewWithTag:13]).userInteractionEnabled = YES; 99 | } 100 | } 101 | @end 102 | -------------------------------------------------------------------------------- /customft/BTOActionSearchViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTOActionSearchViewController.m 3 | // test 4 | // 5 | // Created by Brian Olencki on 11/8/15. 6 | // Copyright © 2015 bolencki13. All rights reserved. 7 | // 8 | 9 | #import "BTOActionSearchViewController.h" 10 | #import "BTOShortCutManager.h" 11 | 12 | #define SCREEN ([UIScreen mainScreen].bounds) 13 | #define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] 14 | 15 | #define URL (@"http://traversedb.com") 16 | #define URL_ALL (@"http://traversedb.com/json") 17 | #define URL_SEARCH (@"http://traversedb.com/json/srs/") 18 | #define URL_NUMBER (@"http://traversedb.com/json/conf/") 19 | #define URL_DOWNLOADED (@"http://traversedb.com/in/") 20 | 21 | @implementation BTOActionSearchViewController 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | if (!aryTableView) { 25 | aryTableView = [NSMutableArray new]; 26 | } 27 | 28 | urlString = URL_ALL; 29 | [self getMoreActions]; 30 | 31 | self.view.backgroundColor = [UIColor whiteColor]; 32 | 33 | UIButton *btnSearch = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 34 | btnSearch.frame = CGRectMake(0,0,20,20); 35 | [btnSearch setTitle:@"Search" forState:UIControlStateNormal]; 36 | [btnSearch addTarget:self action:@selector(search) forControlEvents:UIControlEventTouchUpInside]; 37 | [btnSearch setShowsTouchWhenHighlighted:YES]; 38 | [btnSearch sizeToFit]; 39 | UIBarButtonItem *buttonBar = [[UIBarButtonItem alloc] initWithCustomView:btnSearch]; 40 | [self.navigationItem setRightBarButtonItems:[NSArray arrayWithObjects:buttonBar, nil] animated:NO]; 41 | 42 | UIButton *btnDatabase = [UIButton buttonWithType:UIButtonTypeCustom]; 43 | [btnDatabase addTarget:self action:@selector(website) forControlEvents:UIControlEventTouchUpInside]; 44 | [btnDatabase setBackgroundColor:UIColorFromRGB(0x27AE60)]; 45 | [btnDatabase setFrame:CGRectMake(0, 70, SCREEN.size.width, 50)]; 46 | [btnDatabase setTitle:@"http://traversedb.com" forState:UIControlStateNormal]; 47 | [self.view addSubview:btnDatabase]; 48 | 49 | CGRect frame = CGRectMake(0,150,self.view.bounds.size.width,self.view.bounds.size.height-150); 50 | if (self.view.bounds.size.width > 400) { 51 | frame.size.width = 400; 52 | } 53 | tblActions = [[UITableView alloc] initWithFrame:frame]; 54 | tblActions.delegate = self; 55 | tblActions.dataSource = self; 56 | tblActions.backgroundColor = [UIColor whiteColor]; 57 | [self.view addSubview:tblActions]; 58 | 59 | refreshControl = [[UIRefreshControl alloc] init]; 60 | [refreshControl addTarget:self action:@selector(refreshTable:) forControlEvents:UIControlEventValueChanged]; 61 | [tblActions addSubview:refreshControl]; 62 | } 63 | 64 | #pragma mark - Gather Data 65 | - (void)getMoreActions { 66 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 67 | [aryTableView removeAllObjects]; 68 | 69 | NSURL *url = [NSURL URLWithString:urlString]; 70 | NSData *jsonData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url] returningResponse:nil error:nil]; 71 | 72 | NSArray *json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil]; 73 | 74 | for (NSDictionary *objectSet in json) { 75 | NSArray *aryItem = [[NSArray alloc] initWithObjects:[objectSet objectForKey:@"id"],[NSString stringWithFormat:@"%@-%@",[objectSet objectForKey:@"bundleId"],[objectSet objectForKey:@"title"]], nil]; 76 | [aryTableView addObject:aryItem]; 77 | } 78 | 79 | dispatch_async(dispatch_get_main_queue(), ^(void){ 80 | [tblActions reloadData]; 81 | [refreshControl endRefreshing]; 82 | urlString = URL_ALL; 83 | }); 84 | }); 85 | } 86 | 87 | #pragma mark - UIButton Functions 88 | - (void)search { 89 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Traverse" message:@"Enter Search Paramaters" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Search", nil]; 90 | alert.alertViewStyle = UIAlertViewStylePlainTextInput; 91 | [alert textFieldAtIndex:0].placeholder = @"Search..."; 92 | [alert show]; 93 | } 94 | - (void)website { 95 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:URL]]; 96 | } 97 | 98 | #pragma mark - UITableView Delegate 99 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 100 | if ([aryTableView count] > 0) { 101 | return [aryTableView count]; 102 | } else { 103 | return 15; 104 | } 105 | } 106 | - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 107 | static NSString* cellIdentifier = @"CellIdentifier"; 108 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 109 | if (cell == nil) { 110 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 111 | } 112 | 113 | if (indexPath.row < [aryTableView count]) { 114 | cell.textLabel.text = [((NSArray*)[aryTableView objectAtIndex:indexPath.row]) objectAtIndex:1]; ; 115 | } 116 | 117 | return cell; 118 | } 119 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 120 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 121 | } 122 | - (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { 123 | UITableViewRowAction *add = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@" Add Action " handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) { 124 | NSString *itemNumber = [((NSArray*)[aryTableView objectAtIndex:indexPath.row]) objectAtIndex:0]; 125 | 126 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 127 | 128 | NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",URL_NUMBER,itemNumber]]; 129 | NSData *jsonData = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:url] returningResponse:nil error:nil]; 130 | 131 | NSArray *json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil]; 132 | 133 | for (NSDictionary *objectSet in json) { 134 | [[BTOShortCutManager sharedInstance] addShortCutWithTitle:[objectSet objectForKey:@"title"] withSubTitle:[objectSet objectForKey:@"subtitle"] withBundleID:[objectSet objectForKey:@"bundleId"] withURL:[objectSet objectForKey:@"url_scheme"] withIcon:[((NSString*)[objectSet objectForKey:@"icon"]) integerValue] withImage:@""]; 135 | break; 136 | } 137 | 138 | [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@",URL_DOWNLOADED,itemNumber]]] returningResponse:nil error:nil]; 139 | 140 | dispatch_async(dispatch_get_main_queue(), ^(void){ 141 | UIAlertController *alert = [UIAlertController 142 | alertControllerWithTitle:@"Traverse" 143 | message:@"Shortcut Added" 144 | preferredStyle:UIAlertControllerStyleAlert]; 145 | 146 | UIAlertAction *ok = [UIAlertAction actionWithTitle:@"Okay" style:UIAlertActionStyleDefault 147 | handler:nil]; 148 | [alert addAction:ok]; 149 | [self presentViewController:alert animated:YES completion:nil]; 150 | }); 151 | }); 152 | }]; 153 | add.backgroundColor = UIColorFromRGB(0x27AE60); 154 | 155 | return @[add]; 156 | } 157 | - (void)refreshTable:(UIRefreshControl*)sender { 158 | [sender beginRefreshing]; 159 | 160 | [aryTableView removeAllObjects]; 161 | [self getMoreActions]; 162 | } 163 | 164 | #pragma mark - UIAlertView Delegate 165 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 166 | if (buttonIndex == 1) { 167 | NSString *text = [alertView textFieldAtIndex:0].text; 168 | if ([text containsString:@" "]) { 169 | text = [text stringByReplacingOccurrencesOfString:@" " withString:@"%20"]; 170 | } 171 | urlString = [NSString stringWithFormat:@"%@%@",URL_SEARCH,text]; 172 | [self getMoreActions]; 173 | } 174 | } 175 | @end 176 | -------------------------------------------------------------------------------- /customft/CustomFT.mm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import "BTOAddShortCutViewController.h" 5 | #import "BTOOptionsViewController.h" 6 | #import "BTOActionSearchViewController.h" 7 | 8 | @interface PSViewController () 9 | - (void)viewDidLoad; 10 | - (UIView*)view; 11 | - (void)presentViewController:(id)arg1 animated:(BOOL)arg2 completion:(/*^block*/id)arg3 ; 12 | - (void)pushController:(id)arg1 animate:(BOOL)arg2; 13 | @end 14 | 15 | @interface CustomFTListController: PSViewController { 16 | NSMutableArray *aryShortCuts; 17 | UITableView *tblShortCuts; 18 | UIRefreshControl *refreshControl; 19 | } 20 | @end 21 | 22 | #define DONATE (@"Donations accepted.\nThe developer put a lot\nof time and effort into this tweak.") 23 | #define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] 24 | 25 | @implementation CustomFTListController 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | self.view.backgroundColor = [UIColor whiteColor]; 29 | [self getAllObjects]; 30 | 31 | UIButton *btnEdit = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 32 | btnEdit.frame = CGRectMake(0,0,20,20); 33 | [btnEdit setTitle:@"Edit" forState:UIControlStateNormal]; 34 | [btnEdit addTarget:self action:@selector(editTable) forControlEvents:UIControlEventTouchUpInside]; 35 | [btnEdit setShowsTouchWhenHighlighted:YES]; 36 | [btnEdit sizeToFit]; 37 | UIBarButtonItem *buttonBar = [[UIBarButtonItem alloc] initWithCustomView:btnEdit]; 38 | [self.navigationItem setRightBarButtonItems:[NSArray arrayWithObjects:buttonBar, nil] animated:NO]; 39 | 40 | UIButton *btnDatabase = [UIButton buttonWithType:UIButtonTypeCustom]; 41 | [btnDatabase addTarget:self action:@selector(dataBase) forControlEvents:UIControlEventTouchUpInside]; 42 | [btnDatabase setBackgroundColor:UIColorFromRGB(0x27AE60)]; 43 | [btnDatabase setFrame:CGRectMake(0, 70, SCREEN.size.width/2, 50)]; 44 | [btnDatabase setTitle:@"Database" forState:UIControlStateNormal]; 45 | btnDatabase.showsTouchWhenHighlighted = YES; 46 | [self.view addSubview:btnDatabase]; 47 | 48 | UIButton *btnOptions = [UIButton buttonWithType:UIButtonTypeCustom]; 49 | [btnOptions addTarget:self action:@selector(options) forControlEvents:UIControlEventTouchUpInside]; 50 | [btnOptions setBackgroundColor:UIColorFromRGB(0x2980b9)]; 51 | [btnOptions setFrame:CGRectMake(SCREEN.size.width/2, 70, SCREEN.size.width/2, 50)]; 52 | [btnOptions setTitle:@"Options" forState:UIControlStateNormal]; 53 | btnOptions.showsTouchWhenHighlighted = YES; 54 | [self.view addSubview:btnOptions]; 55 | 56 | CGRect frame = CGRectMake(0,200,self.view.bounds.size.width,self.view.bounds.size.height-200); 57 | if (self.view.bounds.size.width > 400) { 58 | frame.size.width = 400; 59 | } 60 | tblShortCuts = [[UITableView alloc] initWithFrame:frame style:UITableViewStylePlain]; 61 | tblShortCuts.dataSource = self; 62 | tblShortCuts.delegate = self; 63 | // tblShortCuts.backgroundColor = UIColorFromRGB(0xf39c12); 64 | [self.view addSubview:tblShortCuts]; 65 | 66 | UIButton *btnDonations = [UIButton buttonWithType:UIButtonTypeCustom]; 67 | [btnDonations addTarget:self action:@selector(donate) forControlEvents:UIControlEventTouchUpInside]; 68 | [btnDonations setBackgroundColor:UIColorFromRGB(0xf39c12)]; 69 | [btnDonations setFrame:CGRectMake(0, 120, SCREEN.size.width, 80)]; 70 | [btnDonations setTitle:DONATE forState:UIControlStateNormal]; 71 | [btnDonations.titleLabel setNumberOfLines:0]; 72 | [btnDonations.titleLabel setTextAlignment:NSTextAlignmentCenter]; 73 | [btnDonations setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 74 | btnDonations.showsTouchWhenHighlighted = YES; 75 | [self.view addSubview:btnDonations]; 76 | 77 | refreshControl = [[UIRefreshControl alloc] init]; 78 | [refreshControl addTarget:self action:@selector(refreshTable) forControlEvents:UIControlEventValueChanged]; 79 | [tblShortCuts addSubview:refreshControl]; 80 | } 81 | 82 | #pragma mark - UIButton Functions 83 | - (void)editTable { 84 | if ([tblShortCuts isEditing] == YES) { 85 | [tblShortCuts setEditing:NO animated:YES]; 86 | [[self navigationItem] setLeftBarButtonItem:nil]; 87 | } else { 88 | [tblShortCuts setEditing:YES animated:YES]; 89 | 90 | UIButton *btnAddCell = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 91 | btnAddCell.frame = CGRectMake(0,0,20,20); 92 | [btnAddCell setTitle:@" + " forState:UIControlStateNormal]; 93 | [btnAddCell addTarget:self action:@selector(addTableCell) forControlEvents:UIControlEventTouchUpInside]; 94 | [btnAddCell setShowsTouchWhenHighlighted:YES]; 95 | [btnAddCell sizeToFit]; 96 | UIBarButtonItem *buttonBar = [[UIBarButtonItem alloc] initWithCustomView:btnAddCell]; 97 | UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; 98 | negativeSpacer.width = 0; 99 | [self.navigationItem setLeftBarButtonItem:buttonBar animated:NO]; 100 | } 101 | } 102 | - (void)addTableCell { 103 | [self presentViewController:[BTOAddShortCutViewController new] animated:YES completion:nil]; 104 | } 105 | - (void)options { 106 | [self presentViewController:[BTOOptionsViewController new] animated:YES completion:nil]; 107 | } 108 | - (void)donate { 109 | SFSafariViewController *webViewController = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:@"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=TFA6F7EYKKT7E&lc=US&item_name=3D%2b&item_number=com%2ebolencki13%2e3d%2b¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted"]]; 110 | [self presentViewController:webViewController animated:YES completion:nil]; 111 | } 112 | - (void)dataBase { 113 | [self pushController:[BTOActionSearchViewController new] animate:YES]; 114 | } 115 | 116 | #pragma mark - RefreshTable 117 | - (void)refreshTable { 118 | [refreshControl beginRefreshing]; 119 | [self getAllObjects]; 120 | [tblShortCuts reloadData]; 121 | [refreshControl endRefreshing]; 122 | } 123 | - (void)getAllObjects { 124 | NSDictionary *tempDict = [[BTOShortCutManager sharedInstance] getShortCuts]; 125 | NSArray *keys = [tempDict allKeys]; 126 | 127 | aryShortCuts = [[NSMutableArray alloc] init]; 128 | 129 | for (NSString *key in keys) { 130 | if (![key isEqualToString:@"com.bolencki13.test-ShortCut"]) { 131 | NSArray *allObjects = [tempDict objectForKey:key]; 132 | for (NSArray *object in allObjects) { 133 | NSString *text = [NSString stringWithFormat:@"%@-%@",[object objectAtIndex:2],[object objectAtIndex:0]]; 134 | [aryShortCuts addObject:text]; 135 | } 136 | } 137 | } 138 | } 139 | 140 | #pragma mark - UITableView Delegate 141 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 142 | return [aryShortCuts count]; 143 | } 144 | - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 145 | static NSString* cellIdentifier = @"CellIdentifier"; 146 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 147 | if (cell == nil) { 148 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 149 | } 150 | cell.textLabel.text = [aryShortCuts objectAtIndex:indexPath.row]; 151 | cell.accessoryType = UITableViewCellAccessoryNone; 152 | // cell.backgroundColor = UIColorFromRGB(0xf39c12); 153 | 154 | return cell; 155 | } 156 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 157 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 158 | 159 | NSString *cellText = ((UITableViewCell*)[tableView cellForRowAtIndexPath:indexPath]).textLabel.text; 160 | NSArray *listItems = [cellText componentsSeparatedByString:@"-"]; 161 | NSString *identifier = [listItems objectAtIndex:0]; 162 | NSString *title = [listItems objectAtIndex:([listItems count]-1)]; 163 | NSArray *item = [[BTOShortCutManager sharedInstance] itemForBundleID:identifier withTitle:title]; 164 | 165 | BTOAddShortCutViewController *controller = [BTOAddShortCutViewController new]; 166 | [self presentViewController:controller animated:YES completion:^{ 167 | controller.txtTitle.text = [item objectAtIndex:0]; 168 | controller.txtSubTitle.text = [item objectAtIndex:1]; 169 | controller.txtBundleID.text = [item objectAtIndex:2]; 170 | [controller setURLText:[item objectAtIndex:3]]; 171 | [controller setIconNumber:[[item objectAtIndex:4] intValue]]; 172 | }]; 173 | 174 | [[BTOShortCutManager sharedInstance] deleteShortCutWithBundleID:[tableView cellForRowAtIndexPath:indexPath].textLabel.text]; 175 | [aryShortCuts removeObject:[aryShortCuts objectAtIndex:indexPath.row]]; 176 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 177 | } 178 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 179 | if ([[tableView cellForRowAtIndexPath:indexPath].textLabel.text isEqualToString:@"Additional Options"] || [[tableView cellForRowAtIndexPath:indexPath].textLabel.text isEqualToString:DONATE] || [[tableView cellForRowAtIndexPath:indexPath].textLabel.text isEqualToString:@"Shortcut Database"]) { 180 | return NO; 181 | } else { 182 | return YES; 183 | } 184 | } 185 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 186 | if (editingStyle == UITableViewCellEditingStyleDelete) { 187 | 188 | [[BTOShortCutManager sharedInstance] deleteShortCutWithBundleID:[tableView cellForRowAtIndexPath:indexPath].textLabel.text]; 189 | [aryShortCuts removeObject:[aryShortCuts objectAtIndex:indexPath.row]]; 190 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 191 | } 192 | } 193 | @end 194 | 195 | // vim:ft=objc 196 | -------------------------------------------------------------------------------- /customft/BTOShortCutManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTOShortCutManager.m 3 | // test 4 | // 5 | // Created by Brian Olencki on 10/17/15. 6 | // Copyright © 2015 bolencki13. All rights reserved. 7 | // 8 | 9 | #import "BTOShortCutManager.h" 10 | #import 11 | 12 | #define PREF_OPTIONS_KEY (@"shortCuts") 13 | #define FILE_PATH (@"/var/mobile/Library/Preferences/com.bolencki13.customft-applicationList.plist") 14 | 15 | @implementation BTOShortCutManager 16 | @synthesize delegate = _delegate; 17 | + (BTOShortCutManager*)sharedInstance { 18 | static dispatch_once_t p = 0; 19 | __strong static id _sharedObject = nil; 20 | dispatch_once(&p, ^{ 21 | _sharedObject = [[self alloc] init]; 22 | }); 23 | return _sharedObject; 24 | } 25 | - (id)init { 26 | if (self == [super init]) { 27 | 28 | } 29 | return self; 30 | } 31 | 32 | #pragma mark - Public Functions 33 | - (NSDictionary*)getShortCuts { 34 | [self checkAndCreate]; 35 | NSDictionary *savedValue = [[NSDictionary alloc] initWithContentsOfFile:FILE_PATH]; 36 | 37 | return savedValue; 38 | } 39 | - (void)deleteShortCutWithBundleID:(NSString *)bundleID { 40 | NSMutableDictionary *dictShortCuts = [[self getShortCuts] mutableCopy]; 41 | NSArray *listItems = [bundleID componentsSeparatedByString:@"-"]; 42 | NSString *identifier = [listItems objectAtIndex:0]; 43 | NSString *title = [listItems objectAtIndex:([listItems count]-1)]; 44 | 45 | NSMutableArray *item = [[dictShortCuts objectForKey:identifier] mutableCopy]; 46 | 47 | if ([item count] == 1) { 48 | [dictShortCuts removeObjectForKey:identifier]; 49 | } else { 50 | for (NSMutableArray *objects in item) { 51 | if ([objects containsObject:title]) { 52 | [item removeObject:objects]; 53 | [dictShortCuts setObject:item forKey:identifier]; 54 | break; 55 | } 56 | } 57 | } 58 | [dictShortCuts writeToFile:FILE_PATH atomically:YES]; 59 | } 60 | - (void)addShortCutWithTitle:(NSString *)title withSubTitle:(NSString *)subTitle withBundleID:(NSString *)bundleID withURL:(NSString*)url withIcon:(NSInteger)iconNumber withImage:(NSString*)image { 61 | if ([title isEqualToString:@""] || [bundleID isEqualToString:@""]) { 62 | return; 63 | } 64 | if ([subTitle isEqualToString:@""]) { 65 | subTitle = @"*ignore*"; 66 | } 67 | 68 | NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile:FILE_PATH]; 69 | NSArray *currentItems = [[NSArray alloc] initWithObjects:title,subTitle,bundleID, url, [NSNumber numberWithInt:iconNumber], image, nil]; 70 | 71 | if ([data objectForKey:bundleID]) { 72 | NSMutableArray *aryDictItem = [[data objectForKey:bundleID] mutableCopy]; 73 | [aryDictItem addObject:currentItems]; 74 | [data setObject:aryDictItem forKey:bundleID]; 75 | } else { 76 | NSMutableArray *aryDictItem = [[NSMutableArray alloc] initWithObjects:currentItems, nil]; 77 | [data setObject:aryDictItem forKey:bundleID]; 78 | } 79 | NSLog(@"%@",[data writeToFile:FILE_PATH atomically:YES] ? @"YES" : @"NO"); 80 | } 81 | - (NSArray*)shortCutsForAppWithBundleID:(NSString*)bundleID { 82 | NSDictionary *tempDict = [self getShortCuts]; 83 | 84 | if ([tempDict objectForKey:bundleID]) { 85 | return (NSArray*)[tempDict objectForKey:bundleID]; 86 | } 87 | return nil; 88 | } 89 | - (NSString*)getURLSchemeForBundleID:(NSString*)bundleID withTitle:(NSString*)title { 90 | NSDictionary *tempDict = [self getShortCuts]; 91 | NSArray *bundleList = (NSArray*)[tempDict objectForKey:bundleID]; 92 | 93 | NSString *url = @""; 94 | for (NSArray *aryTemp in bundleList) { 95 | if ([aryTemp containsObject:title]) { 96 | url = [aryTemp objectAtIndex:3]; 97 | break; 98 | } 99 | } 100 | 101 | return url; 102 | } 103 | - (BOOL)containsBundleID:(NSString*)bundleID { 104 | NSDictionary *tempDict = [self getShortCuts]; 105 | if ([tempDict objectForKey:bundleID]) { 106 | return YES; 107 | } else { 108 | return NO; 109 | } 110 | } 111 | - (UIApplicationShortcutIconType)iconTypeForNumber:(NSInteger)number { 112 | switch (number) { 113 | case 0: 114 | return UIApplicationShortcutIconTypeAdd; 115 | break; 116 | // case 1: 117 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeAlarm]]; 118 | // break; 119 | // case 2: 120 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeAudio]]; 121 | // break; 122 | // case 3: 123 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeBookmark]]; 124 | // break; 125 | // case 4: 126 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeCapturePhoto]]; 127 | // break; 128 | // case 5: 129 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeCaptureVideo]]; 130 | // break; 131 | // case 6: 132 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeCloud]]; 133 | // break; 134 | case 1: 135 | return UIApplicationShortcutIconTypeCompose; 136 | break; 137 | // case 8: 138 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeConfirmation]]; 139 | // break; 140 | // case 9: 141 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeContact]]; 142 | // break; 143 | // case 10: 144 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeDate]]; 145 | // break; 146 | // case 11: 147 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeFavorite]]; 148 | // break; 149 | // case 12: 150 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeHome]]; 151 | // break; 152 | // case 13: 153 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeInvitation]]; 154 | // break; 155 | case 2: 156 | return UIApplicationShortcutIconTypeLocation; 157 | break; 158 | // case 15: 159 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeLove]]; 160 | // break; 161 | // case 16: 162 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeMail]]; 163 | // break; 164 | // case 17: 165 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeMarkLocation]]; 166 | // break; 167 | // case 18: 168 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeMessage]]; 169 | // break; 170 | case 3: 171 | return UIApplicationShortcutIconTypePause; 172 | break; 173 | case 4: 174 | return UIApplicationShortcutIconTypePlay; 175 | break; 176 | // case 21: 177 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeProhibit]]; 178 | // break; 179 | case 5: 180 | return UIApplicationShortcutIconTypeSearch; 181 | break; 182 | case 6: 183 | return UIApplicationShortcutIconTypeShare; 184 | break; 185 | // case 24: 186 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeShuffle]]; 187 | // break; 188 | // case 25: 189 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeTask]]; 190 | // break; 191 | // case 26: 192 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeTaskCompleted]]; 193 | // break; 194 | // case 27: 195 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeTime]]; 196 | // break; 197 | // case 28: 198 | // [self setFTActionWithIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeUpdate]]; 199 | // break; 200 | default: 201 | return UIApplicationShortcutIconTypeAdd; 202 | break; 203 | } 204 | } 205 | - (NSData*)customImageForBundleID:(NSString*)bundleID withTitle:(NSString*)title { 206 | NSDictionary *tempDict = [self getShortCuts]; 207 | NSArray *bundleList = (NSArray*)[tempDict objectForKey:bundleID]; 208 | 209 | NSString *imageURL; 210 | for (NSArray *aryTemp in bundleList) { 211 | if ([aryTemp containsObject:title]) { 212 | imageURL = [aryTemp objectAtIndex:5]; 213 | break; 214 | } 215 | } 216 | NSData *imageData = UIImagePNGRepresentation([UIImage imageWithContentsOfFile:@"/Library/Application Support/CustomFT/kCustomFT.bundle/respring.png"]); 217 | 218 | return imageData; 219 | } 220 | - (NSArray*)itemForBundleID:(NSString*)bundleID withTitle:(NSString*)title { 221 | NSDictionary *tempDict = [self getShortCuts]; 222 | NSArray *bundleList = (NSArray*)[tempDict objectForKey:bundleID]; 223 | 224 | NSArray *item; 225 | for (NSArray *aryTemp in bundleList) { 226 | if ([aryTemp containsObject:title]) { 227 | item = aryTemp; 228 | break; 229 | } 230 | } 231 | 232 | return item; 233 | } 234 | 235 | #pragma mark - Private Functions 236 | - (void)checkAndCreate { 237 | NSFileManager *fileManager = [NSFileManager defaultManager]; 238 | 239 | if (![fileManager fileExistsAtPath:FILE_PATH]){ 240 | NSMutableDictionary *data = [NSMutableDictionary new]; 241 | 242 | NSArray *test = [[NSArray alloc] initWithObjects:[[NSArray alloc] initWithObjects:@"Test-Tittle",@"Test-SubTittle",@"Test-BundleID",@"Test-URL_Scheme",@"Test-Icon#",@"Test-Icon_URL", nil], nil]; 243 | [data setObject:test forKey:@"com.bolencki13.test-ShortCut"]; 244 | 245 | NSArray *respring = [[NSArray alloc] initWithObjects:[[NSArray alloc] initWithObjects:@"Respring",@"Respring Device",@"com.apple.Preferences",@"respring",@"0",@"", nil], nil]; 246 | [data setObject:respring forKey:@"com.apple.Preferences"]; 247 | 248 | [data writeToFile:FILE_PATH atomically:YES]; 249 | } 250 | } 251 | @end 252 | -------------------------------------------------------------------------------- /customft/BTOAddShortCutViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BTOAddShortCutViewController.m 3 | // test 4 | // 5 | // Created by Brian Olencki on 10/17/15. 6 | // Copyright © 2015 bolencki13. All rights reserved. 7 | // 8 | 9 | #import "BTOAddShortCutViewController.h" 10 | #import 11 | #include 12 | #import 13 | 14 | @implementation BTOInputView 15 | @synthesize segmentedControl = _segmentedControl, txtURLScheme = _txtURLScheme; 16 | - (id)initWithFrame:(CGRect)frame { 17 | if (self == [super initWithFrame:frame]) { 18 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(populateEvent:) name:@"BTO_ActivatorEventName" object:nil]; 19 | 20 | NSArray *itemArray = [NSArray arrayWithObjects: @"URL Scheme", @"Activator", @"Shell Script", nil]; 21 | 22 | _segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray]; 23 | _segmentedControl.frame = CGRectMake(0, 0, frame.size.width, 30); 24 | [_segmentedControl addTarget:self action:@selector(segmentChanged:) forControlEvents: UIControlEventValueChanged]; 25 | _segmentedControl.selectedSegmentIndex = 0; 26 | [self addSubview:_segmentedControl]; 27 | 28 | _txtURLScheme = [[UITextField alloc] initWithFrame:CGRectMake(0, 40, frame.size.width, 30)]; 29 | _txtURLScheme.placeholder = @"\%@ = input"; 30 | _txtURLScheme.textAlignment = NSTextAlignmentCenter; 31 | _txtURLScheme.autocapitalizationType = UITextAutocapitalizationTypeNone; 32 | _txtURLScheme.autocorrectionType = UITextAutocorrectionTypeNo; 33 | _txtURLScheme.font = [UIFont systemFontOfSize:24]; 34 | _txtURLScheme.hidden = NO; 35 | [self addSubview:_txtURLScheme]; 36 | 37 | txtSchellScript = [[UITextField alloc] initWithFrame:CGRectMake(0, 40, frame.size.width, 30)]; 38 | txtSchellScript.placeholder = @"Enter Command"; 39 | txtSchellScript.textAlignment = NSTextAlignmentCenter; 40 | txtSchellScript.autocapitalizationType = UITextAutocapitalizationTypeNone; 41 | txtSchellScript.autocorrectionType = UITextAutocorrectionTypeNo; 42 | txtSchellScript.font = [UIFont systemFontOfSize:24]; 43 | txtSchellScript.hidden = YES; 44 | [self addSubview:txtSchellScript]; 45 | } 46 | return self; 47 | } 48 | 49 | #pragma mark - Public Functions 50 | - (NSString*)getURL { 51 | switch (_segmentedControl.selectedSegmentIndex) { 52 | case 0: 53 | return _txtURLScheme.text; 54 | break; 55 | case 1: 56 | return [NSString stringWithFormat:@"activator://%@",activatorAction]; 57 | break; 58 | case 2: 59 | return [NSString stringWithFormat:@"shellScript://%@",txtSchellScript.text]; 60 | break; 61 | 62 | default: 63 | return @""; 64 | break; 65 | } 66 | } 67 | 68 | #pragma mark - Private Functions 69 | - (void)segmentChanged:(UISegmentedControl*)sender { 70 | switch (sender.selectedSegmentIndex) { 71 | case 0: 72 | _txtURLScheme.hidden = NO; 73 | txtSchellScript.hidden = YES; 74 | break; 75 | case 1: 76 | _txtURLScheme.hidden = YES; 77 | txtSchellScript.hidden = YES; 78 | [self loadActivator]; 79 | break; 80 | case 2: 81 | _txtURLScheme.hidden = YES; 82 | txtSchellScript.hidden = NO; 83 | if ([_txtURLScheme.text containsString:@"shellScript://"]) { 84 | txtSchellScript.text = [_txtURLScheme.text stringByReplacingOccurrencesOfString:@"shellScript://" withString:@""]; 85 | } 86 | break; 87 | 88 | default: 89 | break; 90 | } 91 | } 92 | - (void)populateEvent:(NSNotification*)notification { 93 | activatorAction = [notification object]; 94 | _txtURLScheme.text = [NSString stringWithFormat:@"activator://%@",activatorAction]; 95 | } 96 | 97 | #pragma mark - Activator 98 | - (void)loadActivator { 99 | UIResponder *responder = self; 100 | while ([responder isKindOfClass:[UIView class]]) responder = [responder nextResponder]; 101 | UIViewController *viewController = (UIViewController*)responder; 102 | 103 | dlopen("/usr/lib/libactivator.dylib", RTLD_LAZY); 104 | Class la = objc_getClass("LAModeSettingsController"); 105 | if (la) { 106 | static dispatch_once_t p = 0; 107 | dispatch_once(&p, ^{ 108 | Class BTO_la = objc_allocateClassPair(la, [[NSString stringWithFormat:@"BTO_LAModeSettingsController"] UTF8String], 0); 109 | objc_registerClassPair(BTO_la); 110 | 111 | SEL selTable = @selector(tableView:didSelectRowAtIndexPath:); 112 | SEL BTO_selTable = @selector(BTO_tableView:didSelectRowAtIndexPath:); 113 | class_addMethod(BTO_la,selTable,[self methodForSelector:BTO_selTable],[[NSString stringWithFormat:@"myTableSelect"] UTF8String]); 114 | }); 115 | Class myLa = objc_getClass("BTO_LAModeSettingsController"); 116 | [viewController presentViewController:[[myLa alloc] initWithMode:@"springboard"] animated:YES completion:nil]; 117 | } else { 118 | UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Traverse" message:@"If you want to use Activator, please install it in Cydia." preferredStyle:UIAlertControllerStyleAlert]; 119 | UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]; 120 | [alertController addAction:cancelAction]; 121 | [viewController presentViewController:alertController animated:YES completion:nil]; 122 | } 123 | } 124 | - (void)BTO_tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 125 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 126 | 127 | Class myLa = objc_getClass("BTO_LAModeSettingsController"); 128 | NSString *action = [[[myLa alloc] initWithMode:@"springboard"] eventNameForIndexPath:indexPath]; 129 | 130 | [[NSNotificationCenter defaultCenter] postNotificationName:@"BTO_ActivatorEventName" object:action]; 131 | 132 | UIResponder *responder = tableView; 133 | while ([responder isKindOfClass:[UIView class]]) responder = [responder nextResponder]; 134 | UIViewController *viewController = (UIViewController*)responder; 135 | [viewController dismissViewControllerAnimated:YES completion:nil]; 136 | } 137 | @end 138 | 139 | @implementation BTOAddShortCutViewController 140 | @synthesize txtBundleID = _txtBundleID, txtTitle = _txtTitle, txtSubTitle = _txtSubTitle, iconNumber = _iconNumber; 141 | - (void)viewDidLoad { 142 | [super viewDidLoad]; 143 | self.view.backgroundColor = [UIColor whiteColor]; 144 | 145 | UIButton *btnHideKeyBoard = [UIButton buttonWithType:UIButtonTypeSystem]; 146 | [btnHideKeyBoard addTarget:self action:@selector(dismissKeyboard) forControlEvents:UIControlEventTouchUpInside]; 147 | [btnHideKeyBoard setFrame:CGRectMake(SCREEN.size.width-125, 20, 125, 50)]; 148 | [btnHideKeyBoard setTitle:@"Hide Keyboard" forState:UIControlStateNormal]; 149 | [self.view addSubview:btnHideKeyBoard]; 150 | 151 | UIButton *btnBack = [UIButton buttonWithType:UIButtonTypeSystem]; 152 | [btnBack addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; 153 | [btnBack setFrame:CGRectMake(10, 20, 50, 50)]; 154 | [btnBack setTitle:@"Back" forState:UIControlStateNormal]; 155 | [self.view addSubview:btnBack]; 156 | 157 | _txtTitle = [[UITextField alloc] initWithFrame:CGRectMake(10, 100, SCREEN.size.width-20, 30)]; 158 | _txtTitle.placeholder = @"Title"; 159 | _txtTitle.textAlignment = NSTextAlignmentCenter; 160 | _txtTitle.font = [UIFont systemFontOfSize:24]; 161 | [self.view addSubview:_txtTitle]; 162 | 163 | _txtSubTitle = [[UITextField alloc] initWithFrame:CGRectMake(10, 140, SCREEN.size.width-20, 30)]; 164 | _txtSubTitle.placeholder = @"Sub-title"; 165 | _txtSubTitle.textAlignment = NSTextAlignmentCenter; 166 | _txtSubTitle.font = [UIFont systemFontOfSize:24]; 167 | [self.view addSubview:_txtSubTitle]; 168 | 169 | _txtBundleID = [[UITextField alloc] initWithFrame:CGRectMake(10, 180, SCREEN.size.width-20, 30)]; 170 | _txtBundleID.placeholder = @"Bundle ID"; 171 | _txtBundleID.textAlignment = NSTextAlignmentCenter; 172 | _txtBundleID.autocapitalizationType = UITextAutocapitalizationTypeNone; 173 | _txtBundleID.autocorrectionType = UITextAutocorrectionTypeNo; 174 | _txtBundleID.font = [UIFont systemFontOfSize:24]; 175 | [self.view addSubview:_txtBundleID]; 176 | 177 | viewInput = [[BTOInputView alloc] initWithFrame:CGRectMake(10, 220, SCREEN.size.width-20, 70)]; 178 | [self.view addSubview:viewInput]; 179 | 180 | _iconNumber = 0; 181 | aryIcons = [[NSMutableArray alloc] initWithObjects: 182 | @"Add", 183 | // @"Alarm", 184 | // @"Audio", 185 | // @"Bookmark", 186 | // @"CapturePhoto", 187 | // @"CaptureVideo", 188 | // @"Cloud", 189 | @"Compose", 190 | // @"Confirm", 191 | // @"Contact", 192 | // @"Date", 193 | // @"Favorite", 194 | // @"Home", 195 | // @"Invitation", 196 | @"Location", 197 | // @"Love", 198 | // @"Mail", 199 | // @"MarkLocation", 200 | // @"Messages", 201 | @"Pause", 202 | @"Play", 203 | // @"Prohibit", 204 | @"Search", 205 | @"Share", 206 | // @"Shuffle", 207 | // @"Task", 208 | // @"TaskComplete", 209 | // @"Time", 210 | // @"Update", 211 | // @"Custom Image", 212 | nil]; 213 | 214 | pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(SCREEN.size.width/8, 300, SCREEN.size.width*3/4, 100)]; 215 | [pickerView setDataSource: self]; 216 | [pickerView setDelegate: self]; 217 | pickerView.showsSelectionIndicator = YES; 218 | [self.view addSubview: pickerView]; 219 | 220 | pickedImage = @""; 221 | } 222 | 223 | #pragma mark - UIButton Functions 224 | - (void)dismissKeyboard { 225 | for (UIView *view in viewInput.subviews) { 226 | if ([view isMemberOfClass:[UITextField class]]) { 227 | [((UITextField*)view) resignFirstResponder]; 228 | } 229 | } 230 | for (UIView *view in self.view.subviews) { 231 | if ([view isMemberOfClass:[UITextField class]]) { 232 | [((UITextField*)view) resignFirstResponder]; 233 | } 234 | } 235 | } 236 | 237 | #pragma mark - Other 238 | - (void)back { 239 | [self dismissKeyboard]; 240 | [[BTOShortCutManager sharedInstance] addShortCutWithTitle:_txtTitle.text withSubTitle:_txtSubTitle.text withBundleID:_txtBundleID.text withURL:[viewInput getURL] withIcon:_iconNumber withImage:pickedImage]; 241 | [self dismissViewControllerAnimated:YES completion:nil]; 242 | } 243 | - (void)setIconNumber:(NSInteger)iconNumber { 244 | [pickerView selectRow:iconNumber inComponent:0 animated:YES]; 245 | _iconNumber = iconNumber; 246 | } 247 | - (void)setURLText:(NSString*)text { 248 | viewInput.txtURLScheme.text = text; 249 | } 250 | 251 | #pragma mark - UIPickerView Delegate 252 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{ 253 | return 1; 254 | } 255 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{ 256 | return [aryIcons count]; 257 | } 258 | - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{ 259 | return [aryIcons objectAtIndex:row]; 260 | } 261 | - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{ 262 | _iconNumber = row; 263 | return; 264 | if (_iconNumber == [aryIcons count]-1) { 265 | UIImagePickerController *picker = [[UIImagePickerController alloc] init]; 266 | picker.delegate = self; 267 | picker.allowsEditing = YES; 268 | picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 269 | [self presentViewController:picker animated:YES completion:NULL]; 270 | } 271 | } 272 | 273 | #pragma mark - UIImagePickerController Delegate 274 | - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { 275 | pickedImage = info[UIImagePickerControllerReferenceURL]; 276 | [picker dismissViewControllerAnimated:YES completion:NULL]; 277 | [self dismissKeyboard]; 278 | } 279 | @end 280 | -------------------------------------------------------------------------------- /Applications.xm: -------------------------------------------------------------------------------- 1 | #import "HeaderFiles.h" 2 | #import 3 | #import 4 | 5 | %group iOS9 6 | %hook SBApplicationShortcutStoreManager 7 | - (id)shortcutItemsForBundleIdentifier:(NSString*)arg1 { 8 | NSString *bundleID = arg1; 9 | NSArray *aryItems = [NSArray new]; 10 | if (%orig != NULL || %orig != nil) { 11 | aryItems = %orig; 12 | } 13 | NSMutableArray *aryShortcuts = [aryItems mutableCopy]; 14 | 15 | if ([[TRShortCutManager sharedInstance] containsBundleID:bundleID] == YES) { 16 | NSArray *aryObjects = [[TRShortCutManager sharedInstance] shortCutsForAppWithBundleID:bundleID withType:TRShortCutTypeSpringboard]; 17 | [aryShortcuts addObjectsFromArray:aryObjects]; 18 | } 19 | return aryShortcuts; 20 | } 21 | %end 22 | 23 | %hook SBApplicationShortcutMenu 24 | - (id)_shortcutItemsToDisplay { 25 | if ([[NSClassFromString(@"SBControlCenterController") sharedInstance] isVisible] == NO) { 26 | if (self.application == nil) { 27 | return %orig; 28 | } 29 | } 30 | NSMutableArray *objects = [NSMutableArray new]; 31 | [objects addObjectsFromArray:self.application.staticShortcutItems]; 32 | [objects addObjectsFromArray:[[NSClassFromString(@"SBApplicationShortcutStoreManager") sharedManager] shortcutItemsForBundleIdentifier:self.application.bundleIdentifier]]; 33 | 34 | NSUserDefaults *prefs = [[NSUserDefaults alloc] initWithSuiteName:@"com.bolencki13.customft"]; 35 | if ([prefs boolForKey:@"addMenu"] == YES) { 36 | if ([prefs boolForKey:@"addNotEvery"] == NO) { 37 | SBSApplicationShortcutItem *newAction = [[SBSApplicationShortcutItem alloc] init]; 38 | [newAction setIcon:[[SBSApplicationShortcutSystemIcon alloc] initWithType:UIApplicationShortcutIconTypeAdd]]; 39 | [newAction setLocalizedTitle:@"New"]; 40 | [newAction setLocalizedSubtitle:@"Add New Action"]; 41 | [newAction setType:@"com.bolencki13.customft-newAction"]; 42 | [objects addObject:newAction]; 43 | } else if ([prefs boolForKey:@"addNotEvery"] == YES && [objects count] == 0) { 44 | SBSApplicationShortcutItem *newAction = [[SBSApplicationShortcutItem alloc] init]; 45 | [newAction setIcon:[[SBSApplicationShortcutSystemIcon alloc] initWithType:UIApplicationShortcutIconTypeAdd]]; 46 | [newAction setLocalizedTitle:@"New"]; 47 | [newAction setLocalizedSubtitle:@"Add New Action"]; 48 | [newAction setType:@"com.bolencki13.customft-newAction"]; 49 | [objects addObject:newAction]; 50 | } 51 | } 52 | return objects; 53 | } 54 | - (void)menuContentView:(id)arg1 activateShortcutItem:(UIApplicationShortcutItem*)arg2 index:(long long)arg3 { 55 | NSString *input = arg2.type; 56 | if ([input isEqualToString:@"com.bolencki13.customft-newAction"]) { 57 | [self dismissAnimated:YES completionHandler:nil]; 58 | 59 | UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:[TRAddActionSpringBoardController new]]; 60 | UIViewController *rootView = [[UIApplication sharedApplication].keyWindow rootViewController]; 61 | [rootView presentViewController:navigation animated:YES completion:nil]; 62 | return; 63 | } 64 | NSString *bundleID = @""; 65 | NSString *title = @""; 66 | 67 | if ([input containsString:@"-"]) { 68 | NSArray *arySplitString = [input componentsSeparatedByString:@"-"]; 69 | bundleID = [arySplitString objectAtIndex:0]; 70 | title = [arySplitString objectAtIndex:1]; 71 | } 72 | 73 | if ([[TRShortCutManager sharedInstance] containsBundleID:bundleID] == YES) { 74 | NSString *url = [[TRShortCutManager sharedInstance] getURLSchemeForBundleID:bundleID withTitle:title withType:TRShortCutTypeSpringboard]; 75 | 76 | if ([url isEqualToString:@"respring"]) { 77 | system("killall backboardd"); 78 | } else if ([url isEqualToString:@"shutdown"]) { 79 | [(SpringBoard*)[NSClassFromString(@"SpringBoard") sharedApplication] powerDown]; 80 | } else if ([url isEqualToString:@"reboot"]) { 81 | [(SpringBoard*)[NSClassFromString(@"SpringBoard") sharedApplication] reboot]; 82 | } else if ([url isEqualToString:@"safemode"]) { 83 | system("killall -SEGV SpringBoard"); 84 | } else if ([url containsString:@"shellScript://"]) { 85 | const char *command = [[url stringByReplacingOccurrencesOfString:@"shellScript://" withString:@""] UTF8String]; 86 | system(command); 87 | } else if ([url containsString:@"activator://"]) { 88 | NSString *BTOShortCutActivatorEventName = [url stringByReplacingOccurrencesOfString:@"activator://" withString:@""]; 89 | LAEvent *event = [%c(LAEvent) eventWithName:BTOShortCutActivatorEventName mode:[[%c(LAActivator) sharedInstance] currentEventMode]]; 90 | [[%c(LAActivator) sharedInstance] sendEventToListener:event]; 91 | } else { 92 | if ([url containsString:@"\%@"]) { 93 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Traverse" message:@"Enter Search Parameters" preferredStyle:UIAlertControllerStyleAlert]; 94 | 95 | UIAlertAction *ok = [UIAlertAction actionWithTitle:@"Search" style:UIAlertActionStyleDefault 96 | handler:^(UIAlertAction * action) { 97 | UITextField *txtInput = [alert.textFields objectAtIndex:0]; 98 | NSString *finalURL = [NSString stringWithFormat:@"%@%@",[url stringByReplacingOccurrencesOfString:@"\%@" withString:@""],[txtInput.text stringByReplacingOccurrencesOfString:@" " withString:@"\%20"]]; 99 | [(SpringBoard*)[NSClassFromString(@"SpringBoard") sharedApplication] applicationOpenURL:[NSURL URLWithString:finalURL]]; 100 | }]; 101 | UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel 102 | handler:^(UIAlertAction * action) { 103 | [alert dismissViewControllerAnimated:YES completion:nil]; 104 | }]; 105 | [alert addAction:ok]; 106 | [alert addAction:cancel]; 107 | 108 | [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) { 109 | textField.placeholder = @"Search Text"; 110 | }]; 111 | UIViewController *rootView = [[UIApplication sharedApplication].keyWindow rootViewController]; 112 | [rootView presentViewController:alert animated:YES completion:nil]; 113 | } else { 114 | [(SpringBoard*)[NSClassFromString(@"SpringBoard") sharedApplication] applicationOpenURL:[NSURL URLWithString:url]]; 115 | } 116 | } 117 | [self dismissAnimated:YES completionHandler:nil]; 118 | } else { 119 | %orig; 120 | } 121 | } 122 | %end 123 | 124 | %hook SBApplicationShortcutMenuBackgroundView 125 | - (void)layoutSubviews { 126 | %orig; 127 | 128 | if ([[NSFileManager defaultManager] fileExistsAtPath:@"/var/lib/dpkg/info/org.thebigboss.shortcutix.list"]) { 129 | return; 130 | } 131 | 132 | NSUserDefaults *prefs = [[NSUserDefaults alloc] initWithSuiteName:@"com.bolencki13.customft"]; 133 | switch ([prefs integerForKey:@"blur"]) { 134 | case 0: { 135 | UIVisualEffectView *mybackdropView = MSHookIvar(self, "_backdropView"); 136 | [mybackdropView _setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]]; 137 | }break; 138 | case 1:{ 139 | UIVisualEffectView *mybackdropView = MSHookIvar(self, "_backdropView"); 140 | [mybackdropView _setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]]; 141 | }break; 142 | case 2:{ 143 | UIVisualEffectView *mybackdropView = MSHookIvar(self, "_backdropView"); 144 | [mybackdropView _setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]]; 145 | }break; 146 | default:{ 147 | UIVisualEffectView *mybackdropView = MSHookIvar(self, "_backdropView"); 148 | [mybackdropView _setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]]; 149 | }break; 150 | } 151 | } 152 | %end 153 | 154 | %hook SBApplicationShortcutMenuItemView 155 | - (void)_setupViewsWithIcon:(id)arg1 title:(id)arg2 subtitle:(id)arg3 { 156 | %orig; 157 | 158 | if ([[NSFileManager defaultManager] fileExistsAtPath:@"/var/lib/dpkg/info/org.thebigboss.shortcutix.list"]) { 159 | return; 160 | } 161 | 162 | UILabel *mytitleLabel = MSHookIvar(self, "_titleLabel"); 163 | 164 | UIImageView *myiconView = MSHookIvar(self, "_iconView"); 165 | if ([[NSString stringWithFormat:@"%@",[mytitleLabel.text lowercaseString]] isEqualToString:@"respring"]) { 166 | myiconView.image = [UIImage imageWithContentsOfFile:@"/Library/Application Support/CustomFT/kCustomFT.bundle/respring.png"]; 167 | } else if ([[NSString stringWithFormat:@"%@",[mytitleLabel.text lowercaseString]] isEqualToString:@"reboot"]) { 168 | myiconView.image = [UIImage imageWithContentsOfFile:@"/Library/Application Support/CustomFT/kCustomFT.bundle/reboot.png"]; 169 | } else if ([[NSString stringWithFormat:@"%@",[mytitleLabel.text lowercaseString]] isEqualToString:@"shutdown"]) { 170 | myiconView.image = [UIImage imageWithContentsOfFile:@"/Library/Application Support/CustomFT/kCustomFT.bundle/powerOff.png"]; 171 | } else if ([[NSString stringWithFormat:@"%@",[mytitleLabel.text lowercaseString]] isEqualToString:@"safemode"] || [[NSString stringWithFormat:@"%@",[mytitleLabel.text lowercaseString]] isEqualToString:@"safe mode"]) { 172 | myiconView.image = [UIImage imageWithContentsOfFile:@"/Library/Application Support/CustomFT/kCustomFT.bundle/safeMode.png"]; 173 | } 174 | 175 | NSUserDefaults *prefs = [[NSUserDefaults alloc] initWithSuiteName:@"com.bolencki13.customft"]; 176 | 177 | if ([prefs integerForKey:@"blur"] == 2) { 178 | UILabel *mytitleLabel = MSHookIvar(self, "_titleLabel"); 179 | UIImageView *myiconView = MSHookIvar(self, "_iconView"); 180 | 181 | mytitleLabel.textColor = [UIColor whiteColor]; 182 | 183 | UILabel *mysubtitleLabel = MSHookIvar(self, "_subtitleLabel"); 184 | mysubtitleLabel.textColor = [UIColor whiteColor]; 185 | 186 | if ([arg3 isEqualToString:@"FaceTime"] || [arg3 isEqualToString:@"home"] || [arg3 isEqualToString:@"work"] || [arg3 isEqualToString:@"iPhone"] || [arg3 isEqualToString:@"mobile"] || [arg3 isEqualToString:@"main"] || [arg3 isEqualToString:@"home fax"] || [arg3 isEqualToString:@"work fax"] || [arg3 isEqualToString:@"pager"] || [arg3 isEqualToString:@"other"]) return; 187 | myiconView.image = [self invertImage:myiconView.image]; 188 | } 189 | } 190 | %new 191 | - (UIImage *)invertImage:(UIImage *)originalImage { 192 | UIGraphicsBeginImageContext(originalImage.size); 193 | CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy); 194 | CGRect imageRect = CGRectMake(0, 0, originalImage.size.width, originalImage.size.height); 195 | [originalImage drawInRect:imageRect]; 196 | 197 | CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeDifference); 198 | // translate/flip the graphics context (for transforming from CG* coords to UI* coords 199 | CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, originalImage.size.height); 200 | CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0); 201 | //mask the image 202 | CGContextClipToMask(UIGraphicsGetCurrentContext(), imageRect, originalImage.CGImage); 203 | CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(),[UIColor whiteColor].CGColor); 204 | CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, originalImage.size.width, originalImage.size.height)); 205 | UIImage *returnImage = UIGraphicsGetImageFromCurrentImageContext(); 206 | UIGraphicsEndImageContext(); 207 | 208 | return returnImage; 209 | } 210 | %end 211 | %end 212 | 213 | %group iOS10 214 | %hook SBApplicationShortcutStoreManager 215 | - (id)applicationShortcutItemsForBundleIdentifier:(id)arg1 withVersion:(unsigned long long)arg2 { 216 | %log; 217 | %orig; 218 | } 219 | %end 220 | %end 221 | 222 | %ctor { 223 | if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0.0")) { 224 | %init(iOS10); 225 | } else { 226 | %init(iOS9); 227 | } 228 | } 229 | 230 | 231 | // static NSString *BTO_TraverseEventDummy1 = @"com.bolencki13.traverse.dummy.one"; 232 | // static NSString *BTO_TraverseEventDummy2 = @"com.bolencki13.traverse.dummy.two"; 233 | // static NSString *BTO_TraverseEventDummy3 = @"com.bolencki13.traverse.dummy.three"; 234 | // 235 | // @interface BTO_TraverseEventDataSource: NSObject { 236 | // } 237 | // + (id)sharedInstance; 238 | // @end 239 | // @implementation BTO_TraverseEventDataSource 240 | // + (id)sharedInstance { 241 | // static BTO_TraverseEventDataSource *shared = nil; 242 | // if (!shared) { 243 | // shared = [[BTO_TraverseEventDataSource alloc] init]; 244 | // } 245 | // return shared; 246 | // } 247 | // - (id)init { 248 | // if ((self = [super init])) { 249 | // [[objc_getClass("LAActivator") sharedInstance] registerEventDataSource:self forEventName:BTO_TraverseEventDummy1]; 250 | // [[objc_getClass("LAActivator") sharedInstance] registerEventDataSource:self forEventName:BTO_TraverseEventDummy2]; 251 | // [[objc_getClass("LAActivator") sharedInstance] registerEventDataSource:self forEventName:BTO_TraverseEventDummy3]; 252 | // } 253 | // return self; 254 | // } 255 | // - (void)dealloc { 256 | // if ([[objc_getClass("LAActivator") sharedInstance] isRunningInsideSpringBoard]) { 257 | // [[objc_getClass("LAActivator") sharedInstance] unregisterEventDataSourceWithEventName:BTO_TraverseEventDummy1]; 258 | // [[objc_getClass("LAActivator") sharedInstance] unregisterEventDataSourceWithEventName:BTO_TraverseEventDummy2]; 259 | // [[objc_getClass("LAActivator") sharedInstance] unregisterEventDataSourceWithEventName:BTO_TraverseEventDummy3]; 260 | // } 261 | // [super dealloc]; 262 | // } 263 | // - (NSString *)localizedTitleForEventName:(NSString *)eventName { 264 | // NSString *title = @""; 265 | // 266 | // if ([eventName isEqualToString:BTO_TraverseEventDummy1]) { 267 | // title = @"Dummy One"; 268 | // } else if ([eventName isEqualToString:BTO_TraverseEventDummy2]) { 269 | // title = @"Dummy Two"; 270 | // } else if ([eventName isEqualToString:BTO_TraverseEventDummy3]) { 271 | // title = @"Dummy Three"; 272 | // } 273 | // 274 | // return title; 275 | // } 276 | // - (NSString *)localizedGroupForEventName:(NSString *)eventName { 277 | // return @"Traverse"; 278 | // } 279 | // - (NSString *)localizedDescriptionForEventName:(NSString *)eventName { 280 | // NSString *description = @""; 281 | // 282 | // if ([eventName isEqualToString:BTO_TraverseEventDummy1]) { 283 | // description = @"Dummy Event #1 for Traverse"; 284 | // } else if ([eventName isEqualToString:BTO_TraverseEventDummy2]) { 285 | // description = @"Dummy Event #2 for Traverse"; 286 | // } else if ([eventName isEqualToString:BTO_TraverseEventDummy3]) { 287 | // description = @"Dummy Event #3 for Traverse"; 288 | // } 289 | // 290 | // return description; 291 | // } 292 | // - (BOOL)eventWithNameIsHidden:(NSString *)eventName { 293 | // return NO; 294 | // } 295 | // - (BOOL)eventWithNameRequiresAssignment:(NSString *)eventName { 296 | // return NO; 297 | // } 298 | // - (BOOL)eventWithName:(NSString *)eventName isCompatibleWithMode:(NSString *)eventMode { 299 | // if ([eventMode isEqualToString:@"springboard"]) { 300 | // return YES; 301 | // } 302 | // return NO; 303 | // } 304 | // - (BOOL)eventWithNameSupportsUnlockingDeviceToSend:(NSString *)eventName { 305 | // return NO; 306 | // } 307 | // @end 308 | // %ctor { 309 | // %init; 310 | // [%c(BTO_TraverseEventDataSource) sharedInstance]; 311 | // } 312 | 313 | 314 | 315 | // %hook SpringBoard 316 | // - (void)applicationDidFinishLaunching { 317 | // %orig; 318 | // 319 | // #define INITIAL_SET_UP(file) if ([file isEqualToString:@"/var/lib/dpkg/info/com.bolencki13.customft.list"] || [file isEqualToString:@"/var/lib/dpkg/info/org.thebigboss.customft.list"]) { if([[NSFileManager defaultManager] fileExistsAtPath:file]) { [[[UIAlertView alloc] initWithTitle:@"CustomFT" message:@"Please buy CustomFT. The developer put a lot of effort into it." delegate:nil cancelButtonTitle:@"I'll buy it" otherButtonTitles:nil, nil] show]; } } else { [[[UIAlertView alloc] initWithTitle:@"CustomFT" message:@"Please buy CustomFT. The developer put a lot of effort into it." delegate:nil cancelButtonTitle:@"I'll buy it" otherButtonTitles:nil, nil] show];}; 320 | // #define SET_UP @"/var/lib/dpkg/info/com.bolencki13.customft.list" 321 | // INITIAL_SET_UP(SET_UP); 322 | // #undef INITIAL_SET_UP 323 | // #undef SET_UP 324 | // } 325 | // %end 326 | -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | #import 2 | #include 3 | #import 4 | 5 | #import "customft/BTOShortCutManager.h" 6 | #import "customft/BTOAddShortCutViewController.h" 7 | 8 | #define NSLog(FORMAT, ...) NSLog(@"[%@]: %@",@"Traverse" , [NSString stringWithFormat:FORMAT, ##__VA_ARGS__]) 9 | 10 | 11 | @interface SBApplicationShortcutStoreManager : NSObject 12 | + (id)sharedManager; 13 | - (void)saveSynchronously; 14 | - (void)setShortcutItems:(id)arg1 forBundleIdentifier:(id)arg2; 15 | - (id)shortcutItemsForBundleIdentifier:(NSString*)arg1; 16 | - (id)init; 17 | @end 18 | @interface SBApplication : NSObject 19 | @property(copy, nonatomic) NSArray *staticShortcutItems; 20 | - (NSString*)bundleIdentifier; 21 | @end; 22 | @interface SBApplicationShortcutMenu : UIView 23 | @property(retain, nonatomic) SBApplication *application; 24 | - (void)dismissAnimated:(_Bool)arg1 completionHandler:(id)arg2; 25 | - (id)_shortcutItemsToDisplay; 26 | @end 27 | @interface SpringBoard : UIApplication 28 | - (void)reboot; 29 | - (void)powerDown; 30 | @end 31 | @interface SBApplicationShortcutMenuContentView : UIView 32 | @end 33 | 34 | @interface UIApplicationShortcutIcon() 35 | @end 36 | @interface SBSApplicationShortcutIcon : NSObject 37 | @end 38 | @interface SBSApplicationShortcutItem : NSObject 39 | - (void)setIcon:(id)arg1; 40 | - (void)setLocalizedSubtitle:(id)arg1; 41 | - (void)setLocalizedTitle:(id)arg1; 42 | - (void)setType:(id)arg1; 43 | @end 44 | @interface SBSApplicationShortcutSystemIcon : SBSApplicationShortcutIcon 45 | - (id)initWithType:(UIApplicationShortcutIconType)arg1; 46 | @end 47 | @interface SBSApplicationShortcutCustomImageIcon : SBSApplicationShortcutIcon 48 | - (id)initWithImagePNGData:(id)arg1; 49 | @end 50 | @interface SBSApplicationShortcutContactIcon : SBSApplicationShortcutIcon 51 | -(instancetype)initWithContactIdentifier:(NSString *)contactIdentifier; 52 | -(instancetype)initWithFirstName:(NSString*)firstName lastName:(NSString*)lastName; 53 | -(instancetype)initWithFirstName:(NSString*)firstName lastName:(NSString*)lastName imageData:(NSData*)imageData; 54 | @end 55 | 56 | %hook SBApplicationShortcutStoreManager 57 | - (id)shortcutItemsForBundleIdentifier:(NSString*)arg1 { 58 | NSString *bundleID = arg1; 59 | NSArray *aryItems = [NSArray new]; 60 | if (%orig != NULL || %orig != nil) { 61 | aryItems = %orig; 62 | } 63 | NSMutableArray *aryShortcuts = [aryItems mutableCopy]; 64 | 65 | if ([[BTOShortCutManager sharedInstance] containsBundleID:bundleID] == YES) { 66 | NSArray *aryObjects = [[BTOShortCutManager sharedInstance] shortCutsForAppWithBundleID:bundleID]; 67 | NSMutableArray *correctObjects = [NSMutableArray new]; 68 | 69 | for (NSArray *item in aryObjects) { 70 | SBSApplicationShortcutItem *action = [[SBSApplicationShortcutItem alloc] init]; 71 | if ([[item objectAtIndex:4] intValue] == 7) { 72 | [action setIcon:[[SBSApplicationShortcutCustomImageIcon alloc] initWithImagePNGData:[[BTOShortCutManager sharedInstance] customImageForBundleID:[item objectAtIndex:2] withTitle:[item objectAtIndex:0]]]]; 73 | } else { 74 | [action setIcon:[[SBSApplicationShortcutSystemIcon alloc] initWithType:[[BTOShortCutManager sharedInstance] iconTypeForNumber:[[item objectAtIndex:4] intValue]]]]; 75 | } 76 | [action setLocalizedTitle:[item objectAtIndex:0]]; 77 | if ([[item objectAtIndex:1] isEqualToString:@"*ignore*"]) { 78 | [action setLocalizedSubtitle:nil]; 79 | } else { 80 | [action setLocalizedSubtitle:[item objectAtIndex:1]]; 81 | } 82 | [action setType:[NSString stringWithFormat:@"%@-%@",[item objectAtIndex:2],[item objectAtIndex:0]]]; 83 | [correctObjects addObject:action]; 84 | } 85 | [aryShortcuts addObjectsFromArray:correctObjects]; 86 | } 87 | return aryShortcuts; 88 | } 89 | %end 90 | 91 | %hook SBApplicationShortcutMenuContentView 92 | - (id)initWithInitialFrame:(struct CGRect)arg1 containerBounds:(struct CGRect)arg2 orientation:(long long)arg3 shortcutItems:(NSArray *)arg4 application:(SBApplication*)arg5 { 93 | // NSLog(@"%@",[%c(LAActivator) sharedInstance].availableEventNames); 94 | return %orig; 95 | } 96 | %end 97 | 98 | %hook SBApplicationShortcutMenu 99 | - (id)_shortcutItemsToDisplay { 100 | if (self.application == nil) { 101 | return %orig; 102 | } 103 | NSMutableArray *objects = [NSMutableArray new]; 104 | [objects addObjectsFromArray:self.application.staticShortcutItems]; 105 | [objects addObjectsFromArray:[[%c(SBApplicationShortcutStoreManager) sharedManager] shortcutItemsForBundleIdentifier:self.application.bundleIdentifier]]; 106 | 107 | NSUserDefaults *prefs = [[NSUserDefaults alloc] initWithSuiteName:@"com.bolencki13.customft"]; 108 | if ([prefs boolForKey:@"addMenu"] == YES) { 109 | if ([prefs boolForKey:@"addNotEvery"] == NO) { 110 | SBSApplicationShortcutItem *newAction = [[SBSApplicationShortcutItem alloc] init]; 111 | [newAction setIcon:[[SBSApplicationShortcutSystemIcon alloc] initWithType:UIApplicationShortcutIconTypeAdd]]; 112 | [newAction setLocalizedTitle:@"New"]; 113 | [newAction setLocalizedSubtitle:@"Add New Action"]; 114 | [newAction setType:@"com.bolencki13.customft-newAction"]; 115 | [objects addObject:newAction]; 116 | } else if ([prefs boolForKey:@"addNotEvery"] == YES && [objects count] == 0) { 117 | SBSApplicationShortcutItem *newAction = [[SBSApplicationShortcutItem alloc] init]; 118 | [newAction setIcon:[[SBSApplicationShortcutSystemIcon alloc] initWithType:UIApplicationShortcutIconTypeAdd]]; 119 | [newAction setLocalizedTitle:@"New"]; 120 | [newAction setLocalizedSubtitle:@"Add New Action"]; 121 | [newAction setType:@"com.bolencki13.customft-newAction"]; 122 | [objects addObject:newAction]; 123 | } 124 | } 125 | 126 | return objects; 127 | } 128 | - (void)menuContentView:(id)arg1 activateShortcutItem:(UIApplicationShortcutItem*)arg2 index:(long long)arg3 { 129 | NSString *input = arg2.type; 130 | if ([input isEqualToString:@"com.bolencki13.customft-newAction"]) { 131 | [self dismissAnimated:YES completionHandler:nil]; 132 | BTOAddShortCutViewController *controller = [BTOAddShortCutViewController new]; 133 | UIViewController *rootView = [[UIApplication sharedApplication].keyWindow rootViewController]; 134 | [rootView presentViewController:controller animated:YES completion:^{ 135 | controller.txtBundleID.text = self.application.bundleIdentifier; 136 | }]; 137 | return; 138 | } 139 | NSString *bundleID = @""; 140 | NSString *title = @""; 141 | 142 | if ([input containsString:@"-"]) { 143 | NSArray *arySplitString = [input componentsSeparatedByString:@"-"]; 144 | bundleID = [arySplitString objectAtIndex:0]; 145 | title = [arySplitString objectAtIndex:1]; 146 | } 147 | 148 | if ([[BTOShortCutManager sharedInstance] containsBundleID:bundleID] == YES) { 149 | 150 | NSString *url = [[BTOShortCutManager sharedInstance] getURLSchemeForBundleID:bundleID withTitle:title]; 151 | 152 | if ([url isEqualToString:@"respring"]) { 153 | system("killall backboardd"); 154 | } else if ([url isEqualToString:@"shutdown"]) { 155 | [[%c(SpringBoard) sharedApplication] powerDown]; 156 | } else if ([url isEqualToString:@"reboot"]) { 157 | [[%c(SpringBoard) sharedApplication] reboot]; 158 | } else if ([url isEqualToString:@"safemode"]) { 159 | NSArray *aryTemp = @[@"Crash"]; 160 | NSString *crashTime; 161 | crashTime = [aryTemp objectAtIndex:2]; 162 | } else if ([url containsString:@"shellScript://"]) { 163 | const char *command = [[url stringByReplacingOccurrencesOfString:@"shellScript://" withString:@""] UTF8String]; 164 | system(command); 165 | } else if ([url containsString:@"activator://"]) { 166 | NSString *BTOShortCutActivatorEventName = [url stringByReplacingOccurrencesOfString:@"activator://" withString:@""]; 167 | LAEvent *event = [%c(LAEvent) eventWithName:BTOShortCutActivatorEventName mode:[%c(LAActivator) sharedInstance].currentEventMode]; 168 | [[%c(LAActivator) sharedInstance] sendEventToListener:event]; 169 | } else { 170 | if ([url containsString:@"\%@"]) { 171 | UIAlertController *alert = [UIAlertController 172 | alertControllerWithTitle:@"Traverse" 173 | message:@"Enter Search Parameters" 174 | preferredStyle:UIAlertControllerStyleAlert]; 175 | 176 | UIAlertAction *ok = [UIAlertAction actionWithTitle:@"Search" style:UIAlertActionStyleDefault 177 | handler:^(UIAlertAction * action) { 178 | UITextField *txtInput = [alert.textFields objectAtIndex:0]; 179 | NSString *finalURL = [NSString stringWithFormat:@"%@%@",[url stringByReplacingOccurrencesOfString:@"\%@" withString:@""],[txtInput.text stringByReplacingOccurrencesOfString:@" " withString:@"\%20"]]; 180 | [[%c(SpringBoard) sharedApplication] applicationOpenURL:[NSURL URLWithString:finalURL]]; 181 | }]; 182 | UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel 183 | handler:^(UIAlertAction * action) { 184 | [alert dismissViewControllerAnimated:YES completion:nil]; 185 | }]; 186 | [alert addAction:ok]; 187 | [alert addAction:cancel]; 188 | 189 | [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) { 190 | textField.placeholder = @"Search Text"; 191 | }]; 192 | UIViewController *rootView = [[UIApplication sharedApplication].keyWindow rootViewController]; 193 | [rootView presentViewController:alert animated:YES completion:nil]; 194 | } else { 195 | [[%c(SpringBoard) sharedApplication] applicationOpenURL:[NSURL URLWithString:url]]; 196 | } 197 | } 198 | 199 | [self dismissAnimated:YES completionHandler:nil]; 200 | } else { 201 | %orig; 202 | } 203 | } 204 | %end 205 | 206 | @interface UIVisualEffectView(Private) 207 | - (void)_setEffect:(id)arg1; 208 | @end 209 | %hook SBApplicationShortcutMenuBackgroundView 210 | - (void)layoutSubviews { 211 | %orig; 212 | 213 | if ([[NSFileManager defaultManager] fileExistsAtPath:@"/var/lib/dpkg/info/org.thebigboss.shortcutix.list"]) { 214 | return; 215 | } 216 | 217 | NSUserDefaults *prefs = [[NSUserDefaults alloc] initWithSuiteName:@"com.bolencki13.customft"]; 218 | switch ([prefs integerForKey:@"blur"]) { 219 | case 0: { 220 | UIVisualEffectView *mybackdropView = MSHookIvar(self, "_backdropView"); 221 | [mybackdropView _setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]]; 222 | }break; 223 | case 1:{ 224 | UIVisualEffectView *mybackdropView = MSHookIvar(self, "_backdropView"); 225 | [mybackdropView _setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]]; 226 | }break; 227 | case 2:{ 228 | UIVisualEffectView *mybackdropView = MSHookIvar(self, "_backdropView"); 229 | [mybackdropView _setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]]; 230 | }break; 231 | 232 | default:{ 233 | UIVisualEffectView *mybackdropView = MSHookIvar(self, "_backdropView"); 234 | [mybackdropView _setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]]; 235 | }break; 236 | } 237 | } 238 | %end 239 | 240 | @interface SBApplicationShortcutMenuItemView : UIView 241 | @property(retain, nonatomic) UIApplicationShortcutItem *shortcutItem; // @synthesize shortcutItem=_shortcutItem; 242 | - (UIImage *)invertImage:(UIImage *)image; 243 | - (void)delete:(UILongPressGestureRecognizer *)recognizer; 244 | @end 245 | %hook SBApplicationShortcutMenuItemView 246 | - (id)initWithShortcutItem:(id)arg1 menuPosition:(long long)arg2 orientation:(long long)arg3 application:(id)arg4 assetManagerProvider:(id)arg5 monogrammerProvider:(id)arg6 options:(unsigned long long)arg7 { 247 | UILongPressGestureRecognizer *lpgrDelete = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(delete:)]; 248 | lpgrDelete.minimumPressDuration = 1.0; 249 | [self addGestureRecognizer:lpgrDelete]; 250 | 251 | return %orig; 252 | } 253 | - (void)_setupViewsWithIcon:(id)arg1 title:(id)arg2 subtitle:(id)arg3 { 254 | %orig; 255 | 256 | if ([[NSFileManager defaultManager] fileExistsAtPath:@"/var/lib/dpkg/info/org.thebigboss.shortcutix.list"]) { 257 | return; 258 | } 259 | 260 | UILabel *mytitleLabel = MSHookIvar(self, "_titleLabel"); 261 | 262 | UIImageView *myiconView = MSHookIvar(self, "_iconView"); 263 | if ([[NSString stringWithFormat:@"%@",[mytitleLabel.text lowercaseString]] isEqualToString:@"respring"]) { 264 | myiconView.image = [UIImage imageWithContentsOfFile:@"/Library/Application Support/CustomFT/kCustomFT.bundle/respring.png"]; 265 | } else if ([[NSString stringWithFormat:@"%@",[mytitleLabel.text lowercaseString]] isEqualToString:@"reboot"]) { 266 | myiconView.image = [UIImage imageWithContentsOfFile:@"/Library/Application Support/CustomFT/kCustomFT.bundle/reboot.png"]; 267 | } else if ([[NSString stringWithFormat:@"%@",[mytitleLabel.text lowercaseString]] isEqualToString:@"shutdown"]) { 268 | myiconView.image = [UIImage imageWithContentsOfFile:@"/Library/Application Support/CustomFT/kCustomFT.bundle/powerOff.png"]; 269 | } else if ([[NSString stringWithFormat:@"%@",[mytitleLabel.text lowercaseString]] isEqualToString:@"safemode"] || [[NSString stringWithFormat:@"%@",[mytitleLabel.text lowercaseString]] isEqualToString:@"safe mode"]) { 270 | myiconView.image = [UIImage imageWithContentsOfFile:@"/Library/Application Support/CustomFT/kCustomFT.bundle/safeMode.png"]; 271 | } 272 | 273 | NSUserDefaults *prefs = [[NSUserDefaults alloc] initWithSuiteName:@"com.bolencki13.customft"]; 274 | 275 | if ([prefs integerForKey:@"blur"] == 2) { 276 | UILabel *mytitleLabel = MSHookIvar(self, "_titleLabel"); 277 | UIImageView *myiconView = MSHookIvar(self, "_iconView"); 278 | 279 | mytitleLabel.textColor = [UIColor whiteColor]; 280 | 281 | UILabel *mysubtitleLabel = MSHookIvar(self, "_subtitleLabel"); 282 | mysubtitleLabel.textColor = [UIColor whiteColor]; 283 | 284 | if ([arg3 isEqualToString:@"FaceTime"] || [arg3 isEqualToString:@"home"] || [arg3 isEqualToString:@"work"] || [arg3 isEqualToString:@"iPhone"] || [arg3 isEqualToString:@"mobile"] || [arg3 isEqualToString:@"main"] || [arg3 isEqualToString:@"home fax"] || [arg3 isEqualToString:@"work fax"] || [arg3 isEqualToString:@"pager"] || [arg3 isEqualToString:@"other"]) return; 285 | 286 | myiconView.image = [self invertImage:myiconView.image]; 287 | } 288 | } 289 | %new 290 | - (UIImage *)invertImage:(UIImage *)originalImage { 291 | UIGraphicsBeginImageContext(originalImage.size); 292 | CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy); 293 | CGRect imageRect = CGRectMake(0, 0, originalImage.size.width, originalImage.size.height); 294 | [originalImage drawInRect:imageRect]; 295 | 296 | CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeDifference); 297 | // translate/flip the graphics context (for transforming from CG* coords to UI* coords 298 | CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, originalImage.size.height); 299 | CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0); 300 | //mask the image 301 | CGContextClipToMask(UIGraphicsGetCurrentContext(), imageRect, originalImage.CGImage); 302 | CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(),[UIColor whiteColor].CGColor); 303 | CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, originalImage.size.width, originalImage.size.height)); 304 | UIImage *returnImage = UIGraphicsGetImageFromCurrentImageContext(); 305 | UIGraphicsEndImageContext(); 306 | 307 | return returnImage; 308 | } 309 | %new 310 | - (void)delete:(UILongPressGestureRecognizer *)recognizer { 311 | if (recognizer.state == UIGestureRecognizerStateBegan) { 312 | UIAlertController *deleteMenu = [UIAlertController alertControllerWithTitle:@"Traverse" message:@"Are you sure you want to delete this action?" preferredStyle:UIAlertControllerStyleActionSheet]; 313 | 314 | UIAlertAction *cancelItem = [UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleCancel handler:nil]; 315 | UIAlertAction *confirmItem = [UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { 316 | [[BTOShortCutManager sharedInstance] deleteShortCutWithBundleID:self.shortcutItem.type]; 317 | }]; 318 | [deleteMenu addAction:cancelItem]; 319 | [deleteMenu addAction:confirmItem]; 320 | 321 | UIViewController *rootView = [[UIApplication sharedApplication].keyWindow rootViewController]; 322 | [rootView presentViewController:deleteMenu animated:YES completion:nil]; 323 | } 324 | } 325 | %end 326 | 327 | 328 | 329 | // static NSString *BTO_TraverseEventDummy1 = @"com.bolencki13.traverse.dummy.one"; 330 | // static NSString *BTO_TraverseEventDummy2 = @"com.bolencki13.traverse.dummy.two"; 331 | // static NSString *BTO_TraverseEventDummy3 = @"com.bolencki13.traverse.dummy.three"; 332 | // 333 | // @interface BTO_TraverseEventDataSource: NSObject { 334 | // } 335 | // + (id)sharedInstance; 336 | // @end 337 | // @implementation BTO_TraverseEventDataSource 338 | // + (id)sharedInstance { 339 | // static BTO_TraverseEventDataSource *shared = nil; 340 | // if (!shared) { 341 | // shared = [[BTO_TraverseEventDataSource alloc] init]; 342 | // } 343 | // return shared; 344 | // } 345 | // - (id)init { 346 | // if ((self = [super init])) { 347 | // [[objc_getClass("LAActivator") sharedInstance] registerEventDataSource:self forEventName:BTO_TraverseEventDummy1]; 348 | // [[objc_getClass("LAActivator") sharedInstance] registerEventDataSource:self forEventName:BTO_TraverseEventDummy2]; 349 | // [[objc_getClass("LAActivator") sharedInstance] registerEventDataSource:self forEventName:BTO_TraverseEventDummy3]; 350 | // } 351 | // return self; 352 | // } 353 | // - (void)dealloc { 354 | // if ([[objc_getClass("LAActivator") sharedInstance] isRunningInsideSpringBoard]) { 355 | // [[objc_getClass("LAActivator") sharedInstance] unregisterEventDataSourceWithEventName:BTO_TraverseEventDummy1]; 356 | // [[objc_getClass("LAActivator") sharedInstance] unregisterEventDataSourceWithEventName:BTO_TraverseEventDummy2]; 357 | // [[objc_getClass("LAActivator") sharedInstance] unregisterEventDataSourceWithEventName:BTO_TraverseEventDummy3]; 358 | // } 359 | // [super dealloc]; 360 | // } 361 | // - (NSString *)localizedTitleForEventName:(NSString *)eventName { 362 | // NSString *title = @""; 363 | // 364 | // if ([eventName isEqualToString:BTO_TraverseEventDummy1]) { 365 | // title = @"Dummy One"; 366 | // } else if ([eventName isEqualToString:BTO_TraverseEventDummy2]) { 367 | // title = @"Dummy Two"; 368 | // } else if ([eventName isEqualToString:BTO_TraverseEventDummy3]) { 369 | // title = @"Dummy Three"; 370 | // } 371 | // 372 | // return title; 373 | // } 374 | // - (NSString *)localizedGroupForEventName:(NSString *)eventName { 375 | // return @"Traverse"; 376 | // } 377 | // - (NSString *)localizedDescriptionForEventName:(NSString *)eventName { 378 | // NSString *description = @""; 379 | // 380 | // if ([eventName isEqualToString:BTO_TraverseEventDummy1]) { 381 | // description = @"Dummy Event #1 for Traverse"; 382 | // } else if ([eventName isEqualToString:BTO_TraverseEventDummy2]) { 383 | // description = @"Dummy Event #2 for Traverse"; 384 | // } else if ([eventName isEqualToString:BTO_TraverseEventDummy3]) { 385 | // description = @"Dummy Event #3 for Traverse"; 386 | // } 387 | // 388 | // return description; 389 | // } 390 | // - (BOOL)eventWithNameIsHidden:(NSString *)eventName { 391 | // return NO; 392 | // } 393 | // - (BOOL)eventWithNameRequiresAssignment:(NSString *)eventName { 394 | // return NO; 395 | // } 396 | // - (BOOL)eventWithName:(NSString *)eventName isCompatibleWithMode:(NSString *)eventMode { 397 | // if ([eventMode isEqualToString:@"springboard"]) { 398 | // return YES; 399 | // } 400 | // return NO; 401 | // } 402 | // - (BOOL)eventWithNameSupportsUnlockingDeviceToSend:(NSString *)eventName { 403 | // return NO; 404 | // } 405 | // @end 406 | // %ctor { 407 | // %init; 408 | // [%c(BTO_TraverseEventDataSource) sharedInstance]; 409 | // } 410 | 411 | 412 | 413 | // %hook SpringBoard 414 | // - (void)applicationDidFinishLaunching { 415 | // %orig; 416 | // 417 | // #define INITIAL_SET_UP(file) if ([file isEqualToString:@"/var/lib/dpkg/info/com.bolencki13.customft.list"] || [file isEqualToString:@"/var/lib/dpkg/info/org.thebigboss.customft.list"]) { if([[NSFileManager defaultManager] fileExistsAtPath:file]) { [[[UIAlertView alloc] initWithTitle:@"CustomFT" message:@"Please buy CustomFT. The developer put a lot of effort into it." delegate:nil cancelButtonTitle:@"I'll buy it" otherButtonTitles:nil, nil] show]; } } else { [[[UIAlertView alloc] initWithTitle:@"CustomFT" message:@"Please buy CustomFT. The developer put a lot of effort into it." delegate:nil cancelButtonTitle:@"I'll buy it" otherButtonTitles:nil, nil] show];}; 418 | // #define SET_UP @"/var/lib/dpkg/info/com.bolencki13.customft.list" 419 | // INITIAL_SET_UP(SET_UP); 420 | // #undef INITIAL_SET_UP 421 | // #undef SET_UP 422 | // } 423 | // %end 424 | --------------------------------------------------------------------------------