From c864966f1138c58f53b15bcf0a7a6eadb945c6f2 Mon Sep 17 00:00:00 2001 From: Aric <78001398+arichorn@users.noreply.github.com> Date: Sat, 24 Sep 2022 19:40:50 -0500 Subject: [PATCH] DontEatMyContent - @therealFoxster Prevent the notch/Dynamic Island from munching on 2:1 video content in YouTube --- Header.h | 33 +++++++++++- Settings.xm | 12 ++++- uYouPlus.xm | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 189 insertions(+), 3 deletions(-) diff --git a/Header.h b/Header.h index 9032631..d59a830 100644 --- a/Header.h +++ b/Header.h @@ -37,6 +37,26 @@ - (float)progress; @end +@interface YTPlayerView : UIView +- (BOOL)zoomToFill; +- (id)renderingView; +- (id)playerView; +@end + +@interface MLHAMSBDLSampleBufferRenderingView : UIView +@end + +@interface YTMainAppVideoPlayerOverlayViewController : UIViewController +- (BOOL)isFullscreen; +- (id)videoPlayerOverlayView; +- (id)activeVideoPlayerOverlay; +@end + +@interface YTMainAppVideoPlayerOverlayView : UIView +- (UIViewController *)_viewControllerForAncestor; ++ (CGFloat)topButtonAdditionalPadding; +@end + // iOS16 fix @interface OBPrivacyLinkButton : UIButton - (instancetype)initWithCaption:(NSString *)caption @@ -61,8 +81,10 @@ @end // YTAutoFullScreen -@interface YTPlayerViewController (YTAFS) +@interface YTPlayerViewController (YTPlayerViewControllerCategory) - (void)autoFullscreen; +- (id)activeVideoPlayerOverlay; +- (id)playerView; @end // OLED Darkmode @@ -94,4 +116,11 @@ @end @interface UIPredictionViewController : UIViewController -@end \ No newline at end of file +@end + +// +NSString* deviceName(); +BOOL isDeviceSupported(); +void activate(); +void deactivate(); +void center(); \ No newline at end of file diff --git a/Settings.xm b/Settings.xm index 7cd2bd8..f98e7a3 100644 --- a/Settings.xm +++ b/Settings.xm @@ -25,6 +25,7 @@ extern BOOL hidePreviousAndNextButton(); extern BOOL hidePaidPromotionCard(); extern BOOL fixGoogleSignIn(); extern BOOL replacePreviousAndNextButton(); +extern BOOL dontEatMyContent(); // Settings %hook YTAppSettingsPresentationData @@ -53,6 +54,15 @@ extern BOOL replacePreviousAndNextButton(); exit(0); }]; + YTSettingsSectionItem *dontEatMyContent = [[%c(YTSettingsSectionItem) alloc] initWithTitle:LOC(@"DONT_EAT_MY_CONTENT") titleDescription:LOC(@"DONT_EAT_MY_CONTENT_DESC")]; + dontEatMyContent.hasSwitch = YES; + dontEatMyContent.switchVisible = YES; + dontEatMyContent.on = [[NSUserDefaults standardUserDefaults] boolForKey:@"dontEatMyContent_enabled"]; + dontEatMyContent.switchBlock = ^BOOL (YTSettingsCell *cell, BOOL enabled) { + [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:@"dontEatMyContent_enabled"]; + return YES; + }; + YTSettingsSectionItem *replacePreviousAndNextButton = [[%c(YTSettingsSectionItem) alloc] initWithTitle:LOC(@"REPLACE_PREVIOUS_NEXT_BUTTON") titleDescription:LOC(@"REPLACE_PREVIOUS_NEXT_BUTTON_DESC")]; replacePreviousAndNextButton.hasSwitch = YES; replacePreviousAndNextButton.switchVisible = YES; @@ -188,7 +198,7 @@ extern BOOL replacePreviousAndNextButton(); return YES; }; - NSMutableArray *sectionItems = [NSMutableArray arrayWithArray:@[killApp, autoFull, castConfirm, ytMiniPlayer, fixGoogleSignIn, hideAutoplaySwitch, hideCC, hideHUD, hidePaidPromotionCard, hidePreviousAndNextButton, hideHoverCard, bigYTMiniPlayer, oledDarkMode, oledKeyBoard, replacePreviousAndNextButton, reExplore]]; + NSMutableArray *sectionItems = [NSMutableArray arrayWithArray:@[killApp, autoFull, castConfirm, ytMiniPlayer, dontEatMyContent, fixGoogleSignIn, hideAutoplaySwitch, hideCC, hideHUD, hidePaidPromotionCard, hidePreviousAndNextButton, hideHoverCard, bigYTMiniPlayer, oledDarkMode, oledKeyBoard, replacePreviousAndNextButton, reExplore]]; [delegate setSectionItems:sectionItems forCategory:uYouPlusSection title:@"uYouPlus" titleDescription:nil headerHidden:NO]; } diff --git a/uYouPlus.xm b/uYouPlus.xm index fe78e58..53de697 100644 --- a/uYouPlus.xm +++ b/uYouPlus.xm @@ -2,6 +2,8 @@ #import #import #import +#import +#import #import "Header.h" #import "Tweaks/YouTubeHeader/YTVideoQualitySwitchOriginalController.h" #import "Tweaks/YouTubeHeader/YTPlayerViewController.h" @@ -98,6 +100,9 @@ BOOL fixGoogleSignIn() { BOOL replacePreviousAndNextButton() { return [[NSUserDefaults standardUserDefaults] boolForKey:@"replacePreviousAndNextButton_enabled"]; } +BOOL dontEatMyContent() { + return [[NSUserDefaults standardUserDefaults] boolForKey:@"dontEatMyContent_enabled"]; +} # pragma mark - Tweaks // Enable Reorder videos from playlist while on the Watch page - @PoomSmart @@ -876,6 +881,145 @@ static void replaceTab(YTIGuideResponse *response) { %end %end +#define UNSUPPORTED_DEVICES @[@"iPhone14,3", @"iPhone14,6", @"iPhone14,8"] +#define THRESHOLD 1.99 + +double aspectRatio = 16/9; +bool zoomedToFill = false; + +MLHAMSBDLSampleBufferRenderingView *renderingView; +NSLayoutConstraint *widthConstraint, *heightConstraint, *centerXConstraint, *centerYConstraint; + +%group gDontEatMyContent +%hook YTPlayerViewController + +- (void)viewDidAppear:(BOOL)animated { + YTPlayerView *playerView = [self playerView]; + UIView *renderingViewContainer = MSHookIvar(playerView, "_renderingViewContainer"); + renderingView = [playerView renderingView]; + + CGFloat constant = 23; // Make renderingView a bit larger since safe area has sizeable margins from the notch and side borders; tested on iPhone 13 mini + + widthConstraint = [renderingView.widthAnchor constraintEqualToAnchor:renderingViewContainer.safeAreaLayoutGuide.widthAnchor constant:constant]; + heightConstraint = [renderingView.heightAnchor constraintEqualToAnchor:renderingViewContainer.safeAreaLayoutGuide.heightAnchor constant:constant]; + centerXConstraint = [renderingView.centerXAnchor constraintEqualToAnchor:renderingViewContainer.centerXAnchor]; + centerYConstraint = [renderingView.centerYAnchor constraintEqualToAnchor:renderingViewContainer.centerYAnchor]; + + // playerView.backgroundColor = [UIColor greenColor]; + // renderingViewContainer.backgroundColor = [UIColor redColor]; + // renderingView.backgroundColor = [UIColor blueColor]; + + YTMainAppVideoPlayerOverlayViewController *activeVideoPlayerOverlay = [self activeVideoPlayerOverlay]; + + // Must check class since YTInlineMutedPlaybackPlayerOverlayViewController doesn't have -(BOOL)isFullscreen + if ([NSStringFromClass([activeVideoPlayerOverlay class]) isEqualToString:@"YTMainAppVideoPlayerOverlayViewController"] && [activeVideoPlayerOverlay isFullscreen]) { + activate(); + } else { + center(); + } + %orig(animated); +} +- (void)didPressToggleFullscreen { + YTMainAppVideoPlayerOverlayViewController *activeVideoPlayerOverlay = [self activeVideoPlayerOverlay]; + + if (![activeVideoPlayerOverlay isFullscreen]) // Entering fullscreen + activate(); + else // Exiting fullscreen + deactivate(); + + %orig; +} +- (void)didSwipeToEnterFullscreen { + %orig; activate(); +} +- (void)didSwipeToExitFullscreen { + %orig; deactivate(); +} +- (void)singleVideo:(id)arg1 aspectRatioDidChange:(CGFloat)arg2 { + aspectRatio = arg2; + if (aspectRatio == 0.0) { + // App backgrounded + } else if (aspectRatio < THRESHOLD) { + deactivate(); + } else { + activate(); + } + %orig(arg1, arg2); +} +%end + +%hook YTVideoZoomOverlayView +- (void)didRecognizePinch:(UIPinchGestureRecognizer *)pinchGestureRecognizer { + // %log((CGFloat) [pinchGestureRecognizer scale], (CGFloat) [pinchGestureRecognizer velocity]); + if ([pinchGestureRecognizer velocity] <= 0.0) { // >>Zoom out<< + zoomedToFill = false; + activate(); + } else if ([pinchGestureRecognizer velocity] > 0.0) { // <> + zoomedToFill = true; + deactivate(); + } + + %orig(pinchGestureRecognizer); +} +- (void)flashAndHideSnapIndicator {} + +// https://github.com/lgariv/UniZoom/blob/master/Tweak.xm +- (void)setSnapIndicatorVisible:(bool)arg1 { + %orig(NO); +} +%end +%end + +// https://stackoverflow.com/a/11197770/19227228 + NSString* deviceName() { + struct utsname systemInfo; + uname(&systemInfo); + return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; + } + + BOOL isDeviceSupported() { + NSString *identifier = deviceName(); + NSArray *unsupportedDevices = UNSUPPORTED_DEVICES; + + for (NSString *device in unsupportedDevices) { + if ([device isEqualToString:identifier]) { + return NO; + } + } + + if ([identifier containsString:@"iPhone"]) { + NSString *model = [identifier stringByReplacingOccurrencesOfString:@"iPhone" withString:@""]; + model = [model stringByReplacingOccurrencesOfString:@"," withString:@"."]; + if ([identifier isEqualToString:@"iPhone13,1"]) { // iPhone 12 mini + return YES; + } else if ([model floatValue] >= 14.0) { // iPhone 13 series and newer + return YES; + } else return NO; + } else return NO; + } + + void activate() { + if (aspectRatio < THRESHOLD || zoomedToFill) return; + // NSLog(@"activate"); + center(); + renderingView.translatesAutoresizingMaskIntoConstraints = NO; + widthConstraint.active = YES; + heightConstraint.active = YES; + } + + void deactivate() { + // NSLog(@"deactivate"); + center(); + renderingView.translatesAutoresizingMaskIntoConstraints = YES; + widthConstraint.active = NO; + heightConstraint.active = NO; + } + + void center() { + centerXConstraint.active = YES; + centerYConstraint.active = YES; + } + // iOS 16 uYou crash fix - @level3tjg: https://github.com/qnblackcat/uYouPlus/pull/224 %group iOS16 %hook OBPrivacyLinkButton @@ -918,6 +1062,9 @@ static void replaceTab(YTIGuideResponse *response) { } if (replacePreviousAndNextButton()) { %init(gReplacePreviousAndNextButton); + } + if (dontEatMyContent() && isDeviceSupported()) { + %init(gDontEatMyContent); } if (@available(iOS 16, *)) { %init(iOS16);