Compare commits

...
12 Commits
Author SHA1 Message Date
dayanch96 0a98d61920 Merge branch 'main' of https://github.com/dayanch96/YTLite 2023-06-27 13:51:46 +03:00
dayanch96 4fa79b7f58 Bugfixes, Remove Play Next and Continue Watching options 2023-06-27 13:51:13 +03:00
Dan 02253c2396 Merge pull request #2 from xiangfeidexiaohuo/main
update Simplified Chinese
2023-06-27 13:45:05 +03:00
xiangfeidexiaohuo a10cb96afc update Simplified Chinese
Signed-off-by: xiangfeidexiaohuo <jsjson@163.com>
2023-06-27 18:32:32 +08:00
Dan 0a506b266b Update README.md 2023-06-22 23:26:27 +03:00
Dan 75272395f6 Create README.md 2023-06-22 23:24:00 +03:00
dayanch96 2568dec42f Merge branch 'main' of https://github.com/dayanch96/YTLite 2023-06-22 22:21:09 +03:00
dayanch96 af231c8bc3 Advanced mode 2023-06-22 22:19:11 +03:00
Dan 80675bb4a4 Merge pull request #1 from xiangfeidexiaohuo/main
Add Simplified Chinese
2023-06-20 13:57:12 +03:00
xiangfeidexiaohuo 01eeb14410 Add Simplified Chinese
Signed-off-by: xiangfeidexiaohuo <jsjson@163.com>
2023-06-20 18:52:14 +08:00
dayanch96 dc30ee031f Custom YTSettingsSectionItemManager 2023-06-20 13:34:28 +03:00
dayanch96 32da778af8 Settings simplification 2023-06-19 15:03:56 +03:00
13 changed files with 1346 additions and 115 deletions
+2 -2
View File
@@ -5,7 +5,7 @@ endif
DEBUG=0 DEBUG=0
FINALPACKAGE=1 FINALPACKAGE=1
ARCHS = arm64 ARCHS = arm64
PACKAGE_VERSION = 1.0 PACKAGE_VERSION = 2.1
TARGET := iphone:clang:latest:11.0 TARGET := iphone:clang:latest:11.0
include $(THEOS)/makefiles/common.mk include $(THEOS)/makefiles/common.mk
@@ -13,6 +13,6 @@ include $(THEOS)/makefiles/common.mk
TWEAK_NAME = YTLite TWEAK_NAME = YTLite
$(TWEAK_NAME)_FRAMEWORKS = UIKit Foundation $(TWEAK_NAME)_FRAMEWORKS = UIKit Foundation
$(TWEAK_NAME)_CFLAGS = -fobjc-arc -DTWEAK_VERSION=$(PACKAGE_VERSION) $(TWEAK_NAME)_CFLAGS = -fobjc-arc -DTWEAK_VERSION=$(PACKAGE_VERSION)
$(TWEAK_NAME)_FILES = YTLite.x Settings.x $(TWEAK_NAME)_FILES = YTLite.x Settings.x Sideloading.x
include $(THEOS_MAKE_PATH)/tweak.mk include $(THEOS_MAKE_PATH)/tweak.mk
+18
View 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>
+258 -92
View File
@@ -6,6 +6,12 @@
static const NSInteger YTLiteSection = 789; 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() { NSBundle *YTLiteBundle() {
static NSBundle *bundle = nil; static NSBundle *bundle = nil;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
@@ -51,11 +57,41 @@ NSBundle *YTLiteBundle() {
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.dvntm.ytlite.prefschanged"), NULL, NULL, YES); 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@:@) %new(v@:@)
- (void)updateYTLiteSectionWithEntry:(id)entry { - (void)updateYTLiteSectionWithEntry:(id)entry {
NSMutableArray *sectionItems = [NSMutableArray array]; NSMutableArray *sectionItems = [NSMutableArray array];
Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem); Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem);
YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"]; 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") YTSettingsSectionItem *general = [YTSettingsSectionItemClass itemWithTitle:LOC(@"General")
accessibilityIdentifier:nil accessibilityIdentifier:nil
@@ -64,24 +100,8 @@ NSBundle *YTLiteBundle() {
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ NSArray <YTSettingsSectionItem *> *rows = @[
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"RemoveAds") createSwitchItem(LOC(@"RemoveAds"), LOC(@"RemoveAdsDesc"), @"noAds", &kNoAds, selfObject),
titleDescription:LOC(@"RemoveAdsDesc") createSwitchItem(LOC(@"BackgroundPlayback"), LOC(@"BackgroundPlaybackDesc"), @"backgroundPlayback", &kBackgroundPlayback, selfObject)
accessibilityIdentifier:nil
switchOn:kNoAds
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
[self updatePrefsForKey:@"noAds" enabled:enabled];
return YES;
}
settingItemId:0],
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"BackgroundPlayback")
titleDescription:LOC(@"BackgroundPlaybackDesc")
accessibilityIdentifier:nil
switchOn:kBackgroundPlayback
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
[self updatePrefsForKey:@"backgroundPlayback" enabled:enabled];
return YES;
}
settingItemId:0]
]; ];
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"General") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"General") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
@@ -97,41 +117,114 @@ NSBundle *YTLiteBundle() {
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ NSArray <YTSettingsSectionItem *> *rows = @[
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"RemoveCast") createSwitchItem(LOC(@"RemoveCast"), LOC(@"RemoveCastDesc"), @"noCast", &kNoCast, selfObject),
titleDescription:LOC(@"RemoveCastDesc") createSwitchItem(LOC(@"RemoveNotifications"), LOC(@"RemoveNotificationsDesc"), @"removeNotifsButton", &kNoNotifsButton, selfObject),
accessibilityIdentifier:nil createSwitchItem(LOC(@"RemoveSearch"), LOC(@"RemoveSearchDesc"), @"removeSearchButton", &kNoSearchButton, selfObject),
switchOn:kNoCast createSwitchItem(LOC(@"RemoveVoiceSearch"), LOC(@"RemoveVoiceSearchDesc"), @"removeVoiceSearchButton", &kNoVoiceSearchButton, selfObject)
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
[self updatePrefsForKey:@"noCast" enabled:enabled];
return YES;
}
settingItemId:0],
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"RemoveNotifications")
titleDescription:LOC(@"RemoveNotificationsDesc")
accessibilityIdentifier:nil
switchOn:kNoNotifsButton
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
[self updatePrefsForKey:@"removeNotifsButton" enabled:enabled];
return YES;
}
settingItemId:0],
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"RemoveSearch")
titleDescription:LOC(@"RemoveSearchDesc")
accessibilityIdentifier:nil
switchOn:kNoSearchButton
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
[self updatePrefsForKey:@"removeSearchButton" enabled:enabled];
return YES;
}
settingItemId:0]
]; ];
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]]; YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Navbar") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
[settingsViewController pushViewController:picker]; [settingsViewController pushViewController:picker];
return YES; return YES;
}]; }];
[sectionItems addObject:navbar]; [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"), @"endScreenCards", &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") YTSettingsSectionItem *tabbar = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Tabbar")
accessibilityIdentifier:nil accessibilityIdentifier:nil
detailTextBlock:^NSString *() { detailTextBlock:^NSString *() {
@@ -139,51 +232,12 @@ NSBundle *YTLiteBundle() {
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ NSArray <YTSettingsSectionItem *> *rows = @[
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"RemoveLabels") createSwitchItem(LOC(@"RemoveLabels"), LOC(@"RemoveLabelsDesc"), @"removeLabels", &kRemoveLabels, selfObject),
titleDescription:LOC(@"RemoveLabelsDesc") createSwitchItem(LOC(@"ReExplore"), LOC(@"ReExploreDesc"), @"reExplore", &kReExplore, selfObject),
accessibilityIdentifier:nil createSwitchItem(LOC(@"HideShortsTab"), LOC(@"HideShortsTabDesc"), @"removeShorts", &kRemoveShorts, selfObject),
switchOn:kRemoveLabels createSwitchItem(LOC(@"HideSubscriptionsTab"), LOC(@"HideSubscriptionsTabDesc"), @"removeSubscriptions", &kRemoveSubscriptions, selfObject),
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) { createSwitchItem(LOC(@"HideUploadButton"), LOC(@"HideUploadButtonDesc"), @"removeUploads", &kRemoveUploads, selfObject),
[self updatePrefsForKey:@"removeLabels" enabled:enabled]; createSwitchItem(LOC(@"HideLibraryTab"), LOC(@"HideLibraryTabDesc"), @"removeLibrary", &kRemoveLibrary, selfObject)
return YES;
}
settingItemId:0],
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HideShortsTab")
titleDescription:LOC(@"HideShortsTabDesc")
accessibilityIdentifier:nil
switchOn:kRemoveShorts
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
[self updatePrefsForKey:@"removeShorts" enabled:enabled];
return YES;
}
settingItemId:0],
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HideSubscriptionsTab")
titleDescription:LOC(@"HideSubscriptionsTabDesc")
accessibilityIdentifier:nil
switchOn:kRemoveSubscriptions
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
[self updatePrefsForKey:@"removeSubscriptions" enabled:enabled];
return YES;
}
settingItemId:0],
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HideUploadButton")
titleDescription:LOC(@"HideUploadButtonDesc")
accessibilityIdentifier:nil
switchOn:kRemoveUploads
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
[self updatePrefsForKey:@"removeUploads" enabled:enabled];
return YES;
}
settingItemId:0],
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"HideLibraryTab")
titleDescription:LOC(@"HideLibraryTabDesc")
accessibilityIdentifier:nil
switchOn:kRemoveLibrary
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
[self updatePrefsForKey:@"removeLibrary" enabled:enabled];
return YES;
}
settingItemId:0]
]; ];
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Tabbar") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Tabbar") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
@@ -192,21 +246,133 @@ NSBundle *YTLiteBundle() {
}]; }];
[sectionItems addObject:tabbar]; [sectionItems addObject:tabbar];
YTSettingsSectionItem *ps = [%c(YTSettingsSectionItem) itemWithTitle:@"PoomSmart" titleDescription:@"YouTube-X, YTNoPremium, YouTubeHeaders" accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { if (kAdvancedMode) {
YTSettingsSectionItem *other = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Other")
accessibilityIdentifier:nil
detailTextBlock:^NSString *() {
return @"‣";
}
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[
createSwitchItem(LOC(@"RemovePlayNext"), LOC(@"RemovePlayNextDesc"), @"removePlayNext", &kRemovePlayNext, selfObject),
createSwitchItem(LOC(@"NoContinueWatching"), LOC(@"NoContinueWatchingDesc"), @"noContinueWatching", &kNoContinueWatching, selfObject)
];
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Other") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
[settingsViewController pushViewController:picker];
return YES;
}];
[sectionItems addObject:other];
[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/"]]; 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) { 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/"]]; 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") YTSettingsSectionItem *version = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Version")
accessibilityIdentifier:nil accessibilityIdentifier:nil
detailTextBlock:^NSString *() { detailTextBlock:^NSString *() {
return @(OS_STRINGIFY(TWEAK_VERSION)); return @(OS_STRINGIFY(TWEAK_VERSION));
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ps, dayanch96]; 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]]; YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"About") pickerSectionTitle:LOC(@"Credits") rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
[settingsViewController pushViewController:picker]; [settingsViewController pushViewController:picker];
+138
View 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);
}
+112
View File
@@ -1,15 +1,23 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <rootless.h> #import <rootless.h>
#import "../YouTubeHeader/YTIGuideResponse.h"
#import "../YouTubeHeader/YTIGuideResponseSupportedRenderers.h"
#import "../YouTubeHeader/YTIPivotBarSupportedRenderers.h" #import "../YouTubeHeader/YTIPivotBarSupportedRenderers.h"
#import "../YouTubeHeader/YTIPivotBarRenderer.h" #import "../YouTubeHeader/YTIPivotBarRenderer.h"
#import "../YouTubeHeader/YTIBrowseRequest.h"
#import "../YouTubeHeader/YTISectionListRenderer.h" #import "../YouTubeHeader/YTISectionListRenderer.h"
#import "../YouTubeHeader/YTQTMButton.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/YTSettingsViewController.h"
#import "../YouTubeHeader/YTSettingsSectionItem.h" #import "../YouTubeHeader/YTSettingsSectionItem.h"
#import "../YouTubeHeader/YTSettingsSectionItemManager.h" #import "../YouTubeHeader/YTSettingsSectionItemManager.h"
#import "../YouTubeHeader/YTSettingsPickerViewController.h" #import "../YouTubeHeader/YTSettingsPickerViewController.h"
#import "../YouTubeHeader/YTUIUtils.h" #import "../YouTubeHeader/YTUIUtils.h"
#import "../YouTubeHeader/YTIMenuConditionalServiceItemRenderer.h"
extern NSBundle *YTLiteBundle(); extern NSBundle *YTLiteBundle();
@@ -23,11 +31,66 @@ BOOL kBackgroundPlayback;
BOOL kNoCast; BOOL kNoCast;
BOOL kNoNotifsButton; BOOL kNoNotifsButton;
BOOL kNoSearchButton; BOOL kNoSearchButton;
BOOL kNoVoiceSearchButton;
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 kRemoveLabels;
BOOL kReExplore;
BOOL kRemoveShorts; BOOL kRemoveShorts;
BOOL kRemoveSubscriptions; BOOL kRemoveSubscriptions;
BOOL kRemoveUploads; BOOL kRemoveUploads;
BOOL kRemoveLibrary; BOOL kRemoveLibrary;
BOOL kRemovePlayNext;
BOOL kNoContinueWatching;
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 @interface YTPivotBarView : UIView
@end @end
@@ -35,7 +98,56 @@ BOOL kRemoveLibrary;
@interface YTPivotBarItemView : UIView @interface YTPivotBarItemView : UIView
@end @end
@interface YTPivotBarViewController : UIViewController
- (void)selectItemWithPivotIdentifier:(id)pivotIndentifier;
@end
@interface YTRightNavigationButtons : UIView @interface YTRightNavigationButtons : UIView
@property (nonatomic, strong) YTQTMButton *notificationButton; @property (nonatomic, strong) YTQTMButton *notificationButton;
@property (nonatomic, strong) YTQTMButton *searchButton; @property (nonatomic, strong) YTQTMButton *searchButton;
@end @end
@interface YTNavigationBarTitleView : UIView
@end
@interface YTChipCloudCell : UICollectionViewCell
@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)removeCellsAtIndexPath:(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
+452 -19
View File
@@ -28,17 +28,19 @@
- (void)decorateContext:(id)context { if (!kNoAds) %orig; } - (void)decorateContext:(id)context { if (!kNoAds) %orig; }
%end %end
BOOL isAd(YTIElementRenderer *self) { %hook YTIElementRenderer
if (self == nil) return NO; - (NSData *)elementData {
if (self.hasCompatibilityOptions && self.compatibilityOptions.hasAdLoggingData) return YES; if (self.hasCompatibilityOptions && self.compatibilityOptions.hasAdLoggingData)
return nil;
NSString *description = [self description]; NSString *description = [self description];
if (([description containsString:@"brand_promo"] if (([description containsString:@"brand_promo"]
|| [description containsString:@"product_carousel"] || [description containsString:@"product_carousel"]
|| [description containsString:@"product_engagement_panel"] || [description containsString:@"product_engagement_panel"]
|| [description containsString:@"product_item"]) && kNoAds) || [description containsString:@"product_item"]) && kNoAds)
return YES; return [NSData data];
return NO; return %orig;
} }
%end
%hook YTSectionListViewController %hook YTSectionListViewController
- (void)loadWithModel:(YTISectionListRenderer *)model { - (void)loadWithModel:(YTISectionListRenderer *)model {
@@ -47,7 +49,7 @@ BOOL isAd(YTIElementRenderer *self) {
NSIndexSet *removeIndexes = [contentsArray indexesOfObjectsPassingTest:^BOOL(YTISectionListSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) { NSIndexSet *removeIndexes = [contentsArray indexesOfObjectsPassingTest:^BOOL(YTISectionListSupportedRenderers *renderers, NSUInteger idx, BOOL *stop) {
YTIItemSectionRenderer *sectionRenderer = renderers.itemSectionRenderer; YTIItemSectionRenderer *sectionRenderer = renderers.itemSectionRenderer;
YTIItemSectionSupportedRenderers *firstObject = [sectionRenderer.contentsArray firstObject]; YTIItemSectionSupportedRenderers *firstObject = [sectionRenderer.contentsArray firstObject];
return firstObject.hasPromotedVideoRenderer || firstObject.hasCompactPromotedVideoRenderer || firstObject.hasPromotedVideoInlineMutedRenderer || isAd(firstObject.elementRenderer); return firstObject.hasPromotedVideoRenderer || firstObject.hasCompactPromotedVideoRenderer || firstObject.hasPromotedVideoInlineMutedRenderer;
}]; }];
[contentsArray removeObjectsAtIndexes:removeIndexes]; [contentsArray removeObjectsAtIndexes:removeIndexes];
} %orig; } %orig;
@@ -89,15 +91,6 @@ BOOL isAd(YTIElementRenderer *self) {
- (void)showSurveyWithRenderer:(id)arg1 surveyParentResponder:(id)arg2 {} - (void)showSurveyWithRenderer:(id)arg1 surveyParentResponder:(id)arg2 {}
%end %end
// Statement banner
%hook YTPremiumSeasonCardCellController
- (void)setCell:(id)arg1 { arg1 = NULL; %orig; }
%end
%hook YTPremiumSeasonCardView
- (long long)accessibilityElementCount { return 0; }
%end
// Navbar Stuff // Navbar Stuff
// Disable Cast // Disable Cast
%hook MDXPlaybackRouteButtonController %hook MDXPlaybackRouteButtonController
@@ -117,6 +110,288 @@ BOOL isAd(YTIElementRenderer *self) {
if (kNoCast && self.subviews.count > 1 && [self.subviews[1].accessibilityIdentifier isEqualToString:@"id.mdx.playbackroute.button"]) self.subviews[1].hidden = YES; // Hide icon immediately 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 (kNoNotifsButton) self.notificationButton.hidden = YES;
if (kNoSearchButton) self.searchButton.hidden = YES; if (kNoSearchButton) self.searchButton.hidden = YES;
if (kNoVoiceSearchButton && self.subviews.count >= 4 && [self.subviews[2].accessibilityIdentifier isEqualToString:@"id.settings.overflow.button"]) self.subviews[3].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; }
- (void)setFeedHeaderScrollMode:(int)arg1 { kNoSubbar ? %orig(0) : %orig; }
%end
%hook YTChipCloudCell
- (void)layoutSubviews {
if (self.superview && kNoSubbar) {
[self removeFromSuperview];
} %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
// Fit 'Play All' Buttons Text For Localizations
%hook YTQTMButton
- (void)layoutSubviews {
if ([self.accessibilityIdentifier isEqualToString:@"id.playlist.playall.button"]) {
self.titleLabel.adjustsFontSizeToFitWidth = YES;
} %orig;
}
%end
// Fix Playlist Mini-bar Height For Small Screens
%hook YTPlaylistMiniBarView
- (void)setFrame:(CGRect)frame {
if (frame.size.height < 54.0) frame.size.height = 54.0;
%orig(frame);
}
%end
// Remove "Play next in queue" from the menu @PoomSmart (https://github.com/qnblackcat/uYouPlus/issues/1138#issuecomment-1606415080)
%hook YTMenuItemVisibilityHandler
- (BOOL)shouldShowServiceItemRenderer:(YTIMenuConditionalServiceItemRenderer *)renderer {
if (kRemovePlayNext && renderer.icon.iconType == 251) {
return NO;
} return %orig;
}
%end
// Remove Premium Pop-up, Horizontal Video Carousel and Shorts (https://github.com/MiRO92/YTNoShorts)
%hook YTAsyncCollectionView
- (id)cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = %orig;
if ([cell isKindOfClass:objc_lookUpClass("_ASCollectionViewCell")]) {
_ASCollectionViewCell *cell = %orig;
if ([cell respondsToSelector:@selector(node)]) {
NSString *idToRemove = [[cell node] accessibilityIdentifier];
if ([idToRemove isEqualToString:@"statement_banner.view"] ||
(([idToRemove isEqualToString:@"eml.shorts-grid"] || [idToRemove isEqualToString:@"eml.shorts-shelf"]) && kHideShorts)) {
[self removeCellsAtIndexPath:indexPath];
}
}
} else if (([cell isKindOfClass:objc_lookUpClass("YTReelShelfCell")] && kHideShorts) ||
([cell isKindOfClass:objc_lookUpClass("YTHorizontalCardListCell")] && kNoContinueWatching)) {
[self removeCellsAtIndexPath:indexPath];
} return %orig;
}
%new
- (void)removeCellsAtIndexPath:(NSIndexPath *)indexPath {
[self deleteItemsAtIndexPaths:@[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 %end
@@ -149,6 +424,39 @@ BOOL isAd(YTIElementRenderer *self) {
} }
%end %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 // Hide Tab Labels
BOOL hasHomeBar = NO; BOOL hasHomeBar = NO;
CGFloat pivotBarViewHeight; CGFloat pivotBarViewHeight;
@@ -168,14 +476,14 @@ CGFloat pivotBarViewHeight;
if (kRemoveLabels) { if (kRemoveLabels) {
for (UIView *subview in self.subviews) { for (UIView *subview in self.subviews) {
if ([subview isKindOfClass:NSClassFromString(@"YTPivotBarItemViewAccessibilityControl")]) { if ([subview isKindOfClass:objc_lookUpClass("YTPivotBarItemViewAccessibilityControl")]) {
pivotBarAccessibilityControlWidth = CGRectGetWidth(subview.frame); pivotBarAccessibilityControlWidth = CGRectGetWidth(subview.frame);
break; break;
} }
} }
for (UIView *subview in self.subviews) { for (UIView *subview in self.subviews) {
if ([subview isKindOfClass:NSClassFromString(@"YTQTMButton")]) { if ([subview isKindOfClass:objc_lookUpClass("YTQTMButton")]) {
for (UIView *buttonSubview in subview.subviews) { for (UIView *buttonSubview in subview.subviews) {
if ([buttonSubview isKindOfClass:[UILabel class]]) { if ([buttonSubview isKindOfClass:[UILabel class]]) {
[buttonSubview removeFromSuperview]; [buttonSubview removeFromSuperview];
@@ -224,6 +532,36 @@ CGFloat pivotBarViewHeight;
} }
%end %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() { static void reloadPrefs() {
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"YTLite.plist"]; NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"YTLite.plist"];
NSDictionary *prefs = [NSDictionary dictionaryWithContentsOfFile:path]; NSDictionary *prefs = [NSDictionary dictionaryWithContentsOfFile:path];
@@ -233,11 +571,59 @@ static void reloadPrefs() {
kNoCast = [prefs[@"noCast"] boolValue] ?: NO; kNoCast = [prefs[@"noCast"] boolValue] ?: NO;
kNoNotifsButton = [prefs[@"removeNotifsButton"] boolValue] ?: NO; kNoNotifsButton = [prefs[@"removeNotifsButton"] boolValue] ?: NO;
kNoSearchButton = [prefs[@"removeSearchButton"] boolValue] ?: NO; kNoSearchButton = [prefs[@"removeSearchButton"] boolValue] ?: NO;
kNoVoiceSearchButton = [prefs[@"removeVoiceSearchButton"] 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; kRemoveLabels = [prefs[@"removeLabels"] boolValue] ?: NO;
kReExplore = [prefs[@"reExplore"] boolValue] ?: NO;
kRemoveShorts = [prefs[@"removeShorts"] boolValue] ?: NO; kRemoveShorts = [prefs[@"removeShorts"] boolValue] ?: NO;
kRemoveSubscriptions = [prefs[@"removeSubscriptions"] boolValue] ?: NO; kRemoveSubscriptions = [prefs[@"removeSubscriptions"] boolValue] ?: NO;
kRemoveUploads = (prefs[@"removeUploads"] != nil) ? [prefs[@"removeUploads"] boolValue] : YES; kRemoveUploads = (prefs[@"removeUploads"] != nil) ? [prefs[@"removeUploads"] boolValue] : YES;
kRemoveLibrary = [prefs[@"removeLibrary"] boolValue] ?: NO; kRemoveLibrary = [prefs[@"removeLibrary"] boolValue] ?: NO;
kRemovePlayNext = [prefs[@"removePlayNext"] boolValue] ?: NO;
kNoContinueWatching = [prefs[@"noContinueWatching"] boolValue] ?: NO;
kPivotIndex = (prefs[@"pivotIndex"] != nil) ? [prefs[@"pivotIndex"] intValue] : 0;
kAdvancedMode = [prefs[@"advancedMode"] boolValue] ?: NO;
NSDictionary *newSettings = @{ NSDictionary *newSettings = @{
@"noAds" : @(kNoAds), @"noAds" : @(kNoAds),
@@ -245,11 +631,59 @@ static void reloadPrefs() {
@"noCast" : @(kNoCast), @"noCast" : @(kNoCast),
@"removeNotifsButton" : @(kNoNotifsButton), @"removeNotifsButton" : @(kNoNotifsButton),
@"removeSearchButton" : @(kNoSearchButton), @"removeSearchButton" : @(kNoSearchButton),
@"removeVoiceSearchButton" : @(kNoVoiceSearchButton),
@"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), @"removeLabels" : @(kRemoveLabels),
@"reExplore" : @(kReExplore),
@"removeShorts" : @(kRemoveShorts), @"removeShorts" : @(kRemoveShorts),
@"removeSubscriptions" : @(kRemoveSubscriptions), @"removeSubscriptions" : @(kRemoveSubscriptions),
@"removeUploads" : @(kRemoveUploads), @"removeUploads" : @(kRemoveUploads),
@"removeLibrary" : @(kRemoveLibrary) @"removeLibrary" : @(kRemoveLibrary),
@"removePlayNext" : @(kRemovePlayNext),
@"noContinueWatching" : @(kNoContinueWatching),
@"pivotIndex" : @(kPivotIndex),
@"advancedMode" : @(kAdvancedMode)
}; };
if (![newSettings isEqualToDictionary:prefs]) [newSettings writeToFile:path atomically:NO]; if (![newSettings isEqualToDictionary:prefs]) [newSettings writeToFile:path atomically:NO];
@@ -262,5 +696,4 @@ static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStrin
%ctor { %ctor {
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.dvntm.ytlite.prefschanged"), NULL, CFNotificationSuspensionBehaviorCoalesce); CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.dvntm.ytlite.prefschanged"), NULL, CFNotificationSuspensionBehaviorCoalesce);
reloadPrefs(); reloadPrefs();
%init;
} }
@@ -11,10 +11,66 @@
"RemoveNotificationsDesc" = "Hides Notifications button from the Navigation bar."; "RemoveNotificationsDesc" = "Hides Notifications button from the Navigation bar.";
"RemoveSearch" = "Hide Search button"; "RemoveSearch" = "Hide Search button";
"RemoveSearchDesc" = "Hides Search button from the Navigation bar."; "RemoveSearchDesc" = "Hides Search button from the Navigation bar.";
"RemoveVoiceSearch" = "Hide Voice search button";
"RemoveVoiceSearchDesc" = "Hides Voice 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"; "Tabbar" = "Tab bar";
"RemoveLabels" = "Remove labels"; "RemoveLabels" = "Remove labels";
"RemoveLabelsDesc" = "Removes tab 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"; "HideShortsTab" = "Hide Shorts tab";
"HideShortsTabDesc" = "Hides Shorts tab from the Tab bar"; "HideShortsTabDesc" = "Hides Shorts tab from the Tab bar";
"HideSubscriptionsTab" = "Hide Subscriptions tab"; "HideSubscriptionsTab" = "Hide Subscriptions tab";
@@ -24,7 +80,65 @@
"HideLibraryTab" = "Hide Library tab"; "HideLibraryTab" = "Hide Library tab";
"HideLibraryTabDesc" = "Hides Library tab from the Tab bar"; "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.";
"Other" = "Other";
"RemovePlayNext" = "Remove \"Play next in queue\"";
"RemovePlayNextDesc" = "Removes \"Play next in queue\" option from menu.";
"NoContinueWatching" = "Remove \"Continue watching\"";
"NoContinueWatchingDesc" = "Removes the \"Continue watching\" section containing unfinished videos from the Home page.";
"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"; "Version" = "Version";
"About" = "About"; "About" = "About";
"Credits" = "Credits"; "Credits" = "Credits";
"Developer" = "YTLite developer"; "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";
@@ -10,11 +10,67 @@
"RemoveNotifications" = "Скрыть «Уведомления»"; "RemoveNotifications" = "Скрыть «Уведомления»";
"RemoveNotificationsDesc" = "Скрывает кнопку уведомлений с панели навигации."; "RemoveNotificationsDesc" = "Скрывает кнопку уведомлений с панели навигации.";
"RemoveSearch" = "Скрыть «Поиск»"; "RemoveSearch" = "Скрыть «Поиск»";
"RemoveSearchDesc" = "Скрвыает кнопку поиска с панели навигации."; "RemoveSearchDesc" = "Скрывает кнопку поиска с панели навигации.";
"RemoveVoiceSearch" = "Скрыть «Голосовой поиск»";
"RemoveVoiceSearchDesc" = "Скрывает кнопку голосового поиска с панели навигации.";
"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" = "Панель вкладок"; "Tabbar" = "Панель вкладок";
"RemoveLabels" = "Скрыть названия"; "RemoveLabels" = "Скрыть названия";
"RemoveLabelsDesc" = "Скрывает названия вкладок."; "RemoveLabelsDesc" = "Скрывает названия вкладок.";
"ReExplore" = "Вкладка «Навигация» вместо «Shorts»";
"ReExploreDesc" = "Заменяет вкладку «Shorts» на привычную нам «Навигацию».";
"HideShortsTab" = "Скрыть «Shorts»"; "HideShortsTab" = "Скрыть «Shorts»";
"HideShortsTabDesc" = "Скрывает вкладку «Shorts» с панели вкладок."; "HideShortsTabDesc" = "Скрывает вкладку «Shorts» с панели вкладок.";
"HideSubscriptionsTab" = "Скрыть «Подписки»"; "HideSubscriptionsTab" = "Скрыть «Подписки»";
@@ -24,7 +80,65 @@
"HideLibraryTab" = "Скрыть «Библиотеку»"; "HideLibraryTab" = "Скрыть «Библиотеку»";
"HideLibraryTabDesc" = "Скрывает вкладку «Библиотека» с панели вкладок."; "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" = "Скрывает информацию об аудиодорожке в нижней части плеера.";
"Other" = "Другие настройки";
"RemovePlayNext" = "Убрать «Добавить в начало очереди»";
"RemovePlayNextDesc" = "Убирает опцию «Добавить в начало очереди» из меню видео.";
"NoContinueWatching" = "Отключить «Продолжить просмотр»";
"NoContinueWatchingDesc" = "Удаляет блок «Продолжить просмотр» содержащий недосмотренные видео с Главной страницы.";
"Startup" = "Начальная страница";
"Home" = "Главная";
"Explore" = "Навигация";
"ShortsTab" = "Shorts";
"Subscriptions" = "Подписки";
"Library" = "Библиотека";
"Warning" = "Внимание";
"TabIsHidden" = "Скрытая вкладка не может быть выбрана в качестве начальной страницы";
"Version" = "Версия"; "Version" = "Версия";
"About" = "О твике"; "About" = "О твике";
"Credits" = "Авторы"; "Credits" = "Авторы";
"Developer" = "Разработчик твика"; "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" = "固定导航栏";
"StickyNavbarDesc" = "固定导航栏,使其在向下滚动时保持可见。";
"NoSubbar" = "隐藏子栏";
"NoSubbarDesc" = "隐藏导航栏下的子栏(全部、新内容、实时等)。";
"NoYTLogo" = "删除 YouTube Logo";
"NoYTLogoDesc" = "删除导航栏中的 YouTube Logo。";
"Overlay" = "播放界面";
"HideAutoplay" = "隐藏自动播放开关";
"HideAutoplayDesc" = "从播放界面隐藏自动播放开关。";
"HideSubs" = "隐藏字幕按钮";
"HideSubsDesc" = "从播放界面隐藏字幕按钮。";
"NoHUDMsgs" = "隐藏屏显信息";
"NoHUDMsgsDesc" = "隐藏播放界面的所有功能信息。示例:CC按钮打开/关闭、视频循环等。";
"HidePrevNext" = "隐藏上一个和下一个按钮";
"HidePrevNextDesc" = "从播放界面中隐藏上一个和下一个视频按钮。";
"ReplacePrevNext" = "快进和快退按钮";
"ReplacePrevNextDesc" = "将上一个和下一个视频按钮替换为快进和快退按钮。";
"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" = "将短视频选项卡替换为“探索”选项卡";
"ReExploreDesc" = "显示“探索”选项卡,而不是旧版 本中的“短视频”选项卡。";
"HideShortsTab" = "隐藏短视频";
"HideShortsTabDesc" = "从选项卡栏中隐藏短视频。";
"HideSubscriptionsTab" = "隐藏订阅内容";
"HideSubscriptionsTabDesc" = "从选项卡栏中隐藏订阅内容。";
"HideUploadButton" = "隐藏上传按钮";
"HideUploadButtonDesc" = "从选项卡栏中隐藏上传按钮。";
"HideLibraryTab" = "隐藏媒体库";
"HideLibraryTabDesc" = "从选项卡栏中隐藏媒体库。";
"Shorts" = "短视频";
"HideShorts" = "隐藏短视频";
"HideShortsDesc" = "从首页、推荐等隐藏短视频(不适用于观看历史记录)。";
"ShortsProgress" = "启用进度条";
"ShortsProgressDesc" = "在短视频播放器中显示进度条。";
"ResumeShorts" = "不要从短视频开始";
"ResumeShortsDesc" = "防止在打开应用程序时首先启动短视频,如果在观看短视频时关闭,就会发生这种情况。";
"HideShortsLogo" = "隐藏短视频Logo";
"HideShortsLogoDesc" = "隐藏左上角的短视频Logo。";
"HideShortsSearch" = "隐藏搜索按钮";
"HideShortsSearchDesc" = "从短视频播放器中隐藏搜索按钮。";
"HideShortsCamera" = "隐藏相机按钮";
"HideShortsCameraDesc" = "从短视频播放器中隐藏相机按钮。";
"HideShortsMore" = "隐藏更多 (⋮) 按钮";
"HideShortsMoreDesc" = "从短视频播放器中隐藏更多 (⋮) 按钮 。也可以通过长按屏幕来访问它。";
"HideShortsSubscriptions" = "隐藏订阅按钮";
"HideShortsSubscriptionsDesc" = "隐藏短视频暂停时显示的订阅按钮。";
"HideShortsLike" = "隐藏喜欢按钮";
"HideShortsLikeDesc" = "从短视频播放器中隐藏喜欢按钮。";
"HideShortsDislike" = "隐藏不喜欢按钮";
"HideShortsDislikeDesc" = "从短视频播放器中隐藏不喜欢按钮。";
"HideShortsComments" = "隐藏评论按钮";
"HideShortsCommentsDesc" = "从短视频播放器中隐藏评论按钮。";
"HideShortsRemix" = "隐藏混剪按钮";
"HideShortsRemixDesc" = "从短视频播放器中隐藏混剪按钮。";
"HideShortsShare" = "隐藏分享按钮";
"HideShortsShareDesc" = "从短视频播放器中隐藏分享按钮。";
"HideShortsAvatars" = "隐藏发布者头像";
"HideShortsAvatarsDesc" = "隐藏右下角的发布者个人资料头像。";
"HideShortsThanks" = "隐藏捐赠按钮";
"HideShortsThanksDesc" = "从短视频播放器中隐藏捐赠按钮。";
"HideShortsChannelName" = "隐藏发布者名称";
"HideShortsChannelNameDesc" = "从短视频播放器中隐藏发布者名称和订阅按钮。";
"HideShortsDescription" = "隐藏说明";
"HideShortsDescriptionDesc" = "在频道名称下隐藏短视频描述。";
"HideShortsAudioTrack" = "隐藏音频音轨";
"HideShortsAudioTrackDesc" = "从短视频描述下隐藏音频音轨。";
"Startup" = "启动页";
"Home" = "首页";
"Explore" = "探索";
"ShortsTab" = "短视频";
"Subscriptions" = "订阅";
"Library" = "媒体库";
"Warning" = "警告";
"TabIsHidden" = "无法选择隐藏选项卡作为启动页。";
"Version" = "版本";
"About" = "关于";
"Credits" = "信息";
"Developer" = "YTLite开发者";
"Advanced" = "高级模式";
"ResetSettings" = "重置YTLite设置";
"ResetMessage" = "此选项会将YTLite设置重置为默认值并关闭YouTube。\n\n确定要继续吗?";
"Yes" = "是";
"No" = "不";
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.