mirror of
				https://github.com/SoPat712/YTLitePlus.git
				synced 2025-10-31 04:44:14 -04:00 
			
		
		
		
	added files via upload
This commit is contained in:
		
							
								
								
									
										320
									
								
								Tweaks/YouMute/Tweak.x
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										320
									
								
								Tweaks/YouMute/Tweak.x
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,320 @@ | ||||
| #import <rootless.h> | ||||
| #import "../YouTubeHeader/YTColor.h" | ||||
| #import "../YouTubeHeader/YTCommonUtils.h" | ||||
| #import "../YouTubeHeader/YTInlinePlayerBarContainerView.h" | ||||
| #import "../YouTubeHeader/YTMainAppControlsOverlayView.h" | ||||
| #import "../YouTubeHeader/YTMainAppVideoPlayerOverlayViewController.h" | ||||
| #import "../YouTubeHeader/YTSingleVideoController.h" | ||||
| #import "../YouTubeHeader/YTSettingsPickerViewController.h" | ||||
| #import "../YouTubeHeader/YTSettingsViewController.h" | ||||
| #import "../YouTubeHeader/YTSettingsSectionItem.h" | ||||
| #import "../YouTubeHeader/YTSettingsSectionItemManager.h" | ||||
| #import "../YouTubeHeader/YTQTMButton.h" | ||||
| #import "../YouTubeHeader/QTMIcon.h" | ||||
| #import "../YouTubeHeader/UIView+YouTube.h" | ||||
|  | ||||
| #define EnabledKey @"YouMuteEnabled" | ||||
| #define PositionKey @"YouMutePosition" | ||||
|  | ||||
| #define LOC(x) [tweakBundle localizedStringForKey:x value:nil table:nil] | ||||
|  | ||||
| static const NSInteger YouMuteSection = 521; | ||||
|  | ||||
| @interface YTSettingsSectionItemManager (YouMute) | ||||
| - (void)updateYouMuteSectionWithEntry:(id)entry; | ||||
| @end | ||||
|  | ||||
| @interface YTMainAppControlsOverlayView (YouMute) | ||||
| @property (retain, nonatomic) YTQTMButton *muteButton; | ||||
| - (void)didPressMute:(id)arg; | ||||
| @end | ||||
|  | ||||
| @interface YTInlinePlayerBarContainerView (YouMute) | ||||
| @property (retain, nonatomic) YTQTMButton *muteButton; | ||||
| - (void)didPressMute:(id)arg; | ||||
| @end | ||||
|  | ||||
| static BOOL TweakEnabled() { | ||||
|     return [[NSUserDefaults standardUserDefaults] boolForKey:EnabledKey]; | ||||
| } | ||||
|  | ||||
| static int MuteButtonPosition() { | ||||
|     return [[NSUserDefaults standardUserDefaults] integerForKey:PositionKey]; | ||||
| } | ||||
|  | ||||
| static BOOL UseTopMuteButton() { | ||||
|     return TweakEnabled() && MuteButtonPosition() == 0; | ||||
| } | ||||
|  | ||||
| static BOOL UseBottomMuteButton() { | ||||
|     return TweakEnabled() && MuteButtonPosition() == 1; | ||||
| } | ||||
|  | ||||
| static BOOL isMutedTop(YTMainAppControlsOverlayView *self) { | ||||
|     YTMainAppVideoPlayerOverlayViewController *c = [self valueForKey:@"_eventsDelegate"]; | ||||
|     YTSingleVideoController *video = [c valueForKey:@"_currentSingleVideoObservable"]; | ||||
|     return [video isMuted]; | ||||
| } | ||||
|  | ||||
| static BOOL isMutedBottom(YTInlinePlayerBarContainerView *self) { | ||||
|     YTSingleVideoController *video = [self.delegate valueForKey:@"_currentSingleVideo"]; | ||||
|     return [video isMuted]; | ||||
| } | ||||
|  | ||||
| static NSBundle *YTEditResourcesBundle() { | ||||
|     Class YTCommonUtilsClass = %c(YTCommonUtils); | ||||
|     return [YTCommonUtilsClass resourceBundleForModuleName:@"Edit" appBundle:[YTCommonUtilsClass bundleForClass:%c(YTEditBundleIdentifier)]]; | ||||
| } | ||||
|  | ||||
| static UIImage *muteImage(BOOL muted) { | ||||
|     return [%c(QTMIcon) tintImage:[UIImage imageNamed:muted ? @"ic_volume_off" : @"ic_volume_up" inBundle:YTEditResourcesBundle() compatibleWithTraitCollection:nil] color:[%c(YTColor) white1]]; | ||||
| } | ||||
|  | ||||
| static void createMuteButtonTop(YTMainAppControlsOverlayView *self) { | ||||
|     if (!self) return; | ||||
|     CGFloat padding = [[self class] topButtonAdditionalPadding]; | ||||
|     UIImage *image = muteImage(isMutedTop(self)); | ||||
|     self.muteButton = [self buttonWithImage:image accessibilityLabel:@"Mute" verticalContentPadding:padding]; | ||||
|     self.muteButton.hidden = YES; | ||||
|     self.muteButton.alpha = 0; | ||||
|     [self.muteButton addTarget:self action:@selector(didPressMute:) forControlEvents:UIControlEventTouchUpInside]; | ||||
|     @try { | ||||
|         [[self valueForKey:@"_topControlsAccessibilityContainerView"] addSubview:self.muteButton]; | ||||
|     } @catch (id ex) { | ||||
|         [self addSubview:self.muteButton]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void createMuteButtonBottom(YTInlinePlayerBarContainerView *self) { | ||||
|     if (!self) return; | ||||
|     UIImage *image = muteImage(isMutedBottom(self)); | ||||
|     self.muteButton = [%c(YTQTMButton) iconButton]; | ||||
|     self.muteButton.hidden = YES; | ||||
|     self.muteButton.exclusiveTouch = YES; | ||||
|     self.muteButton.alpha = 0; | ||||
|     self.muteButton.minHitTargetSize = 60; | ||||
|     self.muteButton.accessibilityLabel = @"Mute"; | ||||
|     [self.muteButton setImage:image forState:0]; | ||||
|     [self.muteButton sizeToFit]; | ||||
|     [self.muteButton addTarget:self action:@selector(didPressMute:) forControlEvents:UIControlEventTouchUpInside]; | ||||
|     [self addSubview:self.muteButton]; | ||||
| } | ||||
|  | ||||
| static NSMutableArray *topControls(YTMainAppControlsOverlayView *self, NSMutableArray *controls) { | ||||
|     if (UseTopMuteButton()) | ||||
|         [controls insertObject:self.muteButton atIndex:0]; | ||||
|     return controls; | ||||
| } | ||||
|  | ||||
| NSBundle *YouMuteBundle() { | ||||
|     static NSBundle *bundle = nil; | ||||
|     static dispatch_once_t onceToken; | ||||
| 	dispatch_once(&onceToken, ^{ | ||||
|         NSString *tweakBundlePath = [[NSBundle mainBundle] pathForResource:@"YouMute" ofType:@"bundle"]; | ||||
|         if (tweakBundlePath) | ||||
|             bundle = [NSBundle bundleWithPath:tweakBundlePath]; | ||||
|         else | ||||
|             bundle = [NSBundle bundleWithPath:ROOT_PATH_NS(@"/Library/Application Support/YouMute.bundle")]; | ||||
|     }); | ||||
|     return bundle; | ||||
| } | ||||
|  | ||||
| %group Top | ||||
|  | ||||
| %hook YTMainAppVideoPlayerOverlayViewController | ||||
|  | ||||
| - (void)updateTopRightButtonAvailability { | ||||
|     %orig; | ||||
|     YTMainAppVideoPlayerOverlayView *v = [self videoPlayerOverlayView]; | ||||
|     YTMainAppControlsOverlayView *c = [v valueForKey:@"_controlsOverlayView"]; | ||||
|     c.muteButton.hidden = !UseTopMuteButton(); | ||||
|     [c setNeedsLayout]; | ||||
| } | ||||
|  | ||||
| %end | ||||
|  | ||||
| %hook YTMainAppControlsOverlayView | ||||
|  | ||||
| %property (retain, nonatomic) YTQTMButton *muteButton; | ||||
|  | ||||
| - (id)initWithDelegate:(id)delegate { | ||||
|     self = %orig; | ||||
|     createMuteButtonTop(self); | ||||
|     return self; | ||||
| } | ||||
|  | ||||
| - (id)initWithDelegate:(id)delegate autoplaySwitchEnabled:(BOOL)autoplaySwitchEnabled { | ||||
|     self = %orig; | ||||
|     createMuteButtonTop(self); | ||||
|     return self; | ||||
| } | ||||
|  | ||||
| - (NSMutableArray *)topButtonControls { | ||||
|     return topControls(self, %orig); | ||||
| } | ||||
|  | ||||
| - (NSMutableArray *)topControls { | ||||
|     return topControls(self, %orig); | ||||
| } | ||||
|  | ||||
| - (void)setTopOverlayVisible:(BOOL)visible isAutonavCanceledState:(BOOL)canceledState { | ||||
|     if (UseTopMuteButton()) | ||||
|         self.muteButton.alpha = canceledState || !visible ? 0.0 : 1.0; | ||||
|     %orig; | ||||
| } | ||||
|  | ||||
| %new(v@:@) | ||||
| - (void)didPressMute:(id)arg { | ||||
|     YTMainAppVideoPlayerOverlayViewController *c = [self valueForKey:@"_eventsDelegate"]; | ||||
|     YTSingleVideoController *video = [c valueForKey:@"_currentSingleVideoObservable"]; | ||||
|     [video setMuted:![video isMuted]]; | ||||
|     [self.muteButton setImage:muteImage([video isMuted]) forState:0]; | ||||
| } | ||||
|  | ||||
| %end | ||||
|  | ||||
| %end | ||||
|  | ||||
| %group Bottom | ||||
|  | ||||
| %hook YTInlinePlayerBarContainerView | ||||
|  | ||||
| %property (retain, nonatomic) YTQTMButton *muteButton; | ||||
|  | ||||
| - (id)init { | ||||
|     self = %orig; | ||||
|     createMuteButtonBottom(self); | ||||
|     return self; | ||||
| } | ||||
|  | ||||
| - (NSMutableArray *)rightIcons { | ||||
|     NSMutableArray *icons = %orig; | ||||
|     if (UseBottomMuteButton() && ![icons containsObject:self.muteButton]) | ||||
|         [icons insertObject:self.muteButton atIndex:0]; | ||||
|     return icons; | ||||
| } | ||||
|  | ||||
| - (void)updateIconVisibility { | ||||
|     %orig; | ||||
|     if (UseBottomMuteButton()) | ||||
|         self.muteButton.hidden = NO; | ||||
| } | ||||
|  | ||||
| - (void)hideScrubber { | ||||
|     %orig; | ||||
|     if (UseBottomMuteButton()) | ||||
|         self.muteButton.alpha = 0; | ||||
| } | ||||
|  | ||||
| - (void)setPeekableViewVisible:(BOOL)visible fullscreenButtonVisibleShouldMatchPeekableView:(BOOL)match { | ||||
|     %orig; | ||||
|     if (UseBottomMuteButton()) | ||||
|         self.muteButton.alpha = visible ? 1 : 0; | ||||
| } | ||||
|  | ||||
| - (void)layoutSubviews { | ||||
|     %orig; | ||||
|     if (!UseBottomMuteButton()) return; | ||||
|     CGFloat multiFeedWidth = [self respondsToSelector:@selector(multiFeedElementView)] ? [self multiFeedElementView].frame.size.width : 0; | ||||
|     YTQTMButton *enter = [self enterFullscreenButton]; | ||||
|     if ([enter yt_isVisible]) { | ||||
|         CGRect frame = enter.frame; | ||||
|         frame.origin.x -= multiFeedWidth + enter.frame.size.width + 16; | ||||
|         self.muteButton.frame = frame; | ||||
|     } else { | ||||
|         YTQTMButton *exit = [self exitFullscreenButton]; | ||||
|         if ([exit yt_isVisible]) { | ||||
|             CGRect frame = exit.frame; | ||||
|             frame.origin.x -= multiFeedWidth + exit.frame.size.width + 16; | ||||
|             self.muteButton.frame = frame; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| %new(v@:@) | ||||
| - (void)didPressMute:(id)arg { | ||||
|     YTSingleVideoController *video = [self.delegate valueForKey:@"_currentSingleVideo"]; | ||||
|     [video setMuted:![video isMuted]]; | ||||
|     [self.muteButton setImage:muteImage([video isMuted]) forState:0]; | ||||
| } | ||||
|  | ||||
| %end | ||||
|  | ||||
| %end | ||||
|  | ||||
| %group Settings | ||||
|  | ||||
| %hook YTAppSettingsPresentationData | ||||
|  | ||||
| + (NSArray *)settingsCategoryOrder { | ||||
|     NSArray *order = %orig; | ||||
|     NSMutableArray *mutableOrder = [order mutableCopy]; | ||||
|     NSUInteger insertIndex = [order indexOfObject:@(1)]; | ||||
|     if (insertIndex != NSNotFound) | ||||
|         [mutableOrder insertObject:@(YouMuteSection) atIndex:insertIndex + 1]; | ||||
|     return mutableOrder; | ||||
| } | ||||
|  | ||||
| %end | ||||
|  | ||||
| %hook YTSettingsSectionItemManager | ||||
|  | ||||
| %new(v@:@) | ||||
| - (void)updateYouMuteSectionWithEntry:(id)entry { | ||||
|     NSMutableArray *sectionItems = [NSMutableArray array]; | ||||
|     NSBundle *tweakBundle = YouMuteBundle(); | ||||
|     Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem); | ||||
|     YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"]; | ||||
|     YTSettingsSectionItem *master = [YTSettingsSectionItemClass switchItemWithTitle:LOC(@"ENABLED") | ||||
|         titleDescription:nil | ||||
|         accessibilityIdentifier:nil | ||||
|         switchOn:TweakEnabled() | ||||
|         switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { | ||||
|             [[NSUserDefaults standardUserDefaults] setBool:enabled forKey:EnabledKey]; | ||||
|             return YES; | ||||
|         } | ||||
|         settingItemId:0]; | ||||
|     [sectionItems addObject:master]; | ||||
|     YTSettingsSectionItem *position = [YTSettingsSectionItemClass itemWithTitle:LOC(@"POSITION") | ||||
|         accessibilityIdentifier:nil | ||||
|         detailTextBlock:^NSString *() { | ||||
|             return MuteButtonPosition() ? LOC(@"BOTTOM") : LOC(@"TOP"); | ||||
|         } | ||||
|         selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { | ||||
|             NSArray <YTSettingsSectionItem *> *rows = @[ | ||||
|                 [YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"TOP") titleDescription:LOC(@"TOP_DESC") selectBlock:^BOOL (YTSettingsCell *top, NSUInteger arg1) { | ||||
|                     [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:PositionKey]; | ||||
|                     [settingsViewController reloadData]; | ||||
|                     return YES; | ||||
|                 }], | ||||
|                 [YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"BOTTOM") titleDescription:LOC(@"BOTTOM_DESC") selectBlock:^BOOL (YTSettingsCell *bottom, NSUInteger arg1) { | ||||
|                     [[NSUserDefaults standardUserDefaults] setInteger:1 forKey:PositionKey]; | ||||
|                     [settingsViewController reloadData]; | ||||
|                     return YES; | ||||
|                 }] | ||||
|             ]; | ||||
|             YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"POSITION") pickerSectionTitle:nil rows:rows selectedItemIndex:MuteButtonPosition() parentResponder:[self parentResponder]]; | ||||
|             [settingsViewController pushViewController:picker]; | ||||
|             return YES; | ||||
|         }]; | ||||
|     [sectionItems addObject:position]; | ||||
|     [settingsViewController setSectionItems:sectionItems forCategory:YouMuteSection title:@"YouMute" titleDescription:nil headerHidden:NO]; | ||||
| } | ||||
|  | ||||
| - (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry { | ||||
|     if (category == YouMuteSection) { | ||||
|         [self updateYouMuteSectionWithEntry:entry]; | ||||
|         return; | ||||
|     } | ||||
|     %orig; | ||||
| } | ||||
|  | ||||
| %end | ||||
|  | ||||
| %end | ||||
|  | ||||
| %ctor { | ||||
|     %init(Settings); | ||||
|     %init(Top); | ||||
|     %init(Bottom); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Balackburn
					Balackburn