├── safariswiperprefs ├── obj │ ├── .stamp │ └── SafariSwiperPrefs.bundle │ │ ├── .SafariSwiperPrefs.plist.swp │ │ ├── Info.plist │ │ └── SafariSwiperPrefs.plist ├── .theos │ └── obj │ │ ├── .stamp │ │ ├── arm64 │ │ ├── SafariSwiperPrefs.mm.3b890006.o │ │ └── SafariSwiperPrefs.bundle │ │ │ └── SafariSwiperPrefs │ │ ├── armv7 │ │ ├── SafariSwiperPrefs.mm.ac14d21e.o │ │ └── SafariSwiperPrefs.bundle │ │ │ └── SafariSwiperPrefs │ │ ├── armv7s │ │ ├── SafariSwiperPrefs.mm.717dd89a.o │ │ └── SafariSwiperPrefs.bundle │ │ │ └── SafariSwiperPrefs │ │ └── SafariSwiperPrefs.bundle │ │ ├── SafariSwiperPrefs │ │ ├── SafariSwiperPrefs.png │ │ ├── SafariSwiperPrefs@2x.png │ │ ├── SafariSwiperPrefs@3x.png │ │ ├── .SafariSwiperPrefs.plist.swp │ │ ├── Info.plist │ │ └── SafariSwiperPrefs.plist ├── theos ├── Resources │ ├── SafariSwiperPrefs.png │ ├── SafariSwiperPrefs@2x.png │ ├── SafariSwiperPrefs@3x.png │ ├── .SafariSwiperPrefs.plist.swp │ ├── Info.plist │ └── SafariSwiperPrefs.plist ├── entry.plist ├── SafariSwiperPrefs.mm └── Makefile ├── SafariSwiper.plist ├── layout └── Library │ └── Application Support │ └── SafariSwiper │ └── texture.png ├── control ├── Makefile ├── README.md ├── interface.h └── Tweak.xm /safariswiperprefs/obj/.stamp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/.stamp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /safariswiperprefs/theos: -------------------------------------------------------------------------------- 1 | /Users/sam/Projects/ios/safariswiperOLD/theos -------------------------------------------------------------------------------- /SafariSwiper.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "com.apple.mobilesafari" ); }; } 2 | -------------------------------------------------------------------------------- /safariswiperprefs/Resources/SafariSwiperPrefs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/Resources/SafariSwiperPrefs.png -------------------------------------------------------------------------------- /safariswiperprefs/Resources/SafariSwiperPrefs@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/Resources/SafariSwiperPrefs@2x.png -------------------------------------------------------------------------------- /safariswiperprefs/Resources/SafariSwiperPrefs@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/Resources/SafariSwiperPrefs@3x.png -------------------------------------------------------------------------------- /safariswiperprefs/Resources/.SafariSwiperPrefs.plist.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/Resources/.SafariSwiperPrefs.plist.swp -------------------------------------------------------------------------------- /layout/Library/Application Support/SafariSwiper/texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/layout/Library/Application Support/SafariSwiper/texture.png -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/arm64/SafariSwiperPrefs.mm.3b890006.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/.theos/obj/arm64/SafariSwiperPrefs.mm.3b890006.o -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/armv7/SafariSwiperPrefs.mm.ac14d21e.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/.theos/obj/armv7/SafariSwiperPrefs.mm.ac14d21e.o -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/armv7s/SafariSwiperPrefs.mm.717dd89a.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/.theos/obj/armv7s/SafariSwiperPrefs.mm.717dd89a.o -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/SafariSwiperPrefs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/SafariSwiperPrefs -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/SafariSwiperPrefs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/SafariSwiperPrefs.png -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/arm64/SafariSwiperPrefs.bundle/SafariSwiperPrefs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/.theos/obj/arm64/SafariSwiperPrefs.bundle/SafariSwiperPrefs -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/armv7/SafariSwiperPrefs.bundle/SafariSwiperPrefs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/.theos/obj/armv7/SafariSwiperPrefs.bundle/SafariSwiperPrefs -------------------------------------------------------------------------------- /safariswiperprefs/obj/SafariSwiperPrefs.bundle/.SafariSwiperPrefs.plist.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/obj/SafariSwiperPrefs.bundle/.SafariSwiperPrefs.plist.swp -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/SafariSwiperPrefs@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/SafariSwiperPrefs@2x.png -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/SafariSwiperPrefs@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/SafariSwiperPrefs@3x.png -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/armv7s/SafariSwiperPrefs.bundle/SafariSwiperPrefs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/.theos/obj/armv7s/SafariSwiperPrefs.bundle/SafariSwiperPrefs -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/.SafariSwiperPrefs.plist.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stonesam92/SafariSwiper/HEAD/safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/.SafariSwiperPrefs.plist.swp -------------------------------------------------------------------------------- /safariswiperprefs/entry.plist: -------------------------------------------------------------------------------- 1 | { 2 | entry = { 3 | bundle = SafariSwiperPrefs; 4 | cell = PSLinkCell; 5 | detail = SafariSwiperPrefsListController; 6 | icon = SafariSwiperPrefs.png; 7 | isController = 1; 8 | label = SafariSwiper; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.samstone.safariswiper 2 | Name: SafariSwiper 3 | Depends: mobilesubstrate 4 | Version: 1.0.0 5 | Architecture: iphoneos-arm 6 | Description: Quickly swipe between existing tabs in Safari! 7 | Maintainer: Sam Stone 8 | Author: Sam Stone 9 | Section: Tweaks 10 | -------------------------------------------------------------------------------- /safariswiperprefs/SafariSwiperPrefs.mm: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface SafariSwiperPrefsListController: PSListController { 4 | } 5 | @end 6 | 7 | @implementation SafariSwiperPrefsListController 8 | - (id)specifiers { 9 | if(_specifiers == nil) { 10 | _specifiers = [[self loadSpecifiersFromPlistName:@"SafariSwiperPrefs" target:self] retain]; 11 | } 12 | return _specifiers; 13 | } 14 | @end 15 | 16 | // vim:ft=objc 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DEBUG = 0 2 | GO_EASY_ON_ME = 1 3 | TARGET_IPHONEOS_DEPLOYMENT_VERSION = 8.0 4 | ARCHS = armv7 arm64 armv7s 5 | 6 | include theos/makefiles/common.mk 7 | 8 | TWEAK_NAME = SafariSwiper 9 | SafariSwiper_FILES = Tweak.xm CKBlurView.m 10 | SafariSwiper_FRAMEWORKS = UIKit QuartzCore CoreGraphics 11 | 12 | include $(THEOS_MAKE_PATH)/tweak.mk 13 | 14 | after-install:: 15 | install.exec "killall -9 MobileSafari" 16 | SUBPROJECTS += safariswiperprefs 17 | include $(THEOS_MAKE_PATH)/aggregate.mk 18 | -------------------------------------------------------------------------------- /safariswiperprefs/Makefile: -------------------------------------------------------------------------------- 1 | include theos/makefiles/common.mk 2 | 3 | BUNDLE_NAME = SafariSwiperPrefs 4 | SafariSwiperPrefs_FILES = SafariSwiperPrefs.mm 5 | SafariSwiperPrefs_INSTALL_PATH = /Library/PreferenceBundles 6 | SafariSwiperPrefs_FRAMEWORKS = UIKit 7 | SafariSwiperPrefs_PRIVATE_FRAMEWORKS = Preferences 8 | 9 | include $(THEOS_MAKE_PATH)/bundle.mk 10 | 11 | internal-stage:: 12 | $(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences$(ECHO_END) 13 | $(ECHO_NOTHING)cp entry.plist $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences/SafariSwiperPrefs.plist$(ECHO_END) 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SafariSwiper 2 | Available in Cydia for free now! 3 | 4 | Safari's tab switcher in recent versions of iOS looks great, but all of the animations it performs makes it unnecessarily slow to switch tabs. SafariSwiper allows you to quickly switch between tabs by simply swiping along the toolbar: 5 | 6 | ![Demo GIF](http://giant.gfycat.com/WideRelievedAdouri.gif) 7 | 8 | For a better demonstration see the [product video on YouTube](https://www.youtube.com/watch?v=RWZwAwSYi1Q). 9 | 10 | Built with [theos](https://github.com/DHowett/theos). 11 | 12 | For updates, follow me on Twitter [@CmdShiftN](http://twitter.com/cmdshiftn). 13 | -------------------------------------------------------------------------------- /safariswiperprefs/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | SafariSwiperPrefs 9 | CFBundleIdentifier 10 | com.samstone.safariswiperprefs 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 | SafariSwiperPrefsListController 27 | 28 | 29 | -------------------------------------------------------------------------------- /safariswiperprefs/obj/SafariSwiperPrefs.bundle/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | SafariSwiperPrefs 9 | CFBundleIdentifier 10 | com.samstone.safariswiperprefs 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 | SafariSwiperPrefsListController 27 | 28 | 29 | -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | SafariSwiperPrefs 9 | CFBundleIdentifier 10 | com.samstone.safariswiperprefs 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 | SafariSwiperPrefsListController 27 | 28 | 29 | -------------------------------------------------------------------------------- /interface.h: -------------------------------------------------------------------------------- 1 | 2 | #define CGRectZero CGRectMake(0,0,0,0) 3 | 4 | typedef enum { 5 | SSDirectionLeft, 6 | SSDirectionRight 7 | } SSTabChangeDirection; 8 | 9 | @interface TabDocument 10 | - (NSString *)URLString; 11 | @end 12 | 13 | @interface BrowserToolbar : UIToolbar 14 | - (void)setActionEnabled:(BOOL)enabled; 15 | @end 16 | 17 | @interface TabController : NSObject 18 | - (TabDocument *)activeTabDocument; 19 | - (NSArray *)currentTabDocuments; 20 | - (TabDocument *)tabInDirection:(SSTabChangeDirection)direction; 21 | - (BOOL)canSwitchTabInDirection:(SSTabChangeDirection)direction; 22 | - (void)switchTabInDirection:(SSTabChangeDirection)direction; 23 | - (void)setActiveTabDocument:(TabDocument *)document animated:(BOOL)animated; 24 | @end 25 | 26 | @interface BrowserController : NSObject 27 | - (TabController *)tabController; 28 | + (id)sharedBrowserController; 29 | - (void)setupOverlays; 30 | - (UIView *)newTabView; 31 | @end 32 | 33 | @interface MobileSafariWindow : UIWindow 34 | - (void)commonInit; 35 | @end 36 | 37 | @interface CABackdropLayer : CALayer 38 | @end 39 | 40 | typedef enum _UIBackgroundStyle { 41 | UIBackgroundStyleDefault, 42 | UIBackgroundStyleTransparent, 43 | UIBackgroundStyleLightBlur, 44 | UIBackgroundStyleDarkBlur, 45 | UIBackgroundStyleDarkTranslucent 46 | } UIBackgroundStyle; 47 | 48 | @interface UIApplication (UIBackgroundStyle) 49 | - (void)_setBackgroundStyle:(UIBackgroundStyle)style; 50 | - (void)_setApplicationIsOpaque:(BOOL)opaque; 51 | @end 52 | -------------------------------------------------------------------------------- /safariswiperprefs/obj/SafariSwiperPrefs.bundle/SafariSwiperPrefs.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Changes have effect when you relaunch Safari 12 | 13 | 14 | cell 15 | PSSwitchCell 16 | default 17 | 18 | defaults 19 | com.samstone.safariswiper 20 | key 21 | loopPages 22 | label 23 | Loop between first and last tab 24 | 25 | 26 | cell 27 | PSGroupCell 28 | label 29 | Swipe Sensitivity 30 | 31 | 32 | cell 33 | PSSliderCell 34 | max 35 | 2.0 36 | min 37 | 0.5 38 | showValue 39 | 40 | isContinuous 41 | 42 | key 43 | sensitivity 44 | defaults 45 | com.samstone.safariswiper 46 | default 47 | 1.0 48 | 49 | 50 | title 51 | SafariSwiperPrefs 52 | 53 | 54 | -------------------------------------------------------------------------------- /safariswiperprefs/Resources/SafariSwiperPrefs.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | footerText 11 | When enabled, it is possible to swipe between the first and last tabs. 12 | label 13 | Toggles 14 | 15 | 16 | cell 17 | PSSwitchCell 18 | default 19 | 20 | defaults 21 | com.samstone.safariswiper 22 | key 23 | loopPages 24 | label 25 | Circular Tab List 26 | PostNotification 27 | com.samstone.safariswiper 28 | 29 | 30 | cell 31 | PSGroupCell 32 | label 33 | Sensitivity 34 | footerText 35 | Higher sensitivity values reduces the swipe distance required to trigger the tab switch action. 36 | 37 | 38 | cell 39 | PSSliderCell 40 | max 41 | 2.0 42 | min 43 | 0.7 44 | showValue 45 | 46 | isContinuous 47 | 48 | key 49 | sensitivity 50 | defaults 51 | com.samstone.safariswiper 52 | default 53 | 1.2 54 | PostNotification 55 | com.samstone.safariswiper 56 | 57 | 58 | cell 59 | PSGroupCell 60 | footerText 61 | Copyright 2015 Sam Stone 62 | 63 | 64 | icon 65 | SafariSwiperPrefs 66 | title 67 | SafariSwiper 68 | 69 | 70 | -------------------------------------------------------------------------------- /safariswiperprefs/.theos/obj/SafariSwiperPrefs.bundle/SafariSwiperPrefs.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | footerText 11 | When enabled, it is possible to swipe between the first and last tabs. 12 | label 13 | Toggles 14 | 15 | 16 | cell 17 | PSSwitchCell 18 | default 19 | 20 | defaults 21 | com.samstone.safariswiper 22 | key 23 | loopPages 24 | label 25 | Circular Tab List 26 | PostNotification 27 | com.samstone.safariswiper 28 | 29 | 30 | cell 31 | PSGroupCell 32 | label 33 | Sensitivity 34 | footerText 35 | Higher sensitivity values reduces the swipe distance required to trigger the tab switch action. 36 | 37 | 38 | cell 39 | PSSliderCell 40 | max 41 | 2.0 42 | min 43 | 0.7 44 | showValue 45 | 46 | isContinuous 47 | 48 | key 49 | sensitivity 50 | defaults 51 | com.samstone.safariswiper 52 | default 53 | 1.2 54 | PostNotification 55 | com.samstone.safariswiper 56 | 57 | 58 | cell 59 | PSGroupCell 60 | footerText 61 | Copyright 2015 Sam Stone 62 | 63 | 64 | icon 65 | SafariSwiperPrefs 66 | title 67 | SafariSwiper 68 | 69 | 70 | -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | #import 2 | #import "interface.h" 3 | #import "CKBlurView.h" 4 | #import 5 | #import "substrate.h" 6 | 7 | static BOOL tabLoopingEnabled = YES; 8 | static float sensitivity = 1.0; 9 | 10 | #define PREFS_LOCATION @"/var/mobile/Library/Preferences/com.samstone.safariswiper.plist" 11 | 12 | %hook TabController 13 | %new 14 | - (TabDocument *)tabInDirection:(SSTabChangeDirection)direction { 15 | NSArray *currentTabs = [self currentTabDocuments]; 16 | TabDocument *activeTab = [self activeTabDocument]; 17 | int currentIndex = [currentTabs indexOfObject:activeTab]; 18 | int targetIndex = currentIndex + (direction == SSDirectionLeft ? -1 : 1); 19 | 20 | if (targetIndex >= 0 && targetIndex < currentTabs.count) 21 | return currentTabs[targetIndex]; 22 | else if (tabLoopingEnabled && targetIndex == -1) 23 | return currentTabs[currentTabs.count-1]; 24 | else if (tabLoopingEnabled && targetIndex == currentTabs.count) 25 | return currentTabs[0]; 26 | else 27 | return nil; 28 | } 29 | 30 | %new 31 | - (BOOL)canSwitchTabInDirection:(SSTabChangeDirection)direction { 32 | return [self tabInDirection:direction] != nil; 33 | } 34 | 35 | %new 36 | - (void)switchTabInDirection:(SSTabChangeDirection)direction { 37 | TabDocument *newTab = [self tabInDirection:direction]; 38 | [self setActiveTabDocument:newTab animated:NO]; 39 | } 40 | %end 41 | 42 | %hook BrowserToolbar 43 | 44 | - (BrowserToolbar *)initWithPlacement:(long long)arg1 { 45 | self = %orig; 46 | BrowserController *bc = [%c(BrowserController) sharedBrowserController]; 47 | UIPanGestureRecognizer *gr = [[UIPanGestureRecognizer alloc] initWithTarget:bc 48 | action:@selector(didPan:)]; 49 | [gr addTarget:self action:@selector(didPan:)]; 50 | [self addGestureRecognizer:gr]; 51 | [self setActionEnabled:NO]; 52 | [gr release]; 53 | return self; 54 | } 55 | 56 | %new 57 | - (void)didPan:(UIPanGestureRecognizer *)sender { 58 | UIBarButtonItem *bookmarks = MSHookIvar(self, "_bookmarksItem"); 59 | UIBarButtonItem *newTab = MSHookIvar(self, "_addTabItem"); 60 | if (sender.state == UIGestureRecognizerStateCancelled || 61 | sender.state == UIGestureRecognizerStateEnded || 62 | sender.state == UIGestureRecognizerStateFailed) { 63 | bookmarks.enabled = YES; 64 | newTab.enabled = YES; 65 | [self setActionEnabled:YES]; 66 | } else { 67 | bookmarks.enabled = NO; 68 | newTab.enabled = NO; 69 | [self setActionEnabled:NO]; 70 | } 71 | } 72 | 73 | %end 74 | 75 | %hook BrowserController 76 | %new 77 | - (UIView *)newTabView { 78 | UIView *newTabView; 79 | UIView *pageView = MSHookIvar(self, "_pageView"); 80 | for (UIView *subview in pageView.subviews) { 81 | if ([subview isKindOfClass:[UIScrollView class]]) continue; 82 | if ([subview isKindOfClass:[%c(NavigationBar) class]]) continue; 83 | newTabView = subview; 84 | } 85 | 86 | return newTabView; 87 | } 88 | 89 | %new 90 | - (void)didPan:(UIPanGestureRecognizer *)gr { 91 | UIView *pageView = MSHookIvar(self, "_scrollView").superview.superview; 92 | UIView *newTabView = nil; 93 | if (![[self.tabController activeTabDocument] URLString]) { 94 | newTabView = [self newTabView]; 95 | } 96 | CGPoint translation = [gr translationInView:gr.view]; 97 | SSTabChangeDirection direction = translation.x < 0 ? SSDirectionRight : SSDirectionLeft; 98 | CGRect newFrame = pageView.frame; 99 | [self setupOverlays]; 100 | 101 | if (![self.tabController canSwitchTabInDirection:direction]) { 102 | return; 103 | } else if (gr.state == UIGestureRecognizerStateCancelled || 104 | gr.state == UIGestureRecognizerStateEnded || 105 | gr.state == UIGestureRecognizerStateFailed) { 106 | newFrame.origin.x = 0; 107 | [UIView animateWithDuration:0.2 108 | animations:^{ 109 | pageView.frame = newFrame; 110 | newTabView.frame = newFrame; 111 | }]; 112 | } else if (ABS(translation.x * sensitivity) > pageView.frame.size.width * 0.5) { 113 | gr.enabled = NO; 114 | [self.tabController switchTabInDirection:direction]; 115 | newFrame.origin.x = 0; 116 | [UIView animateWithDuration:0.2 117 | animations:^{ 118 | pageView.frame = newFrame; 119 | } 120 | completion:^(BOOL finished) { 121 | gr.enabled = YES; 122 | }]; 123 | } else { 124 | newFrame.origin.x = translation.x * sensitivity; 125 | pageView.frame = newFrame; 126 | newTabView.frame = newFrame; 127 | } 128 | } 129 | 130 | %new 131 | - (void)setupOverlays { 132 | UIView *pageView = MSHookIvar(self, "_scrollView").superview; 133 | pageView.clipsToBounds = YES; 134 | } 135 | 136 | %end 137 | 138 | %hook MobileSafariWindow 139 | - (id)initWithFrame:(CGRect)frame { 140 | self = %orig; 141 | [self setBackgroundColor:[UIColor clearColor]]; 142 | [[UIApplication sharedApplication] _setApplicationIsOpaque:NO]; 143 | return self; 144 | } 145 | 146 | - (id)initWithCoder:(NSCoder *)coder { 147 | self = %orig; 148 | [self setBackgroundColor:[UIColor clearColor]]; 149 | [[UIApplication sharedApplication] _setApplicationIsOpaque:NO]; 150 | return self; 151 | } 152 | 153 | - (void)setBackgroundColor:(UIColor *)color { 154 | %orig([UIColor clearColor]); 155 | } 156 | %end 157 | 158 | %hook UIApplication 159 | - (void)_setBackgroundStyle:(long long)arg1 { 160 | %orig(UIBackgroundStyleDarkTranslucent); 161 | } 162 | %end 163 | 164 | //reload preferences 165 | void reloadSettings(void) { 166 | NSDictionary *prefs = [NSDictionary dictionaryWithContentsOfFile:PREFS_LOCATION]; 167 | NSNumber *sensitivityObj = prefs[@"sensitivity"]; 168 | NSNumber *loopPages = prefs[@"loopPages"]; 169 | sensitivity = sensitivityObj.floatValue; 170 | tabLoopingEnabled = loopPages.boolValue; 171 | } 172 | 173 | %ctor { 174 | reloadSettings(); 175 | CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter(); 176 | CFStringRef identifier = (__bridge CFStringRef)@"com.samstone.safariswiper"; 177 | CFNotificationCenterAddObserver(center, NULL, (CFNotificationCallback)reloadSettings, 178 | identifier, NULL, CFNotificationSuspensionBehaviorCoalesce); 179 | } 180 | --------------------------------------------------------------------------------