diff --git a/Makefile b/Makefile index e6dc0f5..b9c877c 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ endif DEBUG=0 FINALPACKAGE=1 ARCHS = arm64 -PACKAGE_VERSION = 2.3.1 +PACKAGE_VERSION = 2.4 TARGET := iphone:clang:latest:11.0 include $(THEOS)/makefiles/common.mk diff --git a/Settings.x b/Settings.x index f81e082..ded8e35 100644 --- a/Settings.x +++ b/Settings.x @@ -6,15 +6,6 @@ static const NSInteger YTLiteSection = 789; -static void resetYTLiteSettings() { - NSString *prefsPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YTLite.plist"]; - [[NSFileManager defaultManager] removeItemAtPath:prefsPath error:nil]; - - [[UIApplication sharedApplication] performSelector:@selector(suspend)]; - [NSThread sleepForTimeInterval:1.0]; - exit(0); -} - NSBundle *YTLiteBundle() { static NSBundle *bundle = nil; static dispatch_once_t onceToken; @@ -179,6 +170,7 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD NSArray *rows = @[ createSwitchItem(LOC(@"Miniplayer"), LOC(@"MiniplayerDesc"), @"miniplayer", &kMiniplayer, selfObject), createSwitchItem(LOC(@"PortraitFullscreen"), LOC(@"PortraitFullscreenDesc"), @"portraitFullscreen", &kPortraitFullscreen, selfObject), + createSwitchItem(LOC(@"CopyWithTimestamp"), LOC(@"CopyWithTimestampDesc"), @"copyWithTimestamp", &kCopyWithTimestamp, selfObject), createSwitchItem(LOC(@"DisableAutoplay"), LOC(@"DisableAutoplayDesc"), @"disableAutoplay", &kDisableAutoplay, selfObject), createSwitchItem(LOC(@"NoContentWarning"), LOC(@"NoContentWarningDesc"), @"noContentWarning", &kNoContentWarning, selfObject), createSwitchItem(LOC(@"ClassicQuality"), LOC(@"ClassicQualityDesc"), @"classicQuality", &kClassicQuality, selfObject), @@ -240,6 +232,7 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { NSArray *rows = @[ createSwitchItem(LOC(@"RemoveLabels"), LOC(@"RemoveLabelsDesc"), @"removeLabels", &kRemoveLabels, selfObject), + createSwitchItem(LOC(@"RemoveIndicators"), LOC(@"RemoveIndicatorsDesc"), @"removeIndicators", &kRemoveIndicators, selfObject), createSwitchItem(LOC(@"ReExplore"), LOC(@"ReExploreDesc"), @"reExplore", &kReExplore, selfObject), createSwitchItem(LOC(@"HideShortsTab"), LOC(@"HideShortsTabDesc"), @"removeShorts", &kRemoveShorts, selfObject), createSwitchItem(LOC(@"HideSubscriptionsTab"), LOC(@"HideSubscriptionsTabDesc"), @"removeSubscriptions", &kRemoveSubscriptions, selfObject), @@ -392,7 +385,12 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD YTSettingsSectionItem *reset = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"ResetSettings") titleDescription:nil accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTAlertView *alertView = [%c(YTAlertView) confirmationDialogWithAction:^{ - resetYTLiteSettings(); + NSString *prefsPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YTLite.plist"]; + [[NSFileManager defaultManager] removeItemAtPath:prefsPath error:nil]; + + [[UIApplication sharedApplication] performSelector:@selector(suspend)]; + [NSThread sleepForTimeInterval:1.0]; + exit(0); } actionTitle:LOC(@"Yes") cancelTitle:LOC(@"No")]; diff --git a/YTLite.h b/YTLite.h index 0ca9f93..8230fac 100644 --- a/YTLite.h +++ b/YTLite.h @@ -49,6 +49,7 @@ BOOL kNoPromotionCards; BOOL kNoWatermarks; BOOL kMiniplayer; BOOL kPortraitFullscreen; +BOOL kCopyWithTimestamp; BOOL kDisableAutoplay; BOOL kNoContentWarning; BOOL kClassicQuality; @@ -80,6 +81,7 @@ BOOL kHideShortsDescription; BOOL kHideShortsAudioTrack; BOOL kHideShortsPromoCards; BOOL kRemoveLabels; +BOOL kRemoveIndicators; BOOL kReExplore; BOOL kRemoveShorts; BOOL kRemoveSubscriptions; @@ -169,6 +171,9 @@ int kPivotIndex; @interface YTELMView : UIView @end +@interface _ASDisplayView : UIView +@end + @interface MLHAMQueuePlayer : NSObject @property id playerEventCenter; -(void)setRate:(float)rate; @@ -192,4 +197,9 @@ int kPivotIndex; + (instancetype)infoDialog; + (instancetype)confirmationDialogWithAction:(void (^)(void))action actionTitle:(NSString *)actionTitle cancelTitle:(NSString *)cancelTitle; - (void)show; +@end + +@interface YTMainAppVideoPlayerOverlayViewController : UIViewController +@property (readonly, nonatomic) CGFloat mediaTime; +@property (readonly, nonatomic) NSString *videoID; @end \ No newline at end of file diff --git a/YTLite.x b/YTLite.x index b72c7ef..b674b5b 100644 --- a/YTLite.x +++ b/YTLite.x @@ -32,7 +32,7 @@ - (NSData *)elementData { if (self.hasCompatibilityOptions && self.compatibilityOptions.hasAdLoggingData && kNoAds) return nil; - NSArray *adDescriptions = @[@"brand_promo", @"product_carousel", @"product_engagement_panel", @"product_item", @"text_search_ad", @"text_image_button_layout", @"carousel_headered_layout", @"square_image_layout", @"feed_ad_metadata"]; + NSArray *adDescriptions = @[@"brand_promo", @"product_carousel", @"product_engagement_panel", @"product_item", @"text_search_ad", @"text_image_button_layout", @"carousel_headered_layout", @"carousel_footered_layout", @"square_image_layout", @"landscape_image_wide_button_layout", @"feed_ad_metadata"]; NSString *description = [self description]; if (([adDescriptions containsObject:description] && kNoAds) || ([description containsString:@"inline_shorts"] && kHideShorts)) { return [NSData data]; @@ -389,9 +389,22 @@ - (BOOL)shouldExitFullScreenOnFinish { return kExitFullscreen ? YES : NO; } %end -// Disable Double Tap To Seek %hook YTMainAppVideoPlayerOverlayViewController +// Disable Double Tap To Seek - (BOOL)allowDoubleTapToSeekGestureRecognizer { return kNoDoubleTapToSeek ? NO : %orig; } + +// Copy Timestamped Link by Pressing On Pause +- (void)didPressPause:(id)arg1 { + %orig; + + if (kCopyWithTimestamp) { + NSInteger mediaTimeInteger = (NSInteger)self.mediaTime; + NSString *currentTimeLink = [NSString stringWithFormat:@"https://www.youtube.com/watch?v=%@&t=%lds", self.videoID, mediaTimeInteger]; + + UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; + pasteboard.string = currentTimeLink; + } +} %end // Fit 'Play All' Buttons Text For Localizations @@ -528,7 +541,6 @@ - (void)layoutSubviews { %orig; if (kHideShortsDescription && [self.subviews[2].accessibilityIdentifier isEqualToString:@"id.reels_smv_player_title_label"]) self.subviews[2].hidden = YES; - if (kHideShortsThanks && [self.subviews[self.subviews.count - 3].accessibilityIdentifier isEqualToString:@"id.elements.components.suggested_action"]) self.subviews[self.subviews.count - 3].hidden = YES; // Might be useful for older versions if (kHideShortsChannelName) self.subviews[self.subviews.count - 2].hidden = YES; if (kHideShortsAudioTrack) self.subviews.lastObject.hidden = YES; for (UIView *subview in self.subviews) { @@ -539,10 +551,11 @@ } %end -%hook YTELMView + +%hook _ASDisplayView - (void)layoutSubviews { %orig; - if (kHideShortsThanks && [self.subviews.firstObject.accessibilityIdentifier isEqualToString:@"id.elements.components.suggested_action"]) self.subviews.firstObject.hidden = YES; + if (kHideShortsThanks && [self.accessibilityIdentifier isEqualToString:@"id.elements.components.suggested_action"]) self.hidden = YES; } %end @@ -608,6 +621,12 @@ static void replaceTab(YTIGuideResponse *response) { } %end +// Hide Tab Bar Indicators +%hook YTPivotBarIndicatorView +- (void)setFillColor:(id)arg1 { %orig(kRemoveIndicators ? [UIColor clearColor] : arg1); } +- (void)setBorderColor:(id)arg1 { %orig(kRemoveIndicators ? [UIColor clearColor] : arg1); } +%end + // Hide Tab Labels BOOL hasHomeBar = NO; CGFloat pivotBarViewHeight; @@ -745,6 +764,7 @@ static void reloadPrefs() { kNoWatermarks = [prefs[@"noWatermarks"] boolValue] ?: NO; kMiniplayer = [prefs[@"miniplayer"] boolValue] ?: NO; kPortraitFullscreen = [prefs[@"portraitFullscreen"] boolValue] ?: NO; + kCopyWithTimestamp = [prefs[@"copyWithTimestamp"] boolValue] ?: NO; kDisableAutoplay = [prefs[@"disableAutoplay"] boolValue] ?: NO; kNoContentWarning = [prefs[@"noContentWarning"] boolValue] ?: NO; kClassicQuality = [prefs[@"classicQuality"] boolValue] ?: NO; @@ -776,6 +796,7 @@ static void reloadPrefs() { kHideShortsAudioTrack = [prefs[@"hideShortsAudioTrack"] boolValue] ?: NO; kHideShortsPromoCards = [prefs[@"hideShortsPromoCards"] boolValue] ?: NO; kRemoveLabels = [prefs[@"removeLabels"] boolValue] ?: NO; + kRemoveIndicators = [prefs[@"removeIndicators"] boolValue] ?: NO; kReExplore = [prefs[@"reExplore"] boolValue] ?: NO; kRemoveShorts = [prefs[@"removeShorts"] boolValue] ?: NO; kRemoveSubscriptions = [prefs[@"removeSubscriptions"] boolValue] ?: NO; @@ -816,6 +837,7 @@ static void reloadPrefs() { @"noWatermarks" : @(kNoWatermarks), @"miniplayer" : @(kMiniplayer), @"portraitFullscreen" : @(kPortraitFullscreen), + @"copyWithTimestamp" : @(kCopyWithTimestamp), @"disableAutoplay" : @(kDisableAutoplay), @"noContentWarning" : @(kNoContentWarning), @"classicQuality" : @(kClassicQuality), @@ -847,6 +869,7 @@ static void reloadPrefs() { @"hideShortsAudioTrack" : @(kHideShortsAudioTrack), @"hideShortsPromoCards" : @(kHideShortsPromoCards), @"removeLabels" : @(kRemoveLabels), + @"removeIndicators" : @(kRemoveIndicators), @"reExplore" : @(kReExplore), @"removeShorts" : @(kRemoveShorts), @"removeSubscriptions" : @(kRemoveSubscriptions), 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 a963ba2..855642f 100644 --- a/layout/Library/Application Support/YTLite.bundle/en.lproj/Localizable.strings +++ b/layout/Library/Application Support/YTLite.bundle/en.lproj/Localizable.strings @@ -49,6 +49,8 @@ "MiniplayerDesc" = "Enables the mini player for videos that were not originally designed for it, such as videos targeted for children."; "PortraitFullscreen" = "Portrait fullscreen mode"; "PortraitFullscreenDesc" = "Enables portrait fullscreen mode support."; +"CopyWithTimestamp" = "Copy timestamped links"; +"CopyWithTimestampDesc" = "Allows to copy timestamped link to the clipboard by pressing pause button."; "DisableAutoplay" = "Disable Autoplay videos"; "DisableAutoplayDesc" = "Prevents video playback after opening."; "NoContentWarning" = "Skip content warning"; @@ -75,6 +77,8 @@ "Tabbar" = "Tab bar"; "RemoveLabels" = "Remove labels"; "RemoveLabelsDesc" = "Removes tab labels."; +"RemoveIndicators" = "Remove indicators"; +"RemoveIndicatorsDesc" = "Removes tab indicators."; "ReExplore" = "Replace Shorts tab with Explore tab"; "ReExploreDesc" = "Shows Explore tab instead of Shorts tab as on old YouTube versions."; "HideShortsTab" = "Hide Shorts tab"; diff --git a/layout/Library/Application Support/YTLite.bundle/es.lproj/Localizable.strings b/layout/Library/Application Support/YTLite.bundle/es.lproj/Localizable.strings index cb9b0e4..365758d 100644 --- a/layout/Library/Application Support/YTLite.bundle/es.lproj/Localizable.strings +++ b/layout/Library/Application Support/YTLite.bundle/es.lproj/Localizable.strings @@ -49,6 +49,8 @@ "MiniplayerDesc" = "Activa el mini reproductor para vídeos que no fueron diseñados originalmente para ello, como los vídeos dirigidos a niños."; "PortraitFullscreen" = "Modo de pantalla completa vertical"; "PortraitFullscreenDesc" = "Activa el modo de pantalla completa vertical."; +"CopyWithTimestamp" = "Copy timestamped links"; +"CopyWithTimestampDesc" = "Allows to copy timestamped link to the clipboard by pressing pause button."; "DisableAutoplay" = "Desactivar reproducción automática"; "DisableAutoplayDesc" = "Evita la reproducción automática de vídeos después de abrirlos."; "NoContentWarning" = "Omitir advertencia de contenido"; @@ -75,6 +77,8 @@ "Tabbar" = "Barra de pestañas"; "RemoveLabels" = "Eliminar etiquetas"; "RemoveLabelsDesc" = "Elimina las etiquetas de las pestañas."; +"RemoveIndicators" = "Remove indicators"; +"RemoveIndicatorsDesc" = "Removes tab indicators."; "ReExplore" = "Reemplazar pestaña Shorts con pestaña Explorar"; "ReExploreDesc" = "Muestra la pestaña Explorar en lugar de la pestaña Shorts como en versiones antiguas de YouTube."; "HideShortsTab" = "Ocultar pestaña Shorts"; diff --git a/layout/Library/Application Support/YTLite.bundle/fr.lproj/Localizable.strings b/layout/Library/Application Support/YTLite.bundle/fr.lproj/Localizable.strings index 3345840..d30e1a2 100644 --- a/layout/Library/Application Support/YTLite.bundle/fr.lproj/Localizable.strings +++ b/layout/Library/Application Support/YTLite.bundle/fr.lproj/Localizable.strings @@ -49,6 +49,8 @@ "MiniplayerDesc" = "Active le mini-lecteur pour les vidéos qui n'étaient pas initialement conçues pour cela, comme les vidéos destinées aux enfants."; "PortraitFullscreen" = "Mode plein écran en portrait"; "PortraitFullscreenDesc" = "Active la prise en charge du mode plein écran en portrait."; +"CopyWithTimestamp" = "Copy timestamped links"; +"CopyWithTimestampDesc" = "Allows to copy timestamped link to the clipboard by pressing pause button."; "DisableAutoplay" = "Désactiver la lecture automatique des vidéos"; "DisableAutoplayDesc" = "Empêche la lecture des vidéos après ouverture."; "NoContentWarning" = "Passer l'avertissement de contenu"; @@ -75,6 +77,8 @@ "Tabbar" = "Barre d'onglets"; "RemoveLabels" = "Supprimer les sous-titres"; "RemoveLabelsDesc" = "Supprime les sous-titres des onglets."; +"RemoveIndicators" = "Remove indicators"; +"RemoveIndicatorsDesc" = "Removes tab indicators."; "ReExplore" = "Remplacer l'onglet Shorts par l'onglet Explorer"; "ReExploreDesc" = "Affiche l'onglet Explorer à la place de l'onglet Shorts comme dans les anciennes versions de YouTube."; "HideShortsTab" = "Masquer l'onglet Shorts"; diff --git a/layout/Library/Application Support/YTLite.bundle/ja.lproj/Localizable.strings b/layout/Library/Application Support/YTLite.bundle/ja.lproj/Localizable.strings index 93ccf20..726d147 100644 --- a/layout/Library/Application Support/YTLite.bundle/ja.lproj/Localizable.strings +++ b/layout/Library/Application Support/YTLite.bundle/ja.lproj/Localizable.strings @@ -49,6 +49,8 @@ "MiniplayerDesc" = "ミニプレイヤーに対応していない動画(子供向けの動画など)でもミニプレイヤーを有効にします"; "PortraitFullscreen" = "縦画面フルスクリーンモード"; "PortraitFullscreenDesc" = "縦画面フルスクリーンモードをサポートします"; +"CopyWithTimestamp" = "Copy timestamped links"; +"CopyWithTimestampDesc" = "Allows to copy timestamped link to the clipboard by pressing pause button."; "DisableAutoplay" = "自動再生を無効化"; "DisableAutoplayDesc" = "アプリを開いた後に動画の自動再生を防止します"; "NoContentWarning" = "コンテンツ警告をスキップ"; @@ -75,6 +77,8 @@ "Tabbar" = "タブバー"; "RemoveLabels" = "ラベルを削除"; "RemoveLabelsDesc" = "タブラベルを削除します"; +"RemoveIndicators" = "Remove indicators"; +"RemoveIndicatorsDesc" = "Removes tab indicators."; "ReExplore" = "ショートタブを探索タブに置き換え"; "ReExploreDesc" = "古いYouTubeバージョンのように、ショートタブの代わりに探索タブを表示します"; "HideShortsTab" = "ショートタブを非表示"; @@ -165,4 +169,4 @@ "ResetSettings" = "YTLiteの設定をリセット"; "ResetMessage" = "このオプションを選択するとYTLiteの設定がデフォルトにリセットされ、YouTubeが終了します。\n\n続行してもよろしいですか?"; "Yes" = "はい"; -"No" = "いいえ"; +"No" = "いいえ"; \ No newline at end of file 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 8a99e4a..43927ad 100644 --- a/layout/Library/Application Support/YTLite.bundle/ru.lproj/Localizable.strings +++ b/layout/Library/Application Support/YTLite.bundle/ru.lproj/Localizable.strings @@ -49,6 +49,8 @@ "MiniplayerDesc" = "Принудительно активирует миниплеер для видео, в которых изначально не был предназначен (например, видеоролики для детей)."; "PortraitFullscreen" = "Портретный полноэкранный режим"; "PortraitFullscreenDesc" = "Активирует поддержку портретного полноэкранного режима."; +"CopyWithTimestamp" = "Ссылки с временной отметкой"; +"CopyWithTimestampDesc" = "Позволяет скопировать ссылку на видео с временной отметкой в буфер обмена нажатием на кнопку паузы."; "DisableAutoplay" = "Запретить автовоспроизведение"; "DisableAutoplayDesc" = "Принудительно запрещает автовоспроизведение видео при его открытии."; "NoContentWarning" = "Пропускать предупреждения"; @@ -75,6 +77,8 @@ "Tabbar" = "Панель вкладок"; "RemoveLabels" = "Скрыть названия"; "RemoveLabelsDesc" = "Скрывает названия вкладок."; +"RemoveIndicators" = "Скрыть индикаторы"; +"RemoveIndicatorsDesc" = "Скрывает индикаторы вкладок."; "ReExplore" = "Вкладка «Навигация» вместо «Shorts»"; "ReExploreDesc" = "Заменяет вкладку «Shorts» на привычную нам «Навигацию»."; "HideShortsTab" = "Скрыть «Shorts»"; 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 6982e2b..b40c488 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 @@ -49,6 +49,8 @@ "MiniplayerDesc" = "启用迷你播放器来播放最初不是为其设计的视频,例如针对儿童的视频。"; "PortraitFullscreen" = "竖屏全屏模式"; "PortraitFullscreenDesc" = "启用竖屏全屏模式支持。"; +"CopyWithTimestamp" = "Copy timestamped links"; +"CopyWithTimestampDesc" = "Allows to copy timestamped link to the clipboard by pressing pause button."; "DisableAutoplay" = "禁用自动播放视频"; "DisableAutoplayDesc" = "打开后防止视频自动播放。"; "NoContentWarning" = "跳过内容警告"; @@ -75,6 +77,8 @@ "Tabbar" = "选项卡栏"; "RemoveLabels" = "移除标签"; "RemoveLabelsDesc" = "删除选项卡标签。"; +"RemoveIndicators" = "Remove indicators"; +"RemoveIndicatorsDesc" = "Removes tab indicators."; "ReExplore" = "“短视频”替换为“探索”"; "ReExploreDesc" = "在旧版本 YouTube 中将“短视频”选项卡替换为“探索”。"; "HideShortsTab" = "隐藏短视频"; diff --git a/layout/Library/Application Support/YTLite.bundle/zh-Hant.lproj/Localizable.strings b/layout/Library/Application Support/YTLite.bundle/zh-Hant.lproj/Localizable.strings index b018ad5..4edd20b 100644 --- a/layout/Library/Application Support/YTLite.bundle/zh-Hant.lproj/Localizable.strings +++ b/layout/Library/Application Support/YTLite.bundle/zh-Hant.lproj/Localizable.strings @@ -49,6 +49,8 @@ "MiniplayerDesc" = "對於原本不支援迷你播放器的影片(例如針對兒童的影片),啟用迷你播放器"; "PortraitFullscreen" = "直向全螢幕模式"; "PortraitFullscreenDesc" = "啟用直向全螢幕模式"; +"CopyWithTimestamp" = "Copy timestamped links"; +"CopyWithTimestampDesc" = "Allows to copy timestamped link to the clipboard by pressing pause button."; "DisableAutoplay" = "停用自動播放"; "DisableAutoplayDesc" = "在打開應用程式後防止自動播放影片"; "NoContentWarning" = "略過內容警告"; @@ -75,6 +77,8 @@ "Tabbar" = "下方標籤欄"; "RemoveLabels" = "移除標籤文字"; "RemoveLabelsDesc" = "移除標籤文字"; +"RemoveIndicators" = "Remove indicators"; +"RemoveIndicatorsDesc" = "Removes tab indicators."; "ReExplore" = "用探索取代Shorts分頁"; "ReExploreDesc" = "如同舊版YouTube一樣顯示「探索」而非「Shorts」"; "HideShortsTab" = "隱藏Shorts"; diff --git a/packages/com.dvntm.ytlite_2.4_iphoneos-arm.deb b/packages/com.dvntm.ytlite_2.4_iphoneos-arm.deb new file mode 100644 index 0000000..bb1e3df Binary files /dev/null and b/packages/com.dvntm.ytlite_2.4_iphoneos-arm.deb differ diff --git a/packages/com.dvntm.ytlite_2.4_iphoneos-arm64.deb b/packages/com.dvntm.ytlite_2.4_iphoneos-arm64.deb new file mode 100644 index 0000000..b4291c9 Binary files /dev/null and b/packages/com.dvntm.ytlite_2.4_iphoneos-arm64.deb differ