mirror of
https://github.com/SoPat712/YTLitePlus.git
synced 2025-08-22 02:38:45 -04:00
added files via upload
This commit is contained in:
2
Tweaks/YTLite/.gitattributes
vendored
Normal file
2
Tweaks/YTLite/.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
21
Tweaks/YTLite/LICENSE
Normal file
21
Tweaks/YTLite/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 dayanch96
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
18
Tweaks/YTLite/Makefile
Normal file
18
Tweaks/YTLite/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
ifeq ($(ROOTLESS),1)
|
||||
THEOS_PACKAGE_SCHEME=rootless
|
||||
endif
|
||||
|
||||
DEBUG=0
|
||||
FINALPACKAGE=1
|
||||
ARCHS = arm64
|
||||
PACKAGE_VERSION = 2.0
|
||||
TARGET := iphone:clang:latest:11.0
|
||||
|
||||
include $(THEOS)/makefiles/common.mk
|
||||
|
||||
TWEAK_NAME = YTLite
|
||||
$(TWEAK_NAME)_FRAMEWORKS = UIKit Foundation
|
||||
$(TWEAK_NAME)_CFLAGS = -fobjc-arc -DTWEAK_VERSION=$(PACKAGE_VERSION)
|
||||
$(TWEAK_NAME)_FILES = YTLite.x Settings.x Sideloading.x
|
||||
|
||||
include $(THEOS_MAKE_PATH)/tweak.mk
|
18
Tweaks/YTLite/README.md
Normal file
18
Tweaks/YTLite/README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# YTLite
|
||||
Lightweight YouTube Enhancer
|
||||
|
||||
Advanced mode can be activated inside **Version cell**. Then simply reopen YTLite settings
|
||||
|
||||
# How to build it yourself
|
||||
Clone this repo and __[YouTubeHeader by PoomSmart](https://github.com/PoomSmart/YouTubeHeader/)__
|
||||
|
||||
cd YTLite folder and run
|
||||
|
||||
• '**make clean package**' to build deb for rootful device
|
||||
|
||||
• '**make clean package ROOTLESS=1**' to build deb for rootless device
|
||||
|
||||
|
||||
<p align="center">
|
||||
<img src=https://github-production-user-asset-6210df.s3.amazonaws.com/38832025/248051008-4cef3fb5-ab24-4d8c-bc7f-122b1df95996.png?raw=true) />
|
||||
</p>
|
374
Tweaks/YTLite/Settings.x
Normal file
374
Tweaks/YTLite/Settings.x
Normal file
@@ -0,0 +1,374 @@
|
||||
#import "YTLite.h"
|
||||
|
||||
@interface YTSettingsSectionItemManager (YTLite)
|
||||
- (void)updateYTLiteSectionWithEntry:(id)entry;
|
||||
@end
|
||||
|
||||
static const NSInteger YTLiteSection = 789;
|
||||
|
||||
static void resetYTLiteSettings() {
|
||||
NSString *prefsPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YTLite.plist"];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
[fileManager removeItemAtPath:prefsPath error:nil];
|
||||
}
|
||||
|
||||
NSBundle *YTLiteBundle() {
|
||||
static NSBundle *bundle = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *tweakBundlePath = [[NSBundle mainBundle] pathForResource:@"YTLite" ofType:@"bundle"];
|
||||
if (tweakBundlePath)
|
||||
bundle = [NSBundle bundleWithPath:tweakBundlePath];
|
||||
else
|
||||
bundle = [NSBundle bundleWithPath:ROOT_PATH_NS("/Library/Application Support/YTLite.bundle")];
|
||||
});
|
||||
return bundle;
|
||||
}
|
||||
|
||||
// Settings
|
||||
%hook YTAppSettingsPresentationData
|
||||
+ (NSArray *)settingsCategoryOrder {
|
||||
NSArray *order = %orig;
|
||||
NSMutableArray *mutableOrder = [order mutableCopy];
|
||||
NSUInteger insertIndex = [order indexOfObject:@(1)];
|
||||
if (insertIndex != NSNotFound)
|
||||
[mutableOrder insertObject:@(YTLiteSection) atIndex:insertIndex + 1];
|
||||
return mutableOrder;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTSettingsSectionController
|
||||
- (void)setSelectedItem:(NSUInteger)selectedItem {
|
||||
if (selectedItem != NSNotFound) %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTSettingsSectionItemManager
|
||||
%new
|
||||
- (void)updatePrefsForKey:(NSString *)key enabled:(BOOL)enabled {
|
||||
NSString *prefsPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YTLite.plist"];
|
||||
NSMutableDictionary *prefs = [NSMutableDictionary dictionaryWithContentsOfFile:prefsPath];
|
||||
|
||||
if (!prefs) prefs = [NSMutableDictionary dictionary];
|
||||
|
||||
[prefs setObject:@(enabled) forKey:key];
|
||||
[prefs writeToFile:prefsPath atomically:NO];
|
||||
|
||||
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.dvntm.ytlite.prefschanged"), NULL, NULL, YES);
|
||||
}
|
||||
|
||||
%new
|
||||
- (void)updateIntegerPrefsForKey:(NSString *)key intValue:(NSInteger)intValue {
|
||||
NSString *prefsPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YTLite.plist"];
|
||||
NSMutableDictionary *prefs = [NSMutableDictionary dictionaryWithContentsOfFile:prefsPath];
|
||||
|
||||
if (!prefs) prefs = [NSMutableDictionary dictionary];
|
||||
|
||||
[prefs setObject:@(intValue) forKey:key];
|
||||
[prefs writeToFile:prefsPath atomically:NO];
|
||||
|
||||
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.dvntm.ytlite.prefschanged"), NULL, NULL, YES);
|
||||
}
|
||||
|
||||
static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleDescription, NSString *key, BOOL *value, id selfObject) {
|
||||
Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem);
|
||||
YTSettingsSectionItem *item = [YTSettingsSectionItemClass switchItemWithTitle:title
|
||||
titleDescription:titleDescription
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:*value
|
||||
switchBlock:^BOOL(YTSettingsCell *cell, BOOL enabled) {
|
||||
[selfObject updatePrefsForKey:key enabled:enabled];
|
||||
return YES;
|
||||
}
|
||||
settingItemId:0];
|
||||
return item;
|
||||
}
|
||||
|
||||
%new(v@:@)
|
||||
- (void)updateYTLiteSectionWithEntry:(id)entry {
|
||||
NSMutableArray *sectionItems = [NSMutableArray array];
|
||||
Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem);
|
||||
YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"];
|
||||
id selfObject = self;
|
||||
|
||||
YTSettingsSectionItem *space = [%c(YTSettingsSectionItem) itemWithTitle:nil accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { return YES; }];
|
||||
|
||||
YTSettingsSectionItem *general = [YTSettingsSectionItemClass itemWithTitle:LOC(@"General")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return @"‣";
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
createSwitchItem(LOC(@"RemoveAds"), LOC(@"RemoveAdsDesc"), @"noAds", &kNoAds, selfObject),
|
||||
createSwitchItem(LOC(@"BackgroundPlayback"), LOC(@"BackgroundPlaybackDesc"), @"backgroundPlayback", &kBackgroundPlayback, selfObject)
|
||||
];
|
||||
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"General") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:general];
|
||||
|
||||
YTSettingsSectionItem *navbar = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Navbar")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return @"‣";
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
createSwitchItem(LOC(@"RemoveCast"), LOC(@"RemoveCastDesc"), @"noCast", &kNoCast, selfObject),
|
||||
createSwitchItem(LOC(@"RemoveNotifications"), LOC(@"RemoveNotificationsDesc"), @"removeNotifsButton", &kNoNotifsButton, selfObject),
|
||||
createSwitchItem(LOC(@"RemoveSearch"), LOC(@"RemoveSearchDesc"), @"removeSearchButton", &kNoSearchButton, selfObject)
|
||||
];
|
||||
|
||||
if (kAdvancedMode) {
|
||||
YTSettingsSectionItem *addStickyNavbar = createSwitchItem(LOC(@"StickyNavbar"), LOC(@"StickyNavbarDesc"), @"stickyNavbar", &kStickyNavbar, selfObject);
|
||||
rows = [rows arrayByAddingObject:addStickyNavbar];
|
||||
|
||||
YTSettingsSectionItem *addNoSubbar = createSwitchItem(LOC(@"NoSubbar"), LOC(@"NoSubbarDesc"), @"noSubbar", &kNoSubbar, selfObject);
|
||||
rows = [rows arrayByAddingObject:addNoSubbar];
|
||||
|
||||
YTSettingsSectionItem *addNoYTLogo = createSwitchItem(LOC(@"NoYTLogo"), LOC(@"NoYTLogoDesc"), @"noYTLogo", &kNoYTLogo, selfObject);
|
||||
rows = [rows arrayByAddingObject:addNoYTLogo];
|
||||
}
|
||||
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Navbar") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:navbar];
|
||||
|
||||
if (kAdvancedMode) {
|
||||
YTSettingsSectionItem *overlay = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Overlay")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return @"‣";
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
createSwitchItem(LOC(@"HideAutoplay"), LOC(@"HideAutoplayDesc"), @"hideAutoplay", &kHideAutoplay, selfObject),
|
||||
createSwitchItem(LOC(@"HideSubs"), LOC(@"HideSubsDesc"), @"hideSubs", &kHideSubs, selfObject),
|
||||
createSwitchItem(LOC(@"NoHUDMsgs"), LOC(@"NoHUDMsgsDesc"), @"noHUDMsgs", &kNoHUDMsgs, selfObject),
|
||||
createSwitchItem(LOC(@"HidePrevNext"), LOC(@"HidePrevNextDesc"), @"hidePrevNext", &kHidePrevNext, selfObject),
|
||||
createSwitchItem(LOC(@"ReplacePrevNext"), LOC(@"ReplacePrevNextDesc"), @"replacePrevNext", &kReplacePrevNext, selfObject),
|
||||
createSwitchItem(LOC(@"NoDarkBg"), LOC(@"NoDarkBgDesc"), @"noDarkBg", &kNoDarkBg, selfObject),
|
||||
createSwitchItem(LOC(@"NoEndScreenCards"), LOC(@"NoEndScreenCardsDesc"), @"noEndScreenCards", &kEndScreenCards, selfObject),
|
||||
createSwitchItem(LOC(@"NoFullscreenActions"), LOC(@"NoFullscreenActionsDesc"), @"noFullscreenActions", &kNoFullscreenActions, selfObject),
|
||||
createSwitchItem(LOC(@"NoRelatedVids"), LOC(@"NoRelatedVidsDesc"), @"noRelatedVids", &kNoRelatedVids, selfObject),
|
||||
createSwitchItem(LOC(@"NoPromotionCards"), LOC(@"NoPromotionCardsDesc"), @"noPromotionCards", &kNoPromotionCards, selfObject),
|
||||
createSwitchItem(LOC(@"NoWatermarks"), LOC(@"NoWatermarksDesc"), @"noWatermarks", &kNoWatermarks, selfObject)
|
||||
];
|
||||
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Overlay") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:overlay];
|
||||
|
||||
YTSettingsSectionItem *player = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Player")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return @"‣";
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
createSwitchItem(LOC(@"Miniplayer"), LOC(@"MiniplayerDesc"), @"miniplayer", &kMiniplayer, 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),
|
||||
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(@"ExitFullscreen"), LOC(@"ExitFullscreenDesc"), @"exitFullscreen", &kExitFullscreen, selfObject),
|
||||
createSwitchItem(LOC(@"NoDoubleTap2Seek"), LOC(@"NoDoubleTap2SeekDesc"), @"noDoubleTapToSeek", &kNoDoubleTapToSeek, selfObject)
|
||||
];
|
||||
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Player") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:player];
|
||||
|
||||
YTSettingsSectionItem *shorts = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Shorts")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return @"‣";
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
createSwitchItem(LOC(@"HideShorts"), LOC(@"HideShortsDesc"), @"hideShorts", &kHideShorts, selfObject),
|
||||
createSwitchItem(LOC(@"ShortsProgress"), LOC(@"ShortsProgressDesc"), @"shortsProgress", &kShortsProgress, selfObject),
|
||||
createSwitchItem(LOC(@"ResumeShorts"), LOC(@"ResumeShortsDesc"), @"resumeShorts", &kResumeShorts, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsLogo"), LOC(@"HideShortsLogoDesc"), @"hideShortsLogo", &kHideShortsLogo, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsSearch"), LOC(@"HideShortsSearchDesc"), @"hideShortsSearch", &kHideShortsSearch, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsCamera"), LOC(@"HideShortsCameraDesc"), @"hideShortsCamera", &kHideShortsCamera, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsMore"), LOC(@"HideShortsMoreDesc"), @"hideShortsMore", &kHideShortsMore, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsSubscriptions"), LOC(@"HideShortsSubscriptionsDesc"), @"hideShortsSubscriptions", &kHideShortsSubscriptions, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsLike"), LOC(@"HideShortsLikeDesc"), @"hideShortsLike", &kHideShortsLike, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsDislike"), LOC(@"HideShortsDislikeDesc"), @"hideShortsDislike", &kHideShortsDislike, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsComments"), LOC(@"HideShortsCommentsDesc"), @"hideShortsComments", &kHideShortsComments, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsRemix"), LOC(@"HideShortsRemixDesc"), @"hideShortsRemix", &kHideShortsRemix, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsShare"), LOC(@"HideShortsShareDesc"), @"hideShortsShare", &kHideShortsShare, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsAvatars"), LOC(@"HideShortsAvatarsDesc"), @"hideShortsAvatars", &kHideShortsAvatars, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsThanks"), LOC(@"HideShortsThanksDesc"), @"hideShortsThanks", &kHideShortsThanks, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsChannelName"), LOC(@"HideShortsChannelNameDesc"), @"hideShortsChannelName", &kHideShortsChannelName, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsDescription"), LOC(@"HideShortsDescriptionDesc"), @"hideShortsDescription", &kHideShortsDescription, selfObject),
|
||||
createSwitchItem(LOC(@"HideShortsAudioTrack"), LOC(@"HideShortsAudioTrackDesc"), @"hideShortsAudioTrack", &kHideShortsAudioTrack, selfObject)
|
||||
];
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Shorts") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:shorts];
|
||||
}
|
||||
|
||||
YTSettingsSectionItem *tabbar = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Tabbar")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return @"‣";
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
createSwitchItem(LOC(@"RemoveLabels"), LOC(@"RemoveLabelsDesc"), @"removeLabels", &kRemoveLabels, 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),
|
||||
createSwitchItem(LOC(@"HideUploadButton"), LOC(@"HideUploadButtonDesc"), @"removeUploads", &kRemoveUploads, selfObject),
|
||||
createSwitchItem(LOC(@"HideLibraryTab"), LOC(@"HideLibraryTabDesc"), @"removeLibrary", &kRemoveLibrary, selfObject)
|
||||
];
|
||||
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Tabbar") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:tabbar];
|
||||
|
||||
if (kAdvancedMode) {
|
||||
[sectionItems addObject:space];
|
||||
|
||||
YTSettingsSectionItem *startup = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Startup")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
switch (kPivotIndex) {
|
||||
case 1:
|
||||
return LOC(@"ShortsTab");
|
||||
case 2:
|
||||
return LOC(@"Subscriptions");
|
||||
case 3:
|
||||
return LOC(@"Library");
|
||||
case 0:
|
||||
default:
|
||||
return LOC(@"Home");
|
||||
}
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"Home") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *home, NSUInteger arg1) {
|
||||
kPivotIndex = 0;
|
||||
[settingsViewController reloadData];
|
||||
[self updateIntegerPrefsForKey:@"pivotIndex" intValue:kPivotIndex];
|
||||
return YES;
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"ShortsTab") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *shorts, NSUInteger arg1) {
|
||||
if (kRemoveShorts) {
|
||||
YTAlertView *alertView = [%c(YTAlertView) infoDialog];
|
||||
alertView.title = LOC(@"Warning");
|
||||
alertView.subtitle = LOC(@"TabIsHidden");
|
||||
[alertView show];
|
||||
return NO;
|
||||
} else {
|
||||
kPivotIndex = 1;
|
||||
[settingsViewController reloadData];
|
||||
[self updateIntegerPrefsForKey:@"pivotIndex" intValue:kPivotIndex];
|
||||
return YES;
|
||||
}
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"Subscriptions") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *subscriptions, NSUInteger arg1) {
|
||||
if (kRemoveSubscriptions) {
|
||||
YTAlertView *alertView = [%c(YTAlertView) infoDialog];
|
||||
alertView.title = LOC(@"Warning");
|
||||
alertView.subtitle = LOC(@"TabIsHidden");
|
||||
[alertView show];
|
||||
return NO;
|
||||
} else {
|
||||
kPivotIndex = 2;
|
||||
[settingsViewController reloadData];
|
||||
[self updateIntegerPrefsForKey:@"pivotIndex" intValue:kPivotIndex];
|
||||
return YES;
|
||||
}
|
||||
}],
|
||||
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"Library") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *library, NSUInteger arg1) {
|
||||
if (kRemoveLibrary) {
|
||||
YTAlertView *alertView = [%c(YTAlertView) infoDialog];
|
||||
alertView.title = LOC(@"Warning");
|
||||
alertView.subtitle = LOC(@"TabIsHidden");
|
||||
[alertView show];
|
||||
return NO;
|
||||
} else {
|
||||
kPivotIndex = 3;
|
||||
[settingsViewController reloadData];
|
||||
[self updateIntegerPrefsForKey:@"pivotIndex" intValue:kPivotIndex];
|
||||
return YES;
|
||||
}
|
||||
}]
|
||||
];
|
||||
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Startup") pickerSectionTitle:nil rows:rows selectedItemIndex:kPivotIndex parentResponder:[self parentResponder]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:startup];
|
||||
}
|
||||
|
||||
[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) {
|
||||
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/PoomSmart/"]];
|
||||
}];
|
||||
|
||||
YTSettingsSectionItem *miro = [%c(YTSettingsSectionItem) itemWithTitle:@"MiRO92" titleDescription:@"YTNoShorts" accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/MiRO92/"]];
|
||||
}];
|
||||
|
||||
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/"]];
|
||||
}];
|
||||
|
||||
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();
|
||||
exit(0);
|
||||
}
|
||||
actionTitle:LOC(@"Yes")
|
||||
cancelTitle:LOC(@"No")];
|
||||
alertView.title = LOC(@"Warning");
|
||||
alertView.subtitle = LOC(@"ResetMessage");
|
||||
[alertView show];
|
||||
return YES;
|
||||
}];
|
||||
|
||||
YTSettingsSectionItem *version = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Version")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return @(OS_STRINGIFY(TWEAK_VERSION));
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[ps, miro, 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];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:version];
|
||||
|
||||
[settingsViewController setSectionItems:sectionItems forCategory:YTLiteSection title:@"YTLite" titleDescription:nil headerHidden:NO];
|
||||
}
|
||||
|
||||
- (void)updateSectionForCategory:(NSUInteger)category withEntry:(id)entry {
|
||||
if (category == YTLiteSection) {
|
||||
[self updateYTLiteSectionWithEntry:entry];
|
||||
return;
|
||||
} %orig;
|
||||
}
|
||||
%end
|
138
Tweaks/YTLite/Sideloading.x
Normal file
138
Tweaks/YTLite/Sideloading.x
Normal file
@@ -0,0 +1,138 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <dlfcn.h>
|
||||
|
||||
#define YT_BUNDLE_ID @"com.google.ios.youtube"
|
||||
#define YT_NAME @"YouTube"
|
||||
|
||||
@interface SSOConfiguration : NSObject
|
||||
@end
|
||||
|
||||
%group gSideloading
|
||||
// Keychain patching
|
||||
static NSString *accessGroupID() {
|
||||
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
(__bridge NSString *)kSecClassGenericPassword, (__bridge NSString *)kSecClass,
|
||||
@"bundleSeedID", kSecAttrAccount,
|
||||
@"", kSecAttrService,
|
||||
(id)kCFBooleanTrue, kSecReturnAttributes,
|
||||
nil];
|
||||
CFDictionaryRef result = nil;
|
||||
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
|
||||
if (status == errSecItemNotFound)
|
||||
status = SecItemAdd((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
|
||||
if (status != errSecSuccess)
|
||||
return nil;
|
||||
NSString *accessGroup = [(__bridge NSDictionary *)result objectForKey:(__bridge NSString *)kSecAttrAccessGroup];
|
||||
|
||||
return accessGroup;
|
||||
}
|
||||
|
||||
// IAmYouTube (https://github.com/PoomSmart/IAmYouTube/)
|
||||
%hook YTVersionUtils
|
||||
+ (NSString *)appName { return YT_NAME; }
|
||||
+ (NSString *)appID { return YT_BUNDLE_ID; }
|
||||
%end
|
||||
|
||||
%hook GCKBUtils
|
||||
+ (NSString *)appIdentifier { return YT_BUNDLE_ID; }
|
||||
%end
|
||||
|
||||
%hook GPCDeviceInfo
|
||||
+ (NSString *)bundleId { return YT_BUNDLE_ID; }
|
||||
%end
|
||||
|
||||
%hook OGLBundle
|
||||
+ (NSString *)shortAppName { return YT_NAME; }
|
||||
%end
|
||||
|
||||
%hook GVROverlayView
|
||||
+ (NSString *)appName { return YT_NAME; }
|
||||
%end
|
||||
|
||||
%hook OGLPhenotypeFlagServiceImpl
|
||||
- (NSString *)bundleId { return YT_BUNDLE_ID; }
|
||||
%end
|
||||
|
||||
%hook APMAEU
|
||||
+ (BOOL)isFAS { return YES; }
|
||||
%end
|
||||
|
||||
%hook GULAppEnvironmentUtil
|
||||
+ (BOOL)isFromAppStore { return YES; }
|
||||
%end
|
||||
|
||||
%hook SSOConfiguration
|
||||
- (id)initWithClientID:(id)clientID supportedAccountServices:(id)supportedAccountServices {
|
||||
self = %orig;
|
||||
[self setValue:YT_NAME forKey:@"_shortAppName"];
|
||||
[self setValue:YT_BUNDLE_ID forKey:@"_applicationIdentifier"];
|
||||
return self;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook NSBundle
|
||||
- (NSString *)bundleIdentifier {
|
||||
NSArray *address = [NSThread callStackReturnAddresses];
|
||||
Dl_info info = {0};
|
||||
if (dladdr((void *)[address[2] longLongValue], &info) == 0)
|
||||
return %orig;
|
||||
NSString *path = [NSString stringWithUTF8String:info.dli_fname];
|
||||
if ([path hasPrefix:NSBundle.mainBundle.bundlePath])
|
||||
return YT_BUNDLE_ID;
|
||||
return %orig;
|
||||
}
|
||||
- (id)objectForInfoDictionaryKey:(NSString *)key {
|
||||
if ([key isEqualToString:@"CFBundleIdentifier"])
|
||||
return YT_BUNDLE_ID;
|
||||
if ([key isEqualToString:@"CFBundleDisplayName"] || [key isEqualToString:@"CFBundleName"])
|
||||
return YT_NAME;
|
||||
return %orig;
|
||||
}
|
||||
// Fix Google Sign in by @PoomSmart and @level3tjg (qnblackcat/uYouPlus#684)
|
||||
- (NSDictionary *)infoDictionary {
|
||||
NSMutableDictionary *info = %orig.mutableCopy;
|
||||
NSString *altBundleIdentifier = info[@"ALTBundleIdentifier"];
|
||||
if (altBundleIdentifier) info[@"CFBundleIdentifier"] = altBundleIdentifier;
|
||||
return info;
|
||||
}
|
||||
%end
|
||||
|
||||
// Fix login for YouTube 18.13.2 and higher
|
||||
%hook SSOKeychainHelper
|
||||
+ (NSString *)accessGroup {
|
||||
return accessGroupID();
|
||||
}
|
||||
+ (NSString *)sharedAccessGroup {
|
||||
return accessGroupID();
|
||||
}
|
||||
%end
|
||||
|
||||
// Fix login for YouTube 17.33.2 and higher
|
||||
%hook SSOKeychainCore
|
||||
+ (NSString *)accessGroup {
|
||||
return accessGroupID();
|
||||
}
|
||||
|
||||
+ (NSString *)sharedAccessGroup {
|
||||
return accessGroupID();
|
||||
}
|
||||
%end
|
||||
|
||||
// Fix App Group Directory by moving it to documents directory
|
||||
%hook NSFileManager
|
||||
- (NSURL *)containerURLForSecurityApplicationGroupIdentifier:(NSString *)groupIdentifier {
|
||||
if (groupIdentifier != nil) {
|
||||
NSArray *paths = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
|
||||
NSURL *documentsURL = [paths lastObject];
|
||||
return [documentsURL URLByAppendingPathComponent:@"AppGroup"];
|
||||
}
|
||||
return %orig(groupIdentifier);
|
||||
}
|
||||
%end
|
||||
%end
|
||||
|
||||
%ctor {
|
||||
NSString *embeddedMobileProvisionPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:embeddedMobileProvisionPath]) %init(gSideloading);
|
||||
}
|
146
Tweaks/YTLite/YTLite.h
Normal file
146
Tweaks/YTLite/YTLite.h
Normal file
@@ -0,0 +1,146 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <rootless.h>
|
||||
#import "../YouTubeHeader/YTIGuideResponse.h"
|
||||
#import "../YouTubeHeader/YTIGuideResponseSupportedRenderers.h"
|
||||
#import "../YouTubeHeader/YTIPivotBarSupportedRenderers.h"
|
||||
#import "../YouTubeHeader/YTIPivotBarRenderer.h"
|
||||
#import "../YouTubeHeader/YTIBrowseRequest.h"
|
||||
#import "../YouTubeHeader/YTISectionListRenderer.h"
|
||||
#import "../YouTubeHeader/YTQTMButton.h"
|
||||
#import "../YouTubeHeader/YTVideoQualitySwitchOriginalController.h"
|
||||
#import "../YouTubeHeader/YTPlayerViewController.h"
|
||||
#import "../YouTubeHeader/YTPlayerOverlay.h"
|
||||
#import "../YouTubeHeader/YTPlayerOverlayProvider.h"
|
||||
#import "../YouTubeHeader/YTSettingsViewController.h"
|
||||
#import "../YouTubeHeader/YTSettingsSectionItem.h"
|
||||
#import "../YouTubeHeader/YTSettingsSectionItemManager.h"
|
||||
#import "../YouTubeHeader/YTSettingsPickerViewController.h"
|
||||
#import "../YouTubeHeader/YTUIUtils.h"
|
||||
|
||||
extern NSBundle *YTLiteBundle();
|
||||
|
||||
static inline NSString *LOC(NSString *key) {
|
||||
NSBundle *tweakBundle = YTLiteBundle();
|
||||
return [tweakBundle localizedStringForKey:key value:nil table:nil];
|
||||
}
|
||||
|
||||
BOOL kNoAds;
|
||||
BOOL kBackgroundPlayback;
|
||||
BOOL kNoCast;
|
||||
BOOL kNoNotifsButton;
|
||||
BOOL kNoSearchButton;
|
||||
BOOL kStickyNavbar;
|
||||
BOOL kNoSubbar;
|
||||
BOOL kNoYTLogo;
|
||||
BOOL kHideAutoplay;
|
||||
BOOL kHideSubs;
|
||||
BOOL kNoHUDMsgs;
|
||||
BOOL kHidePrevNext;
|
||||
BOOL kReplacePrevNext;
|
||||
BOOL kNoDarkBg;
|
||||
BOOL kEndScreenCards;
|
||||
BOOL kNoFullscreenActions;
|
||||
BOOL kNoRelatedVids;
|
||||
BOOL kNoPromotionCards;
|
||||
BOOL kNoWatermarks;
|
||||
BOOL kMiniplayer;
|
||||
BOOL kDisableAutoplay;
|
||||
BOOL kNoContentWarning;
|
||||
BOOL kClassicQuality;
|
||||
BOOL kDontSnapToChapter;
|
||||
BOOL kRedProgressBar;
|
||||
BOOL kNoHints;
|
||||
BOOL kNoFreeZoom;
|
||||
BOOL kExitFullscreen;
|
||||
BOOL kNoDoubleTapToSeek;
|
||||
BOOL kHideShorts;
|
||||
BOOL kShortsProgress;
|
||||
BOOL kResumeShorts;
|
||||
BOOL kHideShortsLogo;
|
||||
BOOL kHideShortsSearch;
|
||||
BOOL kHideShortsCamera;
|
||||
BOOL kHideShortsMore;
|
||||
BOOL kHideShortsSubscriptions;
|
||||
BOOL kHideShortsLike;
|
||||
BOOL kHideShortsDislike;
|
||||
BOOL kHideShortsComments;
|
||||
BOOL kHideShortsRemix;
|
||||
BOOL kHideShortsShare;
|
||||
BOOL kHideShortsAvatars;
|
||||
BOOL kHideShortsThanks;
|
||||
BOOL kHideShortsChannelName;
|
||||
BOOL kHideShortsDescription;
|
||||
BOOL kHideShortsAudioTrack;
|
||||
BOOL kRemoveLabels;
|
||||
BOOL kReExplore;
|
||||
BOOL kRemoveShorts;
|
||||
BOOL kRemoveSubscriptions;
|
||||
BOOL kRemoveUploads;
|
||||
BOOL kRemoveLibrary;
|
||||
BOOL kAdvancedMode;
|
||||
int kPivotIndex;
|
||||
|
||||
@interface YTSettingsSectionItemManager (Custom)
|
||||
@property (nonatomic, strong) NSMutableDictionary *prefs;
|
||||
@property (nonatomic, strong) NSString *prefsPath;
|
||||
- (void)updatePrefsForKey:(NSString *)key enabled:(BOOL)enabled;
|
||||
- (void)updateIntegerPrefsForKey:(NSString *)key intValue:(NSInteger)intValue;
|
||||
@end
|
||||
|
||||
@interface YTPivotBarView : UIView
|
||||
@end
|
||||
|
||||
@interface YTPivotBarItemView : UIView
|
||||
@end
|
||||
|
||||
@interface YTPivotBarViewController : UIViewController
|
||||
- (void)selectItemWithPivotIdentifier:(id)pivotIndentifier;
|
||||
@end
|
||||
|
||||
@interface YTRightNavigationButtons : UIView
|
||||
@property (nonatomic, strong) YTQTMButton *notificationButton;
|
||||
@property (nonatomic, strong) YTQTMButton *searchButton;
|
||||
@end
|
||||
|
||||
@interface YTNavigationBarTitleView : UIView
|
||||
@end
|
||||
|
||||
@interface YTSegmentableInlinePlayerBarView
|
||||
@property (nonatomic, assign, readwrite) BOOL enableSnapToChapter;
|
||||
@end
|
||||
|
||||
@interface YTPlayabilityResolutionUserActionUIController : NSObject
|
||||
- (void)confirmAlertDidPressConfirm;
|
||||
@end
|
||||
|
||||
@interface YTReelPlayerButton : UIButton
|
||||
@end
|
||||
|
||||
@interface ELMCellNode
|
||||
@end
|
||||
|
||||
@interface _ASCollectionViewCell : UICollectionViewCell
|
||||
- (id)node;
|
||||
@end
|
||||
|
||||
@interface YTAsyncCollectionView : UICollectionView
|
||||
- (void)removeShortsCellAtIndexPath:(NSIndexPath *)indexPath;
|
||||
@end
|
||||
|
||||
@interface YTReelWatchPlaybackOverlayView : UIView
|
||||
@end
|
||||
|
||||
@interface YTReelTransparentStackView : UIView
|
||||
@end
|
||||
|
||||
@interface YTReelWatchHeaderView : UIView
|
||||
@end
|
||||
|
||||
@interface YTAlertView : UIView
|
||||
@property (nonatomic, copy, readwrite) NSString *title;
|
||||
@property (nonatomic, copy, readwrite) NSString *subtitle;
|
||||
+ (instancetype)infoDialog;
|
||||
+ (instancetype)confirmationDialogWithAction:(void (^)(void))action actionTitle:(NSString *)actionTitle cancelTitle:(NSString *)cancelTitle;
|
||||
- (void)show;
|
||||
@end
|
13
Tweaks/YTLite/YTLite.plist
Normal file
13
Tweaks/YTLite/YTLite.plist
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Filter</key>
|
||||
<dict>
|
||||
<key>Bundles</key>
|
||||
<array>
|
||||
<string>com.google.ios.youtube</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
666
Tweaks/YTLite/YTLite.x
Normal file
666
Tweaks/YTLite/YTLite.x
Normal file
@@ -0,0 +1,666 @@
|
||||
#import "YTLite.h"
|
||||
|
||||
// YouTube-X (https://github.com/PoomSmart/YouTube-X/)
|
||||
// Background Playback
|
||||
%hook YTIPlayabilityStatus
|
||||
- (BOOL)isPlayableInBackground { return kBackgroundPlayback ? YES : NO; }
|
||||
%end
|
||||
|
||||
%hook MLVideo
|
||||
- (BOOL)playableInBackground { return kBackgroundPlayback ? YES : NO; }
|
||||
%end
|
||||
|
||||
// Disable Ads
|
||||
%hook YTIPlayerResponse
|
||||
- (BOOL)isMonetized { return kNoAds ? NO : YES; }
|
||||
%end
|
||||
|
||||
%hook YTDataUtils
|
||||
+ (id)spamSignalsDictionary { return kNoAds ? nil : %orig; }
|
||||
+ (id)spamSignalsDictionaryWithoutIDFA { return kNoAds ? nil : %orig; }
|
||||
%end
|
||||
|
||||
%hook YTAdsInnerTubeContextDecorator
|
||||
- (void)decorateContext:(id)context { if (!kNoAds) %orig; }
|
||||
%end
|
||||
|
||||
%hook YTAccountScopedAdsInnerTubeContextDecorator
|
||||
- (void)decorateContext:(id)context { if (!kNoAds) %orig; }
|
||||
%end
|
||||
|
||||
BOOL isAd(YTIElementRenderer *self) {
|
||||
if (self == nil) return NO;
|
||||
if (self.hasCompatibilityOptions && self.compatibilityOptions.hasAdLoggingData) return YES;
|
||||
NSString *description = [self description];
|
||||
if (([description containsString:@"brand_promo"]
|
||||
|| [description containsString:@"product_carousel"]
|
||||
|| [description containsString:@"product_engagement_panel"]
|
||||
|| [description containsString:@"product_item"]) && kNoAds)
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
%hook YTSectionListViewController
|
||||
- (void)loadWithModel:(YTISectionListRenderer *)model {
|
||||
if (kNoAds) {
|
||||
NSMutableArray <YTISectionListSupportedRenderers *> *contentsArray = model.contentsArray;
|
||||
NSIndexSet *removeIndexes = [contentsArray indexesOfObjectsPassingTest:^BOOL(YTISectionListSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) {
|
||||
YTIItemSectionRenderer *sectionRenderer = renderers.itemSectionRenderer;
|
||||
YTIItemSectionSupportedRenderers *firstObject = [sectionRenderer.contentsArray firstObject];
|
||||
return firstObject.hasPromotedVideoRenderer || firstObject.hasCompactPromotedVideoRenderer || firstObject.hasPromotedVideoInlineMutedRenderer || isAd(firstObject.elementRenderer);
|
||||
}];
|
||||
[contentsArray removeObjectsAtIndexes:removeIndexes];
|
||||
} %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
// NOYTPremium (https://github.com/PoomSmart/NoYTPremium)
|
||||
// Alert
|
||||
%hook YTCommerceEventGroupHandler
|
||||
- (void)addEventHandlers {}
|
||||
%end
|
||||
|
||||
// Full-screen
|
||||
%hook YTInterstitialPromoEventGroupHandler
|
||||
- (void)addEventHandlers {}
|
||||
%end
|
||||
|
||||
%hook YTPromosheetEventGroupHandler
|
||||
- (void)addEventHandlers {}
|
||||
%end
|
||||
|
||||
%hook YTPromoThrottleController
|
||||
- (BOOL)canShowThrottledPromo { return NO; }
|
||||
- (BOOL)canShowThrottledPromoWithFrequencyCap:(id)arg1 { return NO; }
|
||||
- (BOOL)canShowThrottledPromoWithFrequencyCaps:(id)arg1 { return NO; }
|
||||
%end
|
||||
|
||||
%hook YTIShowFullscreenInterstitialCommand
|
||||
- (BOOL)shouldThrottleInterstitial { return YES; }
|
||||
%end
|
||||
|
||||
// "Try new features" in settings
|
||||
%hook YTSettingsSectionItemManager
|
||||
- (void)updatePremiumEarlyAccessSectionWithEntry:(id)arg1 {}
|
||||
%end
|
||||
|
||||
// Survey
|
||||
%hook YTSurveyController
|
||||
- (void)showSurveyWithRenderer:(id)arg1 surveyParentResponder:(id)arg2 {}
|
||||
%end
|
||||
|
||||
// Statement banner
|
||||
%hook YTPremiumSeasonCardCellController
|
||||
- (void)setCell:(id)arg1 { arg1 = NULL; %orig; }
|
||||
%end
|
||||
|
||||
%hook YTPremiumSeasonCardView
|
||||
- (long long)accessibilityElementCount { return 0; }
|
||||
%end
|
||||
|
||||
// Navbar Stuff
|
||||
// Disable Cast
|
||||
%hook MDXPlaybackRouteButtonController
|
||||
- (BOOL)isPersistentCastIconEnabled { return kNoCast ? NO : YES; }
|
||||
- (void)updateRouteButton:(id)arg1 { if (!kNoCast) %orig; }
|
||||
- (void)updateAllRouteButtons { if (!kNoCast) %orig; }
|
||||
%end
|
||||
|
||||
%hook YTSettings
|
||||
- (void)setDisableMDXDeviceDiscovery:(BOOL)arg1 { %orig(kNoCast); }
|
||||
%end
|
||||
|
||||
// Hide Cast, Notifications and Search Buttons
|
||||
%hook YTRightNavigationButtons
|
||||
- (void)layoutSubviews {
|
||||
%orig;
|
||||
if (kNoCast && self.subviews.count > 1 && [self.subviews[1].accessibilityIdentifier isEqualToString:@"id.mdx.playbackroute.button"]) self.subviews[1].hidden = YES; // Hide icon immediately
|
||||
if (kNoNotifsButton) self.notificationButton.hidden = YES;
|
||||
if (kNoSearchButton) self.searchButton.hidden = YES;
|
||||
}
|
||||
%end
|
||||
|
||||
// Hide YouTube Logo
|
||||
%hook YTNavigationBarTitleView
|
||||
- (void)layoutSubviews { %orig; if (kNoYTLogo && self.subviews.count > 1 && [self.subviews[1].accessibilityIdentifier isEqualToString:@"id.yoodle.logo"]) self.subviews[1].hidden = YES; }
|
||||
%end
|
||||
|
||||
// Stick Navigation bar
|
||||
%hook YTHeaderView
|
||||
- (BOOL)stickyNavHeaderEnabled { return kStickyNavbar ? YES : NO; }
|
||||
%end
|
||||
|
||||
// Remove Subbar
|
||||
%hook YTMySubsFilterHeaderView
|
||||
- (void)setChipFilterView:(id)arg1 { if (!kNoSubbar) %orig; }
|
||||
%end
|
||||
|
||||
%hook YTHeaderContentComboView
|
||||
- (void)enableSubheaderBarWithView:(id)arg1 { if (!kNoSubbar) %orig; }
|
||||
%end
|
||||
|
||||
%hook YTHeaderContentComboView
|
||||
- (void)setFeedHeaderScrollMode:(int)arg1 { kNoSubbar ? %orig(0) : %orig; }
|
||||
%end
|
||||
|
||||
// Hide Autoplay Switch and Subs Button
|
||||
%hook YTMainAppControlsOverlayView
|
||||
- (void)setAutoplaySwitchButtonRenderer:(id)arg1 { if (!kHideAutoplay) %orig; }
|
||||
- (void)setClosedCaptionsOrSubtitlesButtonAvailable:(BOOL)arg1 { kHideSubs ? %orig(NO) : %orig; }
|
||||
%end
|
||||
|
||||
// Remove HUD Messages
|
||||
%hook YTHUDMessageView
|
||||
- (id)initWithMessage:(id)arg1 dismissHandler:(id)arg2 { return kNoHUDMsgs ? nil : %orig; }
|
||||
%end
|
||||
|
||||
|
||||
%hook YTColdConfig
|
||||
// Hide Next & Previous buttons
|
||||
- (BOOL)removeNextPaddleForSingletonVideos { return kHidePrevNext ? YES : NO; }
|
||||
- (BOOL)removePreviousPaddleForSingletonVideos { return kHidePrevNext ? YES : NO; }
|
||||
// Replace Next & Previous with Fast Forward & Rewind buttons
|
||||
- (BOOL)replaceNextPaddleWithFastForwardButtonForSingletonVods { return kReplacePrevNext ? YES : NO; }
|
||||
- (BOOL)replacePreviousPaddleWithRewindButtonForSingletonVods { return kReplacePrevNext ? YES : NO; }
|
||||
// Disable Free Zoom
|
||||
- (BOOL)videoZoomFreeZoomEnabledGlobalConfig { return kNoFreeZoom ? NO : YES; }
|
||||
// Use System Theme
|
||||
- (BOOL)shouldUseAppThemeSetting { return YES; }
|
||||
// Dismiss Panel By Swiping in Fullscreen Mode
|
||||
- (BOOL)isLandscapeEngagementPanelSwipeRightToDismissEnabled { return YES; }
|
||||
// Remove Video in Playlist By Swiping To The Right
|
||||
- (BOOL)enableSwipeToRemoveInPlaylistWatchEp { return YES; }
|
||||
%end
|
||||
|
||||
// Remove Dark Background in Overlay
|
||||
%hook YTMainAppVideoPlayerOverlayView
|
||||
- (void)setBackgroundVisible:(BOOL)arg1 { kNoDarkBg ? %orig(NO) : %orig; }
|
||||
%end
|
||||
|
||||
// No Endscreen Cards
|
||||
%hook YTCreatorEndscreenView
|
||||
- (void)setHidden:(BOOL)arg1 { kEndScreenCards ? %orig(YES) : %orig; }
|
||||
%end
|
||||
|
||||
// Disable Fullscreen Actions
|
||||
%hook YTFullscreenActionsView
|
||||
- (BOOL)enabled { return kNoFullscreenActions ? NO : YES; }
|
||||
- (void)setEnabled:(BOOL)arg1 { kNoFullscreenActions ? %orig(NO) : %orig; }
|
||||
%end
|
||||
|
||||
// Dont Show Related Videos on Finish
|
||||
%hook YTFullscreenEngagementOverlayController
|
||||
- (void)setRelatedVideosVisible:(BOOL)arg1 { kNoRelatedVids ? %orig(NO) : %orig; }
|
||||
%end
|
||||
|
||||
// Hide Paid Promotion Cards
|
||||
%hook YTMainAppVideoPlayerOverlayViewController
|
||||
- (void)setPaidContentWithPlayerData:(id)data { if (!kNoPromotionCards) %orig; }
|
||||
- (void)playerOverlayProvider:(YTPlayerOverlayProvider *)provider didInsertPlayerOverlay:(YTPlayerOverlay *)overlay {
|
||||
if ([[overlay overlayIdentifier] isEqualToString:@"player_overlay_paid_content"] && kNoPromotionCards) return;
|
||||
%orig;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTInlineMutedPlaybackPlayerOverlayViewController
|
||||
- (void)setPaidContentWithPlayerData:(id)data { if (!kNoPromotionCards) %orig; }
|
||||
%end
|
||||
|
||||
// Remove Watermarks
|
||||
%hook YTAnnotationsViewController
|
||||
- (void)loadFeaturedChannelWatermark { if (!kNoWatermarks) %orig; }
|
||||
%end
|
||||
|
||||
// Forcibly Enable Miniplayer
|
||||
%hook YTWatchMiniBarViewController
|
||||
- (void)updateMiniBarPlayerStateFromRenderer { if (!kMiniplayer) %orig; }
|
||||
%end
|
||||
|
||||
// Disable Autoplay
|
||||
%hook YTPlaybackConfig
|
||||
- (void)setStartPlayback:(BOOL)arg1 { kDisableAutoplay ? %orig(NO) : %orig; }
|
||||
%end
|
||||
|
||||
// Skip Content Warning (https://github.com/qnblackcat/uYouPlus/blob/main/uYouPlus.xm#L452-L454)
|
||||
%hook YTPlayabilityResolutionUserActionUIController
|
||||
- (void)showConfirmAlert { if (kNoContentWarning) [self confirmAlertDidPressConfirm]; }
|
||||
%end
|
||||
|
||||
// Classic Video Quality (https://github.com/PoomSmart/YTClassicVideoQuality)
|
||||
%hook YTVideoQualitySwitchControllerFactory
|
||||
- (id)videoQualitySwitchControllerWithParentResponder:(id)responder {
|
||||
Class originalClass = %c(YTVideoQualitySwitchOriginalController);
|
||||
if (kClassicQuality) {
|
||||
return originalClass ? [[originalClass alloc] initWithParentResponder:responder] : %orig;
|
||||
} return %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
// Disable Snap To Chapter (https://github.com/qnblackcat/uYouPlus/blob/main/uYouPlus.xm#L457-464)
|
||||
%hook YTSegmentableInlinePlayerBarView
|
||||
- (void)didMoveToWindow { %orig; if (kDontSnapToChapter) self.enableSnapToChapter = NO; }
|
||||
%end
|
||||
|
||||
// Red Progress Bar and Gray Buffer Progress
|
||||
%hook YTInlinePlayerBarContainerView
|
||||
- (id)quietProgressBarColor { return kRedProgressBar ? [UIColor redColor] : %orig; }
|
||||
%end
|
||||
|
||||
%hook YTSegmentableInlinePlayerBarView
|
||||
- (void)setBufferedProgressBarColor:(id)arg1 { if (kNoRelatedVids) %orig([UIColor colorWithRed:0.65 green:0.65 blue:0.65 alpha:0.60]); }
|
||||
%end
|
||||
|
||||
// Disable Hints
|
||||
%hook YTSettings
|
||||
- (BOOL)areHintsDisabled { return kNoHints ? YES : NO; }
|
||||
- (void)setHintsDisabled:(BOOL)arg1 { kNoHints ? %orig(YES) : %orig; }
|
||||
%end
|
||||
|
||||
%hook YTUserDefaults
|
||||
- (BOOL)areHintsDisabled { return kNoHints ? YES : NO; }
|
||||
- (void)setHintsDisabled:(BOOL)arg1 { kNoHints ? %orig(YES) : %orig; }
|
||||
%end
|
||||
|
||||
// Exit Fullscreen on Finish
|
||||
%hook YTWatchFlowController
|
||||
- (BOOL)shouldExitFullScreenOnFinish { return kExitFullscreen ? YES : NO; }
|
||||
%end
|
||||
|
||||
// Disable Double Tap To Seek
|
||||
%hook YTDoubleTapToSeekController
|
||||
- (void)enableDoubleTapToSeek:(BOOL)arg1 { kNoDoubleTapToSeek ? %orig(NO) : %orig; }
|
||||
%end
|
||||
|
||||
// Remove Shorts (https://github.com/MiRO92/YTNoShorts)
|
||||
%hook YTAsyncCollectionView
|
||||
- (id)cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (kHideShorts) {
|
||||
UICollectionViewCell *cell = %orig;
|
||||
if ([cell isKindOfClass:NSClassFromString(@"_ASCollectionViewCell")]) {
|
||||
_ASCollectionViewCell *cell = %orig;
|
||||
if ([cell respondsToSelector:@selector(node)]) {
|
||||
if ([[[cell node] accessibilityIdentifier] isEqualToString:@"eml.shorts-shelf"]) {
|
||||
[self removeShortsCellAtIndexPath:indexPath];
|
||||
}
|
||||
}
|
||||
} else if ([cell isKindOfClass:NSClassFromString(@"YTReelShelfCell")]) {
|
||||
[self removeShortsCellAtIndexPath:indexPath];
|
||||
} return %orig;
|
||||
} return %orig;
|
||||
}
|
||||
|
||||
%new
|
||||
- (void)removeShortsCellAtIndexPath:(NSIndexPath *)indexPath {
|
||||
[self deleteItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
|
||||
}
|
||||
%end
|
||||
|
||||
// Shorts Progress Bar (https://github.com/PoomSmart/YTShortsProgress)
|
||||
%hook YTReelPlayerViewController
|
||||
- (BOOL)shouldEnablePlayerBar { return kShortsProgress ? YES : NO; }
|
||||
- (BOOL)shouldAlwaysEnablePlayerBar { return kShortsProgress ? YES : NO; }
|
||||
- (BOOL)shouldEnablePlayerBarOnlyOnPause { return kShortsProgress ? NO : YES; }
|
||||
%end
|
||||
|
||||
%hook YTReelPlayerViewControllerSub
|
||||
- (BOOL)shouldEnablePlayerBar { return kShortsProgress ? YES : NO; }
|
||||
- (BOOL)shouldAlwaysEnablePlayerBar { return kShortsProgress ? YES : NO; }
|
||||
- (BOOL)shouldEnablePlayerBarOnlyOnPause { return kShortsProgress ? NO : YES; }
|
||||
%end
|
||||
|
||||
%hook YTColdConfig
|
||||
- (BOOL)iosEnableVideoPlayerScrubber { return kShortsProgress ? YES : NO; }
|
||||
- (BOOL)mobileShortsTabInlined { return kShortsProgress ? YES : NO; }
|
||||
%end
|
||||
|
||||
%hook YTHotConfig
|
||||
- (BOOL)enablePlayerBarForVerticalVideoWhenControlsHiddenInFullscreen { return kShortsProgress ? YES : NO; }
|
||||
%end
|
||||
|
||||
// Dont Startup Shorts
|
||||
%hook YTShortsStartupCoordinator
|
||||
- (id)evaluateResumeToShorts { return kResumeShorts ? nil : %orig; }
|
||||
%end
|
||||
|
||||
// Hide Shorts Elements
|
||||
%hook YTReelPausedStateCarouselView
|
||||
- (void)setPausedStateCarouselVisible:(BOOL)arg1 animated:(BOOL)arg2 { kHideShortsSubscriptions ? %orig(arg1 = NO, arg2) : %orig; }
|
||||
%end
|
||||
|
||||
%hook YTReelWatchPlaybackOverlayView
|
||||
- (void)setReelLikeButton:(id)arg1 { if (!kHideShortsLike) %orig; }
|
||||
- (void)setReelDislikeButton:(id)arg1 { if (!kHideShortsDislike) %orig; }
|
||||
- (void)setViewCommentButton:(id)arg1 { if (!kHideShortsComments) %orig; }
|
||||
- (void)setRemixButton:(id)arg1 { if (!kHideShortsRemix) %orig; }
|
||||
- (void)setShareButton:(id)arg1 { if (!kHideShortsShare) %orig; }
|
||||
- (void)layoutSubviews {
|
||||
%orig;
|
||||
|
||||
for (UIView *subview in self.subviews) {
|
||||
if (kHideShortsAvatars && [NSStringFromClass([subview class]) isEqualToString:@"YTELMView"]) {
|
||||
subview.hidden = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTReelHeaderView
|
||||
- (void)setTitleLabelVisible:(BOOL)arg1 animated:(BOOL)arg2 { kHideShortsLogo ? %orig(arg1 = NO, arg2) : %orig; }
|
||||
%end
|
||||
|
||||
%hook YTReelTransparentStackView
|
||||
- (void)layoutSubviews {
|
||||
%orig;
|
||||
if (kHideShortsSearch && self.subviews.count >= 3 && [self.subviews[0].accessibilityIdentifier isEqualToString:@"id.ui.generic.button"]) self.subviews[0].hidden = YES;
|
||||
if (kHideShortsCamera && self.subviews.count >= 3 && [self.subviews[1].accessibilityIdentifier isEqualToString:@"id.ui.generic.button"]) self.subviews[1].hidden = YES;
|
||||
if (kHideShortsMore && self.subviews.count >= 3 && [self.subviews[2].accessibilityIdentifier isEqualToString:@"id.ui.generic.button"]) self.subviews[2].hidden = YES;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTReelWatchHeaderView
|
||||
- (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;
|
||||
if (kHideShortsChannelName) self.subviews[self.subviews.count - 2].hidden = YES;
|
||||
if (kHideShortsAudioTrack) self.subviews.lastObject.hidden = YES;
|
||||
}
|
||||
%end
|
||||
|
||||
// Remove Tabs
|
||||
%hook YTPivotBarView
|
||||
- (void)setRenderer:(YTIPivotBarRenderer *)renderer {
|
||||
NSMutableArray <YTIPivotBarSupportedRenderers *> *items = [renderer itemsArray];
|
||||
|
||||
NSDictionary *identifiersToRemove = @{
|
||||
@"FEshorts": @(kRemoveShorts),
|
||||
@"FEsubscriptions": @(kRemoveSubscriptions),
|
||||
@"FEuploads": @(kRemoveUploads),
|
||||
@"FElibrary": @(kRemoveLibrary)
|
||||
};
|
||||
|
||||
for (NSString *identifier in identifiersToRemove) {
|
||||
BOOL shouldRemoveItem = [identifiersToRemove[identifier] boolValue];
|
||||
NSUInteger index = [items indexOfObjectPassingTest:^BOOL(YTIPivotBarSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) {
|
||||
if ([identifier isEqualToString:@"FEuploads"]) {
|
||||
return shouldRemoveItem && [[[renderers pivotBarIconOnlyItemRenderer] pivotIdentifier] isEqualToString:identifier];
|
||||
} else {
|
||||
return shouldRemoveItem && [[[renderers pivotBarItemRenderer] pivotIdentifier] isEqualToString:identifier];
|
||||
}
|
||||
}];
|
||||
|
||||
if (index != NSNotFound) {
|
||||
[items removeObjectAtIndex:index];
|
||||
}
|
||||
} %orig;
|
||||
}
|
||||
%end
|
||||
|
||||
// Replace Shorts with Explore tab (https://github.com/PoomSmart/YTReExplore)
|
||||
static void replaceTab(YTIGuideResponse *response) {
|
||||
NSMutableArray <YTIGuideResponseSupportedRenderers *> *renderers = [response itemsArray];
|
||||
for (YTIGuideResponseSupportedRenderers *guideRenderers in renderers) {
|
||||
YTIPivotBarRenderer *pivotBarRenderer = [guideRenderers pivotBarRenderer];
|
||||
NSMutableArray <YTIPivotBarSupportedRenderers *> *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:LOC(@"Explore") iconType:292];
|
||||
[items insertObject:exploreTab atIndex:1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
%hook YTGuideServiceCoordinator
|
||||
- (void)handleResponse:(YTIGuideResponse *)response withCompletion:(id)completion {
|
||||
if (kReExplore) replaceTab(response);
|
||||
%orig(response, completion);
|
||||
}
|
||||
- (void)handleResponse:(YTIGuideResponse *)response error:(id)error completion:(id)completion {
|
||||
if (kReExplore) replaceTab(response);
|
||||
%orig(response, error, completion);
|
||||
}
|
||||
%end
|
||||
|
||||
// Hide Tab Labels
|
||||
BOOL hasHomeBar = NO;
|
||||
CGFloat pivotBarViewHeight;
|
||||
|
||||
%hook YTPivotBarView
|
||||
- (void)layoutSubviews {
|
||||
%orig;
|
||||
pivotBarViewHeight = self.frame.size.height;
|
||||
}
|
||||
%end
|
||||
|
||||
%hook YTPivotBarItemView
|
||||
- (void)layoutSubviews {
|
||||
%orig;
|
||||
|
||||
CGFloat pivotBarAccessibilityControlWidth;
|
||||
|
||||
if (kRemoveLabels) {
|
||||
for (UIView *subview in self.subviews) {
|
||||
if ([subview isKindOfClass:objc_lookUpClass("YTPivotBarItemViewAccessibilityControl")]) {
|
||||
pivotBarAccessibilityControlWidth = CGRectGetWidth(subview.frame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (UIView *subview in self.subviews) {
|
||||
if ([subview isKindOfClass:objc_lookUpClass("YTQTMButton")]) {
|
||||
for (UIView *buttonSubview in subview.subviews) {
|
||||
if ([buttonSubview isKindOfClass:[UILabel class]]) {
|
||||
[buttonSubview removeFromSuperview];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UIImageView *imageView = nil;
|
||||
for (UIView *buttonSubview in subview.subviews) {
|
||||
if ([buttonSubview isKindOfClass:[UIImageView class]]) {
|
||||
imageView = (UIImageView *)buttonSubview;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (imageView) {
|
||||
CGFloat imageViewHeight = imageView.image.size.height;
|
||||
CGFloat imageViewWidth = imageView.image.size.width;
|
||||
CGRect buttonFrame = subview.frame;
|
||||
|
||||
if (@available(iOS 13.0, *)) {
|
||||
UIWindowScene *mainWindowScene = (UIWindowScene *)[[[UIApplication sharedApplication] connectedScenes] anyObject];
|
||||
if (mainWindowScene) {
|
||||
UIEdgeInsets safeAreaInsets = mainWindowScene.windows.firstObject.safeAreaInsets;
|
||||
if (safeAreaInsets.bottom > 0) {
|
||||
hasHomeBar = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CGFloat yOffset = hasHomeBar ? 15.0 : 0.0;
|
||||
CGFloat xOffset = (pivotBarAccessibilityControlWidth - imageViewWidth) / 2.0;
|
||||
|
||||
buttonFrame.origin.y = (pivotBarViewHeight - imageViewHeight - yOffset) / 2.0;
|
||||
buttonFrame.origin.x = xOffset;
|
||||
|
||||
buttonFrame.size.height = imageViewHeight;
|
||||
buttonFrame.size.width = imageViewWidth;
|
||||
|
||||
subview.frame = buttonFrame;
|
||||
subview.bounds = CGRectMake(0, 0, imageViewWidth, imageViewHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
%end
|
||||
|
||||
// Startup Tab
|
||||
BOOL isTabSelected = NO;
|
||||
%hook YTPivotBarViewController
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
%orig();
|
||||
|
||||
if (!isTabSelected) {
|
||||
NSString *pivotIdentifier;
|
||||
switch (kPivotIndex) {
|
||||
case 0:
|
||||
pivotIdentifier = @"FEwhat_to_watch";
|
||||
break;
|
||||
case 1:
|
||||
pivotIdentifier = @"FEshorts";
|
||||
break;
|
||||
case 2:
|
||||
pivotIdentifier = @"FEsubscriptions";
|
||||
break;
|
||||
case 3:
|
||||
pivotIdentifier = @"FElibrary";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
[self selectItemWithPivotIdentifier:pivotIdentifier];
|
||||
isTabSelected = YES;
|
||||
}
|
||||
}
|
||||
%end
|
||||
|
||||
static void reloadPrefs() {
|
||||
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"YTLite.plist"];
|
||||
NSDictionary *prefs = [NSDictionary dictionaryWithContentsOfFile:path];
|
||||
|
||||
kNoAds = (prefs[@"noAds"] != nil) ? [prefs[@"noAds"] boolValue] : YES;
|
||||
kBackgroundPlayback = (prefs[@"backgroundPlayback"] != nil) ? [prefs[@"backgroundPlayback"] boolValue] : YES;
|
||||
kNoCast = [prefs[@"noCast"] boolValue] ?: NO;
|
||||
kNoNotifsButton = [prefs[@"removeNotifsButton"] boolValue] ?: NO;
|
||||
kNoSearchButton = [prefs[@"removeSearchButton"] boolValue] ?: NO;
|
||||
kStickyNavbar = [prefs[@"stickyNavbar"] boolValue] ?: NO;
|
||||
kNoSubbar = [prefs[@"noSubbar"] boolValue] ?: NO;
|
||||
kNoYTLogo = [prefs[@"noYTLogo"] boolValue] ?: NO;
|
||||
kHideAutoplay = [prefs[@"hideAutoplay"] boolValue] ?: NO;
|
||||
kHideSubs = [prefs[@"hideSubs"] boolValue] ?: NO;
|
||||
kNoHUDMsgs = [prefs[@"noHUDMsgs"] boolValue] ?: NO;
|
||||
kHidePrevNext = [prefs[@"hidePrevNext"] boolValue] ?: NO;
|
||||
kReplacePrevNext = [prefs[@"replacePrevNext"] boolValue] ?: NO;
|
||||
kNoDarkBg = [prefs[@"noDarkBg"] boolValue] ?: NO;
|
||||
kEndScreenCards = [prefs[@"endScreenCards"] boolValue] ?: NO;
|
||||
kNoFullscreenActions = [prefs[@"noFullscreenActions"] boolValue] ?: NO;
|
||||
kNoRelatedVids = [prefs[@"noRelatedVids"] boolValue] ?: NO;
|
||||
kNoPromotionCards = [prefs[@"noPromotionCards"] boolValue] ?: NO;
|
||||
kNoWatermarks = [prefs[@"noWatermarks"] boolValue] ?: NO;
|
||||
kMiniplayer = [prefs[@"miniplayer"] boolValue] ?: NO;
|
||||
kDisableAutoplay = [prefs[@"disableAutoplay"] boolValue] ?: NO;
|
||||
kNoContentWarning = [prefs[@"noContentWarning"] boolValue] ?: NO;
|
||||
kClassicQuality = [prefs[@"classicQuality"] boolValue] ?: NO;
|
||||
kDontSnapToChapter = [prefs[@"dontSnapToChapter"] boolValue] ?: NO;
|
||||
kRedProgressBar = [prefs[@"redProgressBar"] boolValue] ?: NO;
|
||||
kNoHints = [prefs[@"noHints"] boolValue] ?: NO;
|
||||
kNoFreeZoom = [prefs[@"noFreeZoom"] boolValue] ?: NO;
|
||||
kExitFullscreen = [prefs[@"exitFullscreen"] boolValue] ?: NO;
|
||||
kNoDoubleTapToSeek = [prefs[@"noDoubleTapToSeek"] boolValue] ?: NO;
|
||||
kHideShorts = [prefs[@"hideShorts"] boolValue] ?: NO;
|
||||
kShortsProgress = [prefs[@"shortsProgress"] boolValue] ?: NO;
|
||||
kResumeShorts = [prefs[@"resumeShorts"] boolValue] ?: NO;
|
||||
kHideShortsLogo = [prefs[@"hideShortsLogo"] boolValue] ?: NO;
|
||||
kHideShortsSearch = [prefs[@"hideShortsSearch"] boolValue] ?: NO;
|
||||
kHideShortsCamera = [prefs[@"hideShortsCamera"] boolValue] ?: NO;
|
||||
kHideShortsMore = [prefs[@"hideShortsMore"] boolValue] ?: NO;
|
||||
kHideShortsSubscriptions = [prefs[@"hideShortsSubscriptions"] boolValue] ?: NO;
|
||||
kHideShortsLike = [prefs[@"hideShortsLike"] boolValue] ?: NO;
|
||||
kHideShortsDislike = [prefs[@"hideShortsDislike"] boolValue] ?: NO;
|
||||
kHideShortsComments = [prefs[@"hideShortsComments"] boolValue] ?: NO;
|
||||
kHideShortsRemix = [prefs[@"hideShortsRemix"] boolValue] ?: NO;
|
||||
kHideShortsShare = [prefs[@"hideShortsShare"] boolValue] ?: NO;
|
||||
kHideShortsAvatars = [prefs[@"hideShortsAvatars"] boolValue] ?: NO;
|
||||
kHideShortsThanks = [prefs[@"hideShortsThanks"] boolValue] ?: NO;
|
||||
kHideShortsChannelName = [prefs[@"hideShortsChannelName"] boolValue] ?: NO;
|
||||
kHideShortsDescription = [prefs[@"hideShortsDescription"] boolValue] ?: NO;
|
||||
kHideShortsAudioTrack = [prefs[@"hideShortsAudioTrack"] boolValue] ?: NO;
|
||||
kRemoveLabels = [prefs[@"removeLabels"] boolValue] ?: NO;
|
||||
kReExplore = [prefs[@"reExplore"] boolValue] ?: NO;
|
||||
kRemoveShorts = [prefs[@"removeShorts"] boolValue] ?: NO;
|
||||
kRemoveSubscriptions = [prefs[@"removeSubscriptions"] boolValue] ?: NO;
|
||||
kRemoveUploads = (prefs[@"removeUploads"] != nil) ? [prefs[@"removeUploads"] boolValue] : YES;
|
||||
kRemoveLibrary = [prefs[@"removeLibrary"] boolValue] ?: NO;
|
||||
kPivotIndex = (prefs[@"pivotIndex"] != nil) ? [prefs[@"pivotIndex"] intValue] : 0;
|
||||
kAdvancedMode = [prefs[@"advancedMode"] boolValue] ?: NO;
|
||||
|
||||
NSDictionary *newSettings = @{
|
||||
@"noAds" : @(kNoAds),
|
||||
@"backgroundPlayback" : @(kBackgroundPlayback),
|
||||
@"noCast" : @(kNoCast),
|
||||
@"removeNotifsButton" : @(kNoNotifsButton),
|
||||
@"removeSearchButton" : @(kNoSearchButton),
|
||||
@"stickyNavbar" : @(kStickyNavbar),
|
||||
@"noSubbar" : @(kNoSubbar),
|
||||
@"noYTLogo" : @(kNoYTLogo),
|
||||
@"hideAutoplay" : @(kHideAutoplay),
|
||||
@"hideSubs" : @(kHideSubs),
|
||||
@"noHUDMsgs" : @(kNoHUDMsgs),
|
||||
@"hidePrevNext" : @(kHidePrevNext),
|
||||
@"replacePrevNext" : @(kReplacePrevNext),
|
||||
@"noDarkBg" : @(kNoDarkBg),
|
||||
@"endScreenCards" : @(kEndScreenCards),
|
||||
@"noFullscreenActions" : @(kNoFullscreenActions),
|
||||
@"noRelatedVids" : @(kNoRelatedVids),
|
||||
@"noPromotionCards" : @(kNoPromotionCards),
|
||||
@"noWatermarks" : @(kNoWatermarks),
|
||||
@"miniplayer" : @(kMiniplayer),
|
||||
@"disableAutoplay" : @(kDisableAutoplay),
|
||||
@"noContentWarning" : @(kNoContentWarning),
|
||||
@"classicQuality" : @(kClassicQuality),
|
||||
@"dontSnapToChapter" : @(kDontSnapToChapter),
|
||||
@"redProgressBar" : @(kRedProgressBar),
|
||||
@"noHints" : @(kNoHints),
|
||||
@"noFreeZoom" : @(kNoFreeZoom),
|
||||
@"exitFullscreen" : @(kExitFullscreen),
|
||||
@"noDoubleTapToSeek" : @(kNoDoubleTapToSeek),
|
||||
@"hideShorts" : @(kHideShorts),
|
||||
@"shortsProgress" : @(kShortsProgress),
|
||||
@"resumeShorts" : @(kResumeShorts),
|
||||
@"hideShortsLogo" : @(kHideShortsLogo),
|
||||
@"hideShortsSearch" : @(kHideShortsSearch),
|
||||
@"hideShortsCamera" : @(kHideShortsCamera),
|
||||
@"hideShortsMore" : @(kHideShortsMore),
|
||||
@"hideShortsSubscriptions" : @(kHideShortsSubscriptions),
|
||||
@"hideShortsLike" : @(kHideShortsLike),
|
||||
@"hideShortsDislike" : @(kHideShortsDislike),
|
||||
@"hideShortsComments" : @(kHideShortsComments),
|
||||
@"hideShortsRemix" : @(kHideShortsRemix),
|
||||
@"hideShortsShare" : @(kHideShortsShare),
|
||||
@"hideShortsAvatars" : @(kHideShortsAvatars),
|
||||
@"hideShortsThanks" : @(kHideShortsThanks),
|
||||
@"hideShortsChannelName" : @(kHideShortsChannelName),
|
||||
@"hideShortsDescription" : @(kHideShortsDescription),
|
||||
@"hideShortsAudioTrack" : @(kHideShortsAudioTrack),
|
||||
@"removeLabels" : @(kRemoveLabels),
|
||||
@"reExplore" : @(kReExplore),
|
||||
@"removeShorts" : @(kRemoveShorts),
|
||||
@"removeSubscriptions" : @(kRemoveSubscriptions),
|
||||
@"removeUploads" : @(kRemoveUploads),
|
||||
@"removeLibrary" : @(kRemoveLibrary),
|
||||
@"pivotIndex" : @(kPivotIndex),
|
||||
@"advancedMode" : @(kAdvancedMode)
|
||||
};
|
||||
|
||||
if (![newSettings isEqualToDictionary:prefs]) [newSettings writeToFile:path atomically:NO];
|
||||
}
|
||||
|
||||
static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
|
||||
reloadPrefs();
|
||||
}
|
||||
|
||||
%ctor {
|
||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.dvntm.ytlite.prefschanged"), NULL, CFNotificationSuspensionBehaviorCoalesce);
|
||||
reloadPrefs();
|
||||
}
|
9
Tweaks/YTLite/control
Normal file
9
Tweaks/YTLite/control
Normal file
@@ -0,0 +1,9 @@
|
||||
Package: com.dvntm.ytlite
|
||||
Name: YTLite
|
||||
Depends: mobilesubstrate
|
||||
Version: 0.0.1
|
||||
Architecture: iphoneos-arm
|
||||
Description: Lightweight YouTube Enhancer
|
||||
Maintainer: dvntm
|
||||
Author: dvntm
|
||||
Section: Tweaks
|
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.dvntm.ytlite</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>YTLite</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>YTLite</string>
|
||||
</dict>
|
||||
</plist>
|
@@ -0,0 +1,136 @@
|
||||
"General" = "General";
|
||||
"RemoveAds" = "Remove ads";
|
||||
"RemoveAdsDesc" = "Removes in-app ads.";
|
||||
"BackgroundPlayback" = "Background playback";
|
||||
"BackgroundPlaybackDesc" = "Enables background playback.";
|
||||
|
||||
"Navbar" = "Navigation bar";
|
||||
"RemoveCast" = "Hide Cast button";
|
||||
"RemoveCastDesc" = "Hides Cast button from the Navigation bar.";
|
||||
"RemoveNotifications" = "Hide Notifications button";
|
||||
"RemoveNotificationsDesc" = "Hides Notifications button from the Navigation bar.";
|
||||
"RemoveSearch" = "Hide Search button";
|
||||
"RemoveSearchDesc" = "Hides Search button from the Navigation bar.";
|
||||
"StickyNavbar" = "Sticky Navigation bar";
|
||||
"StickyNavbarDesc" = "Pins the Navigation bar so that it remains visible when scrolling down.";
|
||||
"NoSubbar" = "Hide Subbar";
|
||||
"NoSubbarDesc" = "Hides Subbar (All, New to you, Live etc.) under the Navigation bar.";
|
||||
"NoYTLogo" = "Remove YouTube logo";
|
||||
"NoYTLogoDesc" = "Removes YouTube logo in the Navigation bar.";
|
||||
|
||||
"Overlay" = "Overlay";
|
||||
"HideAutoplay" = "Hide Autoplay switch";
|
||||
"HideAutoplayDesc" = "Hides Autoplay switch from the overlay.";
|
||||
"HideSubs" = "Hide Subtitles button";
|
||||
"HideSubsDesc" = "Hides Subtitles button from the overlay.";
|
||||
"NoHUDMsgs" = "Hide HUD Messages";
|
||||
"NoHUDMsgsDesc" = "Hides all feature messages from the player. Example: CC is turned on/off, Video loop is on, etc.";
|
||||
"HidePrevNext" = "Hide Previous and Next buttons";
|
||||
"HidePrevNextDesc" = "Hides Previous and Next video buttons from overlay.";
|
||||
"ReplacePrevNext" = "Fast forward and Rewind buttons";
|
||||
"ReplacePrevNextDesc" = "Replaces Previous and Next video buttons to Fast forward and Rewind buttons in overlay.";
|
||||
"NoDarkBg" = "Remove dark background";
|
||||
"NoDarkBgDesc" = "Removes overlay dark background.";
|
||||
"NoEndScreenCards" = "Hide End screens hover cards";
|
||||
"NoEndScreenCardsDesc" = "Hides End screens (thumbnails) at the end of videos.";
|
||||
"NoFullscreenActions" = "Disable fullscreen actions";
|
||||
"NoFullscreenActionsDesc" = "Disables actions panel in fullscreen mode.";
|
||||
"NoRelatedVids" = "No related videos in overlay";
|
||||
"NoRelatedVidsDesc" = "Removes related videos displayed in the overlay by swiping up.";
|
||||
"NoPromotionCards" = "Hide Paid Promotion cards";
|
||||
"NoPromotionCardsDesc" = "Hides \"Includes Paid Promotions\" card in promotions included videos.";
|
||||
"NoWatermarks" = "Hide Watermarks";
|
||||
"NoWatermarksDesc" = "Hides channel watermarks from the player.";
|
||||
|
||||
"Player" = "Player";
|
||||
"Miniplayer" = "Enable mini player";
|
||||
"MiniplayerDesc" = "Enables the mini player for videos that were not originally designed for it, such as videos targeted for children.";
|
||||
"DisableAutoplay" = "Disable Autoplay videos";
|
||||
"DisableAutoplayDesc" = "Prevents video playback after opening.";
|
||||
"NoContentWarning" = "Skip content warning";
|
||||
"NoContentWarningDesc" = "Skips sensitive content warning message.";
|
||||
"ClassicQuality" = "Classic video quality";
|
||||
"ClassicQualityDesc" = "Brings back classic video quality selection menu.";
|
||||
"DontSnap2Chapter" = "Disable snap to chapter";
|
||||
"DontSnap2ChapterDesc" = "Disables skipping to the next episode by double-tap gesture.";
|
||||
"RedProgressBar" = "Red progress bar";
|
||||
"RedProgressBarDesc" = "Brings back red progress bar.";
|
||||
"NoHints" = "Disable hints";
|
||||
"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.";
|
||||
"ExitFullscreen" = "Exit fullscreen mode on finish";
|
||||
"ExitFullscreenDesc" = "Exits fullscreen mode at the end of video playback.";
|
||||
"NoDoubleTap2Seek" = "Disable double tap to seek";
|
||||
"NoDoubleTap2SeekDesc" = "Disables double tap to seek gesture.";
|
||||
|
||||
"Tabbar" = "Tab bar";
|
||||
"RemoveLabels" = "Remove labels";
|
||||
"RemoveLabelsDesc" = "Removes tab labels.";
|
||||
"ReExplore" = "Replace Shorts tab with Explore tab";
|
||||
"ReExploreDesc" = "Shows Explore tab instead of Shorts tab as on old YouTube versions.";
|
||||
"HideShortsTab" = "Hide Shorts tab";
|
||||
"HideShortsTabDesc" = "Hides Shorts tab from the Tab bar";
|
||||
"HideSubscriptionsTab" = "Hide Subscriptions tab";
|
||||
"HideSubscriptionsTabDesc" = "Hides Subscriptions tab from the Tab bar";
|
||||
"HideUploadButton" = "Hide Upload button";
|
||||
"HideUploadButtonDesc" = "Hides Upload button from the Tab bar";
|
||||
"HideLibraryTab" = "Hide Library tab";
|
||||
"HideLibraryTabDesc" = "Hides Library tab from the Tab bar";
|
||||
|
||||
"Shorts" = "Shorts";
|
||||
"HideShorts" = "Hide Shorts videos";
|
||||
"HideShortsDesc" = "Hides Shorts videos from Homepage, Recommended etc. (Not applied to Watch history)";
|
||||
"ShortsProgress" = "Enable progress bar";
|
||||
"ShortsProgressDesc" = "Displays progress bar in the Shorts overlay.";
|
||||
"ResumeShorts" = "Don't start from Shorts tab";
|
||||
"ResumeShortsDesc" = "Prevents starting from Shorts videos at the opening app, which happens if YouTube was closed while watching Shorts.";
|
||||
"HideShortsLogo" = "Hide Shorts logo";
|
||||
"HideShortsLogoDesc" = "Hides Shorts logo in the top left corner.";
|
||||
"HideShortsSearch" = "Hide Search button";
|
||||
"HideShortsSearchDesc" = "Hides Search button from the Shorts overlay.";
|
||||
"HideShortsCamera" = "Hide Camera button";
|
||||
"HideShortsCameraDesc" = "Hides Camera button from the Shorts overlay.";
|
||||
"HideShortsMore" = "Hide More (⋮) button";
|
||||
"HideShortsMoreDesc" = "Hides More (⋮) button from the Shorts overlay. It's also accessible by long-pressing the screen.";
|
||||
"HideShortsSubscriptions" = "Hide Subscriptions button";
|
||||
"HideShortsSubscriptionsDesc" = "Hides Subscriptions button which appears when Shorts paused.";
|
||||
"HideShortsLike" = "Hide Like button";
|
||||
"HideShortsLikeDesc" = "Hides Like button from the Shorts overlay.";
|
||||
"HideShortsDislike" = "Hide Dislike button";
|
||||
"HideShortsDislikeDesc" = "Hides Dislike button from the Shorts overlay.";
|
||||
"HideShortsComments" = "Hide Comments button";
|
||||
"HideShortsCommentsDesc" = "Hides Comments button from the Shorts overlay.";
|
||||
"HideShortsRemix" = "Hide Remix button";
|
||||
"HideShortsRemixDesc" = "Hides Remix button from the Shorts overlay.";
|
||||
"HideShortsShare" = "Hide Share button";
|
||||
"HideShortsShareDesc" = "Hides Share button from the Shorts overlay.";
|
||||
"HideShortsAvatars" = "Hide channels avatar";
|
||||
"HideShortsAvatarsDesc" = "Hides profile picture in the bottom right corner.";
|
||||
"HideShortsThanks" = "Hide Superthanks button";
|
||||
"HideShortsThanksDesc" = "Hides Superthanks (Donate) button from the Shorts overlay.";
|
||||
"HideShortsChannelName" = "Hide Channel name";
|
||||
"HideShortsChannelNameDesc" = "Hides Channel name and Subscribe button from the Shorts overlay.";
|
||||
"HideShortsDescription" = "Hide Description";
|
||||
"HideShortsDescriptionDesc" = "Hides Shorts description under channel name.";
|
||||
"HideShortsAudioTrack" = "Hide AudioTrack";
|
||||
"HideShortsAudioTrackDesc" = "Hides AudioTrack under Shorts description.";
|
||||
|
||||
"Startup" = "Startup page";
|
||||
"Home" = "Home";
|
||||
"Explore" = "Explore";
|
||||
"ShortsTab" = "Shorts";
|
||||
"Subscriptions" = "Subscriptions";
|
||||
"Library" = "Library";
|
||||
"Warning" = "Warning";
|
||||
"TabIsHidden" = "Hidden tab cannot be selected as startup page";
|
||||
|
||||
"Version" = "Version";
|
||||
"About" = "About";
|
||||
"Credits" = "Credits";
|
||||
"Developer" = "YTLite developer";
|
||||
"Advanced" = "Advanced mode";
|
||||
"ResetSettings" = "Reset YTLite settings";
|
||||
"ResetMessage" = "This option will reset YTLite settings to default and close YouTube.\n\nAre you sure you want to continue?";
|
||||
"Yes" = "Yes";
|
||||
"No" = "No";
|
@@ -0,0 +1,136 @@
|
||||
"General" = "Основные";
|
||||
"RemoveAds" = "Убрать рекламу";
|
||||
"RemoveAdsDesc" = "Убирает рекламу в приложении.";
|
||||
"BackgroundPlayback" = "Фоновое воспроизведение";
|
||||
"BackgroundPlaybackDesc" = "Активирует фоновое воспроизведение.";
|
||||
|
||||
"Navbar" = "Панель навигации";
|
||||
"RemoveCast" = "Скрыть «Трансляция»";
|
||||
"RemoveCastDesc" = "Скрывает кнопку трансляции с панели навигации.";
|
||||
"RemoveNotifications" = "Скрыть «Уведомления»";
|
||||
"RemoveNotificationsDesc" = "Скрывает кнопку уведомлений с панели навигации.";
|
||||
"RemoveSearch" = "Скрыть «Поиск»";
|
||||
"RemoveSearchDesc" = "Скрвыает кнопку поиска с панели навигации.";
|
||||
"StickyNavbar" = "Закрепить панель навигации";
|
||||
"StickyNavbarDesc" = "Закрепляет панель навигации в верхней части экрана, запрещая ему скрываться во время скролла страницы вниз.";
|
||||
"NoSubbar" = "Скрыть наклейки";
|
||||
"NoSubbarDesc" = "Скрывает панель с наклейками (Все, Новое для вас, Сейчас в эфире и т.д.) под панелью навигации.";
|
||||
"NoYTLogo" = "Скрыть логотип YouTube";
|
||||
"NoYTLogoDesc" = "Убирает логотип YouTube с панели навигации.";
|
||||
|
||||
"Overlay" = "Настройки оверлея";
|
||||
"HideAutoplay" = "Скрыть «Автовоспроизведение»";
|
||||
"HideAutoplayDesc" = "Скрывает тумблер «Автовоспроизведение» с оверлея плеера.";
|
||||
"HideSubs" = "Скрыть «Субтитры»";
|
||||
"HideSubsDesc" = "Скрывает кнопку субтитров с оверлея плеера.";
|
||||
"NoHUDMsgs" = "Скрыть сообщения плеера";
|
||||
"NoHUDMsgsDesc" = "Скрывает надписи YouTube, появляющиеся поверх видео.";
|
||||
"HidePrevNext" = "Скрыть «След.» и «Пред.»";
|
||||
"HidePrevNextDesc" = "Убирает переключатели «Следующий» и «Предыдущий» с плеера";
|
||||
"ReplacePrevNext" = "Перемотка вместо «След.» и «Пред.»";
|
||||
"ReplacePrevNextDesc" = "Заменяет переключатели «Следующий» и «Предыдущий» на перемотку на 10 сек. в окне плеера.";
|
||||
"NoDarkBg" = "Не затемнять фон плеера";
|
||||
"NoDarkBgDesc" = "Убирает затемнение экрана под кнопками управления плеером.";
|
||||
"NoEndScreenCards" = "Скрыть рекомендации";
|
||||
"NoEndScreenCardsDesc" = "Скрывает эскизы, отображаемые по окончанию видеоролика.";
|
||||
"NoFullscreenActions" = "Отключить панель действий";
|
||||
"NoFullscreenActionsDesc" = "Отключает панель действий, отображающуюся под прогресс-баром плеера.";
|
||||
"NoRelatedVids" = "Скрыть рекомендации в оверлее";
|
||||
"NoRelatedVidsDesc" = "Скрывает рекомендации, отображаемые по свайпу вверх в плеере.";
|
||||
"NoPromotionCards" = "Скрыть сообщение «Есть реклама»";
|
||||
"NoPromotionCardsDesc" = "Скрывает всплывающее сообщение «Есть реклама» в роликах со спонсорской рекламой.";
|
||||
"NoWatermarks" = "Скрыть водяные знаки";
|
||||
"NoWatermarksDesc" = "Скрывает значки каналов в плеере.";
|
||||
|
||||
"Player" = "Настройки плеера";
|
||||
"Miniplayer" = "Разрешить миниплеер";
|
||||
"MiniplayerDesc" = "Принудительно активирует миниплеер для видео, в которых изначально не был предназначен (например, видеоролики для детей).";
|
||||
"DisableAutoplay" = "Запретить автовоспроизведение";
|
||||
"DisableAutoplayDesc" = "Принудительно запрещает автовоспроизведение видео при его открытии.";
|
||||
"NoContentWarning" = "Пропускать предупреждения";
|
||||
"NoContentWarningDesc" = "Пропускает предупреждения, всплывающие перед воспроизведением некоторого контента.";
|
||||
"ClassicQuality" = "Классический выбор качества";
|
||||
"ClassicQualityDesc" = "Возвращает классическое меню выбора качества в меню плеера.";
|
||||
"DontSnap2Chapter" = "Не перематывать эпизоды";
|
||||
"DontSnap2ChapterDesc" = "Отключает жест перемотки к следующему эпизоду двойным нажатием.";
|
||||
"RedProgressBar" = "Красный прогресс-бар";
|
||||
"RedProgressBarDesc" = "Возвращает красный прогресс-бар вместо нового, серого цвета.";
|
||||
"NoHints" = "Отключить подсказки";
|
||||
"NoHintsDesc" = "Скрывает подсказки от авторов видео, появляющиеся в правом верхнем углу.";
|
||||
"NoFreeZoom" = "Отключить жесты для зума";
|
||||
"NoFreeZoomDesc" = "Отключает жесты приближения для нового зума.";
|
||||
"ExitFullscreen" = "Автовыход из полноэкранного режима";
|
||||
"ExitFullscreenDesc" = "Выходит из полноэкранного режима по окончанию воспроизведения.";
|
||||
"NoDoubleTap2Seek" = "Отключить перемотку двойным тапом";
|
||||
"NoDoubleTap2SeekDesc" = "Отключает перемотку двойным тапом в плеере.";
|
||||
|
||||
"Tabbar" = "Панель вкладок";
|
||||
"RemoveLabels" = "Скрыть названия";
|
||||
"RemoveLabelsDesc" = "Скрывает названия вкладок.";
|
||||
"ReExplore" = "Вкладка «Навигация» вместо «Shorts»";
|
||||
"ReExploreDesc" = "Заменяет вкладку «Shorts» на привычную нам «Навигацию».";
|
||||
"HideShortsTab" = "Скрыть «Shorts»";
|
||||
"HideShortsTabDesc" = "Скрывает вкладку «Shorts» с панели вкладок.";
|
||||
"HideSubscriptionsTab" = "Скрыть «Подписки»";
|
||||
"HideSubscriptionsTabDesc" = "Скрывает вкладку «Подписки» с панели вкладок.";
|
||||
"HideUploadButton" = "Скрыть «Создать» (+)";
|
||||
"HideUploadButtonDesc" = "Скрывает кнопку «Создать» с панели вкладок.";
|
||||
"HideLibraryTab" = "Скрыть «Библиотеку»";
|
||||
"HideLibraryTabDesc" = "Скрывает вкладку «Библиотека» с панели вкладок.";
|
||||
|
||||
"Shorts" = "Настройки Shorts";
|
||||
"HideShorts" = "Скрыть видеоролики Shorts";
|
||||
"HideShortsDesc" = "Скрывает видеоролики, помеченные как Shorts с Главного экрана, Рекомендаций и т.д. (Не применяется к истории просмотров)";
|
||||
"ShortsProgress" = "Показывать прогресс-бар";
|
||||
"ShortsProgressDesc" = "Отображает прогресс-бар в плеере Shorts.";
|
||||
"ResumeShorts" = "Всегда запускать с Главной страницы";
|
||||
"ResumeShortsDesc" = "Предотвращает запуск видеороликов Shorts при открытии YouTube. Это происходит, если закрыть YouTube при просмотре Shorts.";
|
||||
"HideShortsLogo" = "Скрыть логотип Shorts";
|
||||
"HideShortsLogoDesc" = "Скрывает логотип Shorts, расположенный в верхнем левом углу.";
|
||||
"HideShortsSearch" = "Скрыть кнопку «Поиск»";
|
||||
"HideShortsSearchDesc" = "Скрывает кнопку поиска с плеера Shorts.";
|
||||
"HideShortsCamera" = "Скрыть кнопку «Камера»";
|
||||
"HideShortsCameraDesc" = "Скрывает кнопку камеры с плеера Shorts.";
|
||||
"HideShortsMore" = "Скрыть кнопку «⋮»";
|
||||
"HideShortsMoreDesc" = "Скрывает кнопку «Еще» (⋮) с плеера Shorts. Данное меню также доступно долгим нажатием по экрану.";
|
||||
"HideShortsSubscriptions" = "Скрыть «Подписки»";
|
||||
"HideShortsSubscriptionsDesc" = "Скрывает кнопку «Подписки», появляющуюся при остановке воспроизведения.";
|
||||
"HideShortsLike" = "Скрыть кнопку «Лайк»";
|
||||
"HideShortsLikeDesc" = "Скрывает кнопку лайка с плеера Shorts.";
|
||||
"HideShortsDislike" = "Скрыть кнопку «Дизлайк»";
|
||||
"HideShortsDislikeDesc" = "Скрывает кнопку дизлайка с плеера Shorts.";
|
||||
"HideShortsComments" = "Скрыть кнопку «Комментарии»";
|
||||
"HideShortsCommentsDesc" = "Скрывает кнопку комментариев с плеера Shorts.";
|
||||
"HideShortsRemix" = "Скрыть кнопку «Ремикс»";
|
||||
"HideShortsRemixDesc" = "Скрывает кнопку для создания ремикса с плеера Shorts.";
|
||||
"HideShortsShare" = "Скрыть кнопку «Поделиться»";
|
||||
"HideShortsShareDesc" = "Скрывает кнопку поделиться с плеера Shorts.";
|
||||
"HideShortsAvatars" = "Скрыть аватарку";
|
||||
"HideShortsAvatarsDesc" = "Скрывает аватарку пользователя в правом нижнем углу.";
|
||||
"HideShortsThanks" = "Скрыть «Суперспасибо»";
|
||||
"HideShortsThanksDesc" = "Скрывает кнопку отправки доната (суперспасибо) с плеера Shorts.";
|
||||
"HideShortsChannelName" = "Скрыть название канала";
|
||||
"HideShortsChannelNameDesc" = "Скрывает название канала и кнопку «Подписаться» с плеера Shorts.";
|
||||
"HideShortsDescription" = "Скрыть описание ролика";
|
||||
"HideShortsDescriptionDesc" = "Скрывает описание ролика, отображающееся под названием канала.";
|
||||
"HideShortsAudioTrack" = "Скрыть аудиодорожку";
|
||||
"HideShortsAudioTrackDesc" = "Скрывает информацию об аудиодорожке в нижней части плеера.";
|
||||
|
||||
"Startup" = "Начальная страница";
|
||||
"Home" = "Главная";
|
||||
"Explore" = "Навигация";
|
||||
"ShortsTab" = "Shorts";
|
||||
"Subscriptions" = "Подписки";
|
||||
"Library" = "Библиотека";
|
||||
"Warning" = "Внимание";
|
||||
"TabIsHidden" = "Скрытая вкладка не может быть выбрана в качестве начальной страницы";
|
||||
|
||||
"Version" = "Версия";
|
||||
"About" = "О твике";
|
||||
"Credits" = "Авторы";
|
||||
"Developer" = "Разработчик твика";
|
||||
"Advanced" = "Расширенный режим";
|
||||
"ResetSettings" = "Сбросить настройки твика";
|
||||
"ResetMessage" = "Данное действие сбросит настройки YTLite к значениям по умолчанию и закроет YouTube.\n\nУверены, что хотите продолжить?";
|
||||
"Yes" = "Да";
|
||||
"No" = "Нет";
|
@@ -0,0 +1,136 @@
|
||||
"General" = "常规";
|
||||
"RemoveAds" = "移除广告";
|
||||
"RemoveAdsDesc" = "删除程序内的广告";
|
||||
"BackgroundPlayback" = "后台播放";
|
||||
"BackgroundPlaybackDesc" = "启用后台播放";
|
||||
|
||||
"Navbar" = "导航栏";
|
||||
"RemoveCast" = "隐藏投射按钮";
|
||||
"RemoveCastDesc" = "从导航栏中隐藏投射按钮";
|
||||
"RemoveNotifications" = "隐藏通知按钮";
|
||||
"RemoveNotificationsDesc" = "从导航栏中隐藏通知按钮";
|
||||
"RemoveSearch" = "隐藏搜索按钮";
|
||||
"RemoveSearchDesc" = "从导航栏中隐藏搜索按钮";
|
||||
"StickyNavbar" = "Sticky Navigation bar";
|
||||
"StickyNavbarDesc" = "Pins the Navigation bar so that it remains visible when scrolling down.";
|
||||
"NoSubbar" = "Hide Subbar";
|
||||
"NoSubbarDesc" = "Hides Subbar (All, New to you, Live etc.) under the Navigation bar.";
|
||||
"NoYTLogo" = "Remove YouTube logo";
|
||||
"NoYTLogoDesc" = "Removes YouTube logo in the Navigation bar.";
|
||||
|
||||
"Overlay" = "Overlay";
|
||||
"HideAutoplay" = "Hide Autoplay switch";
|
||||
"HideAutoplayDesc" = "Hides Autoplay switch from the overlay.";
|
||||
"HideSubs" = "Hide Subtitles button";
|
||||
"HideSubsDesc" = "Hides Subtitles button from the overlay.";
|
||||
"NoHUDMsgs" = "Hide HUD Messages";
|
||||
"NoHUDMsgsDesc" = "Hides all feature messages from the player. Example: CC is turned on/off, Video loop is on, etc.";
|
||||
"HidePrevNext" = "Hide Previous and Next buttons";
|
||||
"HidePrevNextDesc" = "Hides Previous and Next video buttons from overlay.";
|
||||
"ReplacePrevNext" = "Fast forward and Rewind buttons";
|
||||
"ReplacePrevNextDesc" = "Replaces Previous and Next video buttons to Fast forward and Rewind buttons in overlay.";
|
||||
"NoDarkBg" = "Remove dark background";
|
||||
"NoDarkBgDesc" = "Removes overlay dark background.";
|
||||
"NoEndScreenCards" = "Hide End screens hover cards";
|
||||
"NoEndScreenCardsDesc" = "Hides End screens (thumbnails) at the end of videos.";
|
||||
"NoFullscreenActions" = "Disable fullscreen actions";
|
||||
"NoFullscreenActionsDesc" = "Disables actions panel in fullscreen mode.";
|
||||
"NoRelatedVids" = "No related videos in overlay";
|
||||
"NoRelatedVidsDesc" = "Removes related videos displayed in the overlay by swiping up.";
|
||||
"NoPromotionCards" = "Hide Paid Promotion cards";
|
||||
"NoPromotionCardsDesc" = "Hides \"Includes Paid Promotions\" card in promotions included videos.";
|
||||
"NoWatermarks" = "Hide Watermarks";
|
||||
"NoWatermarksDesc" = "Hides channel watermarks from the player.";
|
||||
|
||||
"Player" = "Player";
|
||||
"Miniplayer" = "Enable mini player";
|
||||
"MiniplayerDesc" = "Enables the mini player for videos that were not originally designed for it, such as videos targeted for children.";
|
||||
"DisableAutoplay" = "Disable Autoplay videos";
|
||||
"DisableAutoplayDesc" = "Prevents video playback after opening.";
|
||||
"NoContentWarning" = "Skip content warning";
|
||||
"NoContentWarningDesc" = "Skips sensitive content warning message.";
|
||||
"ClassicQuality" = "Classic video quality";
|
||||
"ClassicQualityDesc" = "Brings back classic video quality selection menu.";
|
||||
"DontSnap2Chapter" = "Disable snap to chapter";
|
||||
"DontSnap2ChapterDesc" = "Disables skipping to the next episode by double-tap gesture.";
|
||||
"RedProgressBar" = "Red progress bar";
|
||||
"RedProgressBarDesc" = "Brings back red progress bar.";
|
||||
"NoHints" = "Disable hints";
|
||||
"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.";
|
||||
"ExitFullscreen" = "Exit fullscreen mode on finish";
|
||||
"ExitFullscreenDesc" = "Exits fullscreen mode at the end of video playback.";
|
||||
"NoDoubleTap2Seek" = "Disable double tap to seek";
|
||||
"NoDoubleTap2SeekDesc" = "Disables double tap to seek gesture.";
|
||||
|
||||
"Tabbar" = "选项卡栏";
|
||||
"RemoveLabels" = "移除标签";
|
||||
"RemoveLabelsDesc" = "删除选项卡标签";
|
||||
"ReExplore" = "Replace Shorts tab with Explore tab";
|
||||
"ReExploreDesc" = "Shows Explore tab instead of Shorts tab as on old YouTube versions.";
|
||||
"HideShortsTab" = "隐藏短视频";
|
||||
"HideShortsTabDesc" = "从选项卡栏中隐藏短视频";
|
||||
"HideSubscriptionsTab" = "隐藏订阅内容";
|
||||
"HideSubscriptionsTabDesc" = "从选项卡栏中隐藏订阅内容";
|
||||
"HideUploadButton" = "隐藏上传按钮";
|
||||
"HideUploadButtonDesc" = "从选项卡栏中隐藏上传按钮";
|
||||
"HideLibraryTab" = "隐藏媒体库";
|
||||
"HideLibraryTabDesc" = "从选项卡栏中隐藏媒体库";
|
||||
|
||||
"Shorts" = "Shorts";
|
||||
"HideShorts" = "Hide Shorts videos";
|
||||
"HideShortsDesc" = "Hides Shorts videos from Homepage, Recommended etc. (Not applied to Watch history)";
|
||||
"ShortsProgress" = "Enable progress bar";
|
||||
"ShortsProgressDesc" = "Displays progress bar in the Shorts overlay.";
|
||||
"ResumeShorts" = "Don't start from Shorts tab";
|
||||
"ResumeShortsDesc" = "Prevents starting from Shorts videos at the opening app, which happens if YouTube was closed while watching Shorts.";
|
||||
"HideShortsLogo" = "Hide Shorts logo";
|
||||
"HideShortsLogoDesc" = "Hides Shorts logo in the top left corner.";
|
||||
"HideShortsSearch" = "Hide Search button";
|
||||
"HideShortsSearchDesc" = "Hides Search button from the Shorts overlay.";
|
||||
"HideShortsCamera" = "Hide Camera button";
|
||||
"HideShortsCameraDesc" = "Hides Camera button from the Shorts overlay.";
|
||||
"HideShortsMore" = "Hide More (⋮) button";
|
||||
"HideShortsMoreDesc" = "Hides More (⋮) button from the Shorts overlay. It's also accessible by long-pressing the screen.";
|
||||
"HideShortsSubscriptions" = "Hide Subscriptions button";
|
||||
"HideShortsSubscriptionsDesc" = "Hides Subscriptions button which appears when Shorts paused.";
|
||||
"HideShortsLike" = "Hide Like button";
|
||||
"HideShortsLikeDesc" = "Hides Like button from the Shorts overlay.";
|
||||
"HideShortsDislike" = "Hide Dislike button";
|
||||
"HideShortsDislikeDesc" = "Hides Dislike button from the Shorts overlay.";
|
||||
"HideShortsComments" = "Hide Comments button";
|
||||
"HideShortsCommentsDesc" = "Hides Comments button from the Shorts overlay.";
|
||||
"HideShortsRemix" = "Hide Remix button";
|
||||
"HideShortsRemixDesc" = "Hides Remix button from the Shorts overlay.";
|
||||
"HideShortsShare" = "Hide Share button";
|
||||
"HideShortsShareDesc" = "Hides Share button from the Shorts overlay.";
|
||||
"HideShortsAvatars" = "Hide channels avatar";
|
||||
"HideShortsAvatarsDesc" = "Hides profile picture in the bottom right corner.";
|
||||
"HideShortsThanks" = "Hide Superthanks button";
|
||||
"HideShortsThanksDesc" = "Hides Superthanks (Donate) button from the Shorts overlay.";
|
||||
"HideShortsChannelName" = "Hide Channel name";
|
||||
"HideShortsChannelNameDesc" = "Hides Channel name and Subscribe button from the Shorts overlay.";
|
||||
"HideShortsDescription" = "Hide Description";
|
||||
"HideShortsDescriptionDesc" = "Hides Shorts description under channel name.";
|
||||
"HideShortsAudioTrack" = "Hide AudioTrack";
|
||||
"HideShortsAudioTrackDesc" = "Hides AudioTrack under Shorts description.";
|
||||
|
||||
"Startup" = "Startup page";
|
||||
"Home" = "Home";
|
||||
"Explore" = "Explore";
|
||||
"ShortsTab" = "Shorts";
|
||||
"Subscriptions" = "Subscriptions";
|
||||
"Library" = "Library";
|
||||
"Warning" = "Warning";
|
||||
"TabIsHidden" = "Hidden tab cannot be selected as startup page";
|
||||
|
||||
"Version" = "版本";
|
||||
"About" = "关于";
|
||||
"Credits" = "信息";
|
||||
"Developer" = "YTLite开发者";
|
||||
"Advanced" = "Advanced mode";
|
||||
"ResetSettings" = "Reset YTLite settings";
|
||||
"ResetMessage" = "This option will reset YTLite settings to default and close YouTube.\n\nAre you sure you want to continue?";
|
||||
"Yes" = "Yes";
|
||||
"No" = "No";
|
Reference in New Issue
Block a user