From bc385b464488d4b6341816ec9f8c547b2b69b412 Mon Sep 17 00:00:00 2001 From: Chr1sDev Date: Fri, 7 May 2021 23:06:23 -0500 Subject: [PATCH] v1.0.0 --- .gitignore | 3 +- Makefile | 3 + MediaRemote.h | 156 ------------------ Tweak.h | 45 +++++ Tweak.xm | 77 ++++----- control | 2 +- vibinprefs/KRLinkCell.h | 13 ++ vibinprefs/KRLinkCell.m | 133 +++++++++++++++ vibinprefs/KRTableCell.h | 4 + vibinprefs/KRTableCell.m | 25 +++ vibinprefs/KRTwitterCell.h | 5 + vibinprefs/KRTwitterCell.m | 110 ++++++++++++ vibinprefs/Makefile | 15 ++ vibinprefs/Resources/Info.plist | 24 +++ vibinprefs/Resources/Root.plist | 99 +++++++++++ vibinprefs/Resources/icon@2x.png | Bin 0 -> 3824 bytes vibinprefs/Resources/icon@3x.png | Bin 0 -> 7198 bytes vibinprefs/Resources/iconFixed.png | Bin 0 -> 1434 bytes vibinprefs/VBNRootListController.h | 15 ++ vibinprefs/VBNRootListController.m | 54 ++++++ .../Preferences/vibinprefs.plist | 21 +++ 21 files changed, 598 insertions(+), 206 deletions(-) delete mode 100644 MediaRemote.h create mode 100644 Tweak.h create mode 100644 vibinprefs/KRLinkCell.h create mode 100644 vibinprefs/KRLinkCell.m create mode 100644 vibinprefs/KRTableCell.h create mode 100644 vibinprefs/KRTableCell.m create mode 100644 vibinprefs/KRTwitterCell.h create mode 100644 vibinprefs/KRTwitterCell.m create mode 100644 vibinprefs/Makefile create mode 100644 vibinprefs/Resources/Info.plist create mode 100644 vibinprefs/Resources/Root.plist create mode 100644 vibinprefs/Resources/icon@2x.png create mode 100644 vibinprefs/Resources/icon@3x.png create mode 100644 vibinprefs/Resources/iconFixed.png create mode 100644 vibinprefs/VBNRootListController.h create mode 100644 vibinprefs/VBNRootListController.m create mode 100644 vibinprefs/layout/Library/PreferenceLoader/Preferences/vibinprefs.plist diff --git a/.gitignore b/.gitignore index 56a6118..c0b4540 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /.theos -/packages \ No newline at end of file +/packages +.DS_Store \ No newline at end of file diff --git a/Makefile b/Makefile index 4b6668c..441cc7a 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,9 @@ TWEAK_NAME = Vibin Vibin_FILES = $(wildcard *.xm *.m) $(TWEAK_NAME)_PRIVATE_FRAMEWORKS = MediaRemote +$(TWEAK_NAME)_EXTRA_FRAMEWORKS += Cephei Vibin_CFLAGS = -fobjc-arc include $(THEOS_MAKE_PATH)/tweak.mk +SUBPROJECTS += vibinprefs +include $(THEOS_MAKE_PATH)/aggregate.mk diff --git a/MediaRemote.h b/MediaRemote.h deleted file mode 100644 index dada950..0000000 --- a/MediaRemote.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Media remote framework header. - * - * Copyright (c) 2013-2014 Cykey (David Murray) - * All rights reserved. - */ - -#ifndef MEDIAREMOTE_H_ -#define MEDIAREMOTE_H_ - -#include - -#if __cplusplus -extern "C" { -#endif - -#pragma mark - Notifications - - /* - * These are used on the local notification center. - */ - - extern CFStringRef kMRMediaRemoteNowPlayingInfoDidChangeNotification; - extern CFStringRef kMRMediaRemoteNowPlayingPlaybackQueueDidChangeNotification; - extern CFStringRef kMRMediaRemotePickableRoutesDidChangeNotification; - extern CFStringRef kMRMediaRemoteNowPlayingApplicationDidChangeNotification; - extern CFStringRef kMRMediaRemoteNowPlayingApplicationIsPlayingDidChangeNotification; - extern CFStringRef kMRMediaRemoteRouteStatusDidChangeNotification; - -#pragma mark - Keys - - extern CFStringRef kMRMediaRemoteNowPlayingApplicationPIDUserInfoKey; - extern CFStringRef kMRMediaRemoteNowPlayingApplicationIsPlayingUserInfoKey; - extern CFStringRef kMRMediaRemoteNowPlayingInfoAlbum; - extern CFStringRef kMRMediaRemoteNowPlayingInfoArtist; - extern CFStringRef kMRMediaRemoteNowPlayingInfoArtworkData; - extern CFStringRef kMRMediaRemoteNowPlayingInfoArtworkMIMEType; - extern CFStringRef kMRMediaRemoteNowPlayingInfoChapterNumber; - extern CFStringRef kMRMediaRemoteNowPlayingInfoComposer; - extern CFStringRef kMRMediaRemoteNowPlayingInfoDuration; - extern CFStringRef kMRMediaRemoteNowPlayingInfoElapsedTime; - extern CFStringRef kMRMediaRemoteNowPlayingInfoGenre; - extern CFStringRef kMRMediaRemoteNowPlayingInfoIsAdvertisement; - extern CFStringRef kMRMediaRemoteNowPlayingInfoIsBanned; - extern CFStringRef kMRMediaRemoteNowPlayingInfoIsInWishList; - extern CFStringRef kMRMediaRemoteNowPlayingInfoIsLiked; - extern CFStringRef kMRMediaRemoteNowPlayingInfoIsMusicApp; - extern CFStringRef kMRMediaRemoteNowPlayingInfoPlaybackRate; - extern CFStringRef kMRMediaRemoteNowPlayingInfoProhibitsSkip; - extern CFStringRef kMRMediaRemoteNowPlayingInfoQueueIndex; - extern CFStringRef kMRMediaRemoteNowPlayingInfoRadioStationIdentifier; - extern CFStringRef kMRMediaRemoteNowPlayingInfoRepeatMode; - extern CFStringRef kMRMediaRemoteNowPlayingInfoShuffleMode; - extern CFStringRef kMRMediaRemoteNowPlayingInfoStartTime; - extern CFStringRef kMRMediaRemoteNowPlayingInfoSupportsFastForward15Seconds; - extern CFStringRef kMRMediaRemoteNowPlayingInfoSupportsIsBanned; - extern CFStringRef kMRMediaRemoteNowPlayingInfoSupportsIsLiked; - extern CFStringRef kMRMediaRemoteNowPlayingInfoSupportsRewind15Seconds; - extern CFStringRef kMRMediaRemoteNowPlayingInfoTimestamp; - extern CFStringRef kMRMediaRemoteNowPlayingInfoTitle; - extern CFStringRef kMRMediaRemoteNowPlayingInfoTotalChapterCount; - extern CFStringRef kMRMediaRemoteNowPlayingInfoTotalDiscCount; - extern CFStringRef kMRMediaRemoteNowPlayingInfoTotalQueueCount; - extern CFStringRef kMRMediaRemoteNowPlayingInfoTotalTrackCount; - extern CFStringRef kMRMediaRemoteNowPlayingInfoTrackNumber; - extern CFStringRef kMRMediaRemoteNowPlayingInfoUniqueIdentifier; - extern CFStringRef kMRMediaRemoteNowPlayingInfoRadioStationIdentifier; - extern CFStringRef kMRMediaRemoteNowPlayingInfoRadioStationHash; - extern CFStringRef kMRMediaRemoteOptionMediaType; - extern CFStringRef kMRMediaRemoteOptionSourceID; - extern CFStringRef kMRMediaRemoteOptionTrackID; - extern CFStringRef kMRMediaRemoteOptionStationID; - extern CFStringRef kMRMediaRemoteOptionStationHash; - extern CFStringRef kMRMediaRemoteRouteDescriptionUserInfoKey; - extern CFStringRef kMRMediaRemoteRouteStatusUserInfoKey; - -#pragma mark - API - - typedef enum { - /* - * Use nil for userInfo. - */ - kMRPlay = 0, - kMRPause = 1, - kMRTogglePlayPause = 2, - kMRStop = 3, - kMRNextTrack = 4, - kMRPreviousTrack = 5, - kMRToggleShuffle = 6, - kMRToggleRepeat = 7, - kMRStartForwardSeek = 8, - kMREndForwardSeek = 9, - kMRStartBackwardSeek = 10, - kMREndBackwardSeek = 11, - kMRGoBackFifteenSeconds = 12, - kMRSkipFifteenSeconds = 13, - - /* - * Use a NSDictionary for userInfo, which contains three keys: - * kMRMediaRemoteOptionTrackID - * kMRMediaRemoteOptionStationID - * kMRMediaRemoteOptionStationHash - */ - kMRLikeTrack = 0x6A, - kMRBanTrack = 0x6B, - kMRAddTrackToWishList = 0x6C, - kMRRemoveTrackFromWishList = 0x6D - } MRCommand; - - Boolean MRMediaRemoteSendCommand(MRCommand command, id userInfo); - - void MRMediaRemoteSetPlaybackSpeed(int speed); - void MRMediaRemoteSetElapsedTime(double elapsedTime); - - void MRMediaRemoteSetNowPlayingApplicationOverrideEnabled(Boolean enabled); - - void MRMediaRemoteRegisterForNowPlayingNotifications(dispatch_queue_t queue); - void MRMediaRemoteUnregisterForNowPlayingNotifications(); - - void MRMediaRemoteBeginRouteDiscovery(); - void MRMediaRemoteEndRouteDiscovery(); - - CFArrayRef MRMediaRemoteCopyPickableRoutes(); - - typedef void (^MRMediaRemoteGetNowPlayingInfoCompletion)(CFDictionaryRef information); - typedef void (^MRMediaRemoteGetNowPlayingApplicationPIDCompletion)(int PID); - typedef void (^MRMediaRemoteGetNowPlayingApplicationIsPlayingCompletion)(Boolean isPlaying); - - void MRMediaRemoteGetNowPlayingApplicationPID(dispatch_queue_t queue, MRMediaRemoteGetNowPlayingApplicationPIDCompletion completion); - void MRMediaRemoteGetNowPlayingInfo(dispatch_queue_t queue, MRMediaRemoteGetNowPlayingInfoCompletion completion); - void MRMediaRemoteGetNowPlayingApplicationIsPlaying(dispatch_queue_t queue, MRMediaRemoteGetNowPlayingApplicationIsPlayingCompletion completion); - - void MRMediaRemoteKeepAlive(); - void MRMediaRemoteSetElapsedTime(double time); - void MRMediaRemoteSetShuffleMode(int mode); - void MRMediaRemoteSetRepeatMode(int mode); - - /* - * The identifier can be obtained using MRMediaRemoteCopyPickableRoutes. - * Use the 'RouteUID' or the 'RouteName' key. - */ - - int MRMediaRemoteSelectSourceWithID(CFStringRef identifier); - void MRMediaRemoteSetPickedRouteWithPassword(CFStringRef route, CFStringRef password); - - CFArrayRef MRMediaRemoteCopyPickableRoutesForCategory(NSString *category); - Boolean MRMediaRemotePickedRouteHasVolumeControl(); - void MRMediaRemoteSetCanBeNowPlayingApplication(Boolean can); - void MRMediaRemoteSetNowPlayingInfo(CFDictionaryRef information); - - -#if __cplusplus -} -#endif - -#endif /* MEDIAREMOTE_H_ */ \ No newline at end of file diff --git a/Tweak.h b/Tweak.h new file mode 100644 index 0000000..7d5f6af --- /dev/null +++ b/Tweak.h @@ -0,0 +1,45 @@ +#import +#import "SBMediaController.h" +#import + +HBPreferences *preferences; +BOOL enabled; +BOOL enableDND; +BOOL enableHideNotifs; + +@interface NCNotificationListView : UIScrollView +@end + +@interface NCNotificationStructuredListViewController : UIViewController +@property (nonatomic, retain) NCNotificationListView *masterListView; +// %new +-(void)hideNotifs; +-(void)showNotifs; +@end + +//Do Not Disturb +@class DNDModeAssertionLifetime; + +@interface DNDModeAssertionDetails : NSObject ++ (id)userRequestedAssertionDetailsWithIdentifier:(NSString *)identifier modeIdentifier:(NSString *)modeIdentifier lifetime:(DNDModeAssertionLifetime *)lifetime; +- (BOOL)invalidateAllActiveModeAssertionsWithError:(NSError **)error; +- (id)takeModeAssertionWithDetails:(DNDModeAssertionDetails *)assertionDetails error:(NSError **)error; +@end + +@interface DNDModeAssertionService : NSObject ++ (id)serviceForClientIdentifier:(NSString *)clientIdentifier; +- (BOOL)invalidateAllActiveModeAssertionsWithError:(NSError **)error; +- (id)takeModeAssertionWithDetails:(DNDModeAssertionDetails *)assertionDetails error:(NSError **)error; +@end + +static BOOL DNDEnabled; +static DNDModeAssertionService *assertionService; + +typedef struct { + BOOL active; + BOOL enabled; + BOOL sunSchedulePermitted; + int mode; + unsigned long long disableFlags; + BOOL available; +} Status; \ No newline at end of file diff --git a/Tweak.xm b/Tweak.xm index dd9dad5..a3ec5b8 100644 --- a/Tweak.xm +++ b/Tweak.xm @@ -1,17 +1,6 @@ -#import "MediaRemote.h" -#import "SBMediaController.h" -#import - -@interface NCNotificationListView : UIScrollView -@end - -@interface NCNotificationStructuredListViewController : UIViewController -@property (nonatomic, retain) NCNotificationListView *masterListView; -// %new --(void)hideNotifs; --(void)showNotifs; -@end +#import "Tweak.h" +%group VibinTweak %hook NCNotificationStructuredListViewController -(void)viewDidAppear:(BOOL)animated { static dispatch_once_t onceToken; @@ -53,35 +42,7 @@ } %end -//Do Not Disturb -@class DNDModeAssertionLifetime; - -@interface DNDModeAssertionDetails : NSObject -+ (id)userRequestedAssertionDetailsWithIdentifier:(NSString *)identifier modeIdentifier:(NSString *)modeIdentifier lifetime:(DNDModeAssertionLifetime *)lifetime; -- (BOOL)invalidateAllActiveModeAssertionsWithError:(NSError **)error; -- (id)takeModeAssertionWithDetails:(DNDModeAssertionDetails *)assertionDetails error:(NSError **)error; -@end - -@interface DNDModeAssertionService : NSObject -+ (id)serviceForClientIdentifier:(NSString *)clientIdentifier; -- (BOOL)invalidateAllActiveModeAssertionsWithError:(NSError **)error; -- (id)takeModeAssertionWithDetails:(DNDModeAssertionDetails *)assertionDetails error:(NSError **)error; -@end - -static BOOL DNDEnabled; -static DNDModeAssertionService *assertionService; - -typedef struct { - BOOL active; - BOOL enabled; - BOOL sunSchedulePermitted; - int mode; - unsigned long long disableFlags; - BOOL available; -} Status; - - -void enableDND() { +void turnOnDND() { if (!assertionService) { assertionService = (DNDModeAssertionService *)[objc_getClass("DNDModeAssertionService") serviceForClientIdentifier:@"com.apple.donotdisturb.control-center.module"]; } @@ -89,7 +50,7 @@ void enableDND() { [assertionService takeModeAssertionWithDetails:newAssertion error:NULL]; } -void disableDND() { +void turnOffDND() { if (!assertionService) { assertionService = (DNDModeAssertionService *)[objc_getClass("DNDModeAssertionService") serviceForClientIdentifier:@"com.apple.donotdisturb.control-center.module"]; } @@ -120,11 +81,31 @@ SBMediaController *mediaController; %new - (void)currentSongChanged:(NSNotification *)notification { if (mediaController.isPlaying) { - enableDND(); - [[NSNotificationCenter defaultCenter] postNotificationName:@"hideNotificationsOnCS" object:self]; + if (enableDND) { + turnOnDND(); + } + if (enableHideNotifs) { + [[NSNotificationCenter defaultCenter] postNotificationName:@"hideNotificationsOnCS" object:self]; + } } else { - disableDND(); - [[NSNotificationCenter defaultCenter] postNotificationName:@"showNotificationsOnCS" object:self]; + if (enableDND) { + turnOffDND(); + } + if (enableHideNotifs) { + [[NSNotificationCenter defaultCenter] postNotificationName:@"showNotificationsOnCS" object:self]; + } } } -%end \ No newline at end of file +%end + +%end // %group VibinTweak + +%ctor { + preferences = [[HBPreferences alloc] initWithIdentifier:@"com.chr1s.vibinprefs"]; + [preferences registerBool:&enabled default:YES forKey:@"enabled"]; + [preferences registerBool:&enableDND default:YES forKey:@"enableDND"]; + [preferences registerBool:&enableHideNotifs default:YES forKey:@"enableHideNotifs"]; + if (enabled) { + %init(VibinTweak); + } +} \ No newline at end of file diff --git a/control b/control index ab26316..312175f 100644 --- a/control +++ b/control @@ -6,4 +6,4 @@ Description: Don't disrupt the vibe Maintainer: Chr1s Author: Chr1s Section: Tweaks -Depends: mobilesubstrate (>= 0.9.5000) +Depends: mobilesubstrate (>= 0.9.5000), preferenceloader, ws.hbang.common (>= 1.15.1) diff --git a/vibinprefs/KRLinkCell.h b/vibinprefs/KRLinkCell.h new file mode 100644 index 0000000..89bc349 --- /dev/null +++ b/vibinprefs/KRLinkCell.h @@ -0,0 +1,13 @@ +#import "KRTableCell.h" + +@interface KRLinkCell : KRTableCell + +@property (nonatomic, readonly) BOOL isBig; + +@property (nonatomic, retain, readonly) UIView *avatarView; + +@property (nonatomic, retain, readonly) UIImageView *avatarImageView; + +@property (nonatomic, retain) UIImage *avatarImage; + +@end \ No newline at end of file diff --git a/vibinprefs/KRLinkCell.m b/vibinprefs/KRLinkCell.m new file mode 100644 index 0000000..6cbef1d --- /dev/null +++ b/vibinprefs/KRLinkCell.m @@ -0,0 +1,133 @@ +// +// KRLinkCell.m +// Based on Cephei's link cell +// +// Apache 2.0 License for code used in KRPrefsLicense located in preference bundle +// +#import "KRLinkCell.h" +#import +#import +#import +#import + +@implementation KRLinkCell + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier specifier:(PSSpecifier *)specifier +{ + self = [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier specifier:specifier]; + + if (self) { + //_isBig = specifier.properties[@"big"] && ((NSNumber *)specifier.properties[@"big"]).boolValue; + _isBig = YES; + + self.selectionStyle = UITableViewCellSelectionStyleBlue; + self.accessoryView = [[UIImageView alloc] initWithFrame:CGRectMake( 0, 0, 38, 38)];//Image:[UIImage imageNamed:@"safari" inBundle:globalBundle]]; + + self.detailTextLabel.numberOfLines = _isBig ? 0 : 1; + self.detailTextLabel.text = specifier.properties[@"subtitle"] ?: @""; + self.detailTextLabel.textColor = (kCFCoreFoundationVersionNumber < 1600) ? [UIColor grayColor] : [UIColor grayColor]; + + self.textLabel.textColor = (kCFCoreFoundationVersionNumber < 1600) ? [UIColor blackColor] : [UIColor blackColor]; + if (@available(iOS 13, *)) + { + self.tintColor = [UIColor labelColor]; + } + else + { + self.tintColor = [UIColor blackColor]; + } + + if (self.shouldShowAvatar) + { + CGFloat size = _isBig ? 38.f : 29.f; + + UIGraphicsBeginImageContextWithOptions(CGSizeMake(size, size), NO, [UIScreen mainScreen].scale); + specifier.properties[@"iconImage"] = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + _avatarView = [[UIView alloc] initWithFrame:self.imageView.bounds]; + _avatarView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _avatarView.backgroundColor = [UIColor colorWithWhite:0.9f alpha:1]; + _avatarView.userInteractionEnabled = NO; + _avatarView.clipsToBounds = YES; + _avatarView.layer.cornerRadius = IS_IOS_OR_NEWER(iOS_7_0) ? size / 2 : 4.f; + _avatarView.layer.borderWidth = 2; + if (@available(iOS 13, *)) + { + _avatarView.layer.borderColor = [[UIColor colorWithWhite:0.2 alpha:0.3] CGColor]; + } + else + { + _avatarView.layer.borderColor = [[UIColor colorWithWhite:0.2 alpha:0.3] CGColor]; + } + [self.imageView addSubview:_avatarView]; + + if (specifier.properties[@"initials"]) + { + _avatarView.backgroundColor = [UIColor colorWithWhite:0.8f alpha:1]; + + UILabel *label = [[UILabel alloc] initWithFrame:_avatarView.bounds]; + label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + label.font = [UIFont systemFontOfSize:13.f]; + label.textAlignment = NSTextAlignmentCenter; + label.textColor = [UIColor whiteColor]; + label.text = specifier.properties[@"initials"]; + [_avatarView addSubview:label]; + } + else + { + _avatarImageView = [[UIImageView alloc] initWithFrame:_avatarView.bounds]; + _avatarImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _avatarImageView.alpha = 0; + _avatarImageView.userInteractionEnabled = NO; + _avatarImageView.layer.minificationFilter = kCAFilterTrilinear; + [_avatarView addSubview:_avatarImageView]; + + [self loadAvatarIfNeeded]; + } + } + } + + return self; +} + +#pragma mark - Avatar + +- (UIImage *)avatarImage +{ + return _avatarImageView.image; +} + +- (void)setAvatarImage:(UIImage *)avatarImage +{ + _avatarImageView.image = avatarImage; + + if (_avatarImageView.alpha == 0) + { + [UIView animateWithDuration:0.15 + animations:^{ + _avatarImageView.alpha = 1; + } + ]; + } +} +- (void)setSelected:(BOOL)arg1 animated:(BOOL)arg2 +{ + [super setSelected:arg1 animated:arg2]; + + if (!arg1) return; + //[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://github.com/KritantaDev/Axon"] options:@{} completionHandler:nil]; +} + +- (BOOL)shouldShowAvatar +{ + return (self.specifier.properties[@"showAvatar"] && ((NSNumber *)self.specifier.properties[@"showAvatar"]).boolValue) || + self.specifier.properties[@"initials"]; +} + +- (void)loadAvatarIfNeeded +{ + // stub for subclasses +} + +@end \ No newline at end of file diff --git a/vibinprefs/KRTableCell.h b/vibinprefs/KRTableCell.h new file mode 100644 index 0000000..765605f --- /dev/null +++ b/vibinprefs/KRTableCell.h @@ -0,0 +1,4 @@ +#import + +@interface KRTableCell : PSTableCell +@end \ No newline at end of file diff --git a/vibinprefs/KRTableCell.m b/vibinprefs/KRTableCell.m new file mode 100644 index 0000000..848e84e --- /dev/null +++ b/vibinprefs/KRTableCell.m @@ -0,0 +1,25 @@ +// +// KRTableCell.m +// +// This code is directly from HBTintedTableCell in Cephie +// Apache 2.0 License for code used in KRPrefsLicense located in preference bundle +// + +#import "KRTableCell.h" + +@implementation KRTableCell + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.textLabel.textColor = self.tintColor; +} + +- (void)refreshCellContentsWithSpecifier:(PSSpecifier *)specifier { + [super refreshCellContentsWithSpecifier:specifier]; + + if ([self respondsToSelector:@selector(tintColor)]) { + self.textLabel.textColor = self.tintColor; + } +} + +@end \ No newline at end of file diff --git a/vibinprefs/KRTwitterCell.h b/vibinprefs/KRTwitterCell.h new file mode 100644 index 0000000..6de8ec5 --- /dev/null +++ b/vibinprefs/KRTwitterCell.h @@ -0,0 +1,5 @@ +#import "KRLinkCell.h" + +@interface KRTwitterCell : KRLinkCell + +@end \ No newline at end of file diff --git a/vibinprefs/KRTwitterCell.m b/vibinprefs/KRTwitterCell.m new file mode 100644 index 0000000..30b468e --- /dev/null +++ b/vibinprefs/KRTwitterCell.m @@ -0,0 +1,110 @@ +// +// KRTwitterCell.m +// Twitter cell that locally loads pfps +// based on Cephei Framework +// +// Apache 2.0 License for code used in KRPrefsLicense located in preference bundle +// + + +#import "KRTwitterCell.h" +#import +#import +#import + +@interface KRLinkCell () + +- (BOOL)shouldShowAvatar; + +@end + +@interface KRTwitterCell () { + NSString *_user; +} + +@end + +@implementation KRTwitterCell + ++ (NSString *)_urlForUsername:(NSString *)user { + + user = [user stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; + + if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"aphelion://"]]) { + return [@"aphelion://profile/" stringByAppendingString:user]; + } else if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tweetbot://"]]) { + return [@"tweetbot:///user_profile/" stringByAppendingString:user]; + } else if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"twitterrific://"]]) { + return [@"twitterrific:///profile?screen_name=" stringByAppendingString:user]; + } else if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tweetings://"]]) { + return [@"tweetings:///user?screen_name=" stringByAppendingString:user]; + } else if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"twitter://"]]) { + return [@"twitter://user?screen_name=" stringByAppendingString:user]; + } else { + return [@"https://mobile.twitter.com/" stringByAppendingString:user]; + } +} + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier specifier:(PSSpecifier *)specifier +{ + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier specifier:specifier]; + + if (self) { + UIImageView *imageView = (UIImageView *)self.accessoryView; + imageView.image = nil;//[UIImage imageNamed:@"twitter" inBundle:globalBundle]; + [imageView sizeToFit]; + + _user = [specifier.properties[@"accountName"] copy]; + NSAssert(_user, @"User name not provided"); + + specifier.properties[@"url"] = [self.class _urlForUsername:_user]; + + self.detailTextLabel.text = [@"@" stringByAppendingString:_user]; + + [self setCellEnabled:YES]; + + [self loadAvatarIfNeeded]; + } + + return self; +} + +- (void)setSelected:(BOOL)arg1 animated:(BOOL)arg2 +{ + [super setSelected:arg1 animated:arg2]; + + if (!arg1) return; + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[self.class _urlForUsername:_user]] options:@{} completionHandler:nil]; +} + +#pragma mark - Avatar + +- (BOOL)shouldShowAvatar { + // HBLinkTableCell doesn’t want avatars by default, but we do. override its check method so that + // if showAvatar is unset, we return YES + return YES; +} + +- (void)loadAvatarIfNeeded { + if (!_user) { + return; + } + + if (self.avatarImage) { + return; + } + // TODO: fix this + //self.avatarImage = [UIImage imageNamed:[NSString stringWithFormat:@"/Library/PreferenceBundles/SignePrefs.bundle/%@.png", _user]]; + + dispatch_async(dispatch_get_global_queue(0,0), ^{ + // NSData * data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://twitter.com/%@/profile_image?size=original", _user]]]; + NSData * data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:@"https://pbs.twimg.com/profile_images/1357764567171014660/uDm_Ia2I_400x400.jpg"]]; + if ( data == nil ) + return; + dispatch_async(dispatch_get_main_queue(), ^{ + self.avatarImage = [UIImage imageWithData: data]; + }); + }); +} + +@end \ No newline at end of file diff --git a/vibinprefs/Makefile b/vibinprefs/Makefile new file mode 100644 index 0000000..8e68b6f --- /dev/null +++ b/vibinprefs/Makefile @@ -0,0 +1,15 @@ +TARGET := iphone:clang:latest:7.0 +ARCHS = arm64 arm64e + +include $(THEOS)/makefiles/common.mk + +BUNDLE_NAME = vibinprefs + +vibinprefs_FILES = $(wildcard *.m) +vibinprefs_FRAMEWORKS = UIKit +vibinprefs_PRIVATE_FRAMEWORKS = Preferences +$(BUNDLE_NAME)_EXTRA_FRAMEWORKS += Cephei CepheiPrefs +vibinprefs_INSTALL_PATH = /Library/PreferenceBundles +vibinprefs_CFLAGS = -fobjc-arc + +include $(THEOS_MAKE_PATH)/bundle.mk diff --git a/vibinprefs/Resources/Info.plist b/vibinprefs/Resources/Info.plist new file mode 100644 index 0000000..6c161f8 --- /dev/null +++ b/vibinprefs/Resources/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + vibinprefs + CFBundleIdentifier + com.chr1s.vibinprefs + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + NSPrincipalClass + VBNRootListController + + diff --git a/vibinprefs/Resources/Root.plist b/vibinprefs/Resources/Root.plist new file mode 100644 index 0000000..826da7c --- /dev/null +++ b/vibinprefs/Resources/Root.plist @@ -0,0 +1,99 @@ + + + + + items + + + cellClass + KRTwitterCell + label + Chr1s + accountName + chr1sdev + + + cell + PSSwitchCell + default + + defaults + com.chr1s.vibinprefs + key + enabled + label + Enable + PostNotification + com.chr1s.vibinprefs/ReloadPrefs + + + cell + PSGroupCell + label + When music starts + + + cell + PSSwitchCell + default + + defaults + com.chr1s.vibinprefs + key + enableDND + label + Enable Do Not Disturb + PostNotification + com.chr1s.vibinprefs/ReloadPrefs + + + cell + PSSwitchCell + default + + defaults + com.chr1s.vibinprefs + key + enableHideNotifs + label + Hide notifications on lockscreen + PostNotification + com.chr1s.vibinprefs/ReloadPrefs + + + cell + PSGroupCell + label + Links + + + cellClass + HBLinkTableCell + label + Discord + url + https://discord.gg/zHN7yuGqYr + action + discord + + + cellClass + HBLinkTableCell + label + PayPal + action + paypal + + + cellClass + HBLinkTableCell + label + Source Code + action + sourceCode + + + title + Vibin + + diff --git a/vibinprefs/Resources/icon@2x.png b/vibinprefs/Resources/icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..84b938df69aeed1e90aa03be2422e9f1d488dc46 GIT binary patch literal 3824 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 literal 0 HcmV?d00001 diff --git a/vibinprefs/Resources/iconFixed.png b/vibinprefs/Resources/iconFixed.png new file mode 100644 index 0000000000000000000000000000000000000000..0c24479d04fbda97d5f4687b3f7cdd6c560d9608 GIT binary patch literal 1434 zcmV;L1!ek)P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1uscNK~zXfZB|QY zT~!p__r4^}w+V@*R;95;ZHw3x6w!fFK}r!T=tK}ZDAj?Y109G?)PX1!1PA^mf+#vO zYNb{|C>BZ~ZEF2MjU`nRQa}0B*yR1+y{@(QIp^N{(#zX#pR>2gU#<#+cL)6VqiZ6F+$y7PA%+iqAo2+v&k`R)J@uKE!f;RNZwyD!rCCl z2V!J-Z-LA^1#lB3S8Z!~n~uG$u;$ijLjcbIo*1PXV^(U=1v(j!ch=28>&D=(nZOoD zscgWp+p#H@yKgMXz&de$h81)(xifm@i`G06ysCIO*aKwFF?yo?pw0EC15H`qBQnw# zfhdx`ZUIT8c6e#0j-0K_+)`55=kcSL$D3&&3Qc!}bi!oF5sdVS41=Vn69grm0VB}w z!dT?+WKCv4Y6mF8ViIxI3s)+Z!IjsS@TQHC+_oi_EgNDPL;zhKh!)5Zu9He`%#+Dd zlgPJ)nE5it928^?Iis};Z3HH zflrocE(4#jUt{zEh|xNNKnUr^-5tgY1a1=kbOubl7-9}I3#n1WVqYwT7-aJy0 zXZQ8XtB(%JOAimqwre}3gmkk^oo~n(_tXG#S+;3z@`t0nWJA3oPu|xrTd(fW*J247 z^5llodxb11`f{+-n`O`mfIVaDt+uS~B1iHs5|jmkjho8W6?zvjnN* zO+_sAb=se3eL1Mn>5e#+{kwZ*@2%Z(&2UM2@$1p=fPJQ3Dm7LBeRSC|FlKvhwk}f_ z8z5*ShLG4^gDwKfPGoh2iJ>-k-fAOydGU#CG*aw#EvAqL&c=X|Qfm*31^85!&vUs_rWoFjE(J`Gi4whtT zwI$^$?3nXslE1Cy<9;sPn3+!d)G4RV*W_1}hmorw!`bEd19B(Pv_ZaCWgF zD-~A>V!3tSM?Z#Kj`qAT_YTOPut+Q-MzeFYONRPlnVE0O>_St@D6RT1e&+*x%_huM z+c-bhw>P!gwSu4iV(kor+He^XW#D_eey@3u8( zcQ){ZHPt$|g9y2VuY(sp+Wwi6^10*b-%Id%3ZT2OVHfoEYr)-|^g1_N2n0CZ2cI&) o7jT +#import +#import +#import +#import +#import +#import + +@interface VBNRootListController : PSListController +@property (nonatomic, retain) UIBarButtonItem *respringButton; +@property (nonatomic, retain) UILabel *titleLabel; +-(void)discord; +-(void)paypal; +-(void)sourceCode; +@end diff --git a/vibinprefs/VBNRootListController.m b/vibinprefs/VBNRootListController.m new file mode 100644 index 0000000..2668999 --- /dev/null +++ b/vibinprefs/VBNRootListController.m @@ -0,0 +1,54 @@ +#include "VBNRootListController.h" + +@implementation VBNRootListController + +- (instancetype)init { + self = [super init]; + + if (self) { + self.respringButton = [[UIBarButtonItem alloc] initWithTitle:@"Respring" + style:UIBarButtonItemStylePlain + target:self + action:@selector(respring)]; + self.navigationItem.rightBarButtonItem = self.respringButton; + self.navigationItem.titleView = [UIView new]; + self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0,10,10)]; + self.titleLabel.font = [UIFont boldSystemFontOfSize:17]; + self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + self.titleLabel.text = @"Vibin"; + [self.navigationItem.titleView addSubview:self.titleLabel]; + + [NSLayoutConstraint activateConstraints:@[ + [self.titleLabel.topAnchor constraintEqualToAnchor:self.navigationItem.titleView.topAnchor], + [self.titleLabel.leadingAnchor constraintEqualToAnchor:self.navigationItem.titleView.leadingAnchor], + [self.titleLabel.trailingAnchor constraintEqualToAnchor:self.navigationItem.titleView.trailingAnchor], + [self.titleLabel.bottomAnchor constraintEqualToAnchor:self.navigationItem.titleView.bottomAnchor], + ]]; + } + return self; +} + +- (NSArray *)specifiers { + if (!_specifiers) { + _specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self]; + } + + return _specifiers; +} + +-(void)discord { + NSURL *discord = [NSURL URLWithString:@"https://discord.gg/zHN7yuGqYr"]; + [[UIApplication sharedApplication] openURL:discord options:@{} completionHandler:nil]; +} + +-(void)paypal { + NSURL *paypal = [NSURL URLWithString:@"https://paypal.me/chr1sdev"]; + [[UIApplication sharedApplication] openURL:paypal options:@{} completionHandler:nil]; +} + +-(void)sourceCode { + NSURL *source = [NSURL URLWithString:@"https://github.com/Chr1sDev/vibin"]; + [[UIApplication sharedApplication] openURL:source options:@{} completionHandler:nil]; +} + +@end diff --git a/vibinprefs/layout/Library/PreferenceLoader/Preferences/vibinprefs.plist b/vibinprefs/layout/Library/PreferenceLoader/Preferences/vibinprefs.plist new file mode 100644 index 0000000..c08eb84 --- /dev/null +++ b/vibinprefs/layout/Library/PreferenceLoader/Preferences/vibinprefs.plist @@ -0,0 +1,21 @@ + + + + + entry + + bundle + vibinprefs + cell + PSLinkCell + detail + VBNRootListController + icon + icon.png + isController + + label + Vibin + + +