diff --git a/Makefile b/Makefile index 35d8758..c461503 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ endif DEBUG=0 FINALPACKAGE=1 ARCHS = arm64 -PACKAGE_VERSION = 2.1 +PACKAGE_VERSION = 2.2 TARGET := iphone:clang:latest:11.0 include $(THEOS)/makefiles/common.mk diff --git a/Settings.x b/Settings.x index 3866676..1befaa6 100644 --- a/Settings.x +++ b/Settings.x @@ -178,10 +178,12 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD createSwitchItem(LOC(@"DisableAutoplay"), LOC(@"DisableAutoplayDesc"), @"disableAutoplay", &kDisableAutoplay, selfObject), createSwitchItem(LOC(@"NoContentWarning"), LOC(@"NoContentWarningDesc"), @"noContentWarning", &kNoContentWarning, selfObject), createSwitchItem(LOC(@"ClassicQuality"), LOC(@"ClassicQualityDesc"), @"classicQuality", &kClassicQuality, selfObject), + createSwitchItem(LOC(@"ExtraSpeedOptions"), LOC(@"ExtraSpeedOptionsDesc"), @"extraSpeedOptions", &kExtraSpeedOptions, selfObject), createSwitchItem(LOC(@"DontSnap2Chapter"), LOC(@"DontSnap2ChapterDesc"), @"dontSnapToChapter", &kDontSnapToChapter, selfObject), createSwitchItem(LOC(@"RedProgressBar"), LOC(@"RedProgressBarDesc"), @"redProgressBar", &kRedProgressBar, selfObject), createSwitchItem(LOC(@"NoHints"), LOC(@"NoHintsDesc"), @"noHints", &kNoHints, selfObject), createSwitchItem(LOC(@"NoFreeZoom"), LOC(@"NoFreeZoomDesc"), @"noFreeZoom", &kNoFreeZoom, selfObject), + createSwitchItem(LOC(@"AutoFullscreen"), LOC(@"AutoFullscreenDesc"), @"autoFullscreen", &kAutoFullscreen, selfObject), createSwitchItem(LOC(@"ExitFullscreen"), LOC(@"ExitFullscreenDesc"), @"exitFullscreen", &kExitFullscreen, selfObject), createSwitchItem(LOC(@"NoDoubleTap2Seek"), LOC(@"NoDoubleTap2SeekDesc"), @"noDoubleTapToSeek", &kNoDoubleTapToSeek, selfObject) ]; @@ -341,7 +343,7 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD [sectionItems addObject:space]; - YTSettingsSectionItem *ps = [%c(YTSettingsSectionItem) itemWithTitle:@"PoomSmart" titleDescription:@"YouTube-X, YTNoPremium, YTClassicVideoQuality, YTShortsProgress, YTReExplore, SkipContentWarning, YouTubeHeaders" accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { + YTSettingsSectionItem *ps = [%c(YTSettingsSectionItem) itemWithTitle:@"PoomSmart" titleDescription:@"YouTube-X, YTNoPremium, YTClassicVideoQuality, YTShortsProgress, YTReExplore, SkipContentWarning, YTAutoFullscreen, YouTubeHeaders" accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/PoomSmart/"]]; }]; @@ -349,6 +351,10 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/MiRO92/"]]; }]; + YTSettingsSectionItem *lillie = [%c(YTSettingsSectionItem) itemWithTitle:@"Lillie" titleDescription:@"ExtraSpeedOptions" accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { + return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/LillieH1000"]]; + }]; + YTSettingsSectionItem *dayanch96 = [%c(YTSettingsSectionItem) itemWithTitle:@"Dayanch96" titleDescription:LOC(@"Developer") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/Dayanch96/"]]; }]; @@ -372,7 +378,7 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD return @(OS_STRINGIFY(TWEAK_VERSION)); } selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { - NSArray *rows = @[ps, miro, dayanch96, space, createSwitchItem(LOC(@"Advanced"), nil, @"advancedMode", &kAdvancedMode, selfObject), reset]; + NSArray *rows = @[ps, miro, lillie, dayanch96, space, createSwitchItem(LOC(@"Advanced"), nil, @"advancedMode", &kAdvancedMode, selfObject), reset]; YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"About") pickerSectionTitle:LOC(@"Credits") rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; [settingsViewController pushViewController:picker]; diff --git a/YTLite.h b/YTLite.h index c8bce1b..1c309c7 100644 --- a/YTLite.h +++ b/YTLite.h @@ -10,6 +10,7 @@ #import "../YouTubeHeader/YTQTMButton.h" #import "../YouTubeHeader/YTVideoQualitySwitchOriginalController.h" #import "../YouTubeHeader/YTPlayerViewController.h" +#import "../YouTubeHeader/YTWatchController.h" #import "../YouTubeHeader/YTPlayerOverlay.h" #import "../YouTubeHeader/YTPlayerOverlayProvider.h" #import "../YouTubeHeader/YTSettingsViewController.h" @@ -50,10 +51,12 @@ BOOL kMiniplayer; BOOL kDisableAutoplay; BOOL kNoContentWarning; BOOL kClassicQuality; +BOOL kExtraSpeedOptions; BOOL kDontSnapToChapter; BOOL kRedProgressBar; BOOL kNoHints; BOOL kNoFreeZoom; +BOOL kAutoFullscreen; BOOL kExitFullscreen; BOOL kNoDoubleTapToSeek; BOOL kHideShorts; @@ -113,6 +116,10 @@ int kPivotIndex; @interface YTChipCloudCell : UICollectionViewCell @end +@interface YTPlayerViewController (YTAFS) +- (void)autoFullscreen; +@end + @interface YTSegmentableInlinePlayerBarView @property (nonatomic, assign, readwrite) BOOL enableSnapToChapter; @end @@ -144,6 +151,23 @@ int kPivotIndex; @interface YTReelWatchHeaderView : UIView @end +@interface MLHAMQueuePlayer : NSObject +@property id playerEventCenter; +-(void)setRate:(float)rate; +@end + +@interface YTVarispeedSwitchControllerOption : NSObject +- (id)initWithTitle:(id)title rate:(float)rate; +@end + +@interface HAMPlayerInternal : NSObject +- (void)setRate:(float)rate; +@end + +@interface MLPlayerEventCenter : NSObject +- (void)broadcastRateChange:(float)rate; +@end + @interface YTAlertView : UIView @property (nonatomic, copy, readwrite) NSString *title; @property (nonatomic, copy, readwrite) NSString *subtitle; diff --git a/YTLite.x b/YTLite.x index e9b1394..3d18502 100644 --- a/YTLite.x +++ b/YTLite.x @@ -30,7 +30,7 @@ %hook YTIElementRenderer - (NSData *)elementData { - if (self.hasCompatibilityOptions && self.compatibilityOptions.hasAdLoggingData) + if (self.hasCompatibilityOptions && self.compatibilityOptions.hasAdLoggingData && kNoAds) return nil; NSString *description = [self description]; if (([description containsString:@"brand_promo"] @@ -229,9 +229,59 @@ %hook YTVideoQualitySwitchControllerFactory - (id)videoQualitySwitchControllerWithParentResponder:(id)responder { Class originalClass = %c(YTVideoQualitySwitchOriginalController); - if (kClassicQuality) { - return originalClass ? [[originalClass alloc] initWithParentResponder:responder] : %orig; - } return %orig; + if (kClassicQuality) return originalClass ? [[originalClass alloc] initWithParentResponder:responder] : %orig; + return %orig; +} +%end + +// Extra Speed Options (https://github.com/LillieH1000/YouTube-Reborn/blob/v4/Tweak.xm#L853) - Same code but for .x +%hook YTVarispeedSwitchController +- (void *)init { + void *ret = (void *)%orig; + if (kExtraSpeedOptions) { + NSArray *speedOptions = @[@"0.1x", @"0.25x", @"0.5x", @"0.75x", @"1x", @"1.25x", @"1.5x", @"1.75x", @"2x", @"2.5x", @"3x", @"3.5x", @"4x", @"5x"]; + NSMutableArray *speedOptionsCopy = [NSMutableArray new]; + + for (NSString *title in speedOptions) { + float rate = [title floatValue]; + [speedOptionsCopy addObject:[[objc_lookUpClass("YTVarispeedSwitchControllerOption") alloc] initWithTitle:title rate:rate]]; + } + + Ivar optionsIvar = class_getInstanceVariable(object_getClass(self), "_options"); + object_setIvar(self, optionsIvar, [speedOptionsCopy copy]); + + } return ret; +} +%end + +%hook MLHAMQueuePlayer +- (void)setRate:(float)rate { + if (kExtraSpeedOptions) { + Ivar rateIvar = class_getInstanceVariable([self class], "_rate"); + if (rateIvar) { + float* ratePtr = (float *)((__bridge void *)self + ivar_getOffset(rateIvar)); + *ratePtr = rate; + } + + id ytPlayer = object_getIvar(self, class_getInstanceVariable([self class], "_player")); + if ([ytPlayer respondsToSelector:@selector(setRate:)]) { + [ytPlayer setRate:rate]; + } + + [self.playerEventCenter broadcastRateChange:rate]; + } else { + %orig(rate); + } +} +%end + +// Temprorary Fix For 'Classic Video Quality' and 'Extra Speed Options' +%hook YTVersionUtils ++ (NSString *)appVersion { + NSString *originalVersion = %orig; + NSString *fakeVersion = @"18.18.2"; + + return (!kClassicQuality && !kExtraSpeedOptions && [originalVersion compare:fakeVersion options:NSNumericSearch] == NSOrderedDescending) ? originalVersion : fakeVersion; } %end @@ -246,7 +296,7 @@ %end %hook YTSegmentableInlinePlayerBarView -- (void)setBufferedProgressBarColor:(id)arg1 { if (kNoRelatedVids) %orig([UIColor colorWithRed:0.65 green:0.65 blue:0.65 alpha:0.60]); } +- (void)setBufferedProgressBarColor:(id)arg1 { if (kRedProgressBar) %orig([UIColor colorWithRed:0.65 green:0.65 blue:0.65 alpha:0.60]); } %end // Disable Hints @@ -260,6 +310,20 @@ - (void)setHintsDisabled:(BOOL)arg1 { kNoHints ? %orig(YES) : %orig; } %end +// Enter Fullscreen on Start (https://github.com/PoomSmart/YTAutoFullScreen) +%hook YTPlayerViewController +- (void)loadWithPlayerTransition:(id)arg1 playbackConfig:(id)arg2 { + %orig; + if (kAutoFullscreen) [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(autoFullscreen) userInfo:nil repeats:NO]; +} + +%new +- (void)autoFullscreen { + YTWatchController *watchController = [self valueForKey:@"_UIDelegate"]; + [watchController showFullScreen]; +} +%end + // Exit Fullscreen on Finish %hook YTWatchFlowController - (BOOL)shouldExitFullScreenOnFinish { return kExitFullscreen ? YES : NO; } @@ -306,7 +370,7 @@ if ([cell respondsToSelector:@selector(node)]) { NSString *idToRemove = [[cell node] accessibilityIdentifier]; if ([idToRemove isEqualToString:@"statement_banner.view"] || - (([idToRemove isEqualToString:@"eml.shorts-grid"] || [idToRemove isEqualToString:@"eml.shorts-shelf"]) && kHideShorts)) { + (([idToRemove isEqualToString:@"eml.shorts-grid"] || [idToRemove isEqualToString:@"eml.shorts-shelf"] || [idToRemove isEqualToString:@"eml.inline_shorts"]) && kHideShorts)) { [self removeCellsAtIndexPath:indexPath]; } } @@ -590,10 +654,12 @@ static void reloadPrefs() { kDisableAutoplay = [prefs[@"disableAutoplay"] boolValue] ?: NO; kNoContentWarning = [prefs[@"noContentWarning"] boolValue] ?: NO; kClassicQuality = [prefs[@"classicQuality"] boolValue] ?: NO; + kExtraSpeedOptions = [prefs[@"extraSpeedOptions"] boolValue] ?: NO; kDontSnapToChapter = [prefs[@"dontSnapToChapter"] boolValue] ?: NO; kRedProgressBar = [prefs[@"redProgressBar"] boolValue] ?: NO; kNoHints = [prefs[@"noHints"] boolValue] ?: NO; kNoFreeZoom = [prefs[@"noFreeZoom"] boolValue] ?: NO; + kAutoFullscreen = [prefs[@"autoFullscreen"] boolValue] ?: NO; kExitFullscreen = [prefs[@"exitFullscreen"] boolValue] ?: NO; kNoDoubleTapToSeek = [prefs[@"noDoubleTapToSeek"] boolValue] ?: NO; kHideShorts = [prefs[@"hideShorts"] boolValue] ?: NO; @@ -650,10 +716,12 @@ static void reloadPrefs() { @"disableAutoplay" : @(kDisableAutoplay), @"noContentWarning" : @(kNoContentWarning), @"classicQuality" : @(kClassicQuality), + @"extraSpeedOptions" : @(kExtraSpeedOptions), @"dontSnapToChapter" : @(kDontSnapToChapter), @"redProgressBar" : @(kRedProgressBar), @"noHints" : @(kNoHints), @"noFreeZoom" : @(kNoFreeZoom), + @"autoFullscreen" : @(kAutoFullscreen), @"exitFullscreen" : @(kExitFullscreen), @"noDoubleTapToSeek" : @(kNoDoubleTapToSeek), @"hideShorts" : @(kHideShorts), diff --git a/layout/Library/Application Support/YTLite.bundle/en.lproj/Localizable.strings b/layout/Library/Application Support/YTLite.bundle/en.lproj/Localizable.strings index bb77d1a..7cdde4d 100644 --- a/layout/Library/Application Support/YTLite.bundle/en.lproj/Localizable.strings +++ b/layout/Library/Application Support/YTLite.bundle/en.lproj/Localizable.strings @@ -53,6 +53,8 @@ "NoContentWarningDesc" = "Skips sensitive content warning message."; "ClassicQuality" = "Classic video quality"; "ClassicQualityDesc" = "Brings back classic video quality selection menu."; +"ExtraSpeedOptions" = "Extra speed options"; +"ExtraSpeedOptionsDesc" = "Adds more video playback speed options to the player menu."; "DontSnap2Chapter" = "Disable snap to chapter"; "DontSnap2ChapterDesc" = "Disables skipping to the next episode by double-tap gesture."; "RedProgressBar" = "Red progress bar"; @@ -61,6 +63,8 @@ "NoHintsDesc" = "Disables hints by author which appears at the top-right corner during playback."; "NoFreeZoom" = "Disable free zoom gesture"; "NoFreeZoomDesc" = "Disables new free zoom gestures."; +"AutoFullscreen" = "Play videos in fullscreen"; +"AutoFullscreenDesc" = "Automatically plays videos in fullscreen mode."; "ExitFullscreen" = "Exit fullscreen mode on finish"; "ExitFullscreenDesc" = "Exits fullscreen mode at the end of video playback."; "NoDoubleTap2Seek" = "Disable double tap to seek"; diff --git a/layout/Library/Application Support/YTLite.bundle/ru.lproj/Localizable.strings b/layout/Library/Application Support/YTLite.bundle/ru.lproj/Localizable.strings index 7a8c1e0..c28e23e 100644 --- a/layout/Library/Application Support/YTLite.bundle/ru.lproj/Localizable.strings +++ b/layout/Library/Application Support/YTLite.bundle/ru.lproj/Localizable.strings @@ -53,6 +53,8 @@ "NoContentWarningDesc" = "Пропускает предупреждения, всплывающие перед воспроизведением некоторого контента."; "ClassicQuality" = "Классический выбор качества"; "ClassicQualityDesc" = "Возвращает классическое меню выбора качества в меню плеера."; +"ExtraSpeedOptions" = "Больше скоростей воспроизведения"; +"ExtraSpeedOptionsDesc" = "Добавляет больше опций скорости воспроизведения в выпадающее меню плеера."; "DontSnap2Chapter" = "Не перематывать эпизоды"; "DontSnap2ChapterDesc" = "Отключает жест перемотки к следующему эпизоду двойным нажатием."; "RedProgressBar" = "Красный прогресс-бар"; @@ -61,6 +63,8 @@ "NoHintsDesc" = "Скрывает подсказки от авторов видео, появляющиеся в правом верхнем углу."; "NoFreeZoom" = "Отключить жесты для зума"; "NoFreeZoomDesc" = "Отключает жесты приближения для нового зума."; +"AutoFullscreen" = "Воспроизводить в полноэкранном режиме"; +"AutoFullscreenDesc" = "Автоматически воспроизводит ролики в полноэкранном режиме."; "ExitFullscreen" = "Автовыход из полноэкранного режима"; "ExitFullscreenDesc" = "Выходит из полноэкранного режима по окончанию воспроизведения."; "NoDoubleTap2Seek" = "Отключить перемотку двойным тапом"; diff --git a/layout/Library/Application Support/YTLite.bundle/zh-Hans.lproj/Localizable.strings b/layout/Library/Application Support/YTLite.bundle/zh-Hans.lproj/Localizable.strings index 5afff66..f504d9c 100644 --- a/layout/Library/Application Support/YTLite.bundle/zh-Hans.lproj/Localizable.strings +++ b/layout/Library/Application Support/YTLite.bundle/zh-Hans.lproj/Localizable.strings @@ -53,6 +53,8 @@ "NoContentWarningDesc" = "跳过敏感内容警告消息。"; "ClassicQuality" = "经典视频质量"; "ClassicQualityDesc" = "加回经典的视频质量选择菜单。"; +"ExtraSpeedOptions" = "Extra speed options"; +"ExtraSpeedOptionsDesc" = "Adds more video playback speed options to the player menu."; "DontSnap2Chapter" = "禁用双击跳转"; "DontSnap2ChapterDesc" = "禁用通过双击手势跳到下一集。"; "RedProgressBar" = "红色进度条"; @@ -61,6 +63,8 @@ "NoHintsDesc" = "禁用播放期间出现在右上角的作者提示。"; "NoFreeZoom" = "禁用自由缩放手势"; "NoFreeZoomDesc" = "禁用新的自由缩放手势。"; +"AutoFullscreen" = "Play videos in fullscreen"; +"AutoFullscreenDesc" = "Automatically plays videos in fullscreen mode."; "ExitFullscreen" = "完成后退出全屏模式"; "ExitFullscreenDesc" = "在视频播放结束时退出全屏模式。"; "NoDoubleTap2Seek" = "禁用双击搜索"; @@ -141,4 +145,4 @@ "ResetSettings" = "重置YTLite设置"; "ResetMessage" = "此选项会将YTLite设置重置为默认值并关闭YouTube。\n\n确定要继续吗?"; "Yes" = "是"; -"No" = "不"; +"No" = "不"; \ No newline at end of file diff --git a/packages/com.dvntm.ytlite_2.2_iphoneos-arm.deb b/packages/com.dvntm.ytlite_2.2_iphoneos-arm.deb new file mode 100644 index 0000000..fb4af37 Binary files /dev/null and b/packages/com.dvntm.ytlite_2.2_iphoneos-arm.deb differ diff --git a/packages/com.dvntm.ytlite_2.2_iphoneos-arm64.deb b/packages/com.dvntm.ytlite_2.2_iphoneos-arm64.deb new file mode 100644 index 0000000..5440d0a Binary files /dev/null and b/packages/com.dvntm.ytlite_2.2_iphoneos-arm64.deb differ