Merge pull request #680 from therealFoxster/main

Update DontEatMyContent (v1.0.4 -> v1.0.5)
This commit is contained in:
Nguyễn Đạt 2022-11-16 06:39:17 +07:00 committed by GitHub
commit 49ace6eb4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 58 deletions

View file

@ -4,8 +4,8 @@
#define LOC(x) [tweakBundle localizedStringForKey:x value:nil table:nil] #define LOC(x) [tweakBundle localizedStringForKey:x value:nil table:nil]
#define YT_BUNDLE_ID @"com.google.ios.youtube" #define YT_BUNDLE_ID @"com.google.ios.youtube"
#define YT_NAME @"YouTube" #define YT_NAME @"YouTube"
#define UNSUPPORTED_DEVICES @[@"iPhone14,3", @"iPhone14,6", @"iPhone14,8"] // DontEatMycontent #define DEMC_UNSUPPORTED_DEVICES @[@"iPhone14,3", @"iPhone14,6", @"iPhone14,8"] // DontEatMycontent
#define THRESHOLD 1.99 // DontEatMycontent #define DEMC_THRESHOLD 1.99 // DontEatMycontent
#define DEFAULT_RATE 2.0f // YTSpeed #define DEFAULT_RATE 2.0f // YTSpeed
// IAmYouTube // IAmYouTube
@ -42,25 +42,33 @@
@end @end
// DontEatMyContent // DontEatMyContent
NSString* DEMC_getDeviceModelIdentifier();
BOOL DEMC_deviceIsSupported(); BOOL DEMC_deviceIsSupported();
void DEMC_activate(); void DEMC_activate();
void DEMC_deactivate(); void DEMC_deactivate();
void DEMC_centerRenderingView(); void DEMC_centerRenderingView();
@interface YTPlayerView : UIView @interface YTPlayerView : UIView
- (BOOL)zoomToFill;
- (id)renderingView; - (id)renderingView;
- (id)playerView;
@end
@interface MLHAMSBDLSampleBufferRenderingView : UIView
@end @end
@interface YTMainAppVideoPlayerOverlayViewController : UIViewController @interface YTMainAppVideoPlayerOverlayViewController : UIViewController
- (BOOL)isFullscreen; - (BOOL)isFullscreen;
- (id)videoPlayerOverlayView; @end
- (id)activeVideoPlayerOverlay;
@interface HAMSBDLSampleBufferRenderingView : UIView
@end
@interface MLHAMSBDLSampleBufferRenderingView : HAMSBDLSampleBufferRenderingView
@end
@interface YTMainAppEngagementPanelViewController : UIViewController
- (BOOL)isLandscapeEngagementPanel;
- (BOOL)isPeekingSupported;
@end
@interface YTEngagementPanelContainerViewController : UIViewController
- (BOOL)isLandscapeEngagementPanel;
- (BOOL)isPeekingSupported;
@end @end
// YTSpeed // YTSpeed

View file

