├── Makefile ├── README.md ├── ReachPlayer.plist ├── ReachPlayerContainerView.h ├── ReachPlayerContainerView.xm ├── Tweak.h ├── Tweak.xm ├── control ├── packages ├── .DS_Store └── com.nahtedetihw.reachplayer_2.6_iphoneos-arm.deb └── reachplayerprefs ├── .DS_Store ├── Makefile ├── REACHPLAYERPreferences.h ├── REACHPLAYERPreferences.m ├── Resources ├── ACTIVATION.plist ├── ACTIVATION@2x.png ├── ACTIVATION@3x.png ├── BACKGROUND.plist ├── BACKGROUND@2x.png ├── BACKGROUND@3x.png ├── CHANGELOG.png ├── CHANGELOG@2x.png ├── CHANGELOG@3x.png ├── CHECKMARK.png ├── CHECKMARK@2x.png ├── CHECKMARK@3x.png ├── DefaultContainerArtwork.png ├── ENABLE@2x.png ├── ENABLE@3x.png ├── Info.plist ├── LAYOUT.plist ├── LAYOUT@2x.png ├── LAYOUT@3x.png ├── MISC.plist ├── MISC@2x.png ├── MISC@3x.png ├── PAYPAL.png ├── PAYPAL@2x.png ├── PAYPAL@3x.png ├── Root.plist ├── banner.png ├── changelogControllerIcon.png ├── icon@2x.png ├── icon@3x.png ├── twitter.png ├── twitter@2x.png └── twitter@3x.png └── layout └── Library └── PreferenceLoader └── Preferences └── reachplayerprefs.plist /Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:clang:latest:13.0 2 | INSTALL_TARGET_PROCESSES = SpringBoard 3 | 4 | DEBUG=0 5 | FINALPACKAGE=1 6 | ## THEOS_PACKAGE_SCHEME=rootless 7 | 8 | SYSROOT=$(THEOS)/sdks/iphoneos14.2.sdk 9 | 10 | include $(THEOS)/makefiles/common.mk 11 | 12 | TWEAK_NAME = ReachPlayer 13 | 14 | ReachPlayer_FILES = Tweak.xm ReachPlayerContainerView.xm 15 | ReachPlayer_CFLAGS = -fobjc-arc -Wdeprecated-declarations -Wno-deprecated-declarations 16 | ReachPlayer_PRIVATE_FRAMEWORKS = MediaRemote 17 | 18 | include $(THEOS_MAKE_PATH)/tweak.mk 19 | 20 | after-install:: 21 | install.exec "killall -9 Preferences && killall -9 SpringBoard" 22 | SUBPROJECTS += reachplayerprefs 23 | include $(THEOS_MAKE_PATH)/aggregate.mk 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![download](https://i.ibb.co/K0J9F3K/banner.png) 2 | 3 | # ReachPlayer 4 | 5 | ## Now Playing info in Reachability Window! 6 | 7 | ** ReachPlayer adds a sleek interface to your Reachability Window with the now playing song. ** 8 | 9 | * Join my Discord today to report any issues: https://discord.gg/64kVRNzKnF 10 | 11 | ### Source Code 12 | https://github.com/nahtedetihw/ReachPlayer 13 | 14 | ### Follow 15 | 16 | * [**ETHN**](https://twitter.com/ethanwhited) - follow me for more up to date info, or ask me anything. 17 | 18 | * [**Email**](mailto:ethanwhited2208@gmail.com) - open to any questions or concerns. 19 | -------------------------------------------------------------------------------- /ReachPlayer.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "com.apple.springboard" ); }; } 2 | -------------------------------------------------------------------------------- /ReachPlayerContainerView.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "MediaRemote.h" 4 | 5 | static NSString *preferencesNotification = @"com.nahtedetihw.reachplayerprefs/ReloadPrefs"; 6 | 7 | #define bundlePath ([[NSFileManager defaultManager] fileExistsAtPath:@"/Library/PreferenceBundles/reachplayerprefs.bundle/"] ? @"/Library/PreferenceBundles/reachplayerprefs.bundle/" : @"/var/jb/Library/PreferenceBundles/reachplayerprefs.bundle/") 8 | 9 | #define plistPath ([[NSFileManager defaultManager] fileExistsAtPath:@"/var/mobile/Library/Preferences/com.nahtedetihw.reachplayerprefs.plist"] ? @"/var/mobile/Library/Preferences/com.nahtedetihw.reachplayerprefs.plist" : @"/var/jb/var/mobile/Library/Preferences/com.nahtedetihw.reachplayerprefs.plist") 10 | 11 | double positionXRP, positionYRP, artworkSizeRP, reachOffsetRP; 12 | NSInteger layoutStyleRP, blurStyleRP; 13 | 14 | static void loadPreferences() { 15 | NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:plistPath]; 16 | 17 | positionXRP = dict[@"positionX"] ? [dict[@"positionX"] doubleValue] : 0; 18 | positionYRP = dict[@"positionY"] ? [dict[@"positionY"] doubleValue] : 0; 19 | artworkSizeRP = dict[@"artworkSize"] ? [dict[@"artworkSize"] doubleValue] : 160.0; 20 | 21 | layoutStyleRP = dict[@"layoutStyle"] ? [dict[@"layoutStyle"] integerValue] : 0; 22 | blurStyleRP = dict[@"blurStyle"] ? [dict[@"blurStyle"] integerValue] : 0; 23 | } 24 | 25 | @interface _UIBackdropView : UIView 26 | @property (assign,nonatomic) BOOL blurRadiusSetOnce; 27 | @property (nonatomic,copy) NSString * _blurQuality; 28 | @property (assign,nonatomic) double _blurRadius; 29 | -(id)initWithFrame:(CGRect)arg1 autosizesToFitSuperview:(BOOL)arg2 settings:(id)arg3 ; 30 | -(id)initWithSettings:(id)arg1 ; 31 | @end 32 | 33 | @interface _UIBackdropViewSettings : NSObject 34 | +(id)settingsForStyle:(long long)arg1 ; 35 | @end 36 | 37 | @interface UILabel (RP) 38 | - (void)setMarqueeRunning:(BOOL)arg1; 39 | - (void)setMarqueeEnabled:(BOOL)arg1; 40 | - (BOOL)marqueeEnabled; 41 | - (BOOL)marqueeRunning; 42 | @end 43 | 44 | @interface ReachPlayerArtworkContainerView : UIView 45 | @property (nonatomic, strong) UIImageView *artworkView; 46 | @end 47 | 48 | @implementation ReachPlayerArtworkContainerView 49 | @end 50 | 51 | @interface ReachPlayerContainerView : UIView 52 | @property (nonatomic, retain) UIImageView *backgroundImageView; 53 | @property (nonatomic, retain) _UIBackdropView *backgroundBlurView; 54 | @property (nonatomic, retain) ReachPlayerArtworkContainerView *artworkContainerView; 55 | @property (nonatomic, retain) UILabel *nowPlayingInfoSong; 56 | @property (nonatomic, retain) UILabel *nowPlayingInfoArtist; 57 | @property (nonatomic, retain) UILabel *nowPlayingInfoAlbum; 58 | @property (nonatomic, retain) UIStackView *labelsStackView; 59 | @property (nonatomic, retain) UIButton *playPauseButton; 60 | @property (nonatomic, retain) UIButton *nextButton; 61 | @property (nonatomic, retain) UIButton *previousButton; 62 | @property (nonatomic, retain) UIStackView *controlsStackView; 63 | - (void)addBackgroundImage; 64 | - (void)addBackgroundBlur; 65 | - (void)addArtworkContainerView; 66 | - (void)addNowPlayingInfoSong; 67 | - (void)addNowPlayingInfoAlbum; 68 | - (void)addPlayPauseButton; 69 | - (void)addNextButton; 70 | - (void)addPreviousButton; 71 | - (void)playingDidChange:(NSNotification *)notification; 72 | - (void)updateTransition; 73 | - (void)playPause; 74 | -(void)next; 75 | -(void)previous; 76 | - (void)updateImage; 77 | - (void)addLabelsStackView; 78 | - (void)addControlsStackView; 79 | @end 80 | -------------------------------------------------------------------------------- /ReachPlayerContainerView.xm: -------------------------------------------------------------------------------- 1 | #import "ReachPlayerContainerView.h" 2 | 3 | @implementation ReachPlayerContainerView 4 | - (instancetype)init { 5 | self = [super init]; 6 | if (self) { 7 | [self addBackgroundImage]; 8 | [self addBackgroundBlur]; 9 | [self addArtworkContainerView]; 10 | [self addLabelsStackView]; 11 | [self addControlsStackView]; 12 | [self updateImage]; 13 | [self updateTransition]; 14 | 15 | if (self.nowPlayingInfoSong.text == nil) { 16 | [self setHidden:YES]; 17 | } else { 18 | [self setHidden:NO]; 19 | } 20 | 21 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 22 | [notificationCenter addObserver:self selector:@selector(updateImage) name:(__bridge NSString *)kMRMediaRemoteNowPlayingInfoDidChangeNotification object:nil]; 23 | [notificationCenter postNotificationName:(__bridge NSString *)kMRMediaRemoteNowPlayingInfoDidChangeNotification object:nil]; 24 | 25 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playingDidChange:) name:(__bridge NSString *)kMRMediaRemoteNowPlayingApplicationPlaybackStateDidChangeNotification object:nil]; 26 | [[NSNotificationCenter defaultCenter] postNotificationName:(__bridge NSString *)kMRMediaRemoteNowPlayingApplicationPlaybackStateDidChangeNotification object:nil]; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)addBackgroundImage { 32 | self.backgroundImageView = [[UIImageView alloc] initWithFrame:self.bounds]; 33 | self.backgroundImageView.contentMode = UIViewContentModeScaleAspectFill; 34 | [self addSubview:self.backgroundImageView]; 35 | 36 | self.backgroundImageView.translatesAutoresizingMaskIntoConstraints = false; 37 | [self.backgroundImageView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:0].active = YES; 38 | [self.backgroundImageView.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:0].active = YES; 39 | [self.backgroundImageView.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:0].active = YES; 40 | [self.backgroundImageView.topAnchor constraintEqualToAnchor:self.topAnchor constant:0].active = YES; 41 | } 42 | 43 | - (void)addBackgroundBlur { 44 | _UIBackdropViewSettings *settings; 45 | if (blurStyleRP == 0) { 46 | settings = [_UIBackdropViewSettings settingsForStyle:4005]; 47 | } else if (blurStyleRP == 1) { 48 | settings = [_UIBackdropViewSettings settingsForStyle:2]; 49 | } else if (blurStyleRP == 2) { 50 | settings = [_UIBackdropViewSettings settingsForStyle:4000]; 51 | } 52 | 53 | self.backgroundBlurView = [[_UIBackdropView alloc] initWithSettings:settings]; 54 | self.backgroundBlurView.frame = self.backgroundImageView.frame; 55 | [self insertSubview:self.backgroundBlurView aboveSubview:self.backgroundImageView]; 56 | 57 | self.backgroundBlurView.translatesAutoresizingMaskIntoConstraints = false; 58 | [self.backgroundBlurView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:0].active = YES; 59 | [self.backgroundBlurView.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:0].active = YES; 60 | [self.backgroundBlurView.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:0].active = YES; 61 | [self.backgroundBlurView.topAnchor constraintEqualToAnchor:self.topAnchor constant:0].active = YES; 62 | } 63 | 64 | - (void)addArtworkContainerView { 65 | self.artworkContainerView = [[ReachPlayerArtworkContainerView alloc] initWithFrame:CGRectMake(0,0,artworkSizeRP,artworkSizeRP)]; 66 | self.artworkContainerView.contentMode = UIViewContentModeScaleAspectFill; 67 | self.artworkContainerView.layer.masksToBounds = YES; 68 | self.artworkContainerView.layer.cornerCurve = kCACornerCurveContinuous; 69 | self.artworkContainerView.layer.cornerRadius = self.artworkContainerView.frame.size.height/16; 70 | [self addSubview:self.artworkContainerView]; 71 | 72 | self.artworkContainerView.translatesAutoresizingMaskIntoConstraints = false; 73 | [self.artworkContainerView.widthAnchor constraintEqualToConstant:artworkSizeRP].active = true; 74 | [self.artworkContainerView.heightAnchor constraintEqualToConstant:artworkSizeRP].active = true; 75 | if (layoutStyleRP == 0) { 76 | [self.artworkContainerView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor constant:positionXRP-(artworkSizeRP/2)-15].active = true; 77 | [self.artworkContainerView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor constant:positionYRP+(artworkSizeRP/2)].active = true; 78 | } else if (layoutStyleRP == 1) { 79 | [self.artworkContainerView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor constant:positionXRP].active = true; 80 | [self.artworkContainerView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor constant:positionYRP+(artworkSizeRP/2)].active = true; 81 | } 82 | 83 | self.artworkContainerView.artworkView = [[UIImageView alloc] initWithFrame:CGRectMake(0,self.center.y-positionYRP,artworkSizeRP,artworkSizeRP)]; 84 | self.artworkContainerView.artworkView.contentMode = UIViewContentModeScaleAspectFill; 85 | self.artworkContainerView.artworkView.layer.masksToBounds = YES; 86 | self.artworkContainerView.artworkView.layer.cornerCurve = kCACornerCurveContinuous; 87 | self.artworkContainerView.artworkView.layer.cornerRadius = self.artworkContainerView.frame.size.height/16; 88 | [self.artworkContainerView insertSubview:self.artworkContainerView.artworkView atIndex:1]; 89 | 90 | self.artworkContainerView.artworkView.translatesAutoresizingMaskIntoConstraints = false; 91 | [self.artworkContainerView.artworkView.widthAnchor constraintEqualToConstant:artworkSizeRP].active = true; 92 | [self.artworkContainerView.artworkView.heightAnchor constraintEqualToConstant:artworkSizeRP].active = true; 93 | [self.artworkContainerView.artworkView.centerXAnchor constraintEqualToAnchor:self.artworkContainerView.centerXAnchor constant:0].active = true; 94 | [self.artworkContainerView.artworkView.centerYAnchor constraintEqualToAnchor:self.artworkContainerView.centerYAnchor constant:0].active = true; 95 | } 96 | 97 | - (void)addNowPlayingInfoSong { 98 | self.nowPlayingInfoSong = [[UILabel alloc] init]; 99 | [self.nowPlayingInfoSong setMarqueeRunning:YES]; 100 | [self.nowPlayingInfoSong setMarqueeEnabled:YES]; 101 | if (layoutStyleRP == 0) { 102 | self.nowPlayingInfoSong.textAlignment = NSTextAlignmentLeft; 103 | } else if (layoutStyleRP == 1) { 104 | self.nowPlayingInfoSong.textAlignment = NSTextAlignmentCenter; 105 | } 106 | self.nowPlayingInfoSong.font = [UIFont boldSystemFontOfSize:20]; 107 | self.nowPlayingInfoSong.frame = CGRectMake(0, 0, 150, 20); 108 | if (blurStyleRP == 2) { 109 | self.nowPlayingInfoSong.textColor = [UIColor blackColor]; 110 | } else { 111 | self.nowPlayingInfoSong.textColor = [UIColor whiteColor]; 112 | } 113 | self.nowPlayingInfoSong.clipsToBounds = NO; 114 | self.nowPlayingInfoSong.isAccessibilityElement = YES; 115 | self.nowPlayingInfoSong.accessibilityHint = @"Name of the currently playing song."; 116 | [self.labelsStackView addArrangedSubview:self.nowPlayingInfoSong]; 117 | 118 | self.nowPlayingInfoSong.translatesAutoresizingMaskIntoConstraints = false; 119 | [self.nowPlayingInfoSong.widthAnchor constraintEqualToConstant:150].active = true; 120 | [self.nowPlayingInfoSong.heightAnchor constraintEqualToConstant:20].active = true; 121 | } 122 | 123 | - (void)addNowPlayingInfoArtist { 124 | self.nowPlayingInfoArtist = [[UILabel alloc] init]; 125 | [self.nowPlayingInfoArtist setMarqueeRunning:YES]; 126 | [self.nowPlayingInfoArtist setMarqueeEnabled:YES]; 127 | if (layoutStyleRP == 0) { 128 | self.nowPlayingInfoArtist.textAlignment = NSTextAlignmentLeft; 129 | } else if (layoutStyleRP == 1) { 130 | self.nowPlayingInfoArtist.textAlignment = NSTextAlignmentCenter; 131 | } 132 | self.nowPlayingInfoArtist.font = [UIFont boldSystemFontOfSize:14]; 133 | self.nowPlayingInfoArtist.frame = CGRectMake(0, 0, 150, 20); 134 | self.nowPlayingInfoArtist.alpha = 0.6; 135 | if (blurStyleRP == 2) { 136 | self.nowPlayingInfoArtist.textColor = [UIColor blackColor]; 137 | } else { 138 | self.nowPlayingInfoArtist.textColor = [UIColor whiteColor]; 139 | } 140 | self.nowPlayingInfoArtist.clipsToBounds = NO; 141 | self.nowPlayingInfoArtist.isAccessibilityElement = YES; 142 | self.nowPlayingInfoArtist.accessibilityHint = @"Name of the currently playing artist."; 143 | [self.labelsStackView addArrangedSubview:self.nowPlayingInfoArtist]; 144 | 145 | self.nowPlayingInfoArtist.translatesAutoresizingMaskIntoConstraints = false; 146 | [self.nowPlayingInfoArtist.widthAnchor constraintEqualToConstant:150].active = true; 147 | [self.nowPlayingInfoArtist.heightAnchor constraintEqualToConstant:20].active = true; 148 | } 149 | 150 | - (void)addNowPlayingInfoAlbum { 151 | self.nowPlayingInfoAlbum = [[UILabel alloc] init]; 152 | [self.nowPlayingInfoAlbum setMarqueeRunning:YES]; 153 | [self.nowPlayingInfoAlbum setMarqueeEnabled:YES]; 154 | if (layoutStyleRP == 0) { 155 | self.nowPlayingInfoAlbum.textAlignment = NSTextAlignmentLeft; 156 | } else if (layoutStyleRP == 1) { 157 | self.nowPlayingInfoAlbum.textAlignment = NSTextAlignmentCenter; 158 | } 159 | self.nowPlayingInfoAlbum.font = [UIFont systemFontOfSize:14]; 160 | self.nowPlayingInfoAlbum.frame = CGRectMake(0, 0, 150, 20); 161 | self.nowPlayingInfoAlbum.alpha = 0.2; 162 | if (blurStyleRP == 2) { 163 | self.nowPlayingInfoAlbum.textColor = [UIColor blackColor]; 164 | } else { 165 | self.nowPlayingInfoAlbum.textColor = [UIColor whiteColor]; 166 | } 167 | self.nowPlayingInfoAlbum.clipsToBounds = NO; 168 | self.nowPlayingInfoAlbum.isAccessibilityElement = YES; 169 | self.nowPlayingInfoAlbum.accessibilityHint = @"Name of the currently playing album."; 170 | [self.labelsStackView addArrangedSubview:self.nowPlayingInfoAlbum]; 171 | 172 | self.nowPlayingInfoAlbum.translatesAutoresizingMaskIntoConstraints = false; 173 | [self.nowPlayingInfoAlbum.widthAnchor constraintEqualToConstant:150].active = true; 174 | [self.nowPlayingInfoAlbum.heightAnchor constraintEqualToConstant:20].active = true; 175 | } 176 | 177 | - (void)addLabelsStackView { 178 | self.labelsStackView = [UIStackView new]; 179 | self.labelsStackView.frame = CGRectMake(self.center.x+positionXRP+75, self.center.y+positionYRP+30, 150, 60); 180 | self.labelsStackView.transform = CGAffineTransformMakeScale(0.8, 0.8); 181 | self.labelsStackView.axis = UILayoutConstraintAxisVertical; 182 | self.labelsStackView.alignment = UIStackViewAlignmentFill; 183 | self.labelsStackView.distribution = UIStackViewDistributionEqualSpacing; 184 | self.labelsStackView.spacing = 5; 185 | self.labelsStackView.layoutMarginsRelativeArrangement = YES; 186 | [self addNowPlayingInfoSong]; 187 | [self addNowPlayingInfoArtist]; 188 | [self addNowPlayingInfoAlbum]; 189 | self.labelsStackView.translatesAutoresizingMaskIntoConstraints = false; 190 | [self addSubview:self.labelsStackView]; 191 | self.labelsStackView.translatesAutoresizingMaskIntoConstraints = false; 192 | [self.labelsStackView.heightAnchor constraintEqualToConstant:60].active = true; 193 | [self.labelsStackView.widthAnchor constraintEqualToConstant:150].active = true; 194 | if (layoutStyleRP == 0) { 195 | [self.labelsStackView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor constant:positionXRP+75].active = true; 196 | [self.labelsStackView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor constant:positionYRP+40].active = true; 197 | } else if (layoutStyleRP == 1) { 198 | [self.labelsStackView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor constant:positionXRP].active = true; 199 | [self.labelsStackView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor constant:positionYRP+artworkSizeRP+30+10].active = true; 200 | } 201 | } 202 | 203 | - (void)addPreviousButton { 204 | self.previousButton = [UIButton buttonWithType:UIButtonTypeCustom]; 205 | self.previousButton.frame = CGRectMake(0, 0, 27, 12); 206 | [self.previousButton setTitle:@"" forState:UIControlStateNormal]; 207 | [self.previousButton setImage:[[UIImage systemImageNamed:@"backward.fill"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; 208 | if (blurStyleRP == 2) { 209 | self.previousButton.tintColor = [UIColor blackColor]; 210 | } else { 211 | self.previousButton.tintColor = [UIColor whiteColor]; 212 | } 213 | [self.previousButton addTarget:self 214 | action:@selector(previous) 215 | forControlEvents:UIControlEventTouchUpInside]; 216 | self.previousButton.isAccessibilityElement = YES; 217 | self.previousButton.accessibilityHint = @"Next Song Button."; 218 | self.previousButton.imageView.contentMode = UIViewContentModeScaleAspectFit; 219 | self.previousButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill; 220 | self.previousButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill; 221 | [self.previousButton setContentMode:UIViewContentModeCenter]; 222 | [self.controlsStackView addArrangedSubview:self.previousButton]; 223 | 224 | self.previousButton.translatesAutoresizingMaskIntoConstraints = false; 225 | [self.previousButton.widthAnchor constraintEqualToConstant:32].active = true; 226 | [self.previousButton.heightAnchor constraintEqualToConstant:12].active = true; 227 | } 228 | 229 | - (void)addPlayPauseButton { 230 | self.playPauseButton = [UIButton buttonWithType:UIButtonTypeCustom]; 231 | [self.playPauseButton setTitle:@"" forState:UIControlStateNormal]; 232 | self.playPauseButton.frame = CGRectMake(0, 0, 20, 23); 233 | if (blurStyleRP == 2) { 234 | self.playPauseButton.tintColor = [UIColor blackColor]; 235 | } else { 236 | self.playPauseButton.tintColor = [UIColor whiteColor]; 237 | } 238 | 239 | [self.playPauseButton addTarget:self 240 | action:@selector(playPause) 241 | forControlEvents:UIControlEventTouchUpInside]; 242 | self.playPauseButton.isAccessibilityElement = YES; 243 | self.playPauseButton.accessibilityHint = @"Play Pause Song Button."; 244 | self.playPauseButton.imageView.contentMode = UIViewContentModeScaleAspectFit; 245 | self.playPauseButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill; 246 | self.playPauseButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill; 247 | [self.playPauseButton setContentMode:UIViewContentModeCenter]; 248 | [self.controlsStackView addArrangedSubview:self.playPauseButton]; 249 | 250 | self.playPauseButton.translatesAutoresizingMaskIntoConstraints = false; 251 | [self.playPauseButton.widthAnchor constraintEqualToConstant:25].active = true; 252 | [self.playPauseButton.heightAnchor constraintEqualToConstant:28].active = true; 253 | } 254 | 255 | - (void)addNextButton { 256 | self.nextButton = [UIButton buttonWithType:UIButtonTypeCustom]; 257 | self.nextButton.frame = CGRectMake(0, 0, 27, 12); 258 | [self.nextButton setTitle:@"" forState:UIControlStateNormal]; 259 | [self.nextButton setImage:[[UIImage systemImageNamed:@"forward.fill"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; 260 | if (blurStyleRP == 2) { 261 | self.nextButton.tintColor = [UIColor blackColor]; 262 | } else { 263 | self.nextButton.tintColor = [UIColor whiteColor]; 264 | } 265 | [self.nextButton addTarget:self 266 | action:@selector(next) 267 | forControlEvents:UIControlEventTouchUpInside]; 268 | self.nextButton.isAccessibilityElement = YES; 269 | self.nextButton.accessibilityHint = @"Next Song Button."; 270 | self.nextButton.imageView.contentMode = UIViewContentModeScaleAspectFit; 271 | self.nextButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill; 272 | self.nextButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill; 273 | [self.nextButton setContentMode:UIViewContentModeCenter]; 274 | [self.controlsStackView addArrangedSubview:self.nextButton]; 275 | 276 | self.nextButton.translatesAutoresizingMaskIntoConstraints = false; 277 | [self.nextButton.widthAnchor constraintEqualToConstant:32].active = true; 278 | [self.nextButton.heightAnchor constraintEqualToConstant:12].active = true; 279 | } 280 | 281 | - (void)addControlsStackView { 282 | self.controlsStackView = [UIStackView new]; 283 | self.controlsStackView.frame = CGRectMake(self.center.x+positionXRP+47,self.center.y+positionYRP+28.5,94,57); 284 | self.controlsStackView.transform = CGAffineTransformMakeScale(0.8, 0.8); 285 | self.controlsStackView.axis = UILayoutConstraintAxisHorizontal; 286 | self.controlsStackView.alignment = UIStackViewAlignmentFill; 287 | self.controlsStackView.distribution = UIStackViewDistributionEqualSpacing; 288 | self.controlsStackView.spacing = 25; 289 | self.controlsStackView.layoutMarginsRelativeArrangement = YES; 290 | self.controlsStackView.translatesAutoresizingMaskIntoConstraints = false; 291 | [self addPreviousButton]; 292 | [self addPlayPauseButton]; 293 | [self addNextButton]; 294 | [self addSubview:self.controlsStackView]; 295 | self.controlsStackView.translatesAutoresizingMaskIntoConstraints = false; 296 | [self.controlsStackView.heightAnchor constraintEqualToConstant:28].active = true; 297 | [self.controlsStackView.widthAnchor constraintEqualToConstant:144].active = true; 298 | if (layoutStyleRP == 0) { 299 | [self.controlsStackView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor constant:positionXRP+72].active = true; 300 | [self.controlsStackView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor constant:positionYRP+60+10+14].active = true; 301 | } else if (layoutStyleRP == 1) { 302 | [self.controlsStackView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor constant:positionXRP].active = true; 303 | [self.controlsStackView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor constant:positionYRP+artworkSizeRP+70+10+14].active = true; 304 | } 305 | } 306 | 307 | - (void)playingDidChange:(NSNotification *)notification { 308 | MRMediaRemoteGetNowPlayingApplicationIsPlaying(dispatch_get_main_queue(), ^(Boolean isPlayingNow){ 309 | if (isPlayingNow == YES) { 310 | [self.playPauseButton setBackgroundImage:[[UIImage systemImageNamed:@"pause.fill"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; 311 | } else { 312 | [self.playPauseButton setBackgroundImage:[[UIImage systemImageNamed:@"play.fill"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; 313 | } 314 | }); 315 | } 316 | 317 | - (void)updateTransition { 318 | CATransition *transition = [CATransition animation]; 319 | transition.duration = 1.0f; 320 | transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 321 | transition.type = kCATransitionFade; 322 | 323 | [self.artworkContainerView.artworkView.layer addAnimation:transition forKey:nil]; 324 | 325 | CATransition *transitionBG = [CATransition animation]; 326 | transitionBG.duration = 1.0f; 327 | transitionBG.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 328 | transitionBG.type = kCATransitionFade; 329 | 330 | [self.backgroundImageView.layer addAnimation:transitionBG forKey:nil]; 331 | } 332 | 333 | - (void)playPause { 334 | MRMediaRemoteSendCommand(kMRTogglePlayPause, nil); 335 | AudioServicesPlaySystemSound(1519); 336 | } 337 | 338 | -(void)next { 339 | MRMediaRemoteSendCommand(kMRNextTrack, nil); 340 | AudioServicesPlaySystemSound(1519); 341 | } 342 | 343 | -(void)previous { 344 | MRMediaRemoteSendCommand(kMRPreviousTrack, nil); 345 | AudioServicesPlaySystemSound(1519); 346 | } 347 | 348 | - (void)updateImage { 349 | MRMediaRemoteGetNowPlayingInfo(dispatch_get_main_queue(), ^(CFDictionaryRef result) { 350 | if (result) { 351 | NSDictionary *dictionary = (__bridge NSDictionary *)result; 352 | NSString *songName = dictionary[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoTitle]; 353 | NSString *artistName = dictionary[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtist]; 354 | NSString *albumName = dictionary[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoAlbum]; 355 | NSData *artworkData = [dictionary objectForKey:(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtworkData]; 356 | 357 | if (artworkData != nil) { 358 | self.artworkContainerView.artworkView.image = [UIImage imageWithData:artworkData]; 359 | self.backgroundImageView.image = [UIImage imageWithData:artworkData]; 360 | [self updateTransition]; 361 | } 362 | 363 | if (songName != nil) { 364 | self.nowPlayingInfoSong.text = [NSString stringWithFormat:@"%@", songName]; 365 | self.nowPlayingInfoSong.accessibilityLabel = [NSString stringWithFormat:@"%@", songName]; 366 | [self setHidden:NO]; 367 | } else { 368 | self.nowPlayingInfoSong.text = @" "; 369 | self.nowPlayingInfoSong.accessibilityLabel = @" "; 370 | [self setHidden:YES]; 371 | } 372 | 373 | if (artistName != nil) { 374 | self.nowPlayingInfoArtist.text = [NSString stringWithFormat:@"%@", artistName]; 375 | self.nowPlayingInfoArtist.accessibilityLabel = [NSString stringWithFormat:@"%@", songName]; 376 | } else { 377 | self.nowPlayingInfoArtist.text = @" "; 378 | self.nowPlayingInfoArtist.accessibilityLabel = @" "; 379 | } 380 | 381 | if (albumName != nil) { 382 | self.nowPlayingInfoAlbum.text = [NSString stringWithFormat:@"%@", albumName]; 383 | self.nowPlayingInfoAlbum.accessibilityLabel = [NSString stringWithFormat:@"%@", songName]; 384 | } else { 385 | self.nowPlayingInfoAlbum.text = @" "; 386 | self.nowPlayingInfoAlbum.accessibilityLabel = @" "; 387 | } 388 | } else { 389 | self.artworkContainerView.artworkView.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@DefaultContainerArtwork.png", bundlePath]]; 390 | self.backgroundImageView.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@DefaultContainerArtwork.png", bundlePath]]; 391 | } 392 | }); 393 | } 394 | @end 395 | 396 | %ctor { 397 | BOOL shouldLoad = NO; 398 | NSArray *args = [[NSClassFromString(@"NSProcessInfo") processInfo] arguments]; 399 | NSUInteger count = args.count; 400 | if (count != 0) { 401 | NSString *executablePath = args[0]; 402 | if (executablePath) { 403 | NSString *processName = [executablePath lastPathComponent]; 404 | BOOL isSpringBoard = [processName isEqualToString:@"SpringBoard"]; 405 | BOOL isPreferences = [processName isEqualToString:@"Preferences"]; 406 | BOOL isApplication = [executablePath rangeOfString:@"/Application/"].location != NSNotFound || [executablePath rangeOfString:@"/Applications/"].location != NSNotFound; 407 | BOOL isFileProvider = [[processName lowercaseString] rangeOfString:@"fileprovider"].location != NSNotFound; 408 | BOOL skip = [processName isEqualToString:@"AdSheet"] 409 | || [processName isEqualToString:@"CoreAuthUI"] 410 | || [processName isEqualToString:@"InCallService"] 411 | || [processName isEqualToString:@"MessagesNotificationViewService"] 412 | || [executablePath rangeOfString:@".appex/"].location != NSNotFound; 413 | if (!isFileProvider && (isSpringBoard || isApplication || isPreferences) && !skip) { 414 | shouldLoad = YES; 415 | } 416 | } 417 | } 418 | if (shouldLoad) { 419 | 420 | loadPreferences(); // Load prefs 421 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)loadPreferences, (CFStringRef)preferencesNotification, NULL, CFNotificationSuspensionBehaviorCoalesce); 422 | } 423 | } 424 | -------------------------------------------------------------------------------- /Tweak.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #define plistPath ([[NSFileManager defaultManager] fileExistsAtPath:@"/var/mobile/Library/Preferences/com.nahtedetihw.reachplayerprefs.plist"] ? @"/var/mobile/Library/Preferences/com.nahtedetihw.reachplayerprefs.plist" : @"/var/jb/var/mobile/Library/Preferences/com.nahtedetihw.reachplayerprefs.plist") 4 | 5 | static NSString *preferencesNotification = @"com.nahtedetihw.reachplayerprefs/ReloadPrefs"; 6 | 7 | BOOL enable, enableBlur; 8 | double chevronOpacity, keepAliveDuration, positionX, positionY, artworkSize, reachOffset; 9 | NSInteger layoutStyle, blurStyle, activationStyle; 10 | 11 | static void loadPreferences() { 12 | NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:plistPath]; 13 | 14 | enable = dict[@"enable"] ? [dict[@"enable"] boolValue] : NO; 15 | enableBlur = dict[@"enableBlur"] ? [dict[@"enableBlur"] boolValue] : NO; 16 | 17 | chevronOpacity = dict[@"chevronOpacity"] ? [dict[@"chevronOpacity"] doubleValue] : 1.0; 18 | keepAliveDuration = dict[@"keepAliveDuration"] ? [dict[@"keepAliveDuration"] doubleValue] : 0.8; 19 | positionX = dict[@"positionX"] ? [dict[@"positionX"] doubleValue] : 0; 20 | positionY = dict[@"positionY"] ? [dict[@"positionY"] doubleValue] : 0; 21 | artworkSize = dict[@"artworkSize"] ? [dict[@"artworkSize"] doubleValue] : 160.0; 22 | reachOffset = dict[@"reachOffset"] ? [dict[@"reachOffset"] doubleValue] : 0.4; 23 | 24 | layoutStyle = dict[@"layoutStyle"] ? [dict[@"layoutStyle"] integerValue] : 0; 25 | blurStyle = dict[@"blurStyle"] ? [dict[@"blurStyle"] integerValue] : 0; 26 | activationStyle = dict[@"activationStyle"] ? [dict[@"activationStyle"] integerValue] : 0; 27 | } 28 | 29 | @interface SBLockScreenManager : NSObject 30 | +(id)sharedInstance; 31 | -(BOOL)isScreenOn; 32 | @end 33 | 34 | @interface _UIBackdropView : UIView 35 | @property (assign,nonatomic) BOOL blurRadiusSetOnce; 36 | @property (nonatomic,copy) NSString * _blurQuality; 37 | @property (assign,nonatomic) double _blurRadius; 38 | -(id)initWithFrame:(CGRect)arg1 autosizesToFitSuperview:(BOOL)arg2 settings:(id)arg3 ; 39 | -(id)initWithSettings:(id)arg1 ; 40 | @end 41 | 42 | @interface _UIBackdropViewSettings : NSObject 43 | +(id)settingsForStyle:(long long)arg1 ; 44 | @end 45 | 46 | @interface ReachPlayerArtworkContainerView : UIView 47 | @property (nonatomic, strong) UIImageView *artworkView; 48 | @end 49 | 50 | @interface ReachPlayerContainerView : UIView 51 | @property (nonatomic, retain) UIImageView *backgroundImageView; 52 | @property (nonatomic, retain) _UIBackdropView *backgroundBlurView; 53 | @property (nonatomic, retain) ReachPlayerArtworkContainerView *artworkContainerView; 54 | @property (nonatomic, retain) UILabel *nowPlayingInfoSong; 55 | @property (nonatomic, retain) UILabel *nowPlayingInfoArtist; 56 | @property (nonatomic, retain) UILabel *nowPlayingInfoAlbum; 57 | @property (nonatomic, retain) UIButton *playPauseButton; 58 | @property (nonatomic, retain) UIButton *nextButton; 59 | @property (nonatomic, retain) UIButton *previousButton; 60 | @end 61 | 62 | @interface SBWallpaperEffectView : UIVisualEffectView 63 | @end 64 | 65 | @interface SBReachabilityBackgroundView : UIView 66 | @end 67 | 68 | @interface SBReachabilityBackgroundViewController : UIViewController 69 | @property (nonatomic, retain) NSTimer *updateTimer; 70 | - (void)updateReachability; 71 | - (void)addReachPlayerContainerView; 72 | @end 73 | 74 | @interface UIColor (Private) 75 | -(BOOL)_isSimilarToColor:(id)arg1 withinPercentage:(double)arg2 ; 76 | @end 77 | 78 | @interface SBReachabilityManager : NSObject 79 | -(void)_setKeepAliveTimer; 80 | +(id)sharedInstance; 81 | -(void)toggleReachability; 82 | -(BOOL)reachabilityModeActive; 83 | -(void)deactivateReachability; 84 | -(void)_notifyObserversReachabilityYOffsetDidChange; 85 | @end 86 | 87 | @interface SBMediaController 88 | + (id)sharedInstance; 89 | - (BOOL)isPlaying; 90 | @end 91 | 92 | @interface SBReachabilityWindow : UIWindow 93 | - (id)view; 94 | @end 95 | 96 | @interface SBHomeScreenSpotlightViewController : UIViewController 97 | @end 98 | 99 | @interface _UIStatusBarForegroundView : UIView 100 | - (void)toggleStatusReachability:(id)sender; 101 | @end 102 | -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | #import "Tweak.h" 2 | 3 | UIView *emptyView; 4 | ReachPlayerContainerView *containerView; 5 | 6 | %group ReachPlayer 7 | 8 | %hook _UIStatusBarForegroundView 9 | // Double tap status bar to activate 10 | - (id)initWithFrame:(CGRect)frame { 11 | self = %orig; 12 | if (activationStyle == 0) { 13 | UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleStatusReachability:)]; 14 | self.userInteractionEnabled = YES; 15 | tapGesture.numberOfTapsRequired = 2; 16 | [self addGestureRecognizer:tapGesture]; 17 | } 18 | return self; 19 | } 20 | 21 | %new 22 | - (void)toggleStatusReachability:(id)sender { 23 | [[%c(SBReachabilityManager) sharedInstance] toggleReachability]; 24 | } 25 | %end 26 | 27 | %hook UIWindow 28 | // Shake device to activate 29 | - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { 30 | %orig; 31 | if (activationStyle == 1) { 32 | BOOL isScreenOn = MSHookIvar([%c(SBLockScreenManager) sharedInstance], "_isScreenOn"); 33 | if (event.type == UIEventSubtypeMotionShake && self == [[UIApplication sharedApplication] keyWindow] && isScreenOn == YES) { 34 | [[%c(SBReachabilityManager) sharedInstance] toggleReachability]; 35 | } 36 | } 37 | } 38 | 39 | %end 40 | 41 | %hook SBSearchScrollView 42 | // disable Spotlight when Reachability active 43 | -(bool) gestureRecognizerShouldBegin:(id)arg1 { 44 | if ([[%c(SBReachabilityManager) sharedInstance] reachabilityModeActive] == YES) { 45 | return NO; 46 | } 47 | return %orig; 48 | } 49 | 50 | // disable Spotlight when Reachability active 51 | -(BOOL)gestureRecognizer:(id)arg1 shouldRequireFailureOfGestureRecognizer:(id)arg2 { 52 | if ([[%c(SBReachabilityManager) sharedInstance] reachabilityModeActive] == YES) { 53 | return NO; 54 | } 55 | return %orig; 56 | } 57 | %end 58 | 59 | %hook SBReachabilitySettings 60 | -(double)yOffsetFactor { 61 | return reachOffset; 62 | } 63 | 64 | // Sets the vertical offset 65 | - (void)setYOffsetFactor:(double)arg1 { 66 | %orig(reachOffset); 67 | } 68 | 69 | // Support for other devices 70 | - (bool)allowOnAllDevices { 71 | return YES; 72 | } 73 | 74 | // Support for other devices 75 | - (void)setAllowOnAllDevices:(bool)arg1 { 76 | %orig(YES); 77 | } 78 | 79 | %end 80 | 81 | %hook SBReachabilityManager 82 | //-(void)_setKeepAliveTimer { 83 | // remove orig timer 84 | //} 85 | 86 | -(void)_pingKeepAliveWithDuration:(double)arg1 interactedBeforePing:(BOOL)arg2 initialKeepAliveTime:(double)arg3 { 87 | %orig(keepAliveDuration,arg2,0.0); 88 | } 89 | 90 | // Support for other devices 91 | + (bool)reachabilitySupported { 92 | return YES; 93 | } 94 | 95 | // Support for other devices 96 | - (bool)reachabilityEnabled { 97 | return YES; 98 | } 99 | 100 | // Support for other devices 101 | - (void)setReachabilityEnabled:(bool)arg1 { 102 | %orig(YES); 103 | } 104 | 105 | - (void)_panToDeactivateReachability:(id)arg1 { 106 | if (![arg1 isKindOfClass:%c(SBScreenEdgePanGestureRecognizer)]) return; 107 | %orig; 108 | } 109 | 110 | - (_Bool)gestureRecognizerShouldBegin:(id)arg1 { 111 | if ((![arg1 isKindOfClass:%c(SBScreenEdgePanGestureRecognizer)] && ![arg1 isKindOfClass:%c(SBReachabilityGestureRecognizer)])) return false; 112 | return %orig; 113 | } 114 | 115 | - (void)_tapToDeactivateReachability:(id)arg1 { 116 | //remove tap gesture 117 | } 118 | %end 119 | 120 | %hook SBSearchViewController 121 | // Support for other devices 122 | - (bool)reachabilitySupported { 123 | return YES; 124 | } 125 | %end 126 | 127 | 128 | %hook SBAppSwitcherController 129 | // Support for other devices 130 | - (bool)_shouldRespondToReachability { 131 | return YES; 132 | } 133 | %end 134 | 135 | %hook SBIconController 136 | // Support for other devices 137 | - (bool)_shouldRespondToReachability { 138 | return YES; 139 | } 140 | %end 141 | 142 | %hook SBApplication 143 | // Support for other devices 144 | - (bool)isReachabilitySupported { 145 | return YES; 146 | } 147 | 148 | - (void)setReachabilitySupported:(bool)arg1 { 149 | %orig(YES); 150 | } 151 | %end 152 | 153 | %hook SpringBoard 154 | // Support for other devices 155 | - (void)_setReachabilitySupported:(bool)arg1 { 156 | %orig(YES); 157 | } 158 | %end 159 | 160 | %hook SBReachabilityWindow 161 | // thanks NEPETA! put my own twist on it though (passes touches to our view) 162 | - (id)hitTest:(CGPoint)arg1 withEvent:(id)arg2 { 163 | UIView *candidate = %orig; 164 | SBWallpaperEffectView *correctView = MSHookIvar(((SBReachabilityBackgroundView *)self.rootViewController.view), "_topWallpaperEffectView"); 165 | if (arg1.y <= 0) { 166 | candidate = [correctView hitTest:[correctView convertPoint:arg1 fromView:self] withEvent:arg2]; 167 | if (emptyView) { 168 | candidate = emptyView; 169 | emptyView = nil; 170 | } else { 171 | emptyView = candidate; 172 | } 173 | } 174 | return candidate; 175 | } 176 | %end 177 | 178 | %hook SBReachabilityBackgroundView 179 | - (void)setChevronAlpha:(double)arg1 { 180 | if (enable) { 181 | arg1 = chevronOpacity; 182 | %orig; 183 | } 184 | %orig; 185 | } 186 | %end 187 | 188 | %hook SBReachabilityBackgroundViewController 189 | %property (nonatomic, retain) NSTimer *updateTimer; 190 | -(void)viewWillAppear:(BOOL)arg1 { 191 | %orig; 192 | [[%c(SBReachabilityManager) sharedInstance] _notifyObserversReachabilityYOffsetDidChange]; 193 | [self addReachPlayerContainerView]; 194 | } 195 | 196 | %new 197 | - (void)addReachPlayerContainerView { 198 | SBWallpaperEffectView *topWallpaperEffectView = MSHookIvar(((SBReachabilityBackgroundView *)self.view), "_topWallpaperEffectView"); 199 | 200 | if (topWallpaperEffectView != nil) { 201 | containerView = [ReachPlayerContainerView new]; 202 | containerView.frame = topWallpaperEffectView.bounds; 203 | if (enableBlur) { 204 | containerView.backgroundImageView.hidden = NO; 205 | containerView.backgroundBlurView.hidden = NO; 206 | } else { 207 | containerView.backgroundImageView.hidden = YES; 208 | containerView.backgroundBlurView.hidden = YES; 209 | } 210 | [topWallpaperEffectView addSubview:containerView]; 211 | 212 | containerView.translatesAutoresizingMaskIntoConstraints = false; 213 | [containerView.bottomAnchor constraintEqualToAnchor:topWallpaperEffectView.bottomAnchor constant:0].active = YES; 214 | [containerView.leftAnchor constraintEqualToAnchor:topWallpaperEffectView.leftAnchor constant:0].active = YES; 215 | [containerView.rightAnchor constraintEqualToAnchor:topWallpaperEffectView.rightAnchor constant:0].active = YES; 216 | [containerView.topAnchor constraintEqualToAnchor:topWallpaperEffectView.topAnchor constant:0].active = YES; 217 | } 218 | } 219 | /* 220 | %new 221 | - (void)updateReachability { 222 | if ([[%c(SBReachabilityManager) sharedInstance] reachabilityModeActive] == YES) { 223 | [[%c(SBReachabilityManager) sharedInstance] toggleReachability]; 224 | } 225 | } 226 | */ 227 | %end 228 | 229 | %hook SpringBoard 230 | - (void)applicationDidFinishLaunching:(UIApplication *)application { 231 | %orig; 232 | loadPreferences(); 233 | } 234 | %end 235 | %end 236 | 237 | %ctor { 238 | 239 | BOOL shouldLoad = NO; 240 | NSArray *args = [[NSClassFromString(@"NSProcessInfo") processInfo] arguments]; 241 | NSUInteger count = args.count; 242 | if (count != 0) { 243 | NSString *executablePath = args[0]; 244 | if (executablePath) { 245 | NSString *processName = [executablePath lastPathComponent]; 246 | BOOL isSpringBoard = [processName isEqualToString:@"SpringBoard"]; 247 | BOOL isPreferences = [processName isEqualToString:@"Preferences"]; 248 | BOOL isApplication = [executablePath rangeOfString:@"/Application/"].location != NSNotFound || [executablePath rangeOfString:@"/Applications/"].location != NSNotFound; 249 | BOOL isFileProvider = [[processName lowercaseString] rangeOfString:@"fileprovider"].location != NSNotFound; 250 | BOOL skip = [processName isEqualToString:@"AdSheet"] 251 | || [processName isEqualToString:@"CoreAuthUI"] 252 | || [processName isEqualToString:@"InCallService"] 253 | || [processName isEqualToString:@"MessagesNotificationViewService"] 254 | || [executablePath rangeOfString:@".appex/"].location != NSNotFound; 255 | if (!isFileProvider && (isSpringBoard || isApplication || isPreferences) && !skip) { 256 | shouldLoad = YES; 257 | } 258 | } 259 | } 260 | if (shouldLoad) { 261 | 262 | loadPreferences(); // Load prefs 263 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)loadPreferences, (CFStringRef)preferencesNotification, NULL, CFNotificationSuspensionBehaviorCoalesce); 264 | 265 | if (enable) { 266 | %init(ReachPlayer); 267 | return; 268 | } 269 | return; 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.nahtedetihw.reachplayer 2 | Name: ReachPlayer 3 | Version: 2.6 4 | Architecture: iphoneos-arm 5 | Description: Now Playing info in Reachability Window! 6 | Maintainer: Ethan Whited 7 | Author: Ethan Whited 8 | Section: Tweaks 9 | Depends: mobilesubstrate 10 | -------------------------------------------------------------------------------- /packages/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/packages/.DS_Store -------------------------------------------------------------------------------- /packages/com.nahtedetihw.reachplayer_2.6_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/packages/com.nahtedetihw.reachplayer_2.6_iphoneos-arm.deb -------------------------------------------------------------------------------- /reachplayerprefs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/.DS_Store -------------------------------------------------------------------------------- /reachplayerprefs/Makefile: -------------------------------------------------------------------------------- 1 | ARCHS = arm64 arm64e 2 | 3 | include $(THEOS)/makefiles/common.mk 4 | 5 | SYSROOT=$(THEOS)/sdks/iphoneos14.2.sdk 6 | 7 | ##THEOS_PACKAGE_SCHEME=rootless 8 | 9 | BUNDLE_NAME = reachplayerprefs 10 | $(BUNDLE_NAME)_FILES = REACHPLAYERPreferences.m 11 | $(BUNDLE_NAME)_INSTALL_PATH = /Library/PreferenceBundles 12 | $(BUNDLE_NAME)_FRAMEWORKS = UIKit OnBoardingKit 13 | $(BUNDLE_NAME)_PRIVATE_FRAMEWORKS = Preferences 14 | $(BUNDLE_NAME)_CFLAGS = -fobjc-arc -Wdeprecated-declarations -Wno-deprecated-declarations 15 | 16 | include $(THEOS_MAKE_PATH)/bundle.mk 17 | -------------------------------------------------------------------------------- /reachplayerprefs/REACHPLAYERPreferences.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | @interface UIPopoverPresentationController (Private) 6 | @property (assign,setter=_setPopoverBackgroundStyle:,nonatomic) long long _popoverBackgroundStyle; 7 | @property (assign,setter=_setBackgroundBlurDisabled:,nonatomic) BOOL _backgroundBlurDisabled; 8 | @end 9 | 10 | @interface OBButtonTray : UIView 11 | @property (nonatomic,retain) UIVisualEffectView * effectView; 12 | - (void)addButton:(id)arg1; 13 | - (void)addCaptionText:(id)arg1;; 14 | @end 15 | 16 | @interface OBBoldTrayButton : UIButton 17 | - (void)setTitle:(id)arg1 forState:(unsigned long long)arg2; 18 | + (id)buttonWithType:(long long)arg1; 19 | @end 20 | 21 | @interface OBBulletedListItem : UIView 22 | @property (nonatomic,retain) UIImageView * imageView; 23 | @end 24 | 25 | @interface OBBulletedList : UIView 26 | @property (nonatomic,retain) NSMutableArray * items; 27 | @end 28 | 29 | @interface OBWelcomeController : UIViewController 30 | @property (nonatomic,retain) OBBulletedList * bulletedList; 31 | @property (nonatomic, retain) UIView *viewIfLoaded; 32 | @property (nonatomic, strong) UIColor *backgroundColor; 33 | - (OBButtonTray *)buttonTray; 34 | - (id)initWithTitle:(id)arg1 detailText:(id)arg2 icon:(id)arg3; 35 | - (void)addBulletedListItemWithTitle:(id)arg1 description:(id)arg2 image:(id)arg3; 36 | @end 37 | 38 | @interface REACHPLAYERPreferencesListController : PSListController { 39 | 40 | UITableView * _table; 41 | 42 | } 43 | @property (nonatomic, retain) UIBarButtonItem *killButton; 44 | @property (nonatomic, retain) UIView *headerView; 45 | @property (nonatomic, retain) UIImageView *headerImageView; 46 | @property (nonatomic, retain) UILabel *titleLabel; 47 | @property (nonatomic, retain) UIImageView *iconView; 48 | @property (nonatomic, retain) NSArray *versionArray; 49 | @property (nonatomic, retain) OBWelcomeController *changelogController; 50 | - (void)apply:(UIButton *)sender; 51 | - (void)twitter:(UIButton *)sender; 52 | - (void)paypal:(UIButton *)sender; 53 | - (void)handleYesGesture; 54 | - (void)handleNoGesture:(UIButton *)sender; 55 | @end 56 | 57 | @interface REACHPLAYERACTIVATIONPreferencesListController : PSListController 58 | @end 59 | 60 | @interface REACHPLAYERLAYOUTPreferencesListController : PSListController 61 | @end 62 | 63 | @interface REACHPLAYERBACKGROUNDPreferencesListController : PSListController 64 | @end 65 | 66 | @interface REACHPLAYERMISCPreferencesListController : PSListController 67 | @end 68 | -------------------------------------------------------------------------------- /reachplayerprefs/REACHPLAYERPreferences.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "REACHPLAYERPreferences.h" 3 | #import 4 | 5 | static NSString *preferencesNotification = @"com.nahtedetihw.reachplayerprefs/ReloadPrefs"; 6 | 7 | #define bundlePath ([[NSFileManager defaultManager] fileExistsAtPath:@"/Library/PreferenceBundles/reachplayerprefs.bundle/"] ? @"/Library/PreferenceBundles/reachplayerprefs.bundle/" : @"/var/jb/Library/PreferenceBundles/reachplayerprefs.bundle/") 8 | 9 | #define plistPath ([[NSFileManager defaultManager] fileExistsAtPath:@"/var/mobile/Library/Preferences/com.nahtedetihw.reachplayerprefs.plist"] ? @"/var/mobile/Library/Preferences/com.nahtedetihw.reachplayerprefs.plist" : @"/var/jb/var/mobile/Library/Preferences/com.nahtedetihw.reachplayerprefs.plist") 10 | 11 | UIBarButtonItem *changelogButtonItem; 12 | UIBarButtonItem *respringButtonItem; 13 | UIBarButtonItem *twitterButtonItem; 14 | UIBarButtonItem *paypalButtonItem; 15 | UIViewController *popController; 16 | 17 | @implementation REACHPLAYERPreferencesListController 18 | @synthesize killButton; 19 | @synthesize versionArray; 20 | 21 | - (NSArray *)specifiers { 22 | if (!_specifiers) { 23 | _specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self]; 24 | } 25 | 26 | return _specifiers; 27 | } 28 | 29 | - (UITableViewStyle)tableViewStyle { 30 | return UITableViewStyleInsetGrouped; 31 | } 32 | 33 | - (instancetype)init { 34 | 35 | self = [super init]; 36 | 37 | if (self) { 38 | 39 | UIButton *respringButton = [UIButton buttonWithType:UIButtonTypeCustom]; 40 | respringButton.frame = CGRectMake(0,0,30,30); 41 | respringButton.layer.cornerRadius = respringButton.frame.size.height / 2; 42 | respringButton.layer.masksToBounds = YES; 43 | respringButton.backgroundColor = [UIColor colorWithRed:72/255.0f green:97/255.0f blue:112/255.0f alpha:1.0f]; 44 | [respringButton setImage:[[UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@CHECKMARK.png", bundlePath]] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; 45 | [respringButton addTarget:self action:@selector(apply:) forControlEvents:UIControlEventTouchUpInside]; 46 | respringButton.tintColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 47 | 48 | respringButtonItem = [[UIBarButtonItem alloc] initWithCustomView:respringButton]; 49 | 50 | UIButton *changelogButton = [UIButton buttonWithType:UIButtonTypeCustom]; 51 | changelogButton.frame = CGRectMake(0,0,30,30); 52 | changelogButton.layer.cornerRadius = changelogButton.frame.size.height / 2; 53 | changelogButton.layer.masksToBounds = YES; 54 | changelogButton.backgroundColor = [UIColor colorWithRed:72/255.0f green:97/255.0f blue:112/255.0f alpha:1.0f]; 55 | [changelogButton setImage:[[UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@CHANGELOG.png", bundlePath]] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; 56 | [changelogButton addTarget:self action:@selector(showMenu:) forControlEvents:UIControlEventTouchUpInside]; 57 | changelogButton.tintColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 58 | 59 | changelogButtonItem = [[UIBarButtonItem alloc] initWithCustomView:changelogButton]; 60 | 61 | UIButton *twitterButton = [UIButton buttonWithType:UIButtonTypeCustom]; 62 | twitterButton.frame = CGRectMake(0,0,30,30); 63 | twitterButton.layer.cornerRadius = twitterButton.frame.size.height / 2; 64 | twitterButton.layer.masksToBounds = YES; 65 | twitterButton.backgroundColor = [UIColor colorWithRed:72/255.0f green:97/255.0f blue:112/255.0f alpha:1.0f]; 66 | [twitterButton setImage:[[UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@TWITTER.png", bundlePath]] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; 67 | [twitterButton addTarget:self action:@selector(twitter:) forControlEvents:UIControlEventTouchUpInside]; 68 | twitterButton.tintColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 69 | 70 | twitterButtonItem = [[UIBarButtonItem alloc] initWithCustomView:twitterButton]; 71 | 72 | UIButton *paypalButton = [UIButton buttonWithType:UIButtonTypeCustom]; 73 | paypalButton.frame = CGRectMake(0,0,30,30); 74 | paypalButton.layer.cornerRadius = paypalButton.frame.size.height / 2; 75 | paypalButton.layer.masksToBounds = YES; 76 | paypalButton.backgroundColor = [UIColor colorWithRed:72/255.0f green:97/255.0f blue:112/255.0f alpha:1.0f]; 77 | [paypalButton setImage:[[UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@PAYPAL.png", bundlePath]] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; 78 | [paypalButton addTarget:self action:@selector(paypal:) forControlEvents:UIControlEventTouchUpInside]; 79 | paypalButton.tintColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 80 | 81 | paypalButtonItem = [[UIBarButtonItem alloc] initWithCustomView:paypalButton]; 82 | 83 | NSArray *rightButtons; 84 | rightButtons = @[respringButtonItem, changelogButtonItem, twitterButtonItem, paypalButtonItem]; 85 | self.navigationItem.rightBarButtonItems = rightButtons; 86 | self.navigationItem.titleView = [UIView new]; 87 | self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; 88 | self.titleLabel.font = [UIFont boldSystemFontOfSize:18]; 89 | self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO; 90 | self.titleLabel.text = @""; 91 | self.titleLabel.textColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 92 | self.titleLabel.textAlignment = NSTextAlignmentCenter; 93 | [self.navigationItem.titleView addSubview:self.titleLabel]; 94 | 95 | self.iconView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; 96 | self.iconView.contentMode = UIViewContentModeScaleAspectFit; 97 | self.iconView.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@icon.png", bundlePath]]; 98 | self.iconView.translatesAutoresizingMaskIntoConstraints = NO; 99 | self.iconView.alpha = 0.0; 100 | [self.navigationItem.titleView addSubview:self.iconView]; 101 | 102 | [NSLayoutConstraint activateConstraints:@[ 103 | [self.titleLabel.topAnchor constraintEqualToAnchor:self.navigationItem.titleView.topAnchor], 104 | [self.titleLabel.leadingAnchor constraintEqualToAnchor:self.navigationItem.titleView.leadingAnchor], 105 | [self.titleLabel.trailingAnchor constraintEqualToAnchor:self.navigationItem.titleView.trailingAnchor], 106 | [self.titleLabel.bottomAnchor constraintEqualToAnchor:self.navigationItem.titleView.bottomAnchor], 107 | [self.iconView.topAnchor constraintEqualToAnchor:self.navigationItem.titleView.topAnchor], 108 | [self.iconView.leadingAnchor constraintEqualToAnchor:self.navigationItem.titleView.leadingAnchor], 109 | [self.iconView.trailingAnchor constraintEqualToAnchor:self.navigationItem.titleView.trailingAnchor], 110 | [self.iconView.bottomAnchor constraintEqualToAnchor:self.navigationItem.titleView.bottomAnchor], 111 | ]]; 112 | 113 | } 114 | 115 | return self; 116 | 117 | } 118 | 119 | - (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller { 120 | 121 | return UIModalPresentationNone; 122 | } 123 | 124 | - (void)viewWillAppear:(BOOL)animated { 125 | 126 | [super viewWillAppear:animated]; 127 | 128 | self.view.tintColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 129 | [[UIApplication sharedApplication] keyWindow].tintColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 130 | 131 | CGRect frame = self.table.bounds; 132 | frame.origin.y = -frame.size.height; 133 | 134 | self.navigationController.navigationController.navigationBar.tintColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 135 | self.navigationController.navigationController.navigationBar.translucent = YES; 136 | } 137 | 138 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 139 | tableView.tableHeaderView = self.headerView; 140 | return [super tableView:tableView cellForRowAtIndexPath:indexPath]; 141 | } 142 | 143 | - (void)viewDidLoad { 144 | 145 | [super viewDidLoad]; 146 | 147 | self.view.tintColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 148 | [[UIApplication sharedApplication] keyWindow].tintColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 149 | 150 | self.navigationController.navigationController.navigationBar.tintColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 151 | self.navigationController.navigationController.navigationBar.translucent = YES; 152 | 153 | self.headerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200)]; 154 | self.headerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,200,200)]; 155 | self.headerImageView.contentMode = UIViewContentModeScaleAspectFit; 156 | self.headerImageView.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@banner.png", bundlePath]]; 157 | self.headerImageView.translatesAutoresizingMaskIntoConstraints = NO; 158 | 159 | [self.headerView addSubview:self.headerImageView]; 160 | [NSLayoutConstraint activateConstraints:@[ 161 | [self.headerImageView.topAnchor constraintEqualToAnchor:self.headerView.topAnchor], 162 | [self.headerImageView.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor], 163 | [self.headerImageView.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor], 164 | [self.headerImageView.bottomAnchor constraintEqualToAnchor:self.headerView.bottomAnchor], 165 | ]]; 166 | 167 | _table.tableHeaderView = self.headerView; 168 | 169 | [[NSNotificationCenter defaultCenter] addObserver:self 170 | selector:@selector(handleNoGesture:) 171 | name:UIApplicationDidEnterBackgroundNotification object:nil]; 172 | 173 | } 174 | 175 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 176 | CGFloat offsetY = scrollView.contentOffset.y; 177 | 178 | if (offsetY > 40) { 179 | [UIView animateWithDuration:0.2 animations:^{ 180 | self.iconView.alpha = 1.0; 181 | self.titleLabel.alpha = 0.0; 182 | }]; 183 | } else { 184 | [UIView animateWithDuration:0.2 animations:^{ 185 | self.iconView.alpha = 0.0; 186 | self.titleLabel.alpha = 1.0; 187 | }]; 188 | } 189 | 190 | if (offsetY > 0) offsetY = 0; 191 | self.headerImageView.frame = CGRectMake(self.headerView.frame.origin.x, self.headerView.frame.origin.y, self.headerView.frame.size.width, 200 - offsetY); 192 | } 193 | 194 | - (void)viewWillDisappear:(BOOL)animated { 195 | [super viewWillDisappear:animated]; 196 | 197 | [self.navigationController.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor blackColor]}]; 198 | } 199 | 200 | -(id)readPreferenceValue: (PSSpecifier *)specifier { 201 | NSMutableDictionary *settings = [NSMutableDictionary dictionary]; 202 | [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:plistPath]]; 203 | return settings [specifier.properties[@"key"]] ?: specifier.properties[@"default"]; 204 | } 205 | 206 | -(void)setPreferenceValue:(id)value specifier: (PSSpecifier *)specifier { 207 | NSMutableDictionary *settings = [NSMutableDictionary dictionary]; 208 | [settings addEntriesFromDictionary: [NSDictionary dictionaryWithContentsOfFile:plistPath]]; 209 | [settings setObject:value forKey:specifier.properties [@"key"]]; 210 | [settings writeToFile:plistPath atomically:YES]; 211 | [super setPreferenceValue:value specifier :specifier]; 212 | 213 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)preferencesNotification, NULL, NULL, TRUE); 214 | } 215 | 216 | - (void)apply:(UIButton *)sender { 217 | 218 | popController = [[UIViewController alloc] init]; 219 | popController.modalPresentationStyle = UIModalPresentationPopover; 220 | popController.preferredContentSize = CGSizeMake(200,130); 221 | UILabel *respringLabel = [[UILabel alloc] init]; 222 | respringLabel.frame = CGRectMake(20, 20, 160, 60); 223 | respringLabel.numberOfLines = 2; 224 | respringLabel.textAlignment = NSTextAlignmentCenter; 225 | respringLabel.adjustsFontSizeToFitWidth = YES; 226 | respringLabel.font = [UIFont boldSystemFontOfSize:20]; 227 | respringLabel.textColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 228 | respringLabel.text = @"Are you sure you want to respring?"; 229 | [popController.view addSubview:respringLabel]; 230 | 231 | UIButton *yesButton = [UIButton buttonWithType:UIButtonTypeCustom]; 232 | [yesButton addTarget:self 233 | action:@selector(handleYesGesture) 234 | forControlEvents:UIControlEventTouchUpInside]; 235 | [yesButton setTitle:@"Yes" forState:UIControlStateNormal]; 236 | yesButton.titleLabel.font = [UIFont boldSystemFontOfSize:20]; 237 | [yesButton setTitleColor:[UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f] forState:UIControlStateNormal]; 238 | yesButton.frame = CGRectMake(100, 100, 100, 30); 239 | [popController.view addSubview:yesButton]; 240 | 241 | UIButton *noButton = [UIButton buttonWithType:UIButtonTypeCustom]; 242 | [noButton addTarget:self 243 | action:@selector(handleNoGesture:) 244 | forControlEvents:UIControlEventTouchUpInside]; 245 | [noButton setTitle:@"No" forState:UIControlStateNormal]; 246 | noButton.titleLabel.font = [UIFont boldSystemFontOfSize:20]; 247 | [noButton setTitleColor:[UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f] forState:UIControlStateNormal]; 248 | noButton.frame = CGRectMake(0, 100, 100, 30); 249 | [popController.view addSubview:noButton]; 250 | 251 | UIPopoverPresentationController *popover = popController.popoverPresentationController; 252 | popover.delegate = self; 253 | //[popover _setBackgroundBlurDisabled:YES]; 254 | popover.permittedArrowDirections = UIPopoverArrowDirectionUp; 255 | popover.barButtonItem = respringButtonItem; 256 | popover.backgroundColor = [UIColor colorWithRed:72/255.0f green:97/255.0f blue:112/255.0f alpha:1.0f]; 257 | 258 | [self presentViewController:popController animated:YES completion:nil]; 259 | 260 | AudioServicesPlaySystemSound(1519); 261 | 262 | } 263 | 264 | 265 | - (void)showMenu:(id)sender { 266 | 267 | AudioServicesPlaySystemSound(1519); 268 | 269 | self.changelogController = [[OBWelcomeController alloc] initWithTitle:@"ReachPlayer" detailText:@"2.5" icon:[UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@changelogControllerIcon.png", bundlePath]]]; 270 | 271 | [self.changelogController addBulletedListItemWithTitle:@"Y Offset" description:@"Allows Y Offset to be changed right away and not need a respring." image:[UIImage systemImageNamed:@"1.circle.fill"]]; 272 | 273 | self.changelogController.viewIfLoaded.backgroundColor = [UIColor systemBackgroundColor]; 274 | for (OBBulletedListItem *item in self.changelogController.bulletedList.items) { 275 | item.imageView.tintColor = [UIColor colorWithRed:121/255.0f green:145/255.0f blue:153/255.0f alpha:1.0f]; 276 | } 277 | self.changelogController.modalPresentationStyle = UIModalPresentationPageSheet; 278 | self.changelogController.modalInPresentation = NO; 279 | [self presentViewController:self.changelogController animated:YES completion:nil]; 280 | } 281 | - (void)dismissVC { 282 | [self.changelogController dismissViewControllerAnimated:YES completion:nil]; 283 | } 284 | 285 | - (void)twitter:(id)sender { 286 | AudioServicesPlaySystemSound(1519); 287 | 288 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://twitter.com/EthanWhited"] options:@{} completionHandler:nil]; 289 | } 290 | 291 | - (void)paypal:(id)sender { 292 | AudioServicesPlaySystemSound(1519); 293 | 294 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://paypal.me/nahtedetihw"] options:@{} completionHandler:nil]; 295 | } 296 | 297 | - (void)handleYesGesture { 298 | AudioServicesPlaySystemSound(1519); 299 | 300 | [popController dismissViewControllerAnimated:YES completion:nil]; 301 | 302 | pid_t pid; 303 | const char* args[] = {"killall", "SpringBoard", NULL}; 304 | if ([[NSFileManager defaultManager] fileExistsAtPath:@"/usr/bin/killall"]) { 305 | posix_spawn(&pid, "usr/bin/killall", NULL, NULL, (char* const*)args, NULL); 306 | } else { 307 | posix_spawn(&pid, "/var/jb/usr/bin/killall", NULL, NULL, (char* const*)args, NULL); 308 | } 309 | 310 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)preferencesNotification, NULL, NULL, TRUE); 311 | } 312 | 313 | - (void)handleNoGesture:(UIButton *)sender { 314 | [popController dismissViewControllerAnimated:YES completion:nil]; 315 | } 316 | 317 | @end 318 | 319 | @implementation REACHPLAYERACTIVATIONPreferencesListController 320 | - (NSArray *)specifiers { 321 | if (!_specifiers) { 322 | _specifiers = [self loadSpecifiersFromPlistName:@"ACTIVATION" target:self]; 323 | } 324 | 325 | return _specifiers; 326 | } 327 | 328 | - (UITableViewStyle)tableViewStyle { 329 | return UITableViewStyleInsetGrouped; 330 | } 331 | 332 | -(id)readPreferenceValue: (PSSpecifier *)specifier { 333 | NSMutableDictionary *settings = [NSMutableDictionary dictionary]; 334 | [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:plistPath]]; 335 | return settings [specifier.properties[@"key"]] ?: specifier.properties[@"default"]; 336 | } 337 | 338 | -(void)setPreferenceValue:(id)value specifier: (PSSpecifier *)specifier { 339 | NSMutableDictionary *settings = [NSMutableDictionary dictionary]; 340 | [settings addEntriesFromDictionary: [NSDictionary dictionaryWithContentsOfFile: plistPath]]; 341 | [settings setObject:value forKey:specifier.properties [@"key"]]; 342 | [settings writeToFile:plistPath atomically:YES]; 343 | [super setPreferenceValue:value specifier :specifier]; 344 | 345 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)preferencesNotification, NULL, NULL, TRUE); 346 | } 347 | @end 348 | 349 | 350 | @implementation REACHPLAYERLAYOUTPreferencesListController 351 | - (NSArray *)specifiers { 352 | if (!_specifiers) { 353 | _specifiers = [self loadSpecifiersFromPlistName:@"LAYOUT" target:self]; 354 | } 355 | 356 | return _specifiers; 357 | } 358 | 359 | - (UITableViewStyle)tableViewStyle { 360 | return UITableViewStyleInsetGrouped; 361 | } 362 | 363 | -(id)readPreferenceValue: (PSSpecifier *)specifier { 364 | NSMutableDictionary *settings = [NSMutableDictionary dictionary]; 365 | [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:plistPath]]; 366 | return settings [specifier.properties[@"key"]] ?: specifier.properties[@"default"]; 367 | } 368 | 369 | -(void)setPreferenceValue:(id)value specifier: (PSSpecifier *)specifier { 370 | NSMutableDictionary *settings = [NSMutableDictionary dictionary]; 371 | [settings addEntriesFromDictionary: [NSDictionary dictionaryWithContentsOfFile: plistPath]]; 372 | [settings setObject:value forKey:specifier.properties [@"key"]]; 373 | [settings writeToFile:plistPath atomically:YES]; 374 | [super setPreferenceValue:value specifier :specifier]; 375 | 376 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)preferencesNotification, NULL, NULL, TRUE); 377 | } 378 | @end 379 | 380 | @implementation REACHPLAYERBACKGROUNDPreferencesListController 381 | - (NSArray *)specifiers { 382 | if (!_specifiers) { 383 | _specifiers = [self loadSpecifiersFromPlistName:@"BACKGROUND" target:self]; 384 | } 385 | 386 | return _specifiers; 387 | } 388 | 389 | - (UITableViewStyle)tableViewStyle { 390 | return UITableViewStyleInsetGrouped; 391 | } 392 | 393 | -(id)readPreferenceValue: (PSSpecifier *)specifier { 394 | NSMutableDictionary *settings = [NSMutableDictionary dictionary]; 395 | [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:plistPath]]; 396 | return settings [specifier.properties[@"key"]] ?: specifier.properties[@"default"]; 397 | } 398 | 399 | -(void)setPreferenceValue:(id)value specifier: (PSSpecifier *)specifier { 400 | NSMutableDictionary *settings = [NSMutableDictionary dictionary]; 401 | [settings addEntriesFromDictionary: [NSDictionary dictionaryWithContentsOfFile: plistPath]]; 402 | [settings setObject:value forKey:specifier.properties [@"key"]]; 403 | [settings writeToFile:plistPath atomically:YES]; 404 | [super setPreferenceValue:value specifier :specifier]; 405 | 406 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)preferencesNotification, NULL, NULL, TRUE); 407 | } 408 | @end 409 | 410 | @implementation REACHPLAYERMISCPreferencesListController 411 | - (NSArray *)specifiers { 412 | if (!_specifiers) { 413 | _specifiers = [self loadSpecifiersFromPlistName:@"MISC" target:self]; 414 | } 415 | 416 | return _specifiers; 417 | } 418 | 419 | - (UITableViewStyle)tableViewStyle { 420 | return UITableViewStyleInsetGrouped; 421 | } 422 | 423 | -(id)readPreferenceValue: (PSSpecifier *)specifier { 424 | NSMutableDictionary *settings = [NSMutableDictionary dictionary]; 425 | [settings addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:plistPath]]; 426 | return settings [specifier.properties[@"key"]] ?: specifier.properties[@"default"]; 427 | } 428 | 429 | -(void)setPreferenceValue:(id)value specifier: (PSSpecifier *)specifier { 430 | NSMutableDictionary *settings = [NSMutableDictionary dictionary]; 431 | [settings addEntriesFromDictionary: [NSDictionary dictionaryWithContentsOfFile: plistPath]]; 432 | [settings setObject:value forKey:specifier.properties [@"key"]]; 433 | [settings writeToFile:plistPath atomically:YES]; 434 | [super setPreferenceValue:value specifier :specifier]; 435 | 436 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)preferencesNotification, NULL, NULL, TRUE); 437 | } 438 | @end 439 | -------------------------------------------------------------------------------- /reachplayerprefs/Resources/ACTIVATION.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Activation Style 12 | 13 | 14 | cell 15 | PSSegmentCell 16 | default 17 | 0 18 | defaults 19 | com.nahtedetihw.reachplayerprefs 20 | key 21 | activationStyle 22 | validValues 23 | 24 | 0 25 | 1 26 | 27 | validTitles 28 | 29 | StatusBar (Tapx2) 30 | Shake Device 31 | 32 | alignment 33 | 1 34 | PostNotification 35 | com.nahtedetihw.reachplayerprefs/ReloadPrefs 36 | 37 | 38 | cell 39 | PSGroupCell 40 | footerAlignment 41 | 1 42 | footerText 43 | ReachPlayer 44 | 45 | 46 | cell 47 | PSGroupCell 48 | footerAlignment 49 | 1 50 | footerText 51 | 2023 © nahtedetihw 52 | 53 | 54 | title 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /reachplayerprefs/Resources/ACTIVATION@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/ACTIVATION@2x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/ACTIVATION@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/ACTIVATION@3x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/BACKGROUND.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Blurred Background 12 | 13 | 14 | cell 15 | PSSwitchCell 16 | default 17 | 18 | defaults 19 | com.nahtedetihw.reachplayerprefs 20 | key 21 | enableBlur 22 | label 23 | Enable Blurred Background 24 | PostNotification 25 | com.nahtedetihw.reachplayerprefs/ReloadPrefs 26 | 27 | 28 | cell 29 | PSGroupCell 30 | label 31 | Blur Style 32 | 33 | 34 | cell 35 | PSSegmentCell 36 | default 37 | 0 38 | defaults 39 | com.nahtedetihw.reachplayerprefs 40 | key 41 | blurStyle 42 | validValues 43 | 44 | 0 45 | 1 46 | 2 47 | 48 | validTitles 49 | 50 | Dark 51 | Clear 52 | Light 53 | 54 | alignment 55 | 1 56 | PostNotification 57 | com.nahtedetihw.reachplayerprefs/ReloadPrefs 58 | 59 | 60 | cell 61 | PSGroupCell 62 | footerAlignment 63 | 1 64 | footerText 65 | ReachPlayer 66 | 67 | 68 | cell 69 | PSGroupCell 70 | footerAlignment 71 | 1 72 | footerText 73 | 2023 © nahtedetihw 74 | 75 | 76 | title 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /reachplayerprefs/Resources/BACKGROUND@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/BACKGROUND@2x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/BACKGROUND@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/BACKGROUND@3x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/CHANGELOG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/CHANGELOG.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/CHANGELOG@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/CHANGELOG@2x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/CHANGELOG@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/CHANGELOG@3x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/CHECKMARK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/CHECKMARK.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/CHECKMARK@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/CHECKMARK@2x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/CHECKMARK@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/CHECKMARK@3x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/DefaultContainerArtwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/DefaultContainerArtwork.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/ENABLE@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/ENABLE@2x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/ENABLE@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/ENABLE@3x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | reachplayerprefs 9 | CFBundleIdentifier 10 | com.nahtedetihw.reachplayerprefs 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 | REACHPLAYERPreferencesListController 23 | 24 | 25 | -------------------------------------------------------------------------------- /reachplayerprefs/Resources/LAYOUT.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Layout 12 | 13 | 14 | cell 15 | PSSegmentCell 16 | default 17 | 0 18 | defaults 19 | com.nahtedetihw.reachplayerprefs 20 | key 21 | layoutStyle 22 | validValues 23 | 24 | 0 25 | 1 26 | 27 | validTitles 28 | 29 | Side-by-side 30 | Centered 31 | 32 | alignment 33 | 1 34 | PostNotification 35 | com.nahtedetihw.reachplayerprefs/ReloadPrefs 36 | 37 | 38 | cell 39 | PSGroupCell 40 | label 41 | Artwork Size 42 | 43 | 44 | cell 45 | PSSliderCell 46 | default 47 | 180 48 | defaults 49 | com.nahtedetihw.reachplayerprefs 50 | key 51 | artworkSize 52 | max 53 | 400 54 | min 55 | 0 56 | isSegmented 57 | 58 | showValue 59 | 60 | PostNotification 61 | com.nahtedetihw.reachplayerprefs/ReloadPrefs 62 | 63 | 64 | cell 65 | PSGroupCell 66 | label 67 | Position Horizontal 68 | 69 | 70 | cell 71 | PSSliderCell 72 | default 73 | 0 74 | defaults 75 | com.nahtedetihw.reachplayerprefs 76 | key 77 | positionX 78 | max 79 | 500 80 | min 81 | -500 82 | isSegmented 83 | 84 | showValue 85 | 86 | PostNotification 87 | com.nahtedetihw.reachplayerprefs/ReloadPrefs 88 | 89 | 90 | cell 91 | PSGroupCell 92 | label 93 | Position Vertical 94 | 95 | 96 | cell 97 | PSSliderCell 98 | default 99 | 0 100 | defaults 101 | com.nahtedetihw.reachplayerprefs 102 | key 103 | positionY 104 | max 105 | 500 106 | min 107 | -500 108 | isSegmented 109 | 110 | showValue 111 | 112 | PostNotification 113 | com.nahtedetihw.reachplayerprefs/ReloadPrefs 114 | 115 | 116 | cell 117 | PSGroupCell 118 | footerAlignment 119 | 1 120 | footerText 121 | ReachPlayer 122 | 123 | 124 | cell 125 | PSGroupCell 126 | footerAlignment 127 | 1 128 | footerText 129 | 2023 © nahtedetihw 130 | 131 | 132 | title 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /reachplayerprefs/Resources/LAYOUT@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/LAYOUT@2x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/LAYOUT@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/LAYOUT@3x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/MISC.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Reachability Height 12 | 13 | 14 | cell 15 | PSSliderCell 16 | default 17 | 0.4 18 | defaults 19 | com.nahtedetihw.reachplayerprefs 20 | key 21 | reachOffset 22 | max 23 | 0.75 24 | min 25 | 0 26 | isSegmented 27 | 28 | showValue 29 | 30 | PostNotification 31 | com.nahtedetihw.reachplayerprefs/ReloadPrefs 32 | 33 | 34 | cell 35 | PSGroupCell 36 | label 37 | Chevron Transparency 38 | 39 | 40 | cell 41 | PSSliderCell 42 | default 43 | 1 44 | defaults 45 | com.nahtedetihw.reachplayerprefs 46 | key 47 | chevronOpacity 48 | max 49 | 1 50 | min 51 | 0 52 | isSegmented 53 | 54 | showValue 55 | 56 | PostNotification 57 | com.nahtedetihw.reachplayerprefs/ReloadPrefs 58 | 59 | 60 | cell 61 | PSGroupCell 62 | label 63 | Timeout Duration (seconds) 64 | 65 | 66 | cell 67 | PSSliderCell 68 | default 69 | 8 70 | defaults 71 | com.nahtedetihw.reachplayerprefs 72 | key 73 | keepAliveDuration 74 | max 75 | 120 76 | min 77 | 1 78 | isSegmented 79 | 80 | showValue 81 | 82 | PostNotification 83 | com.nahtedetihw.reachplayerprefs/ReloadPrefs 84 | 85 | 86 | cell 87 | PSGroupCell 88 | label 89 | Reachability will stay open for the above number of seconds you choose 90 | 91 | 92 | cell 93 | PSGroupCell 94 | footerAlignment 95 | 1 96 | footerText 97 | ReachPlayer 98 | 99 | 100 | cell 101 | PSGroupCell 102 | footerAlignment 103 | 1 104 | footerText 105 | 2023 © nahtedetihw 106 | 107 | 108 | title 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /reachplayerprefs/Resources/MISC@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/MISC@2x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/MISC@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/MISC@3x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/PAYPAL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/PAYPAL.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/PAYPAL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/PAYPAL@2x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/PAYPAL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/PAYPAL@3x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSSwitchCell 10 | default 11 | 12 | defaults 13 | com.nahtedetihw.reachplayerprefs 14 | key 15 | enable 16 | label 17 | Enable 18 | PostNotification 19 | com.nahtedetihw.reachplayerprefs/ReloadPrefs 20 | icon 21 | ENABLE.png 22 | 23 | 24 | cell 25 | PSGroupCell 26 | label 27 | 28 | 29 | 30 | cell 31 | PSLinkListCell 32 | default 33 | 34 | detail 35 | REACHPLAYERACTIVATIONPreferencesListController 36 | defaults 37 | com.nahtedetihw.reachplayerprefs 38 | label 39 | Activation 40 | icon 41 | ACTIVATION.png 42 | 43 | 44 | cell 45 | PSGroupCell 46 | label 47 | 48 | 49 | 50 | cell 51 | PSLinkListCell 52 | default 53 | 54 | detail 55 | REACHPLAYERLAYOUTPreferencesListController 56 | defaults 57 | com.nahtedetihw.reachplayerprefs 58 | label 59 | Layout 60 | icon 61 | LAYOUT.png 62 | 63 | 64 | cell 65 | PSGroupCell 66 | label 67 | 68 | 69 | 70 | cell 71 | PSLinkListCell 72 | default 73 | 74 | detail 75 | REACHPLAYERBACKGROUNDPreferencesListController 76 | defaults 77 | com.nahtedetihw.reachplayerprefs 78 | label 79 | Background 80 | icon 81 | BACKGROUND.png 82 | 83 | 84 | cell 85 | PSGroupCell 86 | label 87 | 88 | 89 | 90 | cell 91 | PSLinkListCell 92 | default 93 | 94 | detail 95 | REACHPLAYERMISCPreferencesListController 96 | defaults 97 | com.nahtedetihw.reachplayerprefs 98 | label 99 | Misc 100 | icon 101 | MISC.png 102 | 103 | 104 | cell 105 | PSGroupCell 106 | footerAlignment 107 | 1 108 | footerText 109 | ReachPlayer 2.6 110 | 111 | 112 | cell 113 | PSGroupCell 114 | footerAlignment 115 | 1 116 | footerText 117 | 2023 © nahtedetihw 118 | 119 | 120 | title 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /reachplayerprefs/Resources/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/banner.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/changelogControllerIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/changelogControllerIcon.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/icon@2x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/icon@3x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/twitter.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/twitter@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/twitter@2x.png -------------------------------------------------------------------------------- /reachplayerprefs/Resources/twitter@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nahtedetihw/ReachPlayer/89fda7d96ef7cf3df8ec02639e64a6a2d22cf1f6/reachplayerprefs/Resources/twitter@3x.png -------------------------------------------------------------------------------- /reachplayerprefs/layout/Library/PreferenceLoader/Preferences/reachplayerprefs.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | entry 6 | 7 | bundle 8 | reachplayerprefs 9 | cell 10 | PSLinkCell 11 | detail 12 | REACHPLAYERPreferencesListController 13 | icon 14 | icon.png 15 | isController 16 | 17 | label 18 | ReachPlayer 19 | 20 | 21 | 22 | --------------------------------------------------------------------------------