diff --git a/Makefile b/Makefile index 8669f00..e121926 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ TWEAK_NAME = uYouPlus DISPLAY_NAME = YouTube BUNDLE_ID = com.google.ios.youtube -$(TWEAK_NAME)_FILES = Sources/uYouPlus.xm Sources/Settings.xm Sources/Patches.xm +$(TWEAK_NAME)_FILES = Sources/uYouPlus.xm Sources/Settings.xm Sources/Patches.xm Sources/BigYTMiniPlayer.xm Sources/Themes.xm Sources/YTCastConfirm.xm Sources/YTMiniPlayerEnabler.x Sources/YTNoHoverCards.x Sources/YTNoPaidPromo.x Sources/YTReExplore.x Sources/YTStockVolumeHUD.xm $(TWEAK_NAME)_FRAMEWORKS = UIKit Security $(TWEAK_NAME)_CFLAGS = -fobjc-arc -DTWEAK_VERSION=\"$(PACKAGE_VERSION)\" $(TWEAK_NAME)_INJECT_DYLIBS = Tweaks/uYou/Library/MobileSubstrate/DynamicLibraries/uYou.dylib $(THEOS_OBJ_DIR)/libFLEX.dylib $(THEOS_OBJ_DIR)/iSponsorBlock.dylib $(THEOS_OBJ_DIR)/YouPiP.dylib $(THEOS_OBJ_DIR)/YouTubeDislikesReturn.dylib $(THEOS_OBJ_DIR)/YTABConfig.dylib $(THEOS_OBJ_DIR)/YTUHD.dylib $(THEOS_OBJ_DIR)/DontEatMyContent.dylib $(THEOS_OBJ_DIR)/IAmYouTube.dylib $(THEOS_OBJ_DIR)/YTClassicVideoQuality.dylib $(THEOS_OBJ_DIR)/NoYTPremium.dylib $(THEOS_OBJ_DIR)/YTSpeed.dylib diff --git a/Sources/BigYTMiniPlayer.h b/Sources/BigYTMiniPlayer.h new file mode 100644 index 0000000..8e1eef4 --- /dev/null +++ b/Sources/BigYTMiniPlayer.h @@ -0,0 +1,8 @@ +#import "uYouPlus.h" + +@interface YTMainAppVideoPlayerOverlayView : UIView +- (UIViewController *)_viewControllerForAncestor; +@end + +@interface YTWatchMiniBarView : UIView +@end \ No newline at end of file diff --git a/Sources/BigYTMiniPlayer.xm b/Sources/BigYTMiniPlayer.xm new file mode 100644 index 0000000..68b8593 --- /dev/null +++ b/Sources/BigYTMiniPlayer.xm @@ -0,0 +1,31 @@ +#import "BigYTMiniPlayer.h" + +%group BigYTMiniPlayer // https://github.com/Galactic-Dev/BigYTMiniPlayer +%hook YTWatchMiniBarView +- (void)setWatchMiniPlayerLayout:(int)arg1 { + %orig(1); +} +- (int)watchMiniPlayerLayout { + return 1; +} +- (void)layoutSubviews { + %orig; + self.frame = CGRectMake(([UIScreen mainScreen].bounds.size.width - self.frame.size.width), self.frame.origin.y, self.frame.size.width, self.frame.size.height); +} +%end + +%hook YTMainAppVideoPlayerOverlayView +- (BOOL)isUserInteractionEnabled { + if([[self _viewControllerForAncestor].parentViewController.parentViewController isKindOfClass:%c(YTWatchMiniBarViewController)]) { + return NO; + } + return %orig; +} +%end +%end + +%ctor { + if (IS_ENABLED(@"bigYTMiniPlayer_enabled") && (UIDevice.currentDevice.userInterfaceIdiom != UIUserInterfaceIdiomPad)) { + %init(BigYTMiniPlayer); + } +} \ No newline at end of file diff --git a/Sources/Patches.h b/Sources/Patches.h new file mode 100644 index 0000000..0675e85 --- /dev/null +++ b/Sources/Patches.h @@ -0,0 +1,27 @@ +#import "../Tweaks/YouTubeHeader/YTCommonColorPalette.h" +#import "uYouPlus.h" + +// Prevent uYou player bar from showing when not playing downloaded media +@interface PlayerManager : NSObject +- (float)progress; +@end + +// iOS 16 uYou crash fix - @level3tjg: https://github.com/qnblackcat/uYouPlus/pull/224 +@interface OBPrivacyLinkButton : UIButton +- (instancetype)initWithCaption:(NSString *)caption + buttonText:(NSString *)buttonText + image:(UIImage *)image + imageSize:(CGSize)imageSize + useLargeIcon:(BOOL)useLargeIcon + displayLanguage:(NSString *)displayLanguage; +@end + +// uYouLocal fix +// @interface YTLocalPlaybackController : NSObject +// - (id)activeVideo; +// @end + +// uYou theme fix +// @interface YTAppDelegate () +// @property(nonatomic, strong) id downloadsVC; +// @end \ No newline at end of file diff --git a/Sources/Patches.xm b/Sources/Patches.xm index 691aec6..faccffa 100644 --- a/Sources/Patches.xm +++ b/Sources/Patches.xm @@ -1,4 +1,4 @@ -#import "uYouPlus.h" +#import "Patches.h" # pragma mark - YouTube patches @@ -95,6 +95,13 @@ } %end +// Fix navigation bar showing a lighter grey with default dark mode - https://github.com/therealFoxster/uYouPlus/commit/8db8197 +%hook YTCommonColorPalette +- (UIColor *)brandBackgroundSolid { + return self.pageStyle == 1 ? [UIColor colorWithRed:0.05882352941176471 green:0.05882352941176471 blue:0.05882352941176471 alpha:1.0] : %orig; +} +%end + %ctor { %init; if (@available(iOS 16, *)) { diff --git a/Sources/Settings.h b/Sources/Settings.h new file mode 100644 index 0000000..ad4e37c --- /dev/null +++ b/Sources/Settings.h @@ -0,0 +1,23 @@ +#import "../Tweaks/YouTubeHeader/YTSettingsViewController.h" +#import "../Tweaks/YouTubeHeader/YTSearchableSettingsViewController.h" +#import "../Tweaks/YouTubeHeader/YTSettingsSectionItem.h" +#import "../Tweaks/YouTubeHeader/YTSettingsSectionItemManager.h" +#import "../Tweaks/YouTubeHeader/YTUIUtils.h" +#import "../Tweaks/YouTubeHeader/YTSettingsPickerViewController.h" +#import "uYouPlus.h" + +// For displaying snackbars +@interface YTHUDMessage : NSObject ++ (id)messageWithText:(id)text; +- (void)setAction:(id)action; +@end + +@interface GOOHUDMessageAction : NSObject +- (void)setTitle:(NSString *)title; +- (void)setHandler:(void (^)(id))handler; +@end + +@interface GOOHUDManagerInternal : NSObject +- (void)showMessageMainThread:(id)message; ++ (id)sharedInstance; +@end \ No newline at end of file diff --git a/Sources/Settings.xm b/Sources/Settings.xm index 74a45b5..2c6e8c3 100644 --- a/Sources/Settings.xm +++ b/Sources/Settings.xm @@ -1,19 +1,12 @@ -#import "../Tweaks/YouTubeHeader/YTSettingsViewController.h" -#import "../Tweaks/YouTubeHeader/YTSearchableSettingsViewController.h" -#import "../Tweaks/YouTubeHeader/YTSettingsSectionItem.h" -#import "../Tweaks/YouTubeHeader/YTSettingsSectionItemManager.h" -#import "../Tweaks/YouTubeHeader/YTUIUtils.h" -#import "../Tweaks/YouTubeHeader/YTSettingsPickerViewController.h" -#import "uYouPlus.h" +#import "Settings.h" #define VERSION_STRING [[NSString stringWithFormat:@"%@", @(OS_STRINGIFY(TWEAK_VERSION))] stringByReplacingOccurrencesOfString:@"\"" withString:@""] +#define SHOW_RELAUNCH_YT_SNACKBAR [[%c(GOOHUDManagerInternal) sharedInstance] showMessageMainThread:[%c(YTHUDMessage) messageWithText:LOC(@"RESTART_YOUTUBE")]] #define SECTION_HEADER(s) [sectionItems addObject:[%c(YTSettingsSectionItem) itemWithTitle:@"\t" titleDescription:[s uppercaseString] accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger sectionItemIndex) { return NO; }]] #define SWITCH_ITEM(t, d, k) [sectionItems addObject:[YTSettingsSectionItemClass switchItemWithTitle:t titleDescription:d accessibilityIdentifier:nil switchOn:IS_ENABLED(k) switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:k];return YES;} settingItemId:0]] -#define SHOW_RELAUNCH_YT_SNACKBAR [[%c(GOOHUDManagerInternal) sharedInstance] showMessageMainThread:[%c(YTHUDMessage) messageWithText:LOC(@"RESTART_YOUTUBE")]] - #define SWITCH_ITEM2(t, d, k) [sectionItems addObject:[YTSettingsSectionItemClass switchItemWithTitle:t titleDescription:d accessibilityIdentifier:nil switchOn:IS_ENABLED(k) switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {[[NSUserDefaults standardUserDefaults] setBool:enabled forKey:k];SHOW_RELAUNCH_YT_SNACKBAR;return YES;} settingItemId:0]] static const NSInteger uYouPlusSection = 500; diff --git a/Sources/Themes.h b/Sources/Themes.h new file mode 100644 index 0000000..b153f93 --- /dev/null +++ b/Sources/Themes.h @@ -0,0 +1,55 @@ +#import "../Tweaks/YouTubeHeader/YTCommonColorPalette.h" +#import "../Tweaks/YouTubeHeader/ASCollectionView.h" +#import "uYouPlus.h" + +@interface YCHLiveChatView : UIView +@end + +@interface YTFullscreenEngagementOverlayView : UIView +@end + +@interface YTRelatedVideosView : UIView +@end + +@interface ELMView : UIView +@end + +@interface ASWAppSwitcherCollectionViewCell : UIView +@end + +@interface ASScrollView : UIView +@end + +@interface UIKeyboardLayoutStar : UIView +@end + +@interface UIKeyboardDockView : UIView +@end + +@interface _ASDisplayView : UIView +@end + +@interface YTCommentDetailHeaderCell : UIView +@end + +@interface SponsorBlockSettingsController : UITableViewController +@end + +@interface SponsorBlockViewController : UIViewController +@end + +@interface UICandidateViewController : UIViewController +@end + +@interface UIPredictionViewController : UIViewController +@end + +@interface FRPreferences : UITableViewController +@end + +@interface FRPSelectListTable : UITableViewController +@end + +@interface settingsReorderTable : UIViewController +@property(nonatomic, strong) UITableView *tableView; +@end \ No newline at end of file diff --git a/Sources/Themes.xm b/Sources/Themes.xm new file mode 100644 index 0000000..4f4dc3a --- /dev/null +++ b/Sources/Themes.xm @@ -0,0 +1,349 @@ +#import "Themes.h" + +#define IS_DARK_APPEARANCE_ENABLED ([[NSUserDefaults standardUserDefaults] integerForKey:@"page_style"] == 1) +#define IS_OLD_DARK_THEME_SELECTED (APP_THEME_IDX == 1) +#define IS_OLED_DARK_THEME_SELECTED (APP_THEME_IDX == 2) + +# pragma mark - Old dark theme (lighter grey) + +%group gOldDarkTheme +%hook YTColdConfig +- (BOOL)uiSystemsClientGlobalConfigUseDarkerPaletteBgColorForNative { return NO; } +- (BOOL)uiSystemsClientGlobalConfigUseDarkerPaletteTextColorForNative { return NO; } +- (BOOL)enableCinematicContainerOnClient { return NO; } +%end + +%hook _ASDisplayView +- (void)didMoveToWindow { + %orig; + if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.comment_composer"]) { self.backgroundColor = [UIColor clearColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.video_list_entry"]) { self.backgroundColor = [UIColor clearColor]; } +} +%end + +%hook ASCollectionView +- (void)didMoveToWindow { + %orig; + self.superview.backgroundColor = [UIColor colorWithRed:0.129 green:0.129 blue:0.129 alpha:1.0]; +} +%end + +%hook YTFullscreenEngagementOverlayView +- (void)didMoveToWindow { + %orig; + self.subviews[0].backgroundColor = [UIColor clearColor]; +} +%end + +%hook YTRelatedVideosView +- (void)didMoveToWindow { + %orig; + self.subviews[0].backgroundColor = [UIColor clearColor]; +} +%end +%end + +# pragma mark - OLED dark mode by BandarHL + +UIColor* raisedColor = [UIColor colorWithRed:0.035 green:0.035 blue:0.035 alpha:1.0]; + +%group gOLED +%hook YTCommonColorPalette +- (UIColor *)baseBackground { + return self.pageStyle == 1 ? [UIColor blackColor] : %orig; +} +- (UIColor *)brandBackgroundSolid { + return self.pageStyle == 1 ? [UIColor blackColor] : %orig; +} +- (UIColor *)brandBackgroundPrimary { + return self.pageStyle == 1 ? [UIColor blackColor] : %orig; +} +- (UIColor *)brandBackgroundSecondary { + return self.pageStyle == 1 ? [[UIColor blackColor] colorWithAlphaComponent:0.9] : %orig; +} +- (UIColor *)raisedBackground { + return self.pageStyle == 1 ? [UIColor blackColor] : %orig; +} +- (UIColor *)staticBrandBlack { + return self.pageStyle == 1 ? [UIColor blackColor] : %orig; +} +- (UIColor *)generalBackgroundA { + return self.pageStyle == 1 ? [UIColor blackColor] : %orig; +} +%end + +// uYou settings +%hook UITableViewCell +- (void)_layoutSystemBackgroundView { + %orig; + UIView *systemBackgroundView = [self valueForKey:@"_systemBackgroundView"]; + NSString *backgroundViewKey = class_getInstanceVariable(systemBackgroundView.class, "_colorView") ? @"_colorView" : @"_backgroundView"; + ((UIView *)[systemBackgroundView valueForKey:backgroundViewKey]).backgroundColor = [UIColor blackColor]; +} +- (void)_layoutSystemBackgroundView:(BOOL)arg1 { + %orig; + ((UIView *)[[self valueForKey:@"_systemBackgroundView"] valueForKey:@"_colorView"]).backgroundColor = [UIColor blackColor]; +} +%end + +%hook settingsReorderTable +- (void)viewDidLayoutSubviews { + %orig; + self.tableView.backgroundColor = [UIColor blackColor]; +} +%end + +%hook FRPSelectListTable +- (void)viewDidLayoutSubviews { + %orig; + self.tableView.backgroundColor = [UIColor blackColor]; +} +%end + +%hook FRPreferences +- (void)viewDidLayoutSubviews { + %orig; + self.tableView.backgroundColor = [UIColor blackColor]; +} +%end + +%hook YTInnerTubeCollectionViewController +- (UIColor *)backgroundColor:(NSInteger)pageStyle { + return pageStyle == 1 ? [UIColor blackColor] : %orig; +} +%end + +// Explore +%hook ASScrollView +- (void)didMoveToWindow { + %orig; + if (IS_DARK_APPEARANCE_ENABLED) { + self.backgroundColor = [UIColor clearColor]; + } +} +%end + +// Your videos +%hook ASCollectionView +- (void)didMoveToWindow { + %orig; + if (IS_DARK_APPEARANCE_ENABLED && [self.nextResponder isKindOfClass:%c(_ASDisplayView)]) { + self.superview.backgroundColor = [UIColor blackColor]; + } +} +%end + +// Sub menu? +%hook ELMView +- (void)didMoveToWindow { + %orig; + if (IS_DARK_APPEARANCE_ENABLED) { + // self.subviews[0].backgroundColor = [UIColor clearColor]; + } +} +%end + +// iSponsorBlock +%hook SponsorBlockSettingsController +- (void)viewDidLoad { + if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { + %orig; + self.tableView.backgroundColor = [UIColor blackColor]; + } else { return %orig; } +} +%end + +%hook SponsorBlockViewController +- (void)viewDidLoad { + if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { + %orig; + self.view.backgroundColor = [UIColor blackColor]; + } else { return %orig; } +} +%end + +// Search view +%hook YTSearchBarView +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; +} +%end + +// History search view +%hook YTSearchBoxView +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; + +} +%end + +// Comment view +%hook YTCommentView +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; +} +%end + +%hook YTCreateCommentAccessoryView +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; +} +%end + +%hook YTCreateCommentTextView +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; +} +- (void)setTextColor:(UIColor *)color { // fix black text in #Shorts video's comment + return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor whiteColor]) : %orig; +} +%end + +%hook YTCommentDetailHeaderCell +- (void)didMoveToWindow { + %orig; + if (IS_DARK_APPEARANCE_ENABLED) { + // self.subviews[2].backgroundColor = [UIColor blackColor]; + } +} +%end + +%hook YTFormattedStringLabel // YT is werid... +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor clearColor]) : %orig; +} +%end + +// Live chat comment +%hook YCHLiveChatActionPanelView +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; +} +%end + +%hook YTEmojiTextView +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; +} +%end + +%hook YCHLiveChatView +- (void)didMoveToWindow { + %orig; + if (IS_DARK_APPEARANCE_ENABLED) { + // self.subviews[1].backgroundColor = [UIColor blackColor]; + } +} +%end + +%hook YTCollectionView +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; +} +%end + +// +%hook YTBackstageCreateRepostDetailView +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; +} +%end + +// Others +%hook _ASDisplayView +- (void)didMoveToWindow { + %orig; + if (IS_DARK_APPEARANCE_ENABLED) { + if ([self.nextResponder isKindOfClass:%c(ASScrollView)]) { self.backgroundColor = [UIColor clearColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"eml.cvr"]) { self.backgroundColor = [UIColor blackColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"eml.live_chat_text_message"]) { self.backgroundColor = [UIColor blackColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"rich_header"]) { self.backgroundColor = [UIColor blackColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"id.ui.comment_cell"]) { self.backgroundColor = [UIColor blackColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"id.ui.cancel.button"]) { self.superview.backgroundColor = [UIColor clearColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.comment_composer"]) { self.backgroundColor = [UIColor blackColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.video_list_entry"]) { self.backgroundColor = [UIColor blackColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"id.comment.guidelines_text"]) { self.superview.backgroundColor = [UIColor blackColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"id.comment.channel_guidelines_bottom_sheet_container"]) { self.backgroundColor = [UIColor blackColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"id.comment.channel_guidelines_entry_banner_container"]) { self.backgroundColor = [UIColor blackColor]; } + if ([self.accessibilityIdentifier isEqualToString:@"id.comment.comment_group_detail_container"]) { self.backgroundColor = [UIColor clearColor]; } + } +} +%end + +// Open link with... +%hook ASWAppSwitchingSheetHeaderView +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig(raisedColor) : %orig; +} +%end + +%hook ASWAppSwitchingSheetFooterView +- (void)setBackgroundColor:(UIColor *)color { + return IS_DARK_APPEARANCE_ENABLED ? %orig(raisedColor) : %orig; +} +%end + +%hook ASWAppSwitcherCollectionViewCell +- (void)didMoveToWindow { + %orig; + if (IS_DARK_APPEARANCE_ENABLED) { + self.backgroundColor = raisedColor; + // self.subviews[1].backgroundColor = raisedColor; + self.superview.backgroundColor = raisedColor; + } +} +%end + +// Incompatibility with the new YT Dark theme +%hook YTColdConfig +- (BOOL)uiSystemsClientGlobalConfigUseDarkerPaletteBgColorForNative { return NO; } +%end +%end + +# pragma mark - OLED keyboard by @ichitaso <3 - http://gist.github.com/ichitaso/935100fd53a26f18a9060f7195a1be0e + +%group gOLEDKB +%hook UIPredictionViewController +- (void)loadView { + %orig; + [self.view setBackgroundColor:[UIColor blackColor]]; +} +%end + +%hook UICandidateViewController +- (void)loadView { + %orig; + [self.view setBackgroundColor:[UIColor blackColor]]; +} +%end + +%hook UIKeyboardDockView +- (void)didMoveToWindow { + %orig; + self.backgroundColor = [UIColor blackColor]; +} +%end + +%hook UIKeyboardLayoutStar +- (void)didMoveToWindow { + %orig; + self.backgroundColor = [UIColor blackColor]; +} +%end + +%hook UIKBRenderConfig // Prediction text color +- (void)setLightKeyboard:(BOOL)arg1 { %orig(NO); } +%end +%end + +%ctor { + if (IS_OLED_DARK_THEME_SELECTED) { + %init(gOLED); + } + if (IS_OLD_DARK_THEME_SELECTED) { + %init(gOldDarkTheme) + } + if (IS_ENABLED(@"oledKeyBoard_enabled")) { + %init(gOLEDKB); + } +} \ No newline at end of file diff --git a/Sources/YTCastConfirm.xm b/Sources/YTCastConfirm.xm new file mode 100644 index 0000000..c5d5200 --- /dev/null +++ b/Sources/YTCastConfirm.xm @@ -0,0 +1,21 @@ +#import "../Tweaks/YouTubeHeader/YTAlertView.h" +#import "uYouPlus.h" + +extern NSBundle *uYouPlusBundle(); + +// YTCastConfirm: https://github.com/JamieBerghmans/YTCastConfirm +%hook MDXPlaybackRouteButtonController +- (void)didPressButton:(id)arg1 { + if (IS_ENABLED(@"castConfirm_enabled")) { + NSBundle *tweakBundle = uYouPlusBundle(); + YTAlertView *alertView = [%c(YTAlertView) confirmationDialogWithAction:^{ + %orig; + } actionTitle:LOC(@"MSG_YES")]; + alertView.title = LOC(@"CASTING"); + alertView.subtitle = LOC(@"MSG_ARE_YOU_SURE"); + [alertView show]; + } else { + return %orig; + } +} +%end \ No newline at end of file diff --git a/Sources/YTMiniPlayerEnabler.x b/Sources/YTMiniPlayerEnabler.x new file mode 100644 index 0000000..ec82abd --- /dev/null +++ b/Sources/YTMiniPlayerEnabler.x @@ -0,0 +1,9 @@ +#import "uYouPlus.h" + +// YTMiniPlayerEnabler: https://github.com/level3tjg/YTMiniplayerEnabler/ +%hook YTWatchMiniBarViewController +- (void)updateMiniBarPlayerStateFromRenderer { + if (IS_ENABLED(@"ytMiniPlayer_enabled")) {} + else { return %orig; } +} +%end \ No newline at end of file diff --git a/Sources/YTNoHoverCards.x b/Sources/YTNoHoverCards.x new file mode 100644 index 0000000..6c5f819 --- /dev/null +++ b/Sources/YTNoHoverCards.x @@ -0,0 +1,10 @@ +#import "uYouPlus.h" + +// YTNoHoverCards: https://github.com/level3tjg/YTNoHoverCards +%hook YTCreatorEndscreenView +- (void)setHidden:(BOOL)hidden { + if (IS_ENABLED(@"hideHoverCards_enabled")) + hidden = YES; + %orig; +} +%end \ No newline at end of file diff --git a/Sources/YTNoPaidPromo.x b/Sources/YTNoPaidPromo.x new file mode 100644 index 0000000..fb0ca3f --- /dev/null +++ b/Sources/YTNoPaidPromo.x @@ -0,0 +1,22 @@ +#import "../Tweaks/YouTubeHeader/YTPlayerOverlayProvider.h" +#import "../Tweaks/YouTubeHeader/YTPlayerOverlay.h" +#import "uYouPlus.h" + +// YTNoPaidPromo: https://github.com/PoomSmart/YTNoPaidPromo +%hook YTMainAppVideoPlayerOverlayViewController +- (void)setPaidContentWithPlayerData:(id)data { + if (IS_ENABLED(@"hidePaidPromotionCard_enabled")) {} + else { return %orig; } +} +- (void)playerOverlayProvider:(YTPlayerOverlayProvider *)provider didInsertPlayerOverlay:(YTPlayerOverlay *)overlay { + if ([[overlay overlayIdentifier] isEqualToString:@"player_overlay_paid_content"] && IS_ENABLED(@"hidePaidPromotionCard_enabled")) return; + %orig; +} +%end + +%hook YTInlineMutedPlaybackPlayerOverlayViewController +- (void)setPaidContentWithPlayerData:(id)data { + if (IS_ENABLED(@"hidePaidPromotionCard_enabled")) {} + else { return %orig; } +} +%end \ No newline at end of file diff --git a/Sources/YTReExplore.x b/Sources/YTReExplore.x new file mode 100644 index 0000000..275ae8c --- /dev/null +++ b/Sources/YTReExplore.x @@ -0,0 +1,45 @@ +#import "../Tweaks/YouTubeHeader/YTIPivotBarRenderer.h" +#import "../Tweaks/YouTubeHeader/YTIGuideResponse.h" +#import "../Tweaks/YouTubeHeader/YTIGuideResponseSupportedRenderers.h" +#import "../Tweaks/YouTubeHeader/YTIBrowseRequest.h" +#import "uYouPlus.h" + +%group YTReExplore // https://github.com/PoomSmart/YTReExplore/ +static void replaceTab(YTIGuideResponse *response) { + NSMutableArray *renderers = [response itemsArray]; + for (YTIGuideResponseSupportedRenderers *guideRenderers in renderers) { + YTIPivotBarRenderer *pivotBarRenderer = [guideRenderers pivotBarRenderer]; + NSMutableArray *items = [pivotBarRenderer itemsArray]; + NSUInteger shortIndex = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) { + return [[[renderers pivotBarItemRenderer] pivotIdentifier] isEqualToString:@"FEshorts"]; + }]; + if (shortIndex != NSNotFound) { + [items removeObjectAtIndex:shortIndex]; + NSUInteger exploreIndex = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) { + return [[[renderers pivotBarItemRenderer] pivotIdentifier] isEqualToString:[%c(YTIBrowseRequest) browseIDForExploreTab]]; + }]; + if (exploreIndex == NSNotFound) { + YTIPivotBarSupportedRenderers *exploreTab = [%c(YTIPivotBarRenderer) pivotSupportedRenderersWithBrowseId:[%c(YTIBrowseRequest) browseIDForExploreTab] title:@"Explore" iconType:292]; + [items insertObject:exploreTab atIndex:1]; + } + break; + } + } +} +%hook YTGuideServiceCoordinator +- (void)handleResponse:(YTIGuideResponse *)response withCompletion:(id)completion { + replaceTab(response); + %orig(response, completion); +} +- (void)handleResponse:(YTIGuideResponse *)response error:(id)error completion:(id)completion { + replaceTab(response); + %orig(response, error, completion); +} +%end +%end + +%ctor { + if (IS_ENABLED(@"reExplore_enabled")) { + %init(YTReExplore); + } +} \ No newline at end of file diff --git a/Sources/YTStockVolumeHUD.xm b/Sources/YTStockVolumeHUD.xm new file mode 100644 index 0000000..7f4a5bc --- /dev/null +++ b/Sources/YTStockVolumeHUD.xm @@ -0,0 +1,21 @@ +#import "uYouPlus.h" + +%group YTStockVolumeHUD // https://github.com/lilacvibes/YTStockVolumeHUD +%hook YTVolumeBarView +- (void)volumeChanged:(id)arg1 { + %orig(nil); +} +%end + +%hook UIApplication +- (void)setSystemVolumeHUDEnabled:(BOOL)arg1 forAudioCategory:(id)arg2 { + %orig(true, arg2); +} +%end +%end + +%ctor { + if (IS_ENABLED(@"stockVolumeHUD_enabled")) { + %init(YTStockVolumeHUD); + } +} \ No newline at end of file diff --git a/Sources/uYouPlus.h b/Sources/uYouPlus.h index ad18c34..e4fd678 100644 --- a/Sources/uYouPlus.h +++ b/Sources/uYouPlus.h @@ -6,208 +6,32 @@ #import #import -#import "../Tweaks/YouTubeHeader/YTAppDelegate.h" -#import "../Tweaks/YouTubeHeader/YTPlayerViewController.h" -#import "../Tweaks/YouTubeHeader/YTVideoQualitySwitchOriginalController.h" -#import "../Tweaks/YouTubeHeader/YTPlayerViewController.h" -#import "../Tweaks/YouTubeHeader/YTWatchController.h" -#import "../Tweaks/YouTubeHeader/YTIGuideResponse.h" -#import "../Tweaks/YouTubeHeader/YTIGuideResponseSupportedRenderers.h" -#import "../Tweaks/YouTubeHeader/YTIPivotBarSupportedRenderers.h" -#import "../Tweaks/YouTubeHeader/YTIPivotBarRenderer.h" -#import "../Tweaks/YouTubeHeader/YTIBrowseRequest.h" -#import "../Tweaks/YouTubeHeader/YTCommonColorPalette.h" -#import "../Tweaks/YouTubeHeader/ASCollectionView.h" -#import "../Tweaks/YouTubeHeader/YTPlayerOverlay.h" -#import "../Tweaks/YouTubeHeader/YTPlayerOverlayProvider.h" -#import "../Tweaks/YouTubeHeader/YTReelWatchPlaybackOverlayView.h" -#import "../Tweaks/YouTubeHeader/YTReelPlayerBottomButton.h" -#import "../Tweaks/YouTubeHeader/YTReelPlayerViewController.h" -#import "../Tweaks/YouTubeHeader/YTAlertView.h" -#import "../Tweaks/YouTubeHeader/YTISectionListRenderer.h" -#import "../Tweaks/YouTubeHeader/YTIMenuConditionalServiceItemRenderer.h" +#import "Themes.h" // Hide "Buy Super Thanks" banner (_ASDisplayView) +#import "../Tweaks/YouTubeHeader/YTAppDelegate.h" // Activate FLEX +// #import "../Tweaks/YouTubeHeader/YTISectionListRenderer.h" // Hide search ads by @PoomSmart - https://github.com/PoomSmart/YouTube-X #define LOC(x) [tweakBundle localizedStringForKey:x value:nil table:nil] -#define YT_BUNDLE_ID @"com.google.ios.youtube" -#define YT_NAME @"YouTube" #define IS_ENABLED(k) [[NSUserDefaults standardUserDefaults] boolForKey:k] #define APP_THEME_IDX [[NSUserDefaults standardUserDefaults] integerForKey:@"appTheme"] -#define DEFAULT_RATE 2.0f // YTSpeed - -// IAmYouTube -@interface SSOConfiguration : NSObject -@end - -// uYouPlus -@interface YTChipCloudCell : UIView -@end - -@interface YTPlayabilityResolutionUserActionUIController : NSObject // Skips content warning before playing *some videos - @PoomSmart -- (void)confirmAlertDidPressConfirm; -@end - -@interface YTMainAppControlsOverlayView : UIView -@end - -@interface YTTransportControlsButtonView : UIView -@end - -@interface _ASCollectionViewCell : UICollectionViewCell -- (id)node; -@end - -@interface YTAsyncCollectionView : UICollectionView -- (void)removeShortsAndFeaturesAdsAtIndexPath:(NSIndexPath *)indexPath; -@end - -@interface FRPSliderCell : UITableViewCell -@end - -@interface boolSettingsVC : UIViewController -@end - -@interface PlayerManager : NSObject -- (float)progress; -@end +// Disable snap to chapter @interface YTSegmentableInlinePlayerBarView @property (nonatomic, assign, readwrite) BOOL enableSnapToChapter; @end -@interface YTPlaylistHeaderViewController: UIViewController -@property UIButton *downloadsButton; +// Hide autoplay switch / CC button +@interface YTMainAppControlsOverlayView : UIView @end -// YTSpeed -@interface YTVarispeedSwitchControllerOption : NSObject -- (id)initWithTitle:(id)title rate:(float)rate; +// Skips content warning before playing *some videos - @PoomSmart +@interface YTPlayabilityResolutionUserActionUIController : NSObject +- (void)confirmAlertDidPressConfirm; @end -@interface MLHAMQueuePlayer : NSObject -@property id playerEventCenter; -@property id delegate; -- (void)setRate:(float)rate; -- (void)internalSetRate; +// Hide YouTube annoying banner in Home page? - @MiRO92 - YTNoShorts: https://github.com/MiRO92/YTNoShorts +@interface _ASCollectionViewCell : UICollectionViewCell +- (id)node; @end - -@interface MLPlayerStickySettings : NSObject -- (void)setRate:(float)rate; +@interface YTAsyncCollectionView : UICollectionView +- (void)removeShortsAndFeaturesAdsAtIndexPath:(NSIndexPath *)indexPath; @end - -@interface MLPlayerEventCenter : NSObject -- (void)broadcastRateChange:(float)rate; -@end - -@interface HAMPlayerInternal : NSObject -- (void)setRate:(float)rate; -@end - -// iOS16 fix -@interface OBPrivacyLinkButton : UIButton -- (instancetype)initWithCaption:(NSString *)caption - buttonText:(NSString *)buttonText - image:(UIImage *)image - imageSize:(CGSize)imageSize - useLargeIcon:(BOOL)useLargeIcon - displayLanguage:(NSString *)displayLanguage; -@end - -// uYouLocal fix -@interface YTLocalPlaybackController : NSObject -- (id)activeVideo; -@end - -// uYou theme fix -@interface YTAppDelegate () -@property(nonatomic, strong) id downloadsVC; -@end - - -// BigYTMiniPlayer -@interface YTMainAppVideoPlayerOverlayView : UIView -- (UIViewController *)_viewControllerForAncestor; -@end - -@interface YTWatchMiniBarView : UIView -@end - -// YTAutoFullScreen -@interface YTPlayerViewController (YTAFS) -- (void)autoFullscreen; -// DontEatMycontent -- (id)activeVideoPlayerOverlay; -- (id)playerView; -// YTSpeed -@property id activeVideo; -@property float playbackRate; -- (void)singleVideo:(id)video playbackRateDidChange:(float)rate; -@end - -// App Theme -@interface YCHLiveChatView : UIView -@end - -@interface YTFullscreenEngagementOverlayView : UIView -@end - -@interface YTRelatedVideosView : UIView -@end - -@interface ELMView : UIView -@end - -@interface ASWAppSwitcherCollectionViewCell : UIView -@end - -@interface ASScrollView : UIView -@end - -@interface UIKeyboardLayoutStar : UIView -@end - -@interface UIKeyboardDockView : UIView -@end - -@interface _ASDisplayView : UIView -@end - -@interface YTCommentDetailHeaderCell : UIView -@end - -@interface SponsorBlockSettingsController : UITableViewController -@end - -@interface SponsorBlockViewController : UIViewController -@end - -@interface UICandidateViewController : UIViewController -@end - -@interface UIPredictionViewController : UIViewController -@end - -@interface FRPreferences : UITableViewController -@end - -@interface FRPSelectListTable : UITableViewController -@end - -@interface settingsReorderTable : UIViewController -@property(nonatomic, strong) UITableView *tableView; -@end - -// Snack bar -@interface YTHUDMessage : NSObject -+ (id)messageWithText:(id)text; -- (void)setAction:(id)action; -@end - -@interface GOOHUDMessageAction : NSObject -- (void)setTitle:(NSString *)title; -- (void)setHandler:(void (^)(id))handler; -@end - -@interface GOOHUDManagerInternal : NSObject -- (void)showMessageMainThread:(id)message; -+ (id)sharedInstance; -@end \ No newline at end of file diff --git a/Sources/uYouPlus.xm b/Sources/uYouPlus.xm index 2887f97..ed9f63e 100644 --- a/Sources/uYouPlus.xm +++ b/Sources/uYouPlus.xm @@ -1,9 +1,5 @@ #import "uYouPlus.h" -#define IS_DARK_APPEARANCE_ENABLED ([[NSUserDefaults standardUserDefaults] integerForKey:@"page_style"] == 1) -#define IS_OLD_DARK_THEME_SELECTED (APP_THEME_IDX == 1) -#define IS_OLED_DARK_THEME_SELECTED (APP_THEME_IDX == 2) - // Tweak's bundle for Localizations support - @PoomSmart - https://github.com/PoomSmart/YouPiP/commit/aea2473f64c75d73cab713e1e2d5d0a77675024f NSBundle *uYouPlusBundle() { static NSBundle *bundle = nil; @@ -19,18 +15,219 @@ NSBundle *uYouPlusBundle() { } NSBundle *tweakBundle = uYouPlusBundle(); -# pragma mark - Tweaks +# pragma mark - App appearance +// See Themes.xm -// FLEX +# pragma mark - Video player options + +// Disable double tap to seek +%hook YTDoubleTapToSeekController +- (void)enableDoubleTapToSeek:(BOOL)arg1 { + return IS_ENABLED(@"doubleTapToSeek_disabled") ? %orig(NO) : %orig; +} +%end + +// Disable snap to chapter +%hook YTSegmentableInlinePlayerBarView +- (void)didMoveToWindow { + %orig; + if (IS_ENABLED(@"snapToChapter_enabled")) { + self.enableSnapToChapter = NO; + } +} +%end + +// Disable pinch to zoom +%hook YTColdConfig +- (BOOL)videoZoomFreeZoomEnabledGlobalConfig { + return IS_ENABLED(@"pinchToZoom_enabled") ? NO : %orig; +} +%end + +// Enable miniplayer for all videos +// See YTMiniPlayerEnabler.x + +// Use stock iOS volume HUD +// See YTStockVolumeHUD.xm + +# pragma mark - Video control overlay options + +%hook YTMainAppControlsOverlayView +// Hide autoplay switch +- (void)setAutoplaySwitchButtonRenderer:(id)arg1 { // hide Autoplay + if (IS_ENABLED(@"hideAutoplaySwitch_enabled")) {} + else { return %orig; } +} +// Hide CC button +- (void)setClosedCaptionsOrSubtitlesButtonAvailable:(BOOL)arg1 { + return IS_ENABLED(@"hideCC_enabled") ? %orig(NO) : %orig; +} +%end + +// Hide HUD Messages +%hook YTHUDMessageView +- (id)initWithMessage:(id)arg1 dismissHandler:(id)arg2 { + return IS_ENABLED(@"hideHUD_enabled") ? nil : %orig; +} +%end + +// Hide paid promotion banner +// See YTNoPaidPromo.x + +// Hide channel watermark +%hook YTAnnotationsViewController +- (void)loadFeaturedChannelWatermark { + if (IS_ENABLED(@"hideChannelWatermark_enabled")) {} + else { return %orig; } +} +%end + +// Hide next and previous buttons +%group gHidePreviousAndNextButton +%hook YTColdConfig +- (BOOL)removeNextPaddleForSingletonVideos { return YES; } +- (BOOL)removePreviousPaddleForSingletonVideos { return YES; } +%end +%end + +// Replace next and previous buttons with fast forward and rewind +%group gReplacePreviousAndNextButton +%hook YTColdConfig +- (BOOL)replaceNextPaddleWithFastForwardButtonForSingletonVods { return YES; } +- (BOOL)replacePreviousPaddleWithRewindButtonForSingletonVods { return YES; } +%end +%end + +// Bring back the red progress bar - Broken?! +%hook YTInlinePlayerBarContainerView +- (id)quietProgressBarColor { + return IS_ENABLED(@"redProgressBar_enabled") ? [UIColor redColor] : %orig; +} +%end + +// Hide videos' end screens +// See YTNoHoverCards.x + +// Hide engagement panels in full screen +%hook YTColdConfig +- (BOOL)isLandscapeEngagementPanelEnabled { + return IS_ENABLED(@"hideRightPanel_enabled") ? NO : %orig; +} +%end + +// Skips content warning before playing *some videos - @PoomSmart +%hook YTPlayabilityResolutionUserActionUIController +- (void)showConfirmAlert { [self confirmAlertDidPressConfirm]; } +%end + +# pragma mark - Shorts controls overlay options + +// Hide "Buy Super Thanks" banner +%hook _ASDisplayView +- (void)didMoveToWindow { + %orig; + if ((IS_ENABLED(@"hideBuySuperThanks_enabled")) && ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.suggested_action"])) { + self.hidden = YES; + } +} +%end + +// Hide subscriptions button +%hook YTReelWatchRootViewController +- (void)setPausedStateCarouselView { + if (IS_ENABLED(@"hideSubcriptions_enabled")) {} + else { return %orig; } +} +%end + +// Disable resume to Shorts +%hook YTShortsStartupCoordinator +- (id)evaluateResumeToShorts { + return IS_ENABLED(@"disableResumeToShorts") ? nil : %orig; +} +%end + +# pragma mark - Miscellaneous + +// YTCastConfirm +// See YTCastConfirm.xm + +// Disable hints - https://github.com/LillieH001/YouTube-Reborn/blob/v4/ +%group gDisableHints +%hook YTSettings +- (BOOL)areHintsDisabled { + return YES; +} +- (void)setHintsDisabled:(BOOL)arg1 { + %orig(YES); +} +%end +%hook YTUserDefaults +- (BOOL)areHintsDisabled { + return YES; +} +- (void)setHintsDisabled:(BOOL)arg1 { + %orig(YES); +} +%end +%end + +// Enable YouTube startup animation +%hook YTColdConfig +- (BOOL)mainAppCoreClientIosEnableStartupAnimation { + return IS_ENABLED(@"ytStartupAnimation_enabled") ? YES : NO; +} +%end + +// Hide upper bar +%group gHideChipBar +%hook YTMySubsFilterHeaderView +- (void)setChipFilterView:(id)arg1 {} +%end + +%hook YTHeaderContentComboView +- (void)enableSubheaderBarWithView:(id)arg1 {} +%end + +%hook YTHeaderContentComboView +- (void)setFeedHeaderScrollMode:(int)arg1 { %orig(0); } +%end +%end + +// Force iPhone layout +%group giPhoneLayout +%hook UIDevice +- (long long)userInterfaceIdiom { + return NO; +} +%end +%hook UIStatusBarStyleAttributes +- (long long)idiom { + return YES; +} +%end +%hook UIKBTree +- (long long)nativeIdiom { + return YES; +} +%end +%hook UIKBRenderer +- (long long)assetIdiom { + return YES; +} +%end +%end + +# pragma mark - Other hooks + +// Activate FLEX %hook YTAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { BOOL didFinishLaunching = %orig; - if (IS_ENABLED(@"flex_enabled")) { [[%c(FLEXManager) performSelector:@selector(sharedManager)] performSelector:@selector(showExplorer)]; } - return didFinishLaunching; } - (void)appWillResignActive:(id)arg1 { @@ -61,40 +258,6 @@ NSBundle *tweakBundle = uYouPlusBundle(); } %end -// YTMiniPlayerEnabler: https://github.com/level3tjg/YTMiniplayerEnabler/ -%hook YTWatchMiniBarViewController -- (void)updateMiniBarPlayerStateFromRenderer { - if (IS_ENABLED(@"ytMiniPlayer_enabled")) {} - else { return %orig; } -} -%end - -// YTNoHoverCards: https://github.com/level3tjg/YTNoHoverCards -%hook YTCreatorEndscreenView -- (void)setHidden:(BOOL)hidden { - if (IS_ENABLED(@"hideHoverCards_enabled")) - hidden = YES; - %orig; -} -%end - -// YTCastConfirm: https://github.com/JamieBerghmans/YTCastConfirm -%hook MDXPlaybackRouteButtonController -- (void)didPressButton:(id)arg1 { - if (IS_ENABLED(@"castConfirm_enabled")) { - NSBundle *tweakBundle = uYouPlusBundle(); - YTAlertView *alertView = [%c(YTAlertView) confirmationDialogWithAction:^{ - %orig; - } actionTitle:LOC(@"MSG_YES")]; - alertView.title = LOC(@"CASTING"); - alertView.subtitle = LOC(@"MSG_ARE_YOU_SURE"); - [alertView show]; - } else { - return %orig; - } -} -%end - // Hide search ads by @PoomSmart - https://github.com/PoomSmart/YouTube-X // %hook YTIElementRenderer // - (NSData *)elementData { @@ -117,655 +280,27 @@ NSBundle *tweakBundle = uYouPlusBundle(); // } // %end -// YTClassicVideoQuality: https://github.com/PoomSmart/YTClassicVideoQuality -%hook YTVideoQualitySwitchControllerFactory -- (id)videoQualitySwitchControllerWithParentResponder:(id)responder { - Class originalClass = %c(YTVideoQualitySwitchOriginalController); - return originalClass ? [[originalClass alloc] initWithParentResponder:responder] : %orig; -} -%end - // A/B flags %hook YTColdConfig -- (BOOL)respectDeviceCaptionSetting { return NO; } // YouRememberCaption: https://poomsmart.github.io/repo/depictions/youremembercaption.html -- (BOOL)isLandscapeEngagementPanelSwipeRightToDismissEnabled { return YES; } // Swipe right to dismiss the right panel in fullscreen mode +// YouRememberCaption: https://poomsmart.github.io/repo/depictions/youremembercaption.html +- (BOOL)respectDeviceCaptionSetting { return NO; } +// Swipe right to dismiss the right panel in fullscreen mode +- (BOOL)isLandscapeEngagementPanelSwipeRightToDismissEnabled { return YES; } %end -// YTNoPaidPromo: https://github.com/PoomSmart/YTNoPaidPromo -%hook YTMainAppVideoPlayerOverlayViewController -- (void)setPaidContentWithPlayerData:(id)data { - if (IS_ENABLED(@"hidePaidPromotionCard_enabled")) {} - else { return %orig; } -} -- (void)playerOverlayProvider:(YTPlayerOverlayProvider *)provider didInsertPlayerOverlay:(YTPlayerOverlay *)overlay { - if ([[overlay overlayIdentifier] isEqualToString:@"player_overlay_paid_content"] && IS_ENABLED(@"hidePaidPromotionCard_enabled")) return; - %orig; -} -%end - -%hook YTInlineMutedPlaybackPlayerOverlayViewController -- (void)setPaidContentWithPlayerData:(id)data { - if (IS_ENABLED(@"hidePaidPromotionCard_enabled")) {} - else { return %orig; } -} -%end - -// YTReExplore: https://github.com/PoomSmart/YTReExplore/ -%group gReExplore -static void replaceTab(YTIGuideResponse *response) { - NSMutableArray *renderers = [response itemsArray]; - for (YTIGuideResponseSupportedRenderers *guideRenderers in renderers) { - YTIPivotBarRenderer *pivotBarRenderer = [guideRenderers pivotBarRenderer]; - NSMutableArray *items = [pivotBarRenderer itemsArray]; - NSUInteger shortIndex = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) { - return [[[renderers pivotBarItemRenderer] pivotIdentifier] isEqualToString:@"FEshorts"]; - }]; - if (shortIndex != NSNotFound) { - [items removeObjectAtIndex:shortIndex]; - NSUInteger exploreIndex = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) { - return [[[renderers pivotBarItemRenderer] pivotIdentifier] isEqualToString:[%c(YTIBrowseRequest) browseIDForExploreTab]]; - }]; - if (exploreIndex == NSNotFound) { - YTIPivotBarSupportedRenderers *exploreTab = [%c(YTIPivotBarRenderer) pivotSupportedRenderersWithBrowseId:[%c(YTIBrowseRequest) browseIDForExploreTab] title:@"Explore" iconType:292]; - [items insertObject:exploreTab atIndex:1]; - } - break; - } - } -} -%hook YTGuideServiceCoordinator -- (void)handleResponse:(YTIGuideResponse *)response withCompletion:(id)completion { - replaceTab(response); - %orig(response, completion); -} -- (void)handleResponse:(YTIGuideResponse *)response error:(id)error completion:(id)completion { - replaceTab(response); - %orig(response, error, completion); -} -%end -%end - -// BigYTMiniPlayer: https://github.com/Galactic-Dev/BigYTMiniPlayer -%group Main -%hook YTWatchMiniBarView -- (void)setWatchMiniPlayerLayout:(int)arg1 { - %orig(1); -} -- (int)watchMiniPlayerLayout { - return 1; -} -- (void)layoutSubviews { - %orig; - self.frame = CGRectMake(([UIScreen mainScreen].bounds.size.width - self.frame.size.width), self.frame.origin.y, self.frame.size.width, self.frame.size.height); -} -%end - -%hook YTMainAppVideoPlayerOverlayView -- (BOOL)isUserInteractionEnabled { - if([[self _viewControllerForAncestor].parentViewController.parentViewController isKindOfClass:%c(YTWatchMiniBarViewController)]) { - return NO; - } - return %orig; -} -%end -%end - - -# pragma mark - uYouPlus - -// Video Player Options -// Skips content warning before playing *some videos - @PoomSmart -%hook YTPlayabilityResolutionUserActionUIController -- (void)showConfirmAlert { [self confirmAlertDidPressConfirm]; } -%end - -// Disable snap to chapter -%hook YTSegmentableInlinePlayerBarView -- (void)didMoveToWindow { - %orig; - if (IS_ENABLED(@"snapToChapter_enabled")) { - self.enableSnapToChapter = NO; - } -} -%end - -// Disable Pinch to zoom -%hook YTColdConfig -- (BOOL)videoZoomFreeZoomEnabledGlobalConfig { - return IS_ENABLED(@"pinchToZoom_enabled") ? NO : %orig; -} -%end - -// YTStockVolumeHUD - https://github.com/lilacvibes/YTStockVolumeHUD -%group gStockVolumeHUD -%hook YTVolumeBarView -- (void)volumeChanged:(id)arg1 { - %orig(nil); -} -%end - -%hook UIApplication -- (void)setSystemVolumeHUDEnabled:(BOOL)arg1 forAudioCategory:(id)arg2 { - %orig(true, arg2); -} -%end -%end - -%hook YTDoubleTapToSeekController -- (void)enableDoubleTapToSeek:(BOOL)arg1 { - return IS_ENABLED(@"doubleTapToSeek_disabled") ? %orig(NO) : %orig; -} -%end - -// Video Controls Overlay Options -// Hide CC / Autoplay switch -%hook YTMainAppControlsOverlayView -- (void)setClosedCaptionsOrSubtitlesButtonAvailable:(BOOL)arg1 { // hide CC button - return IS_ENABLED(@"hideCC_enabled") ? %orig(NO) : %orig; -} -- (void)setAutoplaySwitchButtonRenderer:(id)arg1 { // hide Autoplay - if (IS_ENABLED(@"hideAutoplaySwitch_enabled")) {} - else { return %orig; } -} -%end - -// Hide HUD Messages -%hook YTHUDMessageView -- (id)initWithMessage:(id)arg1 dismissHandler:(id)arg2 { - return IS_ENABLED(@"hideHUD_enabled") ? nil : %orig; -} -%end - -// Hide Watermark -%hook YTAnnotationsViewController -- (void)loadFeaturedChannelWatermark { - if (IS_ENABLED(@"hideChannelWatermark_enabled")) {} - else { return %orig; } -} -%end - -// Hide Next & Previous button -%group gHidePreviousAndNextButton -%hook YTColdConfig -- (BOOL)removeNextPaddleForSingletonVideos { return YES; } -- (BOOL)removePreviousPaddleForSingletonVideos { return YES; } -%end -%end - -// Replace Next & Previous button with Fast forward & Rewind button -%group gReplacePreviousAndNextButton -%hook YTColdConfig -- (BOOL)replaceNextPaddleWithFastForwardButtonForSingletonVods { return YES; } -- (BOOL)replacePreviousPaddleWithRewindButtonForSingletonVods { return YES; } -%end -%end - -// Bring back the red progress bar - Broken?! -%hook YTInlinePlayerBarContainerView -- (id)quietProgressBarColor { - return IS_ENABLED(@"redProgressBar_enabled") ? [UIColor redColor] : %orig; -} -%end - -// Disable the right panel in fullscreen mode -%hook YTColdConfig -- (BOOL)isLandscapeEngagementPanelEnabled { - return IS_ENABLED(@"hideRightPanel_enabled") ? NO : %orig; -} -%end - -// Shorts Controls Overlay Options -%hook _ASDisplayView -- (void)didMoveToWindow { - %orig; - if ((IS_ENABLED(@"hideBuySuperThanks_enabled")) && ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.suggested_action"])) { - self.hidden = YES; - } -} -%end - -%hook YTReelWatchRootViewController -- (void)setPausedStateCarouselView { - if (IS_ENABLED(@"hideSubcriptions_enabled")) {} - else { return %orig; } -} -%end - -%hook YTShortsStartupCoordinator -- (id)evaluateResumeToShorts { - return IS_ENABLED(@"disableResumeToShorts") ? nil : %orig; -} -%end - -// Theme Options -// Fix navigation bar showing a lighter grey with default dark mode -%hook YTCommonColorPalette -- (UIColor *)brandBackgroundSolid { - return self.pageStyle == 1 ? [UIColor colorWithRed:0.05882352941176471 green:0.05882352941176471 blue:0.05882352941176471 alpha:1.0] : %orig; -} -%end - -// Old dark theme (gray) -%group gOldDarkTheme -%hook YTColdConfig -- (BOOL)uiSystemsClientGlobalConfigUseDarkerPaletteBgColorForNative { return NO; } -- (BOOL)uiSystemsClientGlobalConfigUseDarkerPaletteTextColorForNative { return NO; } -- (BOOL)enableCinematicContainerOnClient { return NO; } -%end - -%hook _ASDisplayView -- (void)didMoveToWindow { - %orig; - if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.comment_composer"]) { self.backgroundColor = [UIColor clearColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.video_list_entry"]) { self.backgroundColor = [UIColor clearColor]; } -} -%end - -%hook ASCollectionView -- (void)didMoveToWindow { - %orig; - self.superview.backgroundColor = [UIColor colorWithRed:0.129 green:0.129 blue:0.129 alpha:1.0]; -} -%end - -%hook YTFullscreenEngagementOverlayView -- (void)didMoveToWindow { - %orig; - self.subviews[0].backgroundColor = [UIColor clearColor]; -} -%end - -%hook YTRelatedVideosView -- (void)didMoveToWindow { - %orig; - self.subviews[0].backgroundColor = [UIColor clearColor]; -} -%end -%end - -// OLED dark mode by BandarHL -UIColor* raisedColor = [UIColor colorWithRed:0.035 green:0.035 blue:0.035 alpha:1.0]; -%group gOLED -%hook YTCommonColorPalette -- (UIColor *)baseBackground { - return self.pageStyle == 1 ? [UIColor blackColor] : %orig; -} -- (UIColor *)brandBackgroundSolid { - return self.pageStyle == 1 ? [UIColor blackColor] : %orig; -} -- (UIColor *)brandBackgroundPrimary { - return self.pageStyle == 1 ? [UIColor blackColor] : %orig; -} -- (UIColor *)brandBackgroundSecondary { - return self.pageStyle == 1 ? [[UIColor blackColor] colorWithAlphaComponent:0.9] : %orig; -} -- (UIColor *)raisedBackground { - return self.pageStyle == 1 ? [UIColor blackColor] : %orig; -} -- (UIColor *)staticBrandBlack { - return self.pageStyle == 1 ? [UIColor blackColor] : %orig; -} -- (UIColor *)generalBackgroundA { - return self.pageStyle == 1 ? [UIColor blackColor] : %orig; -} -%end - -// uYou settings -%hook UITableViewCell -- (void)_layoutSystemBackgroundView { - %orig; - UIView *systemBackgroundView = [self valueForKey:@"_systemBackgroundView"]; - NSString *backgroundViewKey = class_getInstanceVariable(systemBackgroundView.class, "_colorView") ? @"_colorView" : @"_backgroundView"; - ((UIView *)[systemBackgroundView valueForKey:backgroundViewKey]).backgroundColor = [UIColor blackColor]; -} -- (void)_layoutSystemBackgroundView:(BOOL)arg1 { - %orig; - ((UIView *)[[self valueForKey:@"_systemBackgroundView"] valueForKey:@"_colorView"]).backgroundColor = [UIColor blackColor]; -} -%end - -%hook settingsReorderTable -- (void)viewDidLayoutSubviews { - %orig; - self.tableView.backgroundColor = [UIColor blackColor]; -} -%end - -%hook FRPSelectListTable -- (void)viewDidLayoutSubviews { - %orig; - self.tableView.backgroundColor = [UIColor blackColor]; -} -%end - -%hook FRPreferences -- (void)viewDidLayoutSubviews { - %orig; - self.tableView.backgroundColor = [UIColor blackColor]; -} -%end - -%hook YTInnerTubeCollectionViewController -- (UIColor *)backgroundColor:(NSInteger)pageStyle { - return pageStyle == 1 ? [UIColor blackColor] : %orig; -} -%end - -// Explore -%hook ASScrollView -- (void)didMoveToWindow { - %orig; - if (IS_DARK_APPEARANCE_ENABLED) { - self.backgroundColor = [UIColor clearColor]; - } -} -%end - -// Your videos -%hook ASCollectionView -- (void)didMoveToWindow { - %orig; - if (IS_DARK_APPEARANCE_ENABLED && [self.nextResponder isKindOfClass:%c(_ASDisplayView)]) { - self.superview.backgroundColor = [UIColor blackColor]; - } -} -%end - -// Sub menu? -%hook ELMView -- (void)didMoveToWindow { - %orig; - if (IS_DARK_APPEARANCE_ENABLED) { - // self.subviews[0].backgroundColor = [UIColor clearColor]; - } -} -%end - -// iSponsorBlock -%hook SponsorBlockSettingsController -- (void)viewDidLoad { - if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { - %orig; - self.tableView.backgroundColor = [UIColor blackColor]; - } else { return %orig; } -} -%end - -%hook SponsorBlockViewController -- (void)viewDidLoad { - if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { - %orig; - self.view.backgroundColor = [UIColor blackColor]; - } else { return %orig; } -} -%end - -// Search View -%hook YTSearchBarView -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; -} -%end - -// History Search view -%hook YTSearchBoxView -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; - -} -%end - -// Comment view -%hook YTCommentView -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; -} -%end - -%hook YTCreateCommentAccessoryView -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; -} -%end - -%hook YTCreateCommentTextView -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; -} -- (void)setTextColor:(UIColor *)color { // fix black text in #Shorts video's comment - return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor whiteColor]) : %orig; -} -%end - -%hook YTCommentDetailHeaderCell -- (void)didMoveToWindow { - %orig; - if (IS_DARK_APPEARANCE_ENABLED) { - // self.subviews[2].backgroundColor = [UIColor blackColor]; - } -} -%end - -%hook YTFormattedStringLabel // YT is werid... -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor clearColor]) : %orig; -} -%end - -// Live chat comment -%hook YCHLiveChatActionPanelView -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; -} -%end - -%hook YTEmojiTextView -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; -} -%end - -%hook YCHLiveChatView -- (void)didMoveToWindow { - %orig; - if (IS_DARK_APPEARANCE_ENABLED) { - // self.subviews[1].backgroundColor = [UIColor blackColor]; - } -} -%end - -%hook YTCollectionView -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; -} -%end - -// -%hook YTBackstageCreateRepostDetailView -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig([UIColor blackColor]) : %orig; -} -%end - -// Others -%hook _ASDisplayView -- (void)didMoveToWindow { - %orig; - if (IS_DARK_APPEARANCE_ENABLED) { - if ([self.nextResponder isKindOfClass:%c(ASScrollView)]) { self.backgroundColor = [UIColor clearColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"eml.cvr"]) { self.backgroundColor = [UIColor blackColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"eml.live_chat_text_message"]) { self.backgroundColor = [UIColor blackColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"rich_header"]) { self.backgroundColor = [UIColor blackColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"id.ui.comment_cell"]) { self.backgroundColor = [UIColor blackColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"id.ui.cancel.button"]) { self.superview.backgroundColor = [UIColor clearColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.comment_composer"]) { self.backgroundColor = [UIColor blackColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"id.elements.components.video_list_entry"]) { self.backgroundColor = [UIColor blackColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"id.comment.guidelines_text"]) { self.superview.backgroundColor = [UIColor blackColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"id.comment.channel_guidelines_bottom_sheet_container"]) { self.backgroundColor = [UIColor blackColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"id.comment.channel_guidelines_entry_banner_container"]) { self.backgroundColor = [UIColor blackColor]; } - if ([self.accessibilityIdentifier isEqualToString:@"id.comment.comment_group_detail_container"]) { self.backgroundColor = [UIColor clearColor]; } - } -} -%end - -// Open link with... -%hook ASWAppSwitchingSheetHeaderView -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig(raisedColor) : %orig; -} -%end - -%hook ASWAppSwitchingSheetFooterView -- (void)setBackgroundColor:(UIColor *)color { - return IS_DARK_APPEARANCE_ENABLED ? %orig(raisedColor) : %orig; -} -%end - -%hook ASWAppSwitcherCollectionViewCell -- (void)didMoveToWindow { - %orig; - if (IS_DARK_APPEARANCE_ENABLED) { - self.backgroundColor = raisedColor; - // self.subviews[1].backgroundColor = raisedColor; - self.superview.backgroundColor = raisedColor; - } -} -%end - -// Incompatibility with the new YT Dark theme -%hook YTColdConfig -- (BOOL)uiSystemsClientGlobalConfigUseDarkerPaletteBgColorForNative { return NO; } -%end -%end - -// OLED keyboard by @ichitaso <3 - http://gist.github.com/ichitaso/935100fd53a26f18a9060f7195a1be0e -%group gOLEDKB -%hook UIPredictionViewController -- (void)loadView { - %orig; - [self.view setBackgroundColor:[UIColor blackColor]]; -} -%end - -%hook UICandidateViewController -- (void)loadView { - %orig; - [self.view setBackgroundColor:[UIColor blackColor]]; -} -%end - -%hook UIKeyboardDockView -- (void)didMoveToWindow { - %orig; - self.backgroundColor = [UIColor blackColor]; -} -%end - -%hook UIKeyboardLayoutStar -- (void)didMoveToWindow { - %orig; - self.backgroundColor = [UIColor blackColor]; -} -%end - -%hook UIKBRenderConfig // Prediction text color -- (void)setLightKeyboard:(BOOL)arg1 { %orig(NO); } -%end -%end - -// Miscellaneous -// Disable hints - https://github.com/LillieH001/YouTube-Reborn/blob/v4/ -%group gDisableHints -%hook YTSettings -- (BOOL)areHintsDisabled { - return YES; -} -- (void)setHintsDisabled:(BOOL)arg1 { - %orig(YES); -} -%end -%hook YTUserDefaults -- (BOOL)areHintsDisabled { - return YES; -} -- (void)setHintsDisabled:(BOOL)arg1 { - %orig(YES); -} -%end -%end - -// Hide the Chip Bar (Upper Bar) in Home feed -%group gHideChipBar -%hook YTMySubsFilterHeaderView -- (void)setChipFilterView:(id)arg1 {} -%end - -%hook YTHeaderContentComboView -- (void)enableSubheaderBarWithView:(id)arg1 {} -%end - -%hook YTHeaderContentComboView -- (void)setFeedHeaderScrollMode:(int)arg1 { %orig(0); } -%end -%end - -%group giPhoneLayout -%hook UIDevice -- (long long)userInterfaceIdiom { - return NO; -} -%end -%hook UIStatusBarStyleAttributes -- (long long)idiom { - return YES; -} -%end -%hook UIKBTree -- (long long)nativeIdiom { - return YES; -} -%end -%hook UIKBRenderer -- (long long)assetIdiom { - return YES; -} -%end -%end - -// YT startup animation -%hook YTColdConfig -- (BOOL)mainAppCoreClientIosEnableStartupAnimation { - return IS_ENABLED(@"ytStartupAnimation_enabled") ? YES : NO; -} -%end +# pragma mark - Constructor -# pragma mark - ctor %ctor { // Load uYou first so its functions are available for hooks. // dlopen([[NSString stringWithFormat:@"%@/Frameworks/uYou.dylib", [[NSBundle mainBundle] bundlePath]] UTF8String], RTLD_LAZY); %init; - if (IS_ENABLED(@"reExplore_enabled")) { - %init(gReExplore); - } - if (IS_ENABLED(@"bigYTMiniPlayer_enabled") && (UIDevice.currentDevice.userInterfaceIdiom != UIUserInterfaceIdiomPad)) { - %init(Main); - } if (IS_ENABLED(@"hidePreviousAndNextButton_enabled")) { %init(gHidePreviousAndNextButton); } if (IS_ENABLED(@"replacePreviousAndNextButton_enabled")) { %init(gReplacePreviousAndNextButton); } - if (IS_OLED_DARK_THEME_SELECTED) { - %init(gOLED); - } - if (IS_OLD_DARK_THEME_SELECTED) { - %init(gOldDarkTheme) - } - if (IS_ENABLED(@"oledKeyBoard_enabled")) { - %init(gOLEDKB); - } if (IS_ENABLED(@"disableHints_enabled")) { %init(gDisableHints); } @@ -775,9 +310,6 @@ UIColor* raisedColor = [UIColor colorWithRed:0.035 green:0.035 blue:0.035 alpha: if (IS_ENABLED(@"iPhoneLayout_enabled") && (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad)) { %init(giPhoneLayout); } - if (IS_ENABLED(@"stockVolumeHUD_enabled")) { - %init(gStockVolumeHUD); - } // Disable updates [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"automaticallyCheckForUpdates"];