Initial release
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
ifeq ($(ROOTLESS),1)
|
||||
THEOS_PACKAGE_SCHEME=rootless
|
||||
endif
|
||||
|
||||
DEBUG=0
|
||||
FINALPACKAGE=1
|
||||
ARCHS = arm64
|
||||
PACKAGE_VERSION = 1.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
|
||||
|
||||
include $(THEOS_MAKE_PATH)/tweak.mk
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
#import "YTLite.h"
|
||||
|
||||
@interface YTSettingsSectionItemManager (YTLite)
|
||||
- (void)updateYTLiteSectionWithEntry:(id)entry;
|
||||
@end
|
||||
|
||||
static const NSInteger YTLiteSection = 789;
|
||||
|
||||
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(v@:@)
|
||||
- (void)updateYTLiteSectionWithEntry:(id)entry {
|
||||
NSMutableArray *sectionItems = [NSMutableArray array];
|
||||
Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem);
|
||||
YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"];
|
||||
|
||||
YTSettingsSectionItem *general = [YTSettingsSectionItemClass itemWithTitle:LOC(@"General")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return @"‣";
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"RemoveAds")
|
||||
titleDescription:LOC(@"RemoveAdsDesc")
|
||||
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]];
|
||||
[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 = @[
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"RemoveCast")
|
||||
titleDescription:LOC(@"RemoveCastDesc")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:kNoCast
|
||||
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]
|
||||
];
|
||||
|
||||
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];
|
||||
|
||||
YTSettingsSectionItem *tabbar = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Tabbar")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return @"‣";
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[
|
||||
[YTSettingsSectionItemClass switchItemWithTitle:LOC(@"RemoveLabels")
|
||||
titleDescription:LOC(@"RemoveLabelsDesc")
|
||||
accessibilityIdentifier:nil
|
||||
switchOn:kRemoveLabels
|
||||
switchBlock:^BOOL (YTSettingsCell *cell, BOOL enabled) {
|
||||
[self updatePrefsForKey:@"removeLabels" enabled:enabled];
|
||||
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]];
|
||||
[settingsViewController pushViewController:picker];
|
||||
return YES;
|
||||
}];
|
||||
[sectionItems addObject:tabbar];
|
||||
|
||||
YTSettingsSectionItem *ps = [%c(YTSettingsSectionItem) itemWithTitle:@"PoomSmart" titleDescription:@"YouTube-X, YTNoPremium, YouTubeHeaders" accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/PoomSmart/"]];
|
||||
}];
|
||||
|
||||
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 *version = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Version")
|
||||
accessibilityIdentifier:nil
|
||||
detailTextBlock:^NSString *() {
|
||||
return @(OS_STRINGIFY(TWEAK_VERSION));
|
||||
}
|
||||
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
|
||||
NSArray <YTSettingsSectionItem *> *rows = @[ps, dayanch96];
|
||||
|
||||
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
|
||||
@@ -0,0 +1,41 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <rootless.h>
|
||||
#import "../YouTubeHeader/YTIPivotBarSupportedRenderers.h"
|
||||
#import "../YouTubeHeader/YTIPivotBarRenderer.h"
|
||||
#import "../YouTubeHeader/YTISectionListRenderer.h"
|
||||
#import "../YouTubeHeader/YTQTMButton.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 kRemoveLabels;
|
||||
BOOL kRemoveShorts;
|
||||
BOOL kRemoveSubscriptions;
|
||||
BOOL kRemoveUploads;
|
||||
BOOL kRemoveLibrary;
|
||||
|
||||
@interface YTPivotBarView : UIView
|
||||
@end
|
||||
|
||||
@interface YTPivotBarItemView : UIView
|
||||
@end
|
||||
|
||||
@interface YTRightNavigationButtons : UIView
|
||||
@property (nonatomic, strong) YTQTMButton *notificationButton;
|
||||
@property (nonatomic, strong) YTQTMButton *searchButton;
|
||||
@end
|
||||
@@ -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>
|
||||
@@ -0,0 +1,266 @@
|
||||
#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
|
||||
|
||||
// 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
|
||||
|
||||
// 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:NSClassFromString(@"YTPivotBarItemViewAccessibilityControl")]) {
|
||||
pivotBarAccessibilityControlWidth = CGRectGetWidth(subview.frame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (UIView *subview in self.subviews) {
|
||||
if ([subview isKindOfClass:NSClassFromString(@"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
|
||||
|
||||
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;
|
||||
kRemoveLabels = [prefs[@"removeLabels"] 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;
|
||||
|
||||
NSDictionary *newSettings = @{
|
||||
@"noAds" : @(kNoAds),
|
||||
@"backgroundPlayback" : @(kBackgroundPlayback),
|
||||
@"noCast" : @(kNoCast),
|
||||
@"removeNotifsButton" : @(kNoNotifsButton),
|
||||
@"removeSearchButton" : @(kNoSearchButton),
|
||||
@"removeLabels" : @(kRemoveLabels),
|
||||
@"removeShorts" : @(kRemoveShorts),
|
||||
@"removeSubscriptions" : @(kRemoveSubscriptions),
|
||||
@"removeUploads" : @(kRemoveUploads),
|
||||
@"removeLibrary" : @(kRemoveLibrary)
|
||||
};
|
||||
|
||||
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();
|
||||
%init;
|
||||
}
|
||||
@@ -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,30 @@
|
||||
"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.";
|
||||
|
||||
"Tabbar" = "Tab bar";
|
||||
"RemoveLabels" = "Remove labels";
|
||||
"RemoveLabelsDesc" = "Removes tab labels.";
|
||||
"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";
|
||||
|
||||
"Version" = "Version";
|
||||
"About" = "About";
|
||||
"Credits" = "Credits";
|
||||
"Developer" = "YTLite developer";
|
||||
@@ -0,0 +1,30 @@
|
||||
"General" = "Основные";
|
||||
"RemoveAds" = "Убрать рекламу";
|
||||
"RemoveAdsDesc" = "Убирает рекламу в приложении.";
|
||||
"BackgroundPlayback" = "Фоновое воспроизведение";
|
||||
"BackgroundPlaybackDesc" = "Активирует фоновое воспроизведение.";
|
||||
|
||||
"Navbar" = "Панель навигации";
|
||||
"RemoveCast" = "Скрыть «Трансляция»";
|
||||
"RemoveCastDesc" = "Скрывает кнопку трансляции с панели навигации.";
|
||||
"RemoveNotifications" = "Скрыть «Уведомления»";
|
||||
"RemoveNotificationsDesc" = "Скрывает кнопку уведомлений с панели навигации.";
|
||||
"RemoveSearch" = "Скрыть «Поиск»";
|
||||
"RemoveSearchDesc" = "Скрвыает кнопку поиска с панели навигации.";
|
||||
|
||||
"Tabbar" = "Панель вкладок";
|
||||
"RemoveLabels" = "Скрыть названия";
|
||||
"RemoveLabelsDesc" = "Скрывает названия вкладок.";
|
||||
"HideShortsTab" = "Скрыть «Shorts»";
|
||||
"HideShortsTabDesc" = "Скрывает вкладку «Shorts» с панели вкладок.";
|
||||
"HideSubscriptionsTab" = "Скрыть «Подписки»";
|
||||
"HideSubscriptionsTabDesc" = "Скрывает вкладку «Подписки» с панели вкладок.";
|
||||
"HideUploadButton" = "Скрыть «Создать» (+)";
|
||||
"HideUploadButtonDesc" = "Скрывает кнопку «Создать» с панели вкладок.";
|
||||
"HideLibraryTab" = "Скрыть «Библиотеку»";
|
||||
"HideLibraryTabDesc" = "Скрывает вкладку «Библиотека» с панели вкладок.";
|
||||
|
||||
"Version" = "Версия";
|
||||
"About" = "О твике";
|
||||
"Credits" = "Авторы";
|
||||
"Developer" = "Разработчик твика";
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user