diff --git a/Localizations/uYouPlus.bundle/AppIcons/2013/2013@2x.png b/Localizations/uYouPlus.bundle/AppIcons/2013/2013@2x.png new file mode 100644 index 0000000000..2a755c24dc Binary files /dev/null and b/Localizations/uYouPlus.bundle/AppIcons/2013/2013@2x.png differ diff --git a/Localizations/uYouPlus.bundle/AppIcons/2013/2013@3x.png b/Localizations/uYouPlus.bundle/AppIcons/2013/2013@3x.png new file mode 100644 index 0000000000..40e9950c73 Binary files /dev/null and b/Localizations/uYouPlus.bundle/AppIcons/2013/2013@3x.png differ diff --git a/Localizations/uYouPlus.bundle/AppIcons/2017_Gold/2017_Gold@2x.png b/Localizations/uYouPlus.bundle/AppIcons/2017_Gold/2017_Gold@2x.png new file mode 100644 index 0000000000..ca248ad7de Binary files /dev/null and b/Localizations/uYouPlus.bundle/AppIcons/2017_Gold/2017_Gold@2x.png differ diff --git a/Localizations/uYouPlus.bundle/AppIcons/2017_Gold/2017_Gold@3x.png b/Localizations/uYouPlus.bundle/AppIcons/2017_Gold/2017_Gold@3x.png new file mode 100644 index 0000000000..ef77a45bc3 Binary files /dev/null and b/Localizations/uYouPlus.bundle/AppIcons/2017_Gold/2017_Gold@3x.png differ diff --git a/Localizations/uYouPlus.bundle/AppIcons/Gold/Gold@2x.png b/Localizations/uYouPlus.bundle/AppIcons/Gold/Gold@2x.png new file mode 100644 index 0000000000..15aed68189 Binary files /dev/null and b/Localizations/uYouPlus.bundle/AppIcons/Gold/Gold@2x.png differ diff --git a/Localizations/uYouPlus.bundle/AppIcons/Gold/Gold@3x.png b/Localizations/uYouPlus.bundle/AppIcons/Gold/Gold@3x.png new file mode 100644 index 0000000000..1a37a4958e Binary files /dev/null and b/Localizations/uYouPlus.bundle/AppIcons/Gold/Gold@3x.png differ diff --git a/Localizations/uYouPlus.bundle/AppIcons/Shorts/Shorts@2x.png b/Localizations/uYouPlus.bundle/AppIcons/Shorts/Shorts@2x.png new file mode 100644 index 0000000000..54858bafd4 Binary files /dev/null and b/Localizations/uYouPlus.bundle/AppIcons/Shorts/Shorts@2x.png differ diff --git a/Localizations/uYouPlus.bundle/AppIcons/Shorts/Shorts@3x.png b/Localizations/uYouPlus.bundle/AppIcons/Shorts/Shorts@3x.png new file mode 100644 index 0000000000..61b8670a12 Binary files /dev/null and b/Localizations/uYouPlus.bundle/AppIcons/Shorts/Shorts@3x.png differ diff --git a/Localizations/uYouPlus.bundle/UI/explore_24pt.png b/Localizations/uYouPlus.bundle/UI/explore_24pt.png new file mode 100644 index 0000000000..eae709a406 Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/explore_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/explore_selected_24pt.png b/Localizations/uYouPlus.bundle/UI/explore_selected_24pt.png new file mode 100644 index 0000000000..2a699fb154 Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/explore_selected_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/home_24pt.png b/Localizations/uYouPlus.bundle/UI/home_24pt.png new file mode 100644 index 0000000000..c67a4e0a04 Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/home_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/home_selected_24pt.png b/Localizations/uYouPlus.bundle/UI/home_selected_24pt.png new file mode 100644 index 0000000000..2ad001cea8 Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/home_selected_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/notifications_24pt.png b/Localizations/uYouPlus.bundle/UI/notifications_24pt.png new file mode 100644 index 0000000000..fe5ae23074 Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/notifications_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/notifications_selected_24pt.png b/Localizations/uYouPlus.bundle/UI/notifications_selected_24pt.png new file mode 100644 index 0000000000..b1ed4c9f5c Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/notifications_selected_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/subscriptions_24pt.png b/Localizations/uYouPlus.bundle/UI/subscriptions_24pt.png new file mode 100644 index 0000000000..8bc36876a8 Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/subscriptions_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/subscriptions_selected_24pt.png b/Localizations/uYouPlus.bundle/UI/subscriptions_selected_24pt.png new file mode 100644 index 0000000000..69f1059962 Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/subscriptions_selected_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/yt_outline_bar_graph_box_vertical_24pt.png b/Localizations/uYouPlus.bundle/UI/yt_outline_bar_graph_box_vertical_24pt.png new file mode 100644 index 0000000000..1dce28fd76 Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/yt_outline_bar_graph_box_vertical_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/yt_outline_clapperboard_24pt.png b/Localizations/uYouPlus.bundle/UI/yt_outline_clapperboard_24pt.png new file mode 100644 index 0000000000..a86e37d472 Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/yt_outline_clapperboard_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/yt_outline_download_24pt.png b/Localizations/uYouPlus.bundle/UI/yt_outline_download_24pt.png new file mode 100644 index 0000000000..79f0123a2f Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/yt_outline_download_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/yt_outline_gear_24pt.png b/Localizations/uYouPlus.bundle/UI/yt_outline_gear_24pt.png new file mode 100644 index 0000000000..f11c8b3797 Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/yt_outline_gear_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/yt_outline_my_videos_24pt.png b/Localizations/uYouPlus.bundle/UI/yt_outline_my_videos_24pt.png new file mode 100644 index 0000000000..59ec1224bc Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/yt_outline_my_videos_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/yt_outline_question_circle_24pt.png b/Localizations/uYouPlus.bundle/UI/yt_outline_question_circle_24pt.png new file mode 100644 index 0000000000..d6568b867c Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/yt_outline_question_circle_24pt.png differ diff --git a/Localizations/uYouPlus.bundle/UI/yt_outline_search_24pt.png b/Localizations/uYouPlus.bundle/UI/yt_outline_search_24pt.png new file mode 100644 index 0000000000..4932327b39 Binary files /dev/null and b/Localizations/uYouPlus.bundle/UI/yt_outline_search_24pt.png differ diff --git a/Makefile b/Makefile index 604b19eb15..f089ea2c89 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -export TARGET = iphone:clang:16.4:14.0 +export TARGET = iphone:clang:16.5:14.0 export ARCHS = arm64 export libcolorpicker_ARCHS = arm64 diff --git a/README.md b/README.md index df6fbf10e8..6fa61145ba 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,6 @@ [![Wiki](https://img.shields.io/badge/Wiki-blue?style=flat)](#wiki)
# Credits -- Special thanks to all the developers who have worked on uYouPlus/uYouEnhanced! - @@ -204,13 +202,13 @@ balackburn - + @@ -224,6 +222,15 @@
bhackel + + +
- - + +
-theos +dodieboy
+ + + +
+theos +
@@ -337,14 +344,29 @@ or [qnblackcat/Building - Wiki](https://github.com/qnblackcat/uYouPlus/wiki/Buil See [Installation - Wiki](https://github.com/qnblackcat/uYouPlus/wiki/Installation). # Support the developers -- [**MiRO92**](https://twitter.com/miro92): https://github.com/MiRO92/uYou-for-YouTube#support -- [**PoomSmart**](https://github.com/PoomSmart): https://poomsmart.github.io -- [**level3tjg**](https://twitter.com/level3tjg): https://ko-fi.com/level3tjg -- [**BandarHL**](https://twitter.com/bandarhl): https://www.paypal.com/paypalme/BandarHL -- [**julioverne**](https://twitter.com/ijulioverne): https://www.patreon.com/julioverne -- [**Galactic-dev**](https://twitter.com/dev_galactic): - - Paypal: https://www.paypal.com/paypalme/DBrett684 - - Venmo: https://venmo.com/u/DavidBrett + +  + + + +  + + + +  + + + + +  + + +  + + +  + + # Wiki @@ -371,9 +393,9 @@ https://github.com/Balackburn/YTLitePlus/releases - YTLitePlus does not cause your device to overheat, unlike uYouEnhanced. -**Cons** +- YTLitePlus provides faster video & audio downloading than uYouPlus/uYouEnhanced. -- No custom video downloading feature in YTLitePlus. +**Cons** - Video quality on WiFi option is not available in YTLitePlus. diff --git a/Sources/AppIconOptionsController.m b/Sources/AppIconOptionsController.m index 1de53edf9a..d09c3698f9 100644 --- a/Sources/AppIconOptionsController.m +++ b/Sources/AppIconOptionsController.m @@ -24,8 +24,6 @@ - (void)viewDidLoad { self.tableView.delegate = self; [self.view addSubview:self.tableView]; - self.appIcons = @[@"White", @"YTLitePlus", @"Blue", @"Outline", @"2012", @"2013", @"2007", @"Black", @"Oreo", @"uYou", @"2012_Cyan", @"uYouPlus"]; - self.backButton = [UIButton buttonWithType:UIButtonTypeCustom]; NSBundle *backIcon = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"uYouPlus" ofType:@"bundle"]]; UIImage *backImage = [UIImage imageNamed:@"Back.png" inBundle:backIcon compatibleWithTraitCollection:nil]; @@ -72,18 +70,22 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"]; } - NSString *iconName = self.appIcons[indexPath.row]; - cell.textLabel.text = iconName; - - UIImage *iconImage = [UIImage imageNamed:iconName]; - cell.imageView.image = [self createRoundedImage:iconImage size:CGSizeMake(40, 40)]; - + NSString *iconPath = self.appIcons[indexPath.row]; + cell.textLabel.text = [iconPath.lastPathComponent stringByDeletingPathExtension]; + + UIImage *iconImage = [UIImage imageWithContentsOfFile:iconPath]; + cell.imageView.image = iconImage; + cell.imageView.layer.cornerRadius = 10.0; + cell.imageView.clipsToBounds = YES; + cell.imageView.frame = CGRectMake(10, 10, 40, 40); + cell.textLabel.frame = CGRectMake(60, 10, self.view.frame.size.width - 70, 40); + if (indexPath.row == self.selectedIconIndex) { cell.accessoryType = UITableViewCellAccessoryCheckmark; } else { cell.accessoryType = UITableViewCellAccessoryNone; } - + return cell; } @@ -95,6 +97,11 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath } - (void)resetIcon { + NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"]; + NSMutableDictionary *infoDict = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath]; + [infoDict removeObjectForKey:@"ALTAppIcon"]; + [infoDict writeToFile:plistPath atomically:YES]; + [[UIApplication sharedApplication] setAlternateIconName:nil completionHandler:^(NSError * _Nullable error) { if (error) { NSLog(@"Error resetting icon: %@", error.localizedDescription); @@ -102,7 +109,9 @@ - (void)resetIcon { } else { NSLog(@"Icon reset successfully"); [self showAlertWithTitle:@"Success" message:@"Icon reset successfully"]; - [self.tableView reloadData]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self.tableView reloadData]; + }); } }]; } @@ -112,55 +121,50 @@ - (void)saveIcon { NSLog(@"Alternate icons are not supported on this device."); return; } - - NSString *iconName = self.appIcons[self.selectedIconIndex]; - - NSString *path = [[NSBundle mainBundle] pathForResource:@"uYouPlus" ofType:@"bundle"]; - NSBundle *bundle = [NSBundle bundleWithPath:path]; - NSString *imagePath = [bundle pathForResource:iconName ofType:@"png"]; - UIImage *iconImage = [UIImage imageWithContentsOfFile:imagePath]; - - if (!iconImage) { - NSLog(@"Failed to load custom icon image"); - return; - } - - UIImage *roundedIconImage = [self createRoundedImage:iconImage size:CGSizeMake(120, 120)]; // Adjust size as needed - - NSData *imageData = UIImagePNGRepresentation(roundedIconImage); - NSString *newIconPath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@_custom", iconName] ofType:@"png"]; - [imageData writeToFile:newIconPath atomically:YES]; - - [[UIApplication sharedApplication] setAlternateIconName:[NSString stringWithFormat:@"%@_custom", iconName] completionHandler:^(NSError * _Nullable error) { - if (error) { - NSLog(@"Error setting alternate icon: %@", error.localizedDescription); - [self showAlertWithTitle:@"Error" message:@"Failed to set alternate icon"]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSString *selectedIcon = self.selectedIconIndex >= 0 ? self.appIcons[self.selectedIconIndex] : nil; + if (selectedIcon) { + NSString *iconName = [selectedIcon.lastPathComponent stringByDeletingPathExtension]; + + NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"]; + NSMutableDictionary *infoDict = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath]; + [infoDict setObject:iconName forKey:@"ALTAppIcon"]; + [infoDict writeToFile:plistPath atomically:YES]; + + [[UIApplication sharedApplication] setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) { + if (error) { + NSLog(@"Error setting alternate icon: %@", error.localizedDescription); + [self showAlertWithTitle:@"Error" message:@"Failed to set alternate icon"]; + } else { + NSLog(@"Alternate icon set successfully"); + [self showAlertWithTitle:@"Success" message:@"Alternate icon set successfully"]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self.tableView reloadData]; + }); + } + }]; } else { - NSLog(@"Alternate icon set successfully"); - [self showAlertWithTitle:@"Success" message:@"Alternate icon set successfully"]; - [self.tableView reloadData]; + NSLog(@"Selected icon path is nil"); } - }]; + }); } -- (UIImage *)createRoundedImage:(UIImage *)image size:(CGSize)size { +- (UIImage *)resizeImage:(UIImage *)image toSize:(CGSize)size { UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale); - UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, size.width, size.height) cornerRadius:size.width * 0.1]; // Adjust the corner radius as needed - [path addClip]; [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; - UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext(); + UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); - return roundedImage; + return resizedImage; } -- (UIImage *)resizeImage:(UIImage *)image newSize:(CGSize)newSize { // Back Button +- (UIImage *)resizeImage:(UIImage *)image newSize:(CGSize)newSize { UIGraphicsBeginImageContextWithOptions(newSize, NO, [UIScreen mainScreen].scale); [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; - } +} - (void)showAlertWithTitle:(NSString *)title message:(NSString *)message { dispatch_async(dispatch_get_main_queue(), ^{ diff --git a/Sources/uYouPlus.h b/Sources/uYouPlus.h index 96cf63a69d..ff041701ad 100644 --- a/Sources/uYouPlus.h +++ b/Sources/uYouPlus.h @@ -1,53 +1,48 @@ #import -#import -#import #import -#import +#import #import -#import -#import +#import +#import #import - -#import "uYouPlusThemes.h" // Hide "Buy Super Thanks" banner (_ASDisplayView) -#import // Activate FLEX -#import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import #import #import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import #import -#import -#import -#import +#import +#import +#import +#import +#import +#import #import -#import // Fixes uYou crash when trying to play video (#1422) - -// Hide buttons under the video player by @PoomSmart -#import -#import -#import - -// YouTube-X +#import +#import +#import +#import +#import +#import +#import +#import +#import #import +#import +#import +#import #import -#import +#import +#import +#import +#import "uYouPlusThemes.h" // uYouPlus Themes #define LOC(x) [tweakBundle localizedStringForKey:x value:nil table:nil] #define IS_ENABLED(k) [[NSUserDefaults standardUserDefaults] boolForKey:k] @@ -58,12 +53,8 @@ #define LOWCONTRASTMODE_CUTOFF_VERSION @"17.38.10" // LowContrastMode (v17.33.2-17.38.10) // Always show remaining time in video player - @bhackel -@interface YTPlayerBarController : NSObject -@property(nonatomic, strong) YTInlinePlayerBarContainerView *playerBar; -@end -@interface YTInlinePlayerBarContainerView (uYouEnhanced) -@property(nonatomic, assign) BOOL shouldDisplayTimeRemaining; -@end +// Header has been moved to https://github.com/PoomSmart/YouTubeHeader/blob/main/YTPlayerBarController.h +// Header has been moved to https://github.com/PoomSmart/YouTubeHeader/blob/main/YTInlinePlayerBarContainerView.h // IAmYouTube @interface SSOConfiguration : NSObject @@ -90,7 +81,7 @@ @end // YTTapToSeek - https://github.com/bhackel/YTTapToSeek -// Header has been moved to https://github.com/arichornlover/YouTubeHeader/blob/main/YTMainAppVideoPlayerOverlayViewController.h +// Header has been moved to https://github.com/arichornloverALT/YouTubeHeader/blob/main/YTMainAppVideoPlayerOverlayViewController.h // Enable Premium logo - @bhackel @interface YTITopbarLogoRenderer : NSObject @@ -136,12 +127,13 @@ @end // Disable Pull to Full for landscape videos - @bhackel -@interface YTWatchPullToFullController : NSObject -@property(nonatomic, strong) YTWatchViewController *playerViewSource; -@end +// Header has been moved to https://github.com/PoomSmart/YouTubeHeader/blob/main/YTWatchPullToFullController.h + +// Fullscreen to the Right (uYouEnhanced Version) - @arichornlover @interface YTWatchViewController (uYouEnhanced) -@property(nonatomic, strong) YTWatchPullToFullController *pullToFullController; -- (NSUInteger)allowedFullScreenOrientations; +- (UIInterfaceOrientationMask) supportedInterfaceOrientations; +- (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation; +- (void)forceRightFullscreenOrientation; @end // uYouPlus @@ -191,12 +183,16 @@ // Buttons @interface YTRightNavigationButtons : UIView - (id)_viewControllerForAncestor; -@property(readonly, nonatomic) YTQTMButton *searchButton; -@property(readonly, nonatomic) YTQTMButton *notificationButton; -@property(strong, nonatomic) YTQTMButton *sponsorBlockButton; -@property(strong, nonatomic) YTQTMButton *uYouPlusButton; +@property (readonly, nonatomic) NSArray *dynamicButtons; +@property (readonly, nonatomic) NSArray *visibleButtons; +@property (readonly, nonatomic) NSArray *buttons; +@property (readonly, nonatomic) YTQTMButton *searchButton; +@property (readonly, nonatomic) YTQTMButton *notificationButton; +@property (strong, nonatomic) YTQTMButton *sponsorBlockButton; +@property (strong, nonatomic) YTQTMButton *settingsButton; +- (void)setDynamicButtons:(NSArray *)buttons; - (void)setLeadingPadding:(CGFloat)arg1; -- (void)uYouPlusRootOptionsAction; +- (void)settingsAction; @end @interface YTISlimMetadataButtonSupportedRenderers : NSObject diff --git a/Sources/uYouPlus.xm b/Sources/uYouPlus.xm index f566aa8966..0c0534f779 100644 --- a/Sources/uYouPlus.xm +++ b/Sources/uYouPlus.xm @@ -70,6 +70,11 @@ NSBundle *tweakBundle = uYouPlusBundle(); - (BOOL)isMonetized { return NO; } %end +%hook YTAdShieldUtils ++ (id)spamSignalsDictionary { return @{}; } ++ (id)spamSignalsDictionaryWithoutIDFA { return @{}; } +%end + %hook YTDataUtils + (id)spamSignalsDictionary { return @{}; } + (id)spamSignalsDictionaryWithoutIDFA { return @{}; } @@ -102,6 +107,10 @@ NSBundle *tweakBundle = uYouPlusBundle(); %hook YTIPlayerResponse - (BOOL)isMonetized { return NO; } %end +%hook YTAdShieldUtils ++ (id)spamSignalsDictionary { return @{}; } ++ (id)spamSignalsDictionaryWithoutIDFA { return @{}; } +%end %hook YTDataUtils + (id)spamSignalsDictionary { return @{}; } + (id)spamSignalsDictionaryWithoutIDFA { return @{}; } @@ -120,29 +129,44 @@ NSBundle *tweakBundle = uYouPlusBundle(); %orig; } %end -BOOL isAdString(NSString *description) { - if ([description containsString:@"brand_promo"] - || [description containsString:@"carousel_footered_layout"] - || [description containsString:@"carousel_headered_layout"] - || [description containsString:@"feed_ad_metadata"] - || [description containsString:@"full_width_portrait_image_layout"] - || [description containsString:@"full_width_square_image_layout"] - || [description containsString:@"home_video_with_context"] - || [description containsString:@"landscape_image_wide_button_layout"] - || [description containsString:@"product_engagement_panel"] - || [description containsString:@"product_item"] - || [description containsString:@"shelf_header"] - || [description containsString:@"square_image_layout"] - || [description containsString:@"text_image_button_layout"] - || [description containsString:@"text_search_ad"] - || [description containsString:@"expandable_list"] - || [description containsString:@"expandable_metadata"] - || [description containsString:@"video_display_full_layout"] - || [description containsString:@"video_display_full_buttoned_layout"]) - return YES; - return NO; +NSString *getAdString(NSString *description) { + if ([description containsString:@"brand_promo"]) + return @"brand_promo"; + if ([description containsString:@"carousel_footered_layout"]) + return @"carousel_footered_layout"; + if ([description containsString:@"carousel_headered_layout"]) + return @"carousel_headered_layout"; + if ([description containsString:@"feed_ad_metadata"]) + return @"feed_ad_metadata"; + if ([description containsString:@"full_width_portrait_image_layout"]) + return @"full_width_portrait_image_layout"; + if ([description containsString:@"full_width_square_image_layout"]) + return @"full_width_square_image_layout"; + if ([description containsString:@"landscape_image_wide_button_layout"]) + return @"landscape_image_wide_button_layout"; + if ([description containsString:@"post_shelf"]) + return @"post_shelf"; + if ([description containsString:@"product_carousel"]) + return @"product_carousel"; + if ([description containsString:@"product_engagement_panel"]) + return @"product_engagement_panel"; + if ([description containsString:@"product_item"]) + return @"product_item"; + if ([description containsString:@"statement_banner"]) + return @"statement_banner"; + if ([description containsString:@"square_image_layout"]) + return @"square_image_layout"; + if ([description containsString:@"text_image_button_layout"]) + return @"text_image_button_layout"; + if ([description containsString:@"text_search_ad"]) + return @"text_search_ad"; + if ([description containsString:@"video_display_full_layout"]) + return @"video_display_full_layout"; + if ([description containsString:@"video_display_full_buttoned_layout"]) + return @"video_display_full_buttoned_layout"; + return nil; } -NSData *cellDividerData; +static __strong NSData *cellDividerData; %hook YTIElementRenderer - (NSData *)elementData { NSString *description = [self description]; @@ -150,7 +174,16 @@ NSData *cellDividerData; if (!cellDividerData) cellDividerData = %orig; return cellDividerData; } - if ([self respondsToSelector:@selector(hasCompatibilityOptions)] && self.hasCompatibilityOptions && self.compatibilityOptions.hasAdLoggingData) return cellDividerData; + if (!cellDividerData) return %orig; + if ([self respondsToSelector:@selector(hasCompatibilityOptions)] && self.hasCompatibilityOptions && self.compatibilityOptions.hasAdLoggingData) { + // HBLogInfo(@"YTX adLogging 1 %@", cellDividerData); + return cellDividerData; + } + NSString *adString = getAdString(description); + if (adString) { + // HBLogInfo(@"YTX getAdString 1 %@ %@", adString, cellDividerData); + return cellDividerData; + } return %orig; } %end @@ -164,41 +197,23 @@ NSData *cellDividerData; YTIItemSectionRenderer *sectionRenderer = renderers.itemSectionRenderer; YTIItemSectionSupportedRenderers *firstObject = [sectionRenderer.contentsArray firstObject]; YTIElementRenderer *elementRenderer = firstObject.elementRenderer; + if ([elementRenderer respondsToSelector:@selector(hasCompatibilityOptions)] && elementRenderer.hasCompatibilityOptions && elementRenderer.compatibilityOptions.hasAdLoggingData) { + // HBLogInfo(@"YTX adLogging 2 %@", elementRenderer); + return YES; + } NSString *description = [elementRenderer description]; - return isAdString(description) - || [description containsString:@"post_shelf"] - || [description containsString:@"product_carousel"] - || [description containsString:@"statement_banner"]; - }]; - [contentsArray removeObjectsAtIndexes:removeIndexes]; - } - %orig; -} -%end -%hook YTWatchNextResultsViewController -- (void)loadWithModel:(YTISectionListRenderer *)watchNextResults { - if ([watchNextResults isKindOfClass:%c(YTISectionListRenderer)]) { - NSMutableArray *contentsArray = watchNextResults.contentsArray; - NSIndexSet *removeIndexes = [contentsArray indexesOfObjectsPassingTest:^BOOL(YTISectionListSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) { - if (![renderers isKindOfClass:%c(YTISectionListSupportedRenderers)]) - return NO; - YTIItemSectionRenderer *sectionRenderer = renderers.itemSectionRenderer; - YTIItemSectionSupportedRenderers *firstObject = [sectionRenderer.contentsArray firstObject]; - YTIElementRenderer *elementRenderer = firstObject.elementRenderer; - NSString *description = [elementRenderer description]; - return isAdString(description); + NSString *adString = getAdString(description); + if (adString) { + // HBLogInfo(@"YTX getAdString 2 %@ %@", adString, elementRenderer); + return YES; + } + return NO; }]; [contentsArray removeObjectsAtIndexes:removeIndexes]; } %orig; } %end -%hook _ASDisplayView -- (void)didMoveToWindow { - %orig(); - if ([self.accessibilityIdentifier isEqualToString:@"id.products_in_video_with_preview_overlay_badge.view"]) self.hidden = YES; -} -%end %end // Hide YouTube Logo - @dayanch96 @@ -231,7 +246,6 @@ NSData *cellDividerData; %end %end - // Fix App Group Directory by move it to document directory %hook NSFileManager - (NSURL *)containerURLForSecurityApplicationGroupIdentifier:(NSString *)groupIdentifier { @@ -286,6 +300,9 @@ NSData *cellDividerData; - (BOOL)isLandscapeEngagementPanelSwipeRightToDismissEnabled { return YES; } // Swipe right to dismiss the right panel in fullscreen mode - (BOOL)enableModularPlayerBarController { return NO; } // fixes some of the iSponorBlock problems - (BOOL)mainAppCoreClientEnableCairoSettings { return IS_ENABLED(@"newSettingsUI_enabled"); } // New grouped settings UI +- (BOOL)enableIosFloatingMiniplayer { return IS_ENABLED(@"floatingMiniplayer_enabled"); } // Floating Miniplayer +- (BOOL)enableIosFloatingMiniplayerSwipeUpToExpand { return IS_ENABLED(@"floatingMiniplayer_enabled"); } // Floating Miniplayer +- (BOOL)enableIosFloatingMiniplayerRepositioning { return IS_ENABLED(@"floatingMiniplayer2_enabled"); } // Floating Miniplayer (Repositioning Support, Removes Swiping Up Gesture) %end // Fix Casting: https://github.com/arichornlover/uYouEnhanced/issues/606#issuecomment-2098289942 @@ -334,6 +351,21 @@ NSData *cellDividerData; - (BOOL)savedSettingShouldExpire { return NO; } %end +// Restore Settings Button in Navigaton Bar - @arichornlover & @bhackel - https://github.com/arichornlover/uYouEnhanced/issues/178 +/* WILL RESULT IN LOSING THE SETTINGS BUTTON! +%hook YTRightNavigationButtons +- (id)visibleButtons { + Class YTVersionUtilsClass = %c(YTVersionUtils); + NSString *appVersion = [YTVersionUtilsClass performSelector:@selector(appVersion)]; + NSComparisonResult result = [appVersion compare:@"18.35.4" options:NSNumericSearch]; + if (result == NSOrderedAscending) { + return %orig; + } + return [self dynamicButtons]; +} +%end +*/ + // Hide "Get Youtube Premium" in "You" tab - @bhackel %group gHidePremiumPromos %hook YTAppCollectionViewController @@ -546,6 +578,18 @@ NSData *cellDividerData; } %end +// Classic Video Player (Restores the v16.xx.x Video Player Functionality) - @arichornlover +// To-do: disabling "Precise Video Scrubbing" https://9to5google.com/2022/06/29/youtube-precise-video-scrubbing/ +%group gClassicVideoPlayer +%hook YTColdConfig +- (BOOL)isPinchToEnterFullscreenEnabled { return YES; } // Restore Pinch-to-fullscreen +- (BOOL)deprecateTabletPinchFullscreenGestures { return NO; } // Restore Pinch-to-fullscreen +%end +%hook YTHotConfig +- (BOOL)isTabletFullscreenSwipeGesturesEnabled { return NO; } // Disable Swipe-to-fullscreen (iPad) +%end +%end + // Fix LowContrastMode - @arichornlover static int contrastMode() { NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]; @@ -598,7 +642,7 @@ static int contrastMode() { */ %end -// Disable Modern/Rounded Buttons (_ASDisplayView Version's not included) - @arichornlover +// Disable Modern/Rounded Buttons (_ASDisplayView Version's not supported) - @arichornlover %group gDisableModernButtons %hook YTQTMButton // Disable Modern/Rounded Buttons + (BOOL)buttonModernizationEnabled { return NO; } @@ -620,15 +664,29 @@ static int contrastMode() { - (BOOL)cxClientEnableModernizedActionSheet { return NO; } - (BOOL)enableClientShortsSheetsModernization { return NO; } - (BOOL)enableTimestampModernizationForNative { return NO; } -- (BOOL)modernizeElementsTextColor { return NO; } -- (BOOL)modernizeElementsBgColor { return NO; } +- (BOOL)mainAppCoreClientEnableModernIaFeedStretchBottom { return NO; } +- (BOOL)mainAppCoreClientEnableModernIaFrostedBottomBar { return NO; } +- (BOOL)mainAppCoreClientEnableModernIaFrostedPivotBar { return NO; } +- (BOOL)mainAppCoreClientEnableModernIaFrostedPivotBarUpdatedBackdrop { return NO; } +- (BOOL)mainAppCoreClientEnableModernIaFrostedTopBar { return NO; } +- (BOOL)mainAppCoreClientEnableModernIaOpacityPivotBar { return NO; } +- (BOOL)mainAppCoreClientEnableModernIaTopAndBottomBarIconRefresh { return NO; } +- (BOOL)mainAppCoreClientEnableModernizedBedtimeReminderU18DefaultSettings { return NO; } +- (BOOL)modernizeCameoNavbar { return NO; } - (BOOL)modernizeCollectionLockups { return NO; } +- (BOOL)modernizeCollectionLockupsShowVideoCount { return NO; } +- (BOOL)modernizeElementsBgColor { return NO; } +- (BOOL)modernizeElementsTextColor { return NO; } +- (BOOL)postsCreatorClientEnableModernButtonsUi { return NO; } +- (BOOL)pullToFullModernEdu { return NO; } +- (BOOL)showModernMiniplayerRedesign { return NO; } - (BOOL)uiSystemsClientGlobalConfigEnableModernButtonsForNative { return NO; } - (BOOL)uiSystemsClientGlobalConfigIosEnableModernTabsForNative { return NO; } -- (BOOL)uiSystemsClientGlobalConfigIosEnableEpUxUpdates { return NO; } -- (BOOL)uiSystemsClientGlobalConfigIosEnableSheetsUxUpdates { return NO; } - (BOOL)uiSystemsClientGlobalConfigIosEnableSnackbarModernization { return NO; } +- (BOOL)uiSystemsClientGlobalConfigModernizeNativeBgColor { return NO; } +- (BOOL)uiSystemsClientGlobalConfigModernizeNativeTextColor { return NO; } // Disable Rounded Content +- (BOOL)enableIosFloatingMiniplayerRoundedCornerRadius { return YES; } - (BOOL)iosDownloadsPageRoundedThumbs { return NO; } - (BOOL)iosRoundedSearchBarSuggestZeroPadding { return NO; } - (BOOL)uiSystemsClientGlobalConfigEnableRoundedDialogForNative { return NO; } @@ -680,11 +738,21 @@ static int contrastMode() { %end %end -// Hide YouTube Heatwaves in Video Player (YouTube v17.19.2-latest) - @level3tjg - https://www.reddit.com/r/jailbreak/comments/v29yvk/ +// Hide YouTube Heatwaves in Video Player - v17.33.2+ - @arichornlover %group gHideHeatwaves %hook YTInlinePlayerBarContainerView - (BOOL)canShowHeatwave { return NO; } %end +%hook YTPlayerBarHeatwaveView +- (id)initWithFrame:(CGRect)frame heatmap:(id)heat { + return NULL; +} +%end +%hook YTPlayerBarController +- (void)setHeatmap:(id)arg1 { + %orig(NULL); +} +%end %end // YTNoSuggestedVideo - https://github.com/bhackel/YTNoSuggestedVideo @@ -783,6 +851,31 @@ static int contrastMode() { %end %end +// Fullscreen to the Right - @arichornlover +%group gFullscreenToTheRight +%hook YTWatchViewController +- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { + if ([self fullscreen] && UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { + return UIInterfaceOrientationLandscapeRight; + } + return %orig; +} +- (UIInterfaceOrientationMask)supportedInterfaceOrientations { + if ([self fullscreen] && UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { + return UIInterfaceOrientationMaskLandscape; + } + return %orig; +} +%new +- (void)forceRightFullscreenOrientation { + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { + NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight]; + [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; + } +} +%end +%end + // Disable Double tap to skip chapter - @bhackel %hook YTDoubleTapToSeekController - (void)didTwoFingerDoubleTap:(id)arg1 { @@ -793,7 +886,6 @@ static int contrastMode() { } %end - // Disable snap to chapter %hook YTSegmentableInlinePlayerBarView - (void)didMoveToWindow { @@ -804,7 +896,6 @@ static int contrastMode() { } %end - // Disable Pinch to zoom %hook YTColdConfig - (BOOL)videoZoomFreeZoomEnabledGlobalConfig { @@ -973,7 +1064,9 @@ static int contrastMode() { } %end -// Hide Fullscreen Button - @arichornlover - PoomSmart's Newer Version of the *YouQuality* tweak breaks when enabling this +/* +// LEGACY VERSION ⚠️ +// Hide Fullscreen Button - @arichornlover - PoomSmart's 1.2.0+ Versions of the *YouQuality* tweak makes the button invisible when enabling this %hook YTInlinePlayerBarContainerView - (void)layoutSubviews { %orig; @@ -990,6 +1083,18 @@ static int contrastMode() { } } %end +*/ + +// NEW VERSION +// Hide Fullscreen Button - @arichornlover +%group gHideFullscreenButton +%hook YTInlinePlayerBarContainerView +- (BOOL)fullscreenButtonDisabled { return YES; } +- (BOOL)canShowFullscreenButton { return NO; } +- (BOOL)canShowFullscreenButtonExperimental { return NO; } +// - (void)setFullscreenButtonDisabled:(BOOL) // Uncomment and might implement this if needed - @arichornlover +%end +%end // Hide HUD Messages %hook YTHUDMessageView @@ -1004,7 +1109,7 @@ static int contrastMode() { return IS_ENABLED(@"hideChannelWatermark_enabled") ? NO : %orig; } %end -// Hide Channel Watermark (for Old YouTube Versions / Backwards Compatibility) +// Hide Channel Watermark (for Backwards Compatibility) %hook YTAnnotationsViewController - (void)loadFeaturedChannelWatermark { if (IS_ENABLED(@"hideChannelWatermark_enabled")) {} @@ -1186,31 +1291,17 @@ static int contrastMode() { } %end -/* -// Hide Shorts Cells - @PoomSmart, @iCrazeiOS & @Dayanch96 +/* DISABLED DUE TO CONFLICTS +// Hide Community Posts - @michael-winay, @arichornlover, @iCrazeiOS @PoomSmart & @Dayanch96 %hook YTIElementRenderer - (NSData *)elementData { NSString *description = [self description]; - if ([NSUserDefaults.standardUserDefaults boolForKey:@"removeShortsCell"]) { // uYou (Hide Shorts Cells) - if ([description containsString:@"shorts_shelf.eml"] || [description containsString:@"#shorts"] || [description containsString:@"shorts_video_cell.eml"] || [description containsString:@"6Shorts"]) { - if (![description containsString:@"history*"]) { - if (!cellDividerData) cellDividerData = %orig; - return cellDividerData; - } - } - } -// Hide Community Posts @michael-winay & @arichornlover if (IS_ENABLED(@"hideCommunityPosts_enabled")) { if ([description containsString:@"post_base_wrapper.eml"]) { - if (!cellDividerData) cellDividerData = %orig; + if (!cellDividerData) cellDividerData = [NSData dataWithBytes:cellDividerDataBytes length:cellDividerDataBytesLength]; return cellDividerData; } } -// etc. - @Dayanch96 - BOOL hasShorts = ([description containsString:@"shorts_shelf.eml"] || [description containsString:@"shorts_video_cell.eml"] || [description containsString:@"6Shorts"]) && ![description containsString:@"history*"]; - BOOL hasShortsInHistory = [description containsString:@"compact_video.eml"] && [description containsString:@"youtube_shorts_"]; - - if (hasShorts || hasShortsInHistory) return cellDividerData; return %orig; } %end @@ -1225,21 +1316,22 @@ static int contrastMode() { color = [UIColor redColor]; } } -// Hide the Button Containers under the Video Player - 17.33.2 and up - @arichornlover + // Hide the Button Containers under the Video Player - 17.33.2 and up - @arichornlover if (IS_ENABLED(@"hideButtonContainers_enabled")) { if ([description containsString:@"id.video.like.button"] || [description containsString:@"id.video.dislike.button"] || [description containsString:@"id.video.share.button"] || [description containsString:@"id.video.remix.button"] || [description containsString:@"id.ui.add_to.offline.button"]) { - color = [UIColor clearColor]; +// self.hidden = YES; } } %orig(color); } %end -// Hide the (Connect / Thanks / Save / Report) Buttons under the Video Player - 17.33.2 and up - @arichornlover (inspired by @PoomSmart's version) LEGACY METHOD ⚠️ +// LEGACY VERSION ⚠️ +// Hide the (Connect / Thanks / Save / Report) Buttons under the Video Player - 17.33.2 and up - @arichornlover (inspired by @PoomSmart's version) %hook _ASDisplayView - (void)layoutSubviews { %orig; @@ -1262,11 +1354,12 @@ static int contrastMode() { } %end +// UPDATED VERSION // Hide the (Connect / Share / Remix / Thanks / Download / Clip / Save / Report) Buttons under the Video Player - 17.33.2 and up - @PoomSmart (inspired by @arichornlover) - METHOD BROKE Server-Side on May 14th 2024 static BOOL findCell(ASNodeController *nodeController, NSArray *identifiers) { for (id child in [nodeController children]) { if ([child isKindOfClass:%c(ELMNodeController)]) { - NSArray *elmChildren = [(ELMNodeController *)child children]; + NSArray *elmChildren = [(ELMNodeController * _Nullable)child children]; for (ELMComponent *elmChild in elmChildren) { for (NSString *identifier in identifiers) { if ([[elmChild description] containsString:identifier]) @@ -1276,8 +1369,8 @@ static BOOL findCell(ASNodeController *nodeController, NSArray *ide } if ([child isKindOfClass:%c(ASNodeController)]) { - ASDisplayNode *childNode = ((ASNodeController *)child).node; // ELMContainerNode - NSArray *yogaChildren = childNode.yogaChildren; + ASDisplayNode *childNode = ((ASNodeController * _Nullable)child).node; // ELMContainerNode + NSArray *yogaChildren = childNode.yogaChildren; for (ASDisplayNode *displayNode in yogaChildren) { if ([identifiers containsObject:displayNode.accessibilityIdentifier]) return YES; @@ -1293,7 +1386,7 @@ static BOOL findCell(ASNodeController *nodeController, NSArray *ide %hook ASCollectionView // This stopped working on May 14th 2024 due to a Server-Side Change from YouTube. -- (CGSize)sizeForElement:(ASCollectionElement *)element { +- (CGSize)sizeForElement:(ASCollectionElement * _Nullable)element { if ([self.accessibilityIdentifier isEqualToString:@"id.video.scrollable_action_bar"]) { ASCellNode *node = [element node]; ASNodeController *nodeController = [node controller]; @@ -1430,19 +1523,6 @@ static BOOL findCell(ASNodeController *nodeController, NSArray *ide } %end -// %hook YTSectionListViewController -// - (void)loadWithModel:(YTISectionListRenderer *)model { -// NSMutableArray *contentsArray = model.contentsArray; -// NSIndexSet *removeIndexes = [contentsArray indexesOfObjectsPassingTest:^BOOL(YTISectionListSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) { -// YTIItemSectionRenderer *sectionRenderer = renderers.itemSectionRenderer; -// YTIItemSectionSupportedRenderers *firstObject = [sectionRenderer.contentsArray firstObject]; -// return firstObject.hasPromotedVideoRenderer || firstObject.hasCompactPromotedVideoRenderer || firstObject.hasPromotedVideoInlineMutedRenderer; -// }]; -// [contentsArray removeObjectsAtIndexes:removeIndexes]; -// %orig; -// } -// %end - // Disable hints - https://github.com/LillieH001/YouTube-Reborn/blob/v4/ %group gDisableHints %hook YTSettings @@ -1485,7 +1565,7 @@ static BOOL findCell(ASNodeController *nodeController, NSArray *ide %end // Hide the chip bar under the video player? -// %hook YTChipCloudCell // +// %hook YTChipCloudCell // - (void)didMoveToWindow { // %orig; // self.hidden = YES; @@ -1550,7 +1630,7 @@ static BOOL findCell(ASNodeController *nodeController, NSArray *ide %end %hook UIKBTree - (long long)nativeIdiom { - return NO; + return YES; } %end %hook UIKBRenderer @@ -1621,6 +1701,9 @@ static BOOL findCell(ASNodeController *nodeController, NSArray *ide if (IS_ENABLED(@"portraitFullscreen_enabled")) { %init(gPortraitFullscreen); } + if (IS_ENABLED(@"fullscreenToTheRight_enabled")) { + %init(gFullscreenToTheRight); + } if (IS_ENABLED(@"hideFullscreenActions_enabled")) { %init(hideFullscreenActions); } @@ -1639,6 +1722,9 @@ static BOOL findCell(ASNodeController *nodeController, NSArray *ide if (IS_ENABLED(@"noVideosInFullscreen_enabled")) { %init(gNoVideosInFullscreen); } + if (IS_ENABLED(@"classicVideoPlayer_enabled")) { + %init(gClassicVideoPlayer); + } if (IS_ENABLED(@"fixLowContrastMode_enabled")) { %init(gFixLowContrastMode); } @@ -1757,6 +1843,7 @@ static BOOL findCell(ASNodeController *nodeController, NSArray *ide [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"removeYouTubeAds"]; } if (![allKeys containsObject:@"uYouAdBlockingWorkaround_enabled"]) { + [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"uYouAdBlockingWorkaroundLite_enabled"]; [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"uYouAdBlockingWorkaround_enabled"]; [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"removeYouTubeAds"]; } diff --git a/Sources/uYouPlusPatches.h b/Sources/uYouPlusPatches.h index b88f7d3484..e9b74f6414 100644 --- a/Sources/uYouPlusPatches.h +++ b/Sources/uYouPlusPatches.h @@ -84,3 +84,13 @@ @interface YTIInnertubeCommandExtensionRoot + (GPBExtensionDescriptor*)innertubeCommand; @end + +@interface YTAccountScopedCommandResponderEvent +@property (nonatomic, strong, readwrite) YTICommand *command; +@end + +@interface YTIShareEntityEndpoint +@property (nonatomic, assign, readwrite) BOOL hasSerializedShareEntity; +@property (nonatomic, copy, readwrite) NSString *serializedShareEntity; ++ (GPBExtensionDescriptor*)shareEntityEndpoint; +@end diff --git a/Sources/uYouPlusPatches.xm b/Sources/uYouPlusPatches.xm index dd9f015ed3..b617753143 100644 --- a/Sources/uYouPlusPatches.xm +++ b/Sources/uYouPlusPatches.xm @@ -109,29 +109,15 @@ static inline NSString* extractIdWithFormat(GPBUnknownFieldSet *fields, NSIntege return [NSString stringWithFormat:format, id]; } -%hook ELMPBShowActionSheetCommand -- (void)executeWithCommandContext:(id)_context handler:(id)_handler { - if (!self.hasOnAppear) - return %orig; - GPBExtensionDescriptor *innertubeCommandDescriptor = [%c(YTIInnertubeCommandExtensionRoot) innertubeCommand]; - if (![self.onAppear hasExtension:innertubeCommandDescriptor]) - return %orig; - YTICommand *innertubeCommand = [self.onAppear getExtension:innertubeCommandDescriptor]; - GPBExtensionDescriptor *updateShareSheetCommandDescriptor = [%c(YTIUpdateShareSheetCommand) updateShareSheetCommand]; - if(![innertubeCommand hasExtension:updateShareSheetCommandDescriptor]) - return %orig; - YTIUpdateShareSheetCommand *updateShareSheetCommand = [innertubeCommand getExtension:updateShareSheetCommandDescriptor]; - if (!updateShareSheetCommand.hasSerializedShareEntity) - return %orig; - - GPBMessage *shareEntity = [%c(GPBMessage) deserializeFromString:updateShareSheetCommand.serializedShareEntity]; +static BOOL showNativeShareSheet(NSString *serializedShareEntity) { + GPBMessage *shareEntity = [%c(GPBMessage) deserializeFromString:serializedShareEntity]; GPBUnknownFieldSet *fields = shareEntity.unknownFields; NSString *shareUrl; if ([fields hasField:ShareEntityFieldClip]) { GPBUnknownField *shareEntityClip = [fields getField:ShareEntityFieldClip]; if ([shareEntityClip.lengthDelimitedList count] != 1) - return %orig; + return FALSE; GPBMessage *clipMessage = [%c(GPBMessage) parseFromData:[shareEntityClip.lengthDelimitedList firstObject] error:nil]; shareUrl = extractIdWithFormat(clipMessage.unknownFields, 1, @"https://youtube.com/clip/%@"); } @@ -152,10 +138,90 @@ static inline NSString* extractIdWithFormat(GPBUnknownFieldSet *fields, NSIntege shareUrl = extractIdWithFormat(fields, ShareEntityFieldVideo, @"https://youtube.com/watch?v=%@"); if (!shareUrl) - return %orig; + return FALSE; UIActivityViewController *activityViewController = [[UIActivityViewController alloc]initWithActivityItems:@[shareUrl] applicationActivities:nil]; [[%c(YTUIUtils) topViewControllerForPresenting] presentViewController:activityViewController animated:YES completion:^{}]; + return TRUE; +} + + +/* -------------------- iPad Layout -------------------- */ + +%hook YTAccountScopedCommandResponderEvent +- (void)send { + GPBExtensionDescriptor *shareEntityEndpointDescriptor = [%c(YTIShareEntityEndpoint) shareEntityEndpoint]; + if (![self.command hasExtension:shareEntityEndpointDescriptor]) + return %orig; + YTIShareEntityEndpoint *shareEntityEndpoint = [self.command getExtension:shareEntityEndpointDescriptor]; + if (!showNativeShareSheet(shareEntityEndpoint.serializedShareEntity)) + return %orig; +} +%end + +/* OLD +%hook YTShareRequestViewController +- (id)initWithService:(id)_service parentResponder:(id)_parentResponder { + id result = %orig; + // disable the default share sheet behavior and force the app to call [YTAccountScopedCommandRouter handleCommand] if available + if ([_parentResponder respondsToSelector:@selector(handleCommand:entry:fromView:sender:completionBlock:)]) { + [_parentResponder handleCommand:nil entry:nil fromView:nil sender:nil completionBlock:nil]; + } + return result; +} +%end + +%hook YTAccountScopedCommandRouter +- (BOOL)handleCommand:(id)command entry:(id)_entry fromView:(id)_fromView sender:(id)_sender completionBlock:(id)_completionBlock { + GPBExtensionDescriptor *shareEntityEndpointDescriptor = [%c(YTIShareEntityEndpoint) shareEntityEndpoint]; + if (![command hasExtension:shareEntityEndpointDescriptor]) + return %orig; + YTIShareEntityEndpoint *shareEntityEndpoint = [command getExtension:shareEntityEndpointDescriptor]; + if(!shareEntityEndpoint.hasSerializedShareEntity) + return %orig; + if (!showNativeShareSheet(shareEntityEndpoint.serializedShareEntity)) + return %orig; + return TRUE; +} +%end +*/ + +/* EXPERIMENTAL +%hook YTAccountScopedCommandRouter +- (BOOL)handleCommand:(id)command entry:(id)_entry fromView:(id)_fromView sender:(id)_sender completionBlock:(id)_completionBlock { + GPBExtensionDescriptor *shareEntityEndpointDescriptor = [%c(YTIShareEntityEndpoint) shareEntityEndpoint]; + if (![command hasExtension:shareEntityEndpointDescriptor]) + return %orig; + YTIShareEntityEndpoint *shareEntityEndpoint = [command getExtension:shareEntityEndpointDescriptor]; + if(!shareEntityEndpoint || !shareEntityEndpoint.hasSerializedShareEntity || !shareEntityEndpoint.serializedShareEntity) { + return %orig; + } + if (!showNativeShareSheet(shareEntityEndpoint.serializedShareEntity)) { + return %orig; + } + return TRUE; +} +%end +*/ + +/* ------------------- iPhone Layout ------------------- */ + +%hook ELMPBShowActionSheetCommand +- (void)executeWithCommandContext:(id)_context handler:(id)_handler { + if (!self.hasOnAppear) + return %orig; + GPBExtensionDescriptor *innertubeCommandDescriptor = [%c(YTIInnertubeCommandExtensionRoot) innertubeCommand]; + if (![self.onAppear hasExtension:innertubeCommandDescriptor]) + return %orig; + YTICommand *innertubeCommand = [self.onAppear getExtension:innertubeCommandDescriptor]; + GPBExtensionDescriptor *updateShareSheetCommandDescriptor = [%c(YTIUpdateShareSheetCommand) updateShareSheetCommand]; + if(![innertubeCommand hasExtension:updateShareSheetCommandDescriptor]) + return %orig; + YTIUpdateShareSheetCommand *updateShareSheetCommand = [innertubeCommand getExtension:updateShareSheetCommandDescriptor]; + if (!updateShareSheetCommand.hasSerializedShareEntity) + return %orig; + if (!showNativeShareSheet(updateShareSheetCommand.serializedShareEntity)) + return %orig; } %end diff --git a/Sources/uYouPlusSettings.xm b/Sources/uYouPlusSettings.xm index 2e878ef772..ffad5a60de 100644 --- a/Sources/uYouPlusSettings.xm +++ b/Sources/uYouPlusSettings.xm @@ -78,7 +78,7 @@ NSArray *copyKeys = @[ /* MAIN Shorts Keys */ @"hideBuySuperThanks_enabled", @"hideSubcriptions_enabled", @"disableResumeToShorts_enabled", @"shortsQualityPicker_enabled", /* MAIN Player UI Keys */ @"redSubscribeButton_enabled", @"hideButtonContainers_enabled", @"hideConnectButton_enabled", @"hideShareButton_enabled", @"hideRemixButton_enabled", @"hideThanksButton_enabled", @"hideDownloadButton_enabled", @"hideClipButton_enabled", @"hideSaveToPlaylistButton_enabled", @"hideReportButton_enabled", @"hidePreviewCommentSection_enabled", @"hideCommentSection_enabled", /* MAIN Overlay Keys */ @"disableAccountSection_enabled", @"disableAutoplaySection_enabled", @"disableTryNewFeaturesSection_enabled", @"disableVideoQualityPreferencesSection_enabled", @"disableNotificationsSection_enabled", @"disableManageAllHistorySection_enabled", @"disableYourDataInYouTubeSection_enabled", @"disablePrivacySection_enabled", @"disableLiveChatSection_enabled", @"hidePremiumPromos_enabled", -/* MAIN App UI Keys */ @"hideHomeTab_enabled", @"lowContrastMode_enabled", @"fixLowContrastMode_enabled", @"disableModernButtons_enabled", @"disableRoundedHints_enabled", @"disableModernFlags_enabled", @"ytNoModernUI_enabled", @"enableVersionSpoofer_enabled", +/* MAIN App UI Keys */ @"hideHomeTab_enabled", @"lowContrastMode_enabled", @"classicVideoPlayer_enabled", @"fixLowContrastMode_enabled", @"disableModernButtons_enabled", @"disableRoundedHints_enabled", @"disableModernFlags_enabled", @"ytNoModernUI_enabled", @"enableVersionSpoofer_enabled", /* MAIN Misc Keys */ @"uYouAdBlockingWorkaroundLite_enabled", @"uYouAdBlockingWorkaround_enabled", @"disableAnimatedYouTubeLogo_enabled", @"centerYouTubeLogo_enabled", @"hideYouTubeLogo_enabled", @"ytStartupAnimation_enabled", @"disableHints_enabled", @"stickNavigationBar_enabled", @"hideSponsorBlockButton_enabled", @"hideChipBar_enabled", @"hidePlayNextInQueue_enabled", @"hideCommunityPosts_enabled", @"hideChannelHeaderLinks_enabled", @"iPhoneLayout_enabled", @"bigYTMiniPlayer_enabled", @"reExplore_enabled", @"autoHideHomeBar_enabled", @"hideSubscriptionsNotificationBadge_enabled", @"fixCasting_enabled", @"newSettingsUI_enabled", @"flex_enabled", /* TWEAK uYou Keys */ @"showedWelcomeVC", @"hideShortsTab", @"hideCreateTab", @"hideCastButton", @"relatedVideosAtTheEndOfYTVideos", @"removeYouTubeAds", @"backgroundPlayback", @"disableAgeRestriction", @"iPadLayout", @"noSuggestedVideoAtEnd", @"shortsProgressBar", @"hideShortsCells", @"removeShortsCell", @"startupPage", /* TWEAK iSB Keys */ @"userID", @"apiInstance", @"minimumDuration", @"skipNoticeDuration", @"kShowModifiedTime", @"showSkipNotice", @"showButtonsInPlayer", @"hideStartEndButtonInPlayer", @"showModifiedTime", @"skipAudioNotification", @"enableSkipCountTracking", @@ -202,7 +202,7 @@ extern NSBundle *uYouPlusBundle(); if (IS_ENABLED(@"replaceCopyandPasteButtons_enabled")) { // Export Settings functionality NSURL *tempFileURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"exported_settings.txt"]]; - NSMutableString *settingsString = [NSMutableNSMutableString string]; + NSMutableString *settingsString = [NSMutableString string]; for (NSString *key in copyKeys) { id value = [[NSUserDefaults standardUserDefaults] objectForKey:key]; if (value) { @@ -213,9 +213,7 @@ extern NSBundle *uYouPlusBundle(); UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithURL:tempFileURL inMode:UIDocumentPickerModeExportToService]; documentPicker.delegate = (id)self; documentPicker.allowsMultipleSelection = NO; - [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:documentPicker animated:YES completion:nil]; - } - return YES; + [settingsViewController presentViewController:documentPicker animated:YES completion:nil]; } else { // Copy Settings functionality (default behavior) NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; @@ -245,7 +243,7 @@ extern NSBundle *uYouPlusBundle(); UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"public.text"] inMode:UIDocumentPickerModeImport]; documentPicker.delegate = (id)self; documentPicker.allowsMultipleSelection = NO; - [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:documentPicker animated:YES completion:nil]; + [settingsViewController presentViewController:documentPicker animated:YES completion:nil]; return YES; } else { // Paste Settings functionality (default behavior) @@ -262,7 +260,7 @@ extern NSBundle *uYouPlusBundle(); NSString *value = components[1]; [[NSUserDefaults standardUserDefaults] setObject:value forKey:key]; } - } + } [settingsViewController reloadData]; SHOW_RELAUNCH_YT_SNACKBAR; } @@ -274,7 +272,7 @@ extern NSBundle *uYouPlusBundle(); ]; [sectionItems addObject:pasteSettings]; - SWITCH_ITEM(LOC(@"REPLACE_COPY_AND_PASTE_BUTTONS"), LOC(@"REPLACE_COPY_AND_PASTE_BUTTONS"), @"replaceCopyandPasteButtons_enabled"); + SWITCH_ITEM(LOC(@"REPLACE_COPY_AND_PASTE_BUTTONS"), LOC(@"REPLACE_COPY_AND_PASTE_BUTTONS_DESC"), @"replaceCopyandPasteButtons_enabled"); YTSettingsSectionItem *exitYT = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"QUIT_YOUTUBE") @@ -294,7 +292,7 @@ extern NSBundle *uYouPlusBundle(); # pragma mark - uYouEnhanced Essential Menu YTSettingsSectionItem *customAppMenu = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"UYOUENHANCED_ESSENTIAL_MENU") - titleDescription:LOC(@"This menu includes App Color Customization & Ability to Clear the Cache 🗑️") + titleDescription:LOC(@"This menu includes App Color Customization 🎨 & Ability to Clear the Cache 🗑️") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { @@ -436,6 +434,24 @@ extern NSBundle *uYouPlusBundle(); } }); ); + SWITCH_ITEM3( + LOC(@"FULLSCREEN_TO_THE_RIGHT"), + LOC(@"FULLSCREEN_TO_THE_RIGHT_DESC"), + @"fullscreenToTheRight_enabled", + ({ + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { + [[NSUserDefaults standardUserDefaults] setBool:enable forKey:@"fullscreenToTheRight_enabled"]; + SHOW_RELAUNCH_YT_SNACKBAR; + return YES; + } else { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Incompatibile" message:@"This Option is Incompatible on an iPad Device." preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]; + [alert addAction:okAction]; + [settingsViewController presentViewController:alert animated:YES completion:nil]; + return NO; + } + }); + ); SWITCH_ITEM2(LOC(@"SLIDE_TO_SEEK"), LOC(@"SLIDE_TO_SEEK_DESC"), @"slideToSeek_enabled"); SWITCH_ITEM2(LOC(@"ENABLE_TAP_TO_SEEK"), LOC(@"ENABLE_TAP_TO_SEEK_DESC"), @"YTTapToSeek_enabled"); SWITCH_ITEM(LOC(@"DISABLE_DOUBLE_TAP_TO_SEEK"), LOC(@"DISABLE_DOUBLE_TAP_TO_SEEK_DESC"), @"doubleTapToSeek_disabled"); @@ -529,7 +545,7 @@ extern NSBundle *uYouPlusBundle(); # pragma mark - Video player button options SECTION_HEADER(LOC(@"VIDEO_PLAYER_BUTTON_OPTIONS")); -// (the options "Red Subscribe Button" and "Hide Button Containers under player" are currently not working) +// (the options "Red Subscribe Button" and "Hide Button Containers under player" are currently not working, would most likely result in effecting the whole entire app.) // // SWITCH_ITEM(LOC(@"RED_SUBSCRIBE_BUTTON"), LOC(@"RED_SUBSCRIBE_BUTTON_DESC"), @"redSubscribeButton_enabled"); // SWITCH_ITEM2(LOC(@"HIDE_BUTTON_CONTAINERS_UNDER_PLAYER"), LOC(@"HIDE_BUTTON_CONTAINERS_UNDER_PLAYER_DESC"), @"hideButtonContainers_enabled"); @@ -639,6 +655,7 @@ extern NSBundle *uYouPlusBundle(); } ]; [sectionItems addObject:lowContrastModeButton]; + SWITCH_ITEM2(LOC(@"CLASSIC_VIDEO_PLAYER"), LOC(@"CLASSIC_VIDEO_PLAYER_DESC"), @"classicVideoPlayer_enabled"); SWITCH_ITEM2(LOC(@"FIX_LOWCONTRASTMODE"), LOC(@"FIX_LOWCONTRASTMODE_DESC"), @"fixLowContrastMode_enabled"); SWITCH_ITEM2(LOC(@"DISABLE_MODERN_BUTTONS"), LOC(@"DISABLE_MODERN_BUTTONS_DESC"), @"disableModernButtons_enabled"); SWITCH_ITEM2(LOC(@"DISABLE_ROUNDED_CORNERS_ON_HINTS"), LOC(@"DISABLE_ROUNDED_CORNERS_ON_HINTS_DESC"), @"disableRoundedHints_enabled"); @@ -1394,22 +1411,24 @@ extern NSBundle *uYouPlusBundle(); [settingsViewController setSectionItems:sectionItems forCategory:uYouPlusSection title:@"uYouEnhanced" titleDescription:LOC(@"TITLE DESCRIPTION") headerHidden:YES]; } -// File Manager (Paste Settings) +// File Manager (Import Settings .txt) - (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray *)urls { if (urls.count > 0) { NSURL *fileURL = urls.firstObject; NSString *fileContents = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:nil]; - NSArray *lines = [fileContents componentsSeparatedByString:@"\n"]; - for (NSString *line in lines) { - NSArray *components = [line componentsSeparatedByString:@": "]; - if (components.count == 2) { - NSString *key = components[0]; - NSString *value = components[1]; - [[NSUserDefaults standardUserDefaults] setObject:value forKey:key]; + if (fileContents.length > 0) { + NSArray *lines = [fileContents componentsSeparatedByString:@"\n"]; + for (NSString *line in lines) { + NSArray *components = [line componentsSeparatedByString:@": "]; + if (components.count == 2) { + NSString *key = components[0]; + NSString *value = components[1]; + [[NSUserDefaults standardUserDefaults] setObject:value forKey:key]; + } } + YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"]; + [settingsViewController reloadData]; } - [settingsViewController reloadData]; - SHOW_RELAUNCH_YT_SNACKBAR; } }