@ -896,7 +896,8 @@ static void replaceTab(YTIGuideResponse *response) {
// DontEatMyContent - @therealFoxster: https://github.com/therealFoxster/DontEatMyContent // DontEatMyContent - @therealFoxster: https://github.com/therealFoxster/DontEatMyContent
static double videoAspectRatio = 16/9; static double videoAspectRatio = 16/9;
static bool isZoomedToFill = false, isFullscreen = false, isNewVideo = true; static bool zoomedToFill = false;
static bool engagementPanelIsVisible = false, removeEngagementPanelViewControllerWithIdentifierCalled = false;
static MLHAMSBDLSampleBufferRenderingView *renderingView; static MLHAMSBDLSampleBufferRenderingView *renderingView;
static NSLayoutConstraint *widthConstraint, *heightConstraint, *centerXConstraint, *centerYConstraint; static NSLayoutConstraint *widthConstraint, *heightConstraint, *centerXConstraint, *centerYConstraint;
@ -917,36 +918,34 @@ static NSLayoutConstraint *widthConstraint, *heightConstraint, *centerXConstrain
UIView *renderingViewContainer = MSHookIvar<UIView *>(playerView, "_renderingViewContainer"); UIView *renderingViewContainer = MSHookIvar<UIView *>(playerView, "_renderingViewContainer");
renderingView = [playerView renderingView]; 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 // Making renderingView a bit larger since constraining to safe area leaves a gap between the notch and video
CGFloat constant = 24.5; // Tested on iPhone 13 mini
widthConstraint = [renderingView.widthAnchor constraintEqualToAnchor:renderingViewContainer.safeAreaLayoutGuide.widthAnchor constant:constant]; widthConstraint = [renderingView.widthAnchor constraintEqualToAnchor:renderingViewContainer.safeAreaLayoutGuide.widthAnchor constant:constant];
heightConstraint = [renderingView.heightAnchor constraintEqualToAnchor:renderingViewContainer.safeAreaLayoutGuide.heightAnchor constant:constant]; heightConstraint = [renderingView.heightAnchor constraintEqualToAnchor:renderingViewContainer.safeAreaLayoutGuide.heightAnchor constant:constant];
centerXConstraint = [renderingView.centerXAnchor constraintEqualToAnchor:renderingViewContainer.centerXAnchor]; centerXConstraint = [renderingView.centerXAnchor constraintEqualToAnchor:renderingViewContainer.centerXAnchor];
centerYConstraint = [renderingView.centerYAnchor constraintEqualToAnchor:renderingViewContainer.centerYAnchor]; centerYConstraint = [renderingView.centerYAnchor constraintEqualToAnchor:renderingViewContainer.centerYAnchor];
// playerView.backgroundColor = [UIColor greenColor]; // playerView.backgroundColor = [UIColor blueColor];
// renderingViewContainer.backgroundColor = [UIColor redColor]; // renderingViewContainer.backgroundColor = [UIColor greenColor];
// renderingView.backgroundColor = [UIColor blueColor]; // renderingView.backgroundColor = [UIColor redColor];
YTMainAppVideoPlayerOverlayViewController *activeVideoPlayerOverlay = [self activeVideoPlayerOverlay]; YTMainAppVideoPlayerOverlayViewController *activeVideoPlayerOverlay = [self activeVideoPlayerOverlay];
// Must check class since YTInlineMutedPlaybackPlayerOverlayViewController doesn't have -(BOOL)isFullscreen // Must check class since YTInlineMutedPlaybackPlayerOverlayViewController doesn't have -(BOOL)isFullscreen
if ([NSStringFromClass([activeVideoPlayerOverlay class]) isEqualToString:@"YTMainAppVideoPlayerOverlayViewController"] if ([NSStringFromClass([activeVideoPlayerOverlay class]) isEqualToString:@"YTMainAppVideoPlayerOverlayViewController"] // isKindOfClass doesn't work for some reason
&& [activeVideoPlayerOverlay isFullscreen]) { && [activeVideoPlayerOverlay isFullscreen]) {
if (!isZoomedToFill) DEMC_activate(); if (!zoomedToFill && !engagementPanelIsVisible) DEMC_activate();
isFullscreen = true;
} else { } else {
DEMC_centerRenderingView(); DEMC_centerRenderingView();
isFullscreen = false;
} }
%orig(animated); %orig(animated);
} }
- (void)didPressToggleFullscreen { - (void)didPressToggleFullscreen {
%orig; %orig;
YTMainAppVideoPlayerOverlayViewController *activeVideoPlayerOverlay = [self activeVideoPlayerOverlay]; if (![[self activeVideoPlayerOverlay] isFullscreen]) { // Entering full screen
if (![activeVideoPlayerOverlay isFullscreen]) { // Entering full screen if (!zoomedToFill && !engagementPanelIsVisible) DEMC_activate();
if (!isZoomedToFill) DEMC_activate();
} else { // Exiting full screen } else { // Exiting full screen
DEMC_deactivate(); DEMC_deactivate();
} }
@ -955,90 +954,127 @@ static NSLayoutConstraint *widthConstraint, *heightConstraint, *centerXConstrain
} }
- (void)didSwipeToEnterFullscreen { - (void)didSwipeToEnterFullscreen {
%orig; %orig;
if (!isZoomedToFill) DEMC_activate(); if (!zoomedToFill && !engagementPanelIsVisible) DEMC_activate();
} }
- (void)didSwipeToExitFullscreen { - (void)didSwipeToExitFullscreen {
%orig; %orig;
DEMC_deactivate(); DEMC_deactivate();
} }
%end // New video played
-(void)playbackController:(id)playbackController didActivateVideo:(id)video withPlaybackData:(id)playbackData {
%hook MLHAMSBDLSampleBufferRenderingView %orig(playbackController, video, playbackData);
- (void)setVideo:(id)video playerConfig:(id)playerConfig { if ([[self activeVideoPlayerOverlay] isFullscreen]) // New video played while in full screen (landscape)
%orig(video, playerConfig); // Activate since new videos played in full screen aren't zoomed-to-fill by default
isNewVideo = true; // (i.e. the notch/Dynamic Island will cut into content when playing a new video in full screen)
DEMC_activate();
engagementPanelIsVisible = false;
removeEngagementPanelViewControllerWithIdentifierCalled = false;
} }
%end %end
// Pinch to zoom
%hook YTVideoFreeZoomOverlayView %hook YTVideoFreeZoomOverlayView
- (void)didRecognizePinch:(UIPinchGestureRecognizer *)pinchGestureRecognizer { - (void)didRecognizePinch:(UIPinchGestureRecognizer *)pinchGestureRecognizer {
// Pinched to zoom in/out
DEMC_deactivate(); DEMC_deactivate();
%orig(pinchGestureRecognizer); %orig(pinchGestureRecognizer);
} }
// Detect zoom to fill // Detect zoom to fill
- (void)showLabelForSnapState:(NSInteger)snapState { - (void)showLabelForSnapState:(NSInteger)snapState {
if (snapState == 0) { // Original if (snapState == 0) { // Original
isZoomedToFill = false; zoomedToFill = false;
DEMC_activate(); DEMC_activate();
} else if (snapState == 1) { // Zoomed to fill } else if (snapState == 1) { // Zoomed to fill
isZoomedToFill = true; zoomedToFill = true;
// No need to deactivate constraints as it's already done in -(void)didRecognizePinch:(UIPinchGestureRecognizer *) // No need to deactivate constraints as it's already done in -(void)didRecognizePinch:(UIPinchGestureRecognizer *)
} }
%orig(snapState); %orig(snapState);
} }
- (void)setEnabled:(BOOL)enabled {
%orig(enabled);
if (enabled && isNewVideo && isFullscreen) { // New video played while in full screen (landscape)
DEMC_activate(); // Activate since new videos played in full screen aren't zoomed-to-fill for first play (i.e. the notch/Dynamic Island will cut into content when playing a new video in full screen)
isNewVideo = false;
}
}
%end %end
// Mini bar dismiss
%hook YTWatchMiniBarViewController %hook YTWatchMiniBarViewController
- (void)dismissMiniBarWithVelocity:(CGFloat)velocity gestureType:(int)gestureType { - (void)dismissMiniBarWithVelocity:(CGFloat)velocity gestureType:(int)gestureType {
%orig(velocity, gestureType); %orig(velocity, gestureType);
isZoomedToFill = false; // Setting to false since YouTube undoes zoom-to-fill when mini bar is dismissed zoomedToFill = false; // Setting to false since YouTube undoes zoom-to-fill when mini bar is dismissed
} }
- (void)dismissMiniBarWithVelocity:(CGFloat)velocity gestureType:(int)gestureType skipShouldDismissCheck:(BOOL)skipShouldDismissCheck { - (void)dismissMiniBarWithVelocity:(CGFloat)velocity gestureType:(int)gestureType skipShouldDismissCheck:(BOOL)skipShouldDismissCheck {
%orig(velocity, gestureType, skipShouldDismissCheck); %orig(velocity, gestureType, skipShouldDismissCheck);
isZoomedToFill = false; zoomedToFill = false;
} }
%end %end
%end// gDontEatMyContent %hook YTMainAppEngagementPanelViewController
// Engagement panel (comment, description, etc.) about to show up
// https://stackoverflow.com/a/11197770/19227228 - (void)viewWillAppear:(BOOL)animated {
NSString* DEMC_getDeviceModelIdentifier() { if ([self isPeekingSupported]) {
struct utsname systemInfo; // Shorts (only Shorts support peeking, I think)
uname(&systemInfo); } else {
return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; // Everything else
engagementPanelIsVisible = true;
if ([self isLandscapeEngagementPanel]) {
DEMC_deactivate();
}
}
%orig(animated);
} }
// Engagement panel about to dismiss
// - (void)viewDidDisappear:(BOOL)animated { %orig; %log; } // Called too late & isn't reliable so sometimes constraints aren't activated even when engagement panel is closed
%end
%hook YTEngagementPanelContainerViewController
// Engagement panel about to dismiss
- (void)notifyEngagementPanelContainerControllerWillHideFinalPanel { // Called in time but crashes if plays new video while in full screen causing engagement panel dismissal
// Must check if engagement panel was dismissed because new video played
// (i.e. if -(void)removeEngagementPanelViewControllerWithIdentifier:(id) was called prior)
if (![self isPeekingSupported] && !removeEngagementPanelViewControllerWithIdentifierCalled) {
engagementPanelIsVisible = false;
if ([self isLandscapeEngagementPanel] && !zoomedToFill) {
DEMC_activate();
}
}
%orig;
}
- (void)removeEngagementPanelViewControllerWithIdentifier:(id)identifier {
// Usually called when engagement panel is open & new video is played or mini bar is dismissed
removeEngagementPanelViewControllerWithIdentifierCalled = true;
%orig(identifier);
}
%end
%end// group gDontEatMyContent
BOOL DEMC_deviceIsSupported() { BOOL DEMC_deviceIsSupported() {
NSString *identifier = DEMC_getDeviceModelIdentifier(); // Get device model identifier (e.g. iPhone14,4)
NSArray *unsupportedDevices = UNSUPPORTED_DEVICES; // https://stackoverflow.com/a/11197770/19227228
struct utsname systemInfo;
uname(&systemInfo);
NSString *deviceModelID = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
for (NSString *device in unsupportedDevices) { NSArray *unsupportedModelIDs = DEMC_UNSUPPORTED_DEVICES;
if ([device isEqualToString:identifier]) { for (NSString *identifier in unsupportedModelIDs) {
if ([deviceModelID isEqualToString:identifier]) {
return NO; return NO;
} }
} }
if ([identifier containsString:@"iPhone"]) { if ([deviceModelID containsString:@"iPhone"]) {
NSString *model = [identifier stringByReplacingOccurrencesOfString:@"iPhone" withString:@""]; if ([deviceModelID isEqualToString:@"iPhone13,1"]) {
model = [model stringByReplacingOccurrencesOfString:@"," withString:@"."]; // iPhone 12 mini
if ([identifier isEqualToString:@"iPhone13,1"]) { // iPhone 12 mini
return YES; return YES;
} else if ([model floatValue] >= 14.0) { // iPhone 13 series and newer }
NSString *modelNumber = [[deviceModelID stringByReplacingOccurrencesOfString:@"iPhone" withString:@""] stringByReplacingOccurrencesOfString:@"," withString:@"."];
if ([modelNumber floatValue] >= 14.0) {
// iPhone 13 series and newer
return YES; return YES;
} else return NO; } else return NO;
} else return NO; } else return NO;
} }
void DEMC_activate() { void DEMC_activate() {
if (videoAspectRatio < THRESHOLD) DEMC_deactivate(); if (videoAspectRatio < DEMC_THRESHOLD) {
DEMC_deactivate();
return;
}
// NSLog(@"activate"); // NSLog(@"activate");
DEMC_centerRenderingView(); DEMC_centerRenderingView();
renderingView.translatesAutoresizingMaskIntoConstraints = NO; renderingView.translatesAutoresizingMaskIntoConstraints = NO;