mirror of
https://github.com/SoPat712/YTLitePlus.git
synced 2025-10-30 12:33:57 -04:00
added files via upload
This commit is contained in:
17
Tweaks/DontEatMyContent/.gitignore
vendored
Normal file
17
Tweaks/DontEatMyContent/.gitignore
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
.theos/
|
||||
packages/
|
||||
.test/
|
||||
|
||||
# Temporary files
|
||||
*~
|
||||
~$*.doc*
|
||||
~$*.xls*
|
||||
~$*.ppt*
|
||||
*.xlk
|
||||
*.pdf
|
||||
|
||||
# .DS_Store files
|
||||
*.DS_Store
|
||||
|
||||
# Preference files
|
||||
.vscode/
|
||||
1
Tweaks/DontEatMyContent/DontEatMyContent.plist
Normal file
1
Tweaks/DontEatMyContent/DontEatMyContent.plist
Normal file
@@ -0,0 +1 @@
|
||||
{ Filter = { Bundles = ( "com.google.ios.youtube" ); }; }
|
||||
21
Tweaks/DontEatMyContent/LICENSE.md
Normal file
21
Tweaks/DontEatMyContent/LICENSE.md
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Foxster
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
12
Tweaks/DontEatMyContent/Makefile
Normal file
12
Tweaks/DontEatMyContent/Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
TARGET := iphone:clang:latest:14.0
|
||||
ARCHS = arm64
|
||||
|
||||
include $(THEOS)/makefiles/common.mk
|
||||
|
||||
TWEAK_NAME = DontEatMyContent
|
||||
|
||||
DontEatMyContent_FILES = Tweak.x Settings.x
|
||||
DontEatMyContent_CFLAGS = -fobjc-arc
|
||||
DontEatMyContent_FRAMEWORKS = UIKit
|
||||
|
||||
include $(THEOS_MAKE_PATH)/tweak.mk
|
||||
37
Tweaks/DontEatMyContent/README.md
Normal file
37
Tweaks/DontEatMyContent/README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# DontEatMyContent
|
||||
Prevent the notch/Dynamic Island from munching on 2:1 video content in YouTube
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/therealFoxster/DontEatMyContent/assets/77606385/57a0243e-503c-490a-9c4a-3c95ebcdb582" width="640">
|
||||
</p>
|
||||
|
||||
## How It Works
|
||||
The rendering view is constrained to the safe area layout guide of its container so it will always be below the notch and Dynamic Island. These constraints are only activated for videos with 2:1 aspect ratio or wider to prevent unintended effects on videos with smaller aspect ratios.
|
||||
|
||||
## Compatibility
|
||||
Supports iPhone 12 mini, iPhone 13 series and newer **except** iPhone SE 3rd generation, iPhone 13 Pro Max and iPhone 14 Plus.
|
||||
|
||||
> **Note**: From [v1.0.4](https://github.com/therealFoxster/DontEatMyContent/releases/tag/v1.0.4) onwards, the tweak only supports YouTube versions that got the [October 2022 redesign](https://blog.youtube/news-and-events/an-updated-look-and-feel-for-youtube/). v1.0.4 was tested and confirmed to be working with YouTube v17.43.1.
|
||||
|
||||
## Grab It
|
||||
- IPA file: https://therealfoxster.github.io/altsource-viewer/app?source=https://therealfoxster.github.io/altsource/apps.json&id=com.google.ios.youtube
|
||||
- DEB file: https://github.com/therealFoxster/DontEatMyContent/releases/latest
|
||||
|
||||
## Preview (iPhone 13 mini)
|
||||
### Original Implementation
|
||||
<p align="center">
|
||||
<img src="https://github.com/therealFoxster/DontEatMyContent/assets/77606385/3254c8ce-79ba-4dea-aab6-060fb124a3c4" width="640">
|
||||
</p>
|
||||
|
||||
### Tweaked Implementation
|
||||
<p align="center">
|
||||
<img src="https://github.com/therealFoxster/DontEatMyContent/assets/77606385/5aa852e5-de70-4e3c-9024-d692510c80e5" width="640">
|
||||
</p>
|
||||
|
||||
### Zoomed to Fill
|
||||
<p align="center">
|
||||
<img src="https://github.com/therealFoxster/DontEatMyContent/assets/77606385/aac6841c-4330-4021-aa11-d5185165f2d4" width="640">
|
||||
</p>
|
||||
|
||||
## License
|
||||
[The MIT License](LICENSE.md)
|
||||
167
Tweaks/DontEatMyContent/Settings.x
Normal file
167
Tweaks/DontEatMyContent/Settings.x
Normal file
@@ -0,0 +1,167 @@
|
||||
#import "Tweak.h"
|
||||
|
||||
// Adapted from
|
||||
// https://github.com/PoomSmart/YouPiP/blob/bd04bf37be3d01540db418061164ae17a8f0298e/Settings.x
|
||||
// https://github.com/qnblackcat/uYouPlus/blob/265927b3900d886e2085d05bfad7cd4157be87d2/Settings.xm
|
||||
|
||||
extern void DEMC_showSnackBar(NSString *text);
|
||||
extern NSBundle *DEMC_getTweakBundle();
|
||||
extern CGFloat constant;
|
||||
|
||||
static const NSInteger sectionId = 517; // DontEatMyContent's section ID (just a random number)
|
||||
|
||||
// Category for additional functions
|
||||
@interface YTSettingsSectionItemManager (_DEMC)
|
||||
- (void)updateDEMCSectionWithEntry:(id)entry;
|
||||
@end
|
||||
|
||||
%group DEMC_Settings
|
||||
|
||||
%hook YTAppSettingsPresentationData
|
||||
+ (NSArray *)settingsCategoryOrder {
|
||||
NSArray *order = %orig;
|
||||
NSMutableArray *mutableOrder = [order mutableCopy];
|
||||
NSUInteger insertIndex = [order indexOfObject:@(1)]; // Index of Settings > General
|
||||
if (insertIndex != NSNotFound)
|
||||
[mutableOrder insertObject:@(sectionId) atIndex:insertIndex + 1]; // Insert DontEatMyContent settings under General
|
||||
return mutableOrder;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTSettingsSectionItemManager
|
||||
%new
|
||||
- (void)updateDEMCSectionWithEntry:(id)entry {
|
||||
YTSettingsViewController *delegate = [self valueForKey:@"_dataDelegate"];
|
||||
NSMutableArray *sectionItems = [NSMutableArray array]; // Create autoreleased array
|
||||
NSBundle *bundle = DEMC_getTweakBundle();
|
||||
|
||||
// Enabled
|
||||
YTSettingsSectionItem *enabled = [%c(YTSettingsSectionItem) switchItemWithTitle:LOCALIZED_STRING(@"ENABLED")
|
||||
titleDescription:LOCALIZED_STRING(@"TWEAK_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IS_TWEAK_ENABLED
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:ENABLED_KEY];
|
||||
|
||||
YTAlertView *alert = [%c(YTAlertView) confirmationDialogWithAction:^
|
||||
{
|
||||
// https://stackoverflow.com/a/17802404/19227228
|
||||
[[UIApplication sharedApplication] performSelector:@selector(suspend)];
|
||||
[NSThread sleepForTimeInterval:0.5];
|
||||
exit(0);
|
||||
}
|
||||
actionTitle:LOCALIZED_STRING(@"EXIT")
|
||||
cancelTitle:LOCALIZED_STRING(@"LATER")
|
||||
];
|
||||
alert.title = DEMC;
|
||||
alert.subtitle = LOCALIZED_STRING(@"EXIT_YT_DESC");
|
||||
[alert show];
|
||||
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0
|
||||
];
|
||||
[sectionItems addObject:enabled];
|
||||
|
||||
// Safe area constant
|
||||
YTSettingsSectionItem *constraintConstant = [%c(YTSettingsSectionItem) itemWithTitle:LOCALIZED_STRING(@"SAFE_AREA_CONST")
|
||||
titleDescription:LOCALIZED_STRING(@"SAFE_AREA_CONST_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return [NSString stringWithFormat:@"%.1f", constant];
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger sectionItemIndex) {
|
||||
__block YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"];
|
||||
NSMutableArray *rows = [NSMutableArray array];
|
||||
|
||||
float currentConstant = 20.0;
|
||||
float storedConstant = [[NSUserDefaults standardUserDefaults] floatForKey:SAFE_AREA_CONSTANT_KEY];;
|
||||
UInt8 index = 0, selectedIndex = 0;
|
||||
while (currentConstant <= 25.0) {
|
||||
NSString *title = [NSString stringWithFormat:@"%.1f", currentConstant];
|
||||
if (currentConstant == DEFAULT_CONSTANT)
|
||||
title = [NSString stringWithFormat:@"%.1f (%@)", currentConstant, LOCALIZED_STRING(@"DEFAULT")];
|
||||
if (currentConstant == storedConstant)
|
||||
selectedIndex = index;
|
||||
[rows addObject:[%c(YTSettingsSectionItem) checkmarkItemWithTitle:title
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger sectionItemIndex) {
|
||||
[[NSUserDefaults standardUserDefaults] setFloat:currentConstant forKey:SAFE_AREA_CONSTANT_KEY];
|
||||
constant = currentConstant;
|
||||
[settingsViewController reloadData]; // Refresh section's detail text (constant)
|
||||
DEMC_showSnackBar(LOCALIZED_STRING(@"SAFE_AREA_CONST_MESSAGE"));
|
||||
return YES;
|
||||
}
|
||||
]];
|
||||
currentConstant += 0.5; index++;
|
||||
}
|
||||
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOCALIZED_STRING(@"SAFE_AREA_CONST")
|
||||
pickerSectionTitle:nil
|
||||
rows:rows
|
||||
selectedItemIndex:selectedIndex
|
||||
parentResponder:[self parentResponder]
|
||||
];
|
||||
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}
|
||||
];
|
||||
if (IS_TWEAK_ENABLED) [sectionItems addObject:constraintConstant];
|
||||
|
||||
// Color views
|
||||
YTSettingsSectionItem *colorViews = [%c(YTSettingsSectionItem) switchItemWithTitle:LOCALIZED_STRING(@"COLOR_VIEWS")
|
||||
titleDescription:LOCALIZED_STRING(@"COLOR_VIEWS_DESC")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:IS_COLOR_VIEWS_ENABLED
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:COLOR_VIEWS_ENABLED_KEY];
|
||||
DEMC_showSnackBar(LOCALIZED_STRING(@"CHANGES_SAVED"));
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0
|
||||
];
|
||||
if (IS_TWEAK_ENABLED) [sectionItems addObject:colorViews];
|
||||
|
||||
// Report an issue
|
||||
YTSettingsSectionItem *reportIssue = [%c(YTSettingsSectionItem) itemWithTitle:LOCALIZED_STRING(@"REPORT_ISSUE")
|
||||
titleDescription:nil
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:nil
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger sectionItemIndex) {
|
||||
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/therealFoxster/DontEatMyContent/issues/new"]];
|
||||
}
|
||||
];
|
||||
[sectionItems addObject:reportIssue];
|
||||
|
||||
// View source code
|
||||
YTSettingsSectionItem *sourceCode = [%c(YTSettingsSectionItem) itemWithTitle:LOCALIZED_STRING(@"SOURCE_CODE")
|
||||
titleDescription:nil
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:nil
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger sectionItemIndex) {
|
||||
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/therealFoxster/DontEatMyContent"]];
|
||||
}
|
||||
];
|
||||
[sectionItems addObject:sourceCode];
|
||||
|
||||
[delegate setSectionItems:sectionItems
|
||||
forCategory:sectionId
|
||||
title:DEMC
|
||||
titleDescription:nil
|
||||
headerHidden:NO
|
||||
];
|
||||
}
|
||||
- (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry {
|
||||
if (category == sectionId) {
|
||||
[self updateDEMCSectionWithEntry:entry];
|
||||
return;
|
||||
}
|
||||
%orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%end // group DEMC_Settings
|
||||
|
||||
%ctor {
|
||||
%init(DEMC_Settings);
|
||||
}
|
||||
108
Tweaks/DontEatMyContent/Tweak.h
Normal file
108
Tweaks/DontEatMyContent/Tweak.h
Normal file
@@ -0,0 +1,108 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#define DEMC @"DontEatMyContent"
|
||||
|
||||
// Keys
|
||||
#define ENABLED_KEY @"DEMC_enabled"
|
||||
#define COLOR_VIEWS_ENABLED_KEY @"DEMC_colorViewsEnabled"
|
||||
#define SAFE_AREA_CONSTANT_KEY @"DEMC_safeAreaConstant"
|
||||
|
||||
#define DEFAULT_CONSTANT 22.0
|
||||
#define IS_TWEAK_ENABLED [[NSUserDefaults standardUserDefaults] boolForKey:ENABLED_KEY]
|
||||
#define IS_COLOR_VIEWS_ENABLED [[NSUserDefaults standardUserDefaults] boolForKey:COLOR_VIEWS_ENABLED_KEY]
|
||||
#define LOCALIZED_STRING(s) [bundle localizedStringForKey:s value:nil table:nil]
|
||||
|
||||
@interface YTPlayerViewController : UIViewController
|
||||
- (id)activeVideoPlayerOverlay;
|
||||
- (id)playerView;
|
||||
- (BOOL)isCurrentVideoVertical;
|
||||
@end
|
||||
|
||||
@interface YTPlayerView : UIView
|
||||
- (id)renderingView;
|
||||
@end
|
||||
|
||||
@interface YTMainAppVideoPlayerOverlayViewController : UIViewController
|
||||
- (BOOL)isFullscreen;
|
||||
@end
|
||||
|
||||
@interface MLHAMSBDLSampleBufferRenderingView : UIView
|
||||
@end
|
||||
|
||||
@interface YTMainAppEngagementPanelViewController : UIViewController
|
||||
- (BOOL)isLandscapeEngagementPanel;
|
||||
- (BOOL)isPeekingSupported;
|
||||
@end
|
||||
|
||||
@interface YTEngagementPanelContainerViewController : UIViewController
|
||||
- (BOOL)isLandscapeEngagementPanel;
|
||||
- (BOOL)isPeekingSupported;
|
||||
@end
|
||||
|
||||
@interface YTLabel : UILabel
|
||||
@property (nonatomic, copy, readwrite) NSString *text;
|
||||
@end
|
||||
|
||||
@interface YTSettingsCell : UICollectionViewCell
|
||||
@end
|
||||
|
||||
@interface YTSettingsSectionItemManager : NSObject
|
||||
- (id)parentResponder;
|
||||
@end
|
||||
|
||||
@interface YTSettingsPickerViewController : UIViewController
|
||||
- (instancetype)initWithNavTitle:(NSString *)navTitle
|
||||
pickerSectionTitle:(NSString *)pickerSectionTitle
|
||||
rows:(NSArray *)rows
|
||||
selectedItemIndex:(NSUInteger)selectedItemIndex
|
||||
parentResponder:(id)parentResponder;
|
||||
@end
|
||||
|
||||
@interface YTSettingsSectionItem : NSObject
|
||||
+ (instancetype)switchItemWithTitle:(NSString *)title
|
||||
titleDescription:(NSString *)titleDescription
|
||||
accessibilityIdentifier:(NSString *)accessibilityIdentifier
|
||||
switchOn:(BOOL)switchOn
|
||||
switchBlock:(BOOL (^)(YTSettingsCell *, BOOL))switchBlock
|
||||
settingItemId:(int)settingItemId;
|
||||
+ (instancetype)itemWithTitle:(NSString *)title
|
||||
titleDescription:(NSString *)titleDescription
|
||||
accessibilityIdentifier:(NSString *)accessibilityIdentifier
|
||||
detailTextBlock:(id)detailTextBlock
|
||||
selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock;
|
||||
+ (instancetype)checkmarkItemWithTitle:(NSString *)title
|
||||
selectBlock:(BOOL (^)(YTSettingsCell *, NSUInteger))selectBlock;
|
||||
@end
|
||||
|
||||
@interface YTSettingsViewController : UIViewController
|
||||
- (void)setSectionItems:(NSMutableArray <YTSettingsSectionItem *> *)sectionItems
|
||||
forCategory:(NSInteger)category
|
||||
title:(NSString *)title
|
||||
titleDescription:(NSString *)titleDescription
|
||||
headerHidden:(BOOL)headerHidden;
|
||||
- (void)pushViewController:(UIViewController *)viewController;
|
||||
- (void)reloadData;
|
||||
@end
|
||||
|
||||
// Alert
|
||||
@interface YTAlertView : UIView
|
||||
@property (nonatomic, copy, readwrite) NSString *title;
|
||||
@property (nonatomic, copy, readwrite) NSString *subtitle;
|
||||
+ (instancetype)confirmationDialogWithAction:(void (^)(void))action
|
||||
actionTitle:(NSString *)actionTitle
|
||||
cancelTitle:(NSString *)cancelTitle;
|
||||
- (void)show;
|
||||
@end
|
||||
|
||||
// Snack bar
|
||||
@interface YTHUDMessage : NSObject
|
||||
+ (id)messageWithText:(id)text;
|
||||
@end
|
||||
@interface GOOHUDManagerInternal : NSObject
|
||||
- (void)showMessageMainThread:(id)message;
|
||||
+ (id)sharedInstance;
|
||||
@end
|
||||
|
||||
@interface YTUIUtils : NSObject
|
||||
+ (BOOL)openURL:(NSURL *)url;
|
||||
@end
|
||||
279
Tweaks/DontEatMyContent/Tweak.x
Normal file
279
Tweaks/DontEatMyContent/Tweak.x
Normal file
@@ -0,0 +1,279 @@
|
||||
#import <sys/utsname.h>
|
||||
#import <rootless.h>
|
||||
#import "Tweak.h"
|
||||
|
||||
#define UNSUPPORTED_DEVICES @[@"iPhone14,3", @"iPhone14,6", @"iPhone14,8"]
|
||||
#define THRESHOLD 1.99
|
||||
|
||||
CGFloat constant; // Makes rendering view a bit larger since constraining to safe area leaves a gap between the notch/Dynamic Island and video
|
||||
static CGFloat videoAspectRatio = 16/9;
|
||||
static BOOL isZoomedToFill = NO;
|
||||
static BOOL isEngagementPanelVisible = NO;
|
||||
static BOOL isRemoveEngagementPanelViewControllerWithIdentifierCalled = NO;
|
||||
|
||||
static MLHAMSBDLSampleBufferRenderingView *renderingView;
|
||||
static NSLayoutConstraint *widthConstraint, *heightConstraint, *centerXConstraint, *centerYConstraint;
|
||||
|
||||
static BOOL DEMC_isDeviceSupported();
|
||||
static void DEMC_activateConstraints();
|
||||
static void DEMC_deactivateConstraints();
|
||||
static void DEMC_centerRenderingView();
|
||||
void DEMC_showSnackBar(NSString *text);
|
||||
NSBundle *DEMC_getTweakBundle();
|
||||
|
||||
%group DEMC_Tweak
|
||||
|
||||
// Retrieve video aspect ratio
|
||||
%hook YTPlayerView
|
||||
- (void)setAspectRatio:(CGFloat)aspectRatio {
|
||||
%orig(aspectRatio);
|
||||
videoAspectRatio = aspectRatio;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTPlayerViewController
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
YTPlayerView *playerView = [self playerView];
|
||||
UIView *renderingViewContainer = [playerView valueForKey:@"_renderingViewContainer"];
|
||||
renderingView = [playerView renderingView];
|
||||
|
||||
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];
|
||||
|
||||
if (IS_COLOR_VIEWS_ENABLED) {
|
||||
playerView.backgroundColor = [UIColor blueColor];
|
||||
renderingViewContainer.backgroundColor = [UIColor greenColor];
|
||||
renderingView.backgroundColor = [UIColor redColor];
|
||||
} else {
|
||||
playerView.backgroundColor = nil;
|
||||
renderingViewContainer.backgroundColor = nil;
|
||||
renderingView.backgroundColor = [UIColor blackColor];
|
||||
}
|
||||
|
||||
YTMainAppVideoPlayerOverlayViewController *activeVideoPlayerOverlay = [self activeVideoPlayerOverlay];
|
||||
|
||||
// Must check class since YTInlineMutedPlaybackPlayerOverlayViewController doesn't have -(BOOL)isFullscreen
|
||||
if ([activeVideoPlayerOverlay isKindOfClass:%c(YTMainAppVideoPlayerOverlayViewController)] &&
|
||||
[activeVideoPlayerOverlay isFullscreen] && !isZoomedToFill && !isEngagementPanelVisible)
|
||||
DEMC_activateConstraints();
|
||||
|
||||
%orig(animated);
|
||||
}
|
||||
// New video played
|
||||
- (void)playbackController:(id)playbackController didActivateVideo:(id)video withPlaybackData:(id)playbackData {
|
||||
%orig(playbackController, video, playbackData);
|
||||
|
||||
isEngagementPanelVisible = NO;
|
||||
isRemoveEngagementPanelViewControllerWithIdentifierCalled = NO;
|
||||
|
||||
if ([[self activeVideoPlayerOverlay] isFullscreen])
|
||||
// New video played while in full screen (landscape)
|
||||
// Activate since new videos played in full screen aren't zoomed-to-fill by default
|
||||
// (i.e. the notch/Dynamic Island will cut into content when playing a new video in full screen)
|
||||
DEMC_activateConstraints();
|
||||
else if (![self isCurrentVideoVertical] && ((YTPlayerView *)[self playerView]).userInteractionEnabled)
|
||||
DEMC_deactivateConstraints();
|
||||
}
|
||||
- (void)setPlayerViewLayout:(int)layout {
|
||||
%orig(layout);
|
||||
|
||||
if (![[self activeVideoPlayerOverlay] isKindOfClass:%c(YTMainAppVideoPlayerOverlayViewController)]) return;
|
||||
|
||||
switch (layout) {
|
||||
case 1: // Mini bar
|
||||
break;
|
||||
case 2:
|
||||
DEMC_deactivateConstraints();
|
||||
break;
|
||||
case 3: // Fullscreen
|
||||
if (!isZoomedToFill && !isEngagementPanelVisible) DEMC_activateConstraints();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
%end
|
||||
|
||||
// Pinch to zoom
|
||||
%hook YTVideoFreeZoomOverlayView
|
||||
- (void)didRecognizePinch:(UIPinchGestureRecognizer *)pinchGestureRecognizer {
|
||||
DEMC_deactivateConstraints();
|
||||
%orig(pinchGestureRecognizer);
|
||||
}
|
||||
// Detect zoom to fill
|
||||
- (void)showLabelForSnapState:(NSInteger)snapState {
|
||||
if (snapState == 0) { // Original
|
||||
isZoomedToFill = NO;
|
||||
DEMC_activateConstraints();
|
||||
} else if (snapState == 1) { // Zoomed to fill
|
||||
isZoomedToFill = YES;
|
||||
// No need to deactivate constraints as it's already done in -(void)didRecognizePinch:(UIPinchGestureRecognizer *)
|
||||
}
|
||||
%orig(snapState);
|
||||
}
|
||||
%end
|
||||
|
||||
// Mini bar dismiss
|
||||
%hook YTWatchMiniBarViewController
|
||||
- (void)dismissMiniBarWithVelocity:(CGFloat)velocity gestureType:(int)gestureType {
|
||||
%orig(velocity, gestureType);
|
||||
isZoomedToFill = NO; // YouTube undoes zoom-to-fill when mini bar is dismissed
|
||||
}
|
||||
- (void)dismissMiniBarWithVelocity:(CGFloat)velocity gestureType:(int)gestureType skipShouldDismissCheck:(BOOL)skipShouldDismissCheck {
|
||||
%orig(velocity, gestureType, skipShouldDismissCheck);
|
||||
isZoomedToFill = NO;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTMainAppEngagementPanelViewController
|
||||
// Engagement panel (comment, description, etc.) about to show up
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
if ([self isPeekingSupported]) {
|
||||
// Shorts (only Shorts support peeking, I think)
|
||||
} else {
|
||||
// Everything else
|
||||
isEngagementPanelVisible = YES;
|
||||
if ([self isLandscapeEngagementPanel]) {
|
||||
DEMC_deactivateConstraints();
|
||||
}
|
||||
}
|
||||
%orig(animated);
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTEngagementPanelContainerViewController
|
||||
// Engagement panel about to dismiss
|
||||
- (void)notifyEngagementPanelContainerControllerWillHideFinalPanel {
|
||||
// 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] && !isRemoveEngagementPanelViewControllerWithIdentifierCalled) {
|
||||
isEngagementPanelVisible = NO;
|
||||
if ([self isLandscapeEngagementPanel] && !isZoomedToFill) {
|
||||
DEMC_activateConstraints();
|
||||
}
|
||||
}
|
||||
%orig;
|
||||
}
|
||||
- (void)removeEngagementPanelViewControllerWithIdentifier:(id)identifier {
|
||||
// Usually called when engagement panel is open & new video is played or mini bar is dismissed
|
||||
isRemoveEngagementPanelViewControllerWithIdentifierCalled = YES;
|
||||
%orig(identifier);
|
||||
}
|
||||
%end
|
||||
|
||||
%end // group DEMC_Tweak
|
||||
|
||||
%group DEMC_UnsupportedDevice
|
||||
|
||||
// Get tweak settings' index path & prevent it from being opened on unsupported devices
|
||||
id settingsCollectionView;
|
||||
NSIndexPath *tweakIndexPath;
|
||||
%hook YTCollectionViewController
|
||||
- (id)collectionView:(id)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
YTSettingsCell *cell = %orig;
|
||||
if ([cell isKindOfClass:%c(YTSettingsCell)]) {
|
||||
YTLabel *title = [cell valueForKey:@"_titleLabel"];
|
||||
if ([title.text isEqualToString:DEMC]) {
|
||||
settingsCollectionView = collectionView;
|
||||
tweakIndexPath = indexPath;
|
||||
}
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
- (BOOL)collectionView:(id)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (collectionView == settingsCollectionView && indexPath == tweakIndexPath) {
|
||||
NSBundle *bundle = DEMC_getTweakBundle();
|
||||
DEMC_showSnackBar(LOCALIZED_STRING(@"UNSUPPORTED_DEVICE"));
|
||||
return NO;
|
||||
}
|
||||
return %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%end // group DEMC_UnsupportedDevice
|
||||
|
||||
%ctor {
|
||||
if (!DEMC_isDeviceSupported()) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:ENABLED_KEY];
|
||||
%init(DEMC_UnsupportedDevice);
|
||||
return;
|
||||
}
|
||||
|
||||
constant = [[NSUserDefaults standardUserDefaults] floatForKey:SAFE_AREA_CONSTANT_KEY];
|
||||
if (constant == 0) { // First launch probably
|
||||
constant = DEFAULT_CONSTANT;
|
||||
[[NSUserDefaults standardUserDefaults] setFloat:constant forKey:SAFE_AREA_CONSTANT_KEY];
|
||||
}
|
||||
if (IS_TWEAK_ENABLED) %init(DEMC_Tweak);
|
||||
}
|
||||
|
||||
static BOOL DEMC_isDeviceSupported() {
|
||||
// Get device model identifier (e.g. iPhone14,4)
|
||||
// https://stackoverflow.com/a/11197770/19227228
|
||||
struct utsname systemInfo;
|
||||
uname(&systemInfo);
|
||||
NSString *deviceModelId = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
|
||||
|
||||
NSArray *unsupportedModelIds = UNSUPPORTED_DEVICES;
|
||||
for (NSString *identifier in unsupportedModelIds) {
|
||||
if ([deviceModelId isEqualToString:identifier]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
if ([deviceModelId containsString:@"iPhone"]) {
|
||||
if ([deviceModelId isEqualToString:@"iPhone13,1"]) {
|
||||
// iPhone 12 mini
|
||||
return YES;
|
||||
}
|
||||
NSString *modelNumber = [[deviceModelId stringByReplacingOccurrencesOfString:@"iPhone" withString:@""] stringByReplacingOccurrencesOfString:@"," withString:@"."];
|
||||
if ([modelNumber floatValue] >= 14.0) {
|
||||
// iPhone 13 series and newer
|
||||
return YES;
|
||||
} else return NO;
|
||||
} else return NO;
|
||||
}
|
||||
|
||||
static void DEMC_activateConstraints() {
|
||||
if (videoAspectRatio < THRESHOLD) {
|
||||
DEMC_deactivateConstraints();
|
||||
return;
|
||||
}
|
||||
// NSLog(@"activate");
|
||||
DEMC_centerRenderingView();
|
||||
renderingView.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
widthConstraint.active = YES;
|
||||
heightConstraint.active = YES;
|
||||
}
|
||||
|
||||
static void DEMC_deactivateConstraints() {
|
||||
// NSLog(@"deactivate");
|
||||
renderingView.translatesAutoresizingMaskIntoConstraints = YES;
|
||||
}
|
||||
|
||||
static void DEMC_centerRenderingView() {
|
||||
centerXConstraint.active = YES;
|
||||
centerYConstraint.active = YES;
|
||||
}
|
||||
|
||||
void DEMC_showSnackBar(NSString *text) {
|
||||
YTHUDMessage *message = [%c(YTHUDMessage) messageWithText:text];
|
||||
GOOHUDManagerInternal *manager = [%c(GOOHUDManagerInternal) sharedInstance];
|
||||
[manager showMessageMainThread:message];
|
||||
}
|
||||
|
||||
NSBundle *DEMC_getTweakBundle() {
|
||||
static NSBundle *bundle = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"DontEatMyContent" ofType:@"bundle"];
|
||||
if (bundlePath)
|
||||
bundle = [NSBundle bundleWithPath:bundlePath];
|
||||
else // Rootless
|
||||
bundle = [NSBundle bundleWithPath:ROOT_PATH_NS(@"/Library/Application Support/DontEatMyContent.bundle")];
|
||||
});
|
||||
return bundle;
|
||||
}
|
||||
9
Tweaks/DontEatMyContent/control
Normal file
9
Tweaks/DontEatMyContent/control
Normal file
@@ -0,0 +1,9 @@
|
||||
Package: me.foxster.donteatmycontent
|
||||
Name: DontEatMyContent
|
||||
Version: 1.0.10
|
||||
Architecture: iphoneos-arm
|
||||
Description: Prevent the notch/Dynamic Island from munching on 2:1 video content in YouTube
|
||||
Maintainer: Foxster
|
||||
Author: Foxster
|
||||
Section: Tweaks
|
||||
Depends: mobilesubstrate (>= 0.9.5000), firmware (>= 14.0)
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>me.foxster.donteatmycontent</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>DontEatMyContent</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,21 @@
|
||||
"ENABLED" = "Enabled";
|
||||
"TWEAK_DESC" = "Prevents the notch/Dynamic Island from cutting into 2:1 videos (e.g., MKBHD's videos)";
|
||||
|
||||
"SAFE_AREA_CONST" = "Safe area constant";
|
||||
"SAFE_AREA_CONST_DESC" = "Customize this constant to push the video closer to or further away from the notch/Dynamic Island. The larger the constant, the closer the video will be to the notch/Dynamic Island, and vice versa";
|
||||
"DEFAULT" = "default";
|
||||
"SAFE_AREA_CONST_MESSAGE" = "Your changes were saved. If a video is currently playing, dismiss it for changes to take effect";
|
||||
|
||||
"COLOR_VIEWS" = "Colored views";
|
||||
"COLOR_VIEWS_DESC" = "Sets a red background for the rendering view, green for the rendering view container, and blue for the player view; useful for debugging";
|
||||
|
||||
"REPORT_ISSUE" = "Report an issue";
|
||||
"SOURCE_CODE" = "View source code";
|
||||
|
||||
"CHANGES_SAVED" = "Your changes were saved";
|
||||
|
||||
"EXIT" = "Exit";
|
||||
"LATER" = "Later";
|
||||
"EXIT_YT_DESC" = "Relaunch YouTube to apply changes";
|
||||
|
||||
"UNSUPPORTED_DEVICE" = "This device is not supported";
|
||||
Reference in New Issue
Block a user