Compare commits

...
21 Commits
Author SHA1 Message Date
Dan 2f601de852 Create FUNDING.yml 2024-03-06 21:04:07 +03:00
Dan bde14ad82b Merge pull request #74 from hiepvk/main
Update Localizable.strings
2024-03-02 12:47:05 +03:00
Hiệpvk 970c566046 Update Localizable.strings 2024-03-02 15:48:58 +07:00
Dan d7c5e540a4 Merge pull request #69 from mumuisdog/main
Update zh-Hant Localizable
2024-03-01 01:01:10 +03:00
Dan 86b5688eae Update Localizable.strings 2024-03-01 01:00:50 +03:00
Dan 341b1cde9d Merge pull request #73 from Deci8BelioS/main
Update Localizable.strings Spanish
2024-03-01 00:55:18 +03:00
DeciBelioS e27e0fa8cf Update Localizable.strings Spanish 2024-02-29 19:50:39 +01:00
mumuisdog e0c7f92288 Update Localizable.strings 2024-02-29 00:46:10 +08:00
Dan 9cf2ca008c Merge pull request #68 from xiangfeidexiaohuo/main
update zh-Hans
2024-02-28 16:37:45 +03:00
xiangfeidexiaohuo 1265e80d15 update zh-Hans
Signed-off-by: xiangfeidexiaohuo <jsjson@163.com>
2024-02-28 21:33:13 +08:00
Dan 56a5e906f3 Merge pull request #67 from Balackburn/main
Updated fr localization
2024-02-28 15:49:34 +03:00
Dan 154ea37acd Update Localizable.strings 2024-02-28 15:47:44 +03:00
Balackburn 0d83236666 Updated fr localization 2024-02-28 13:45:00 +01:00
dayanch96 5bf8181815 2.7 2024-02-28 15:02:46 +03:00
Dan b6958ac963 Merge pull request #66 from xiangfeidexiaohuo/main
update zh-Hans
2024-02-27 12:00:12 +03:00
xiangfeidexiaohuo 8187bbaa13 update zh-Hans
Signed-off-by: xiangfeidexiaohuo <jsjson@163.com>
2024-02-26 23:41:10 +08:00
Dan 5d2c85cb14 Update Localizable.strings 2024-02-24 04:17:39 +03:00
Dan 71b52fc82b Merge pull request #64 from hiepvk/main
Update Localizable.strings
2024-02-22 23:02:50 +03:00
Hiệpvk 6cc81886c0 Update Localizable.strings 2024-02-22 23:06:13 +07:00
Dan 0671598943 Merge pull request #63 from mumuisdog/main
Update zh-Hant Localizable
2024-02-22 17:40:54 +03:00
mumuisdog 8886fb7b61 Update Localizable.strings 2024-02-22 22:26:55 +08:00
21 changed files with 1651 additions and 482 deletions
+2
View File
@@ -0,0 +1,2 @@
github: dayanch96
ko_fi: dayanch96
+3 -3
View File
@@ -5,14 +5,14 @@ endif
DEBUG=0 DEBUG=0
FINALPACKAGE=1 FINALPACKAGE=1
ARCHS = arm64 ARCHS = arm64
PACKAGE_VERSION = 2.6.3 PACKAGE_VERSION = 2.7
TARGET := iphone:clang:latest:13.0 TARGET := iphone:clang:latest:13.0
include $(THEOS)/makefiles/common.mk include $(THEOS)/makefiles/common.mk
TWEAK_NAME = YTLite TWEAK_NAME = YTLite
$(TWEAK_NAME)_FRAMEWORKS = UIKit Foundation $(TWEAK_NAME)_FRAMEWORKS = UIKit Foundation SystemConfiguration
$(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 Sideloading.x $(TWEAK_NAME)_FILES = $(wildcard *.x *.m)
include $(THEOS_MAKE_PATH)/tweak.mk include $(THEOS_MAKE_PATH)/tweak.mk
+103
View File
@@ -0,0 +1,103 @@
/*
Copyright (c) 2011, Tony Million.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
//! Project version number for MacOSReachability.
FOUNDATION_EXPORT double ReachabilityVersionNumber;
//! Project version string for MacOSReachability.
FOUNDATION_EXPORT const unsigned char ReachabilityVersionString[];
/**
* Create NS_ENUM macro if it does not exist on the targeted version of iOS or OS X.
*
* @see http://nshipster.com/ns_enum-ns_options/
**/
#ifndef NS_ENUM
#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#endif
extern NSString *const kReachabilityChangedNotification;
typedef NS_ENUM(NSInteger, NetworkStatus) {
// Apple NetworkStatus Compatible Names.
NotReachable = 0,
ReachableViaWiFi = 2,
ReachableViaWWAN = 1
};
@class Reachability;
typedef void (^NetworkReachable)(Reachability * reachability);
typedef void (^NetworkUnreachable)(Reachability * reachability);
typedef void (^NetworkReachability)(Reachability * reachability, SCNetworkConnectionFlags flags);
@interface Reachability : NSObject
@property (nonatomic, copy) NetworkReachable reachableBlock;
@property (nonatomic, copy) NetworkUnreachable unreachableBlock;
@property (nonatomic, copy) NetworkReachability reachabilityBlock;
@property (nonatomic, assign) BOOL reachableOnWWAN;
+(instancetype)reachabilityWithHostname:(NSString*)hostname;
// This is identical to the function above, but is here to maintain
//compatibility with Apples original code. (see .m)
+(instancetype)reachabilityWithHostName:(NSString*)hostname;
+(instancetype)reachabilityForInternetConnection;
+(instancetype)reachabilityWithAddress:(void *)hostAddress;
+(instancetype)reachabilityForLocalWiFi;
+(instancetype)reachabilityWithURL:(NSURL*)url;
-(instancetype)initWithReachabilityRef:(SCNetworkReachabilityRef)ref;
-(BOOL)startNotifier;
-(void)stopNotifier;
-(BOOL)isReachable;
-(BOOL)isReachableViaWWAN;
-(BOOL)isReachableViaWiFi;
// WWAN may be available, but not active until a connection has been established.
// WiFi may require a connection for VPN on Demand.
-(BOOL)isConnectionRequired; // Identical DDG variant.
-(BOOL)connectionRequired; // Apple's routine.
// Dynamic, on demand connection?
-(BOOL)isConnectionOnDemand;
// Is user intervention required?
-(BOOL)isInterventionRequired;
-(NetworkStatus)currentReachabilityStatus;
-(SCNetworkReachabilityFlags)reachabilityFlags;
-(NSString*)currentReachabilityString;
-(NSString*)currentReachabilityFlags;
@end
+508
View File
@@ -0,0 +1,508 @@
/*
Copyright (c) 2011, Tony Million.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#import "Reachability.h"
#import <sys/socket.h>
#import <netinet/in.h>
#import <netinet6/in6.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
NSString *const kReachabilityChangedNotification = @"kReachabilityChangedNotification";
@interface Reachability ()
@property (nonatomic, assign) SCNetworkReachabilityRef reachabilityRef;
@property (nonatomic, strong) dispatch_queue_t reachabilitySerialQueue;
@property (nonatomic, strong) id reachabilityObject;
-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags;
-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags;
@end
static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags)
{
return [NSString stringWithFormat:@"%c%c %c%c%c%c%c%c%c",
#if TARGET_OS_IPHONE
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
#else
'X',
#endif
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-'];
}
// Start listening for reachability notifications on the current run loop
static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
{
#pragma unused (target)
Reachability *reachability = ((__bridge Reachability*)info);
// We probably don't need an autoreleasepool here, as GCD docs state each queue has its own autorelease pool,
// but what the heck eh?
@autoreleasepool
{
[reachability reachabilityChanged:flags];
}
}
@implementation Reachability
#pragma mark - Class Constructor Methods
+(instancetype)reachabilityWithHostName:(NSString*)hostname
{
return [Reachability reachabilityWithHostname:hostname];
}
+(instancetype)reachabilityWithHostname:(NSString*)hostname
{
SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]);
if (ref)
{
id reachability = [[self alloc] initWithReachabilityRef:ref];
return reachability;
}
return nil;
}
+(instancetype)reachabilityWithAddress:(void *)hostAddress
{
SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
if (ref)
{
id reachability = [[self alloc] initWithReachabilityRef:ref];
return reachability;
}
return nil;
}
+(instancetype)reachabilityForInternetConnection
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
return [self reachabilityWithAddress:&zeroAddress];
}
+(instancetype)reachabilityForLocalWiFi
{
struct sockaddr_in localWifiAddress;
bzero(&localWifiAddress, sizeof(localWifiAddress));
localWifiAddress.sin_len = sizeof(localWifiAddress);
localWifiAddress.sin_family = AF_INET;
// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
return [self reachabilityWithAddress:&localWifiAddress];
}
+(instancetype)reachabilityWithURL:(NSURL*)url
{
id reachability;
NSString *host = url.host;
BOOL isIpAddress = [self isIpAddress:host];
if (isIpAddress)
{
NSNumber *port = url.port ?: [url.scheme isEqualToString:@"https"] ? @(443) : @(80);
struct sockaddr_in address;
address.sin_len = sizeof(address);
address.sin_family = AF_INET;
address.sin_port = htons([port intValue]);
address.sin_addr.s_addr = inet_addr([host UTF8String]);
reachability = [self reachabilityWithAddress:&address];
}
else
{
reachability = [self reachabilityWithHostname:host];
}
return reachability;
}
+(BOOL)isIpAddress:(NSString*)host
{
struct in_addr pin;
return 1 == inet_aton([host UTF8String], &pin);
}
// Initialization methods
-(instancetype)initWithReachabilityRef:(SCNetworkReachabilityRef)ref
{
self = [super init];
if (self != nil)
{
self.reachableOnWWAN = YES;
self.reachabilityRef = ref;
// We need to create a serial queue.
// We allocate this once for the lifetime of the notifier.
self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL);
}
return self;
}
-(void)dealloc
{
[self stopNotifier];
if(self.reachabilityRef)
{
CFRelease(self.reachabilityRef);
self.reachabilityRef = nil;
}
self.reachableBlock = nil;
self.unreachableBlock = nil;
self.reachabilityBlock = nil;
self.reachabilitySerialQueue = nil;
}
#pragma mark - Notifier Methods
// Notifier
// NOTE: This uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD
// - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS.
// INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want)
-(BOOL)startNotifier
{
// allow start notifier to be called multiple times
if(self.reachabilityObject && (self.reachabilityObject == self))
{
return YES;
}
SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL };
context.info = (__bridge void *)self;
if(SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context))
{
// Set it as our reachability queue, which will retain the queue
if(SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue))
{
// this should do a retain on ourself, so as long as we're in notifier mode we shouldn't disappear out from under ourselves
// woah
self.reachabilityObject = self;
return YES;
}
else
{
#ifdef DEBUG
NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError()));
#endif
// UH OH - FAILURE - stop any callbacks!
SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL);
}
}
else
{
#ifdef DEBUG
NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError()));
#endif
}
// if we get here we fail at the internet
self.reachabilityObject = nil;
return NO;
}
-(void)stopNotifier
{
// First stop, any callbacks!
SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL);
// Unregister target from the GCD serial dispatch queue.
SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL);
self.reachabilityObject = nil;
}
#pragma mark - reachability tests
// This is for the case where you flick the airplane mode;
// you end up getting something like this:
//Reachability: WR ct-----
//Reachability: -- -------
//Reachability: WR ct-----
//Reachability: -- -------
// We treat this as 4 UNREACHABLE triggers - really apple should do better than this
#define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection)
-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags
{
BOOL connectionUP = YES;
if(!(flags & kSCNetworkReachabilityFlagsReachable))
connectionUP = NO;
if( (flags & testcase) == testcase )
connectionUP = NO;
#if TARGET_OS_IPHONE
if(flags & kSCNetworkReachabilityFlagsIsWWAN)
{
// We're on 3G.
if(!self.reachableOnWWAN)
{
// We don't want to connect when on 3G.
connectionUP = NO;
}
}
#endif
return connectionUP;
}
-(BOOL)isReachable
{
SCNetworkReachabilityFlags flags;
if(!SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
return NO;
return [self isReachableWithFlags:flags];
}
-(BOOL)isReachableViaWWAN
{
#if TARGET_OS_IPHONE
SCNetworkReachabilityFlags flags = 0;
if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
// Check we're REACHABLE
if(flags & kSCNetworkReachabilityFlagsReachable)
{
// Now, check we're on WWAN
if(flags & kSCNetworkReachabilityFlagsIsWWAN)
{
return YES;
}
}
}
#endif
return NO;
}
-(BOOL)isReachableViaWiFi
{
SCNetworkReachabilityFlags flags = 0;
if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
// Check we're reachable
if((flags & kSCNetworkReachabilityFlagsReachable))
{
#if TARGET_OS_IPHONE
// Check we're NOT on WWAN
if((flags & kSCNetworkReachabilityFlagsIsWWAN))
{
return NO;
}
#endif
return YES;
}
}
return NO;
}
// WWAN may be available, but not active until a connection has been established.
// WiFi may require a connection for VPN on Demand.
-(BOOL)isConnectionRequired
{
return [self connectionRequired];
}
-(BOOL)connectionRequired
{
SCNetworkReachabilityFlags flags;
if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
}
return NO;
}
// Dynamic, on demand connection?
-(BOOL)isConnectionOnDemand
{
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) &&
(flags & (kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand)));
}
return NO;
}
// Is user intervention required?
-(BOOL)isInterventionRequired
{
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) &&
(flags & kSCNetworkReachabilityFlagsInterventionRequired));
}
return NO;
}
#pragma mark - reachability status stuff
-(NetworkStatus)currentReachabilityStatus
{
if([self isReachable])
{
if([self isReachableViaWiFi])
return ReachableViaWiFi;
#if TARGET_OS_IPHONE
return ReachableViaWWAN;
#endif
}
return NotReachable;
}
-(SCNetworkReachabilityFlags)reachabilityFlags
{
SCNetworkReachabilityFlags flags = 0;
if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
return flags;
}
return 0;
}
-(NSString*)currentReachabilityString
{
NetworkStatus temp = [self currentReachabilityStatus];
if(temp == ReachableViaWWAN)
{
// Updated for the fact that we have CDMA phones now!
return NSLocalizedString(@"Cellular", @"");
}
if (temp == ReachableViaWiFi)
{
return NSLocalizedString(@"WiFi", @"");
}
return NSLocalizedString(@"No Connection", @"");
}
-(NSString*)currentReachabilityFlags
{
return reachabilityFlags([self reachabilityFlags]);
}
#pragma mark - Callback function calls this method
-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags
{
if([self isReachableWithFlags:flags])
{
if(self.reachableBlock)
{
self.reachableBlock(self);
}
}
else
{
if(self.unreachableBlock)
{
self.unreachableBlock(self);
}
}
if(self.reachabilityBlock)
{
self.reachabilityBlock(self, flags);
}
// this makes sure the change notification happens on the MAIN THREAD
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification
object:self];
});
}
#pragma mark - Debug Description
- (NSString *) description
{
NSString *description = [NSString stringWithFormat:@"<%@: %p (%@)>",
NSStringFromClass([self class]), self, [self currentReachabilityFlags]];
return description;
}
@end
+272 -203
View File
@@ -41,6 +41,21 @@ static NSString *GetCacheSize() {
} }
%end %end
%hook YTSettingsCell
- (void)layoutSubviews {
%orig;
BOOL isYTLite = [self.accessibilityIdentifier isEqualToString:@"YTLiteSectionItem"];
YTTouchFeedbackController *feedback = [self valueForKey:@"_touchFeedbackController"];
ABCSwitch *abcSwitch = [self valueForKey:@"_switch"];
if (isYTLite) {
feedback.feedbackColor = [UIColor colorWithRed:0.75 green:0.50 blue:0.90 alpha:1.0];
abcSwitch.onTintColor = [UIColor colorWithRed:0.75 green:0.50 blue:0.90 alpha:1.0];
}
}
%end
%hook YTSettingsSectionItemManager %hook YTSettingsSectionItemManager
%new %new
- (void)updatePrefsForKey:(NSString *)key enabled:(BOOL)enabled { - (void)updatePrefsForKey:(NSString *)key enabled:(BOOL)enabled {
@@ -68,12 +83,13 @@ static NSString *GetCacheSize() {
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.dvntm.ytlite.prefschanged"), NULL, NULL, YES); CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.dvntm.ytlite.prefschanged"), NULL, NULL, YES);
} }
static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleDescription, NSString *key, BOOL *value, id selfObject) { static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *key, BOOL *value, id selfObject) {
Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem); Class YTSettingsSectionItemClass = %c(YTSettingsSectionItem);
Class YTAlertViewClass = %c(YTAlertView); Class YTAlertViewClass = %c(YTAlertView);
YTSettingsSectionItem *item = [YTSettingsSectionItemClass switchItemWithTitle:title
titleDescription:titleDescription YTSettingsSectionItem *item = [YTSettingsSectionItemClass switchItemWithTitle:LOC(title)
accessibilityIdentifier:nil titleDescription:LOC([NSString stringWithFormat:@"%@Desc", title])
accessibilityIdentifier:@"YTLiteSectionItem"
switchOn:*value switchOn:*value
switchBlock:^BOOL(YTSettingsCell *cell, BOOL enabled) { switchBlock:^BOOL(YTSettingsCell *cell, BOOL enabled) {
if ([key isEqualToString:@"shortsOnlyMode"]) { if ([key isEqualToString:@"shortsOnlyMode"]) {
@@ -107,17 +123,17 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"]; YTSettingsViewController *settingsViewController = [self valueForKey:@"_settingsViewControllerDelegate"];
id selfObject = self; id selfObject = self;
YTSettingsSectionItem *space = [%c(YTSettingsSectionItem) itemWithTitle:nil accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { return YES; }]; YTSettingsSectionItem *space = [%c(YTSettingsSectionItem) itemWithTitle:nil accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:nil selectBlock:nil];
YTSettingsSectionItem *general = [YTSettingsSectionItemClass itemWithTitle:LOC(@"General") YTSettingsSectionItem *general = [YTSettingsSectionItemClass itemWithTitle:LOC(@"General")
accessibilityIdentifier:nil accessibilityIdentifier:@"YTLiteSectionItem"
detailTextBlock:^NSString *() { detailTextBlock:^NSString *() {
return @"‣"; return @"‣";
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ NSArray <YTSettingsSectionItem *> *rows = @[
createSwitchItem(LOC(@"RemoveAds"), LOC(@"RemoveAdsDesc"), @"noAds", &kNoAds, selfObject), createSwitchItem(@"RemoveAds", @"noAds", &kNoAds, selfObject),
createSwitchItem(LOC(@"BackgroundPlayback"), LOC(@"BackgroundPlaybackDesc"), @"backgroundPlayback", &kBackgroundPlayback, selfObject) createSwitchItem(@"BackgroundPlayback", @"backgroundPlayback", &kBackgroundPlayback, selfObject)
]; ];
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]];
@@ -127,26 +143,26 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
[sectionItems addObject:general]; [sectionItems addObject:general];
YTSettingsSectionItem *navbar = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Navbar") YTSettingsSectionItem *navbar = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Navbar")
accessibilityIdentifier:nil accessibilityIdentifier:@"YTLiteSectionItem"
detailTextBlock:^NSString *() { detailTextBlock:^NSString *() {
return @"‣"; return @"‣";
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ NSArray <YTSettingsSectionItem *> *rows = @[
createSwitchItem(LOC(@"RemoveCast"), LOC(@"RemoveCastDesc"), @"noCast", &kNoCast, selfObject), createSwitchItem(@"RemoveCast", @"noCast", &kNoCast, selfObject),
createSwitchItem(LOC(@"RemoveNotifications"), LOC(@"RemoveNotificationsDesc"), @"removeNotifsButton", &kNoNotifsButton, selfObject), createSwitchItem(@"RemoveNotifications", @"removeNotifsButton", &kNoNotifsButton, selfObject),
createSwitchItem(LOC(@"RemoveSearch"), LOC(@"RemoveSearchDesc"), @"removeSearchButton", &kNoSearchButton, selfObject), createSwitchItem(@"RemoveSearch", @"removeSearchButton", &kNoSearchButton, selfObject),
createSwitchItem(LOC(@"RemoveVoiceSearch"), LOC(@"RemoveVoiceSearchDesc"), @"removeVoiceSearchButton", &kNoVoiceSearchButton, selfObject) createSwitchItem(@"RemoveVoiceSearch", @"removeVoiceSearchButton", &kNoVoiceSearchButton, selfObject)
]; ];
if (kAdvancedMode) { if (kAdvancedMode) {
YTSettingsSectionItem *addStickyNavbar = createSwitchItem(LOC(@"StickyNavbar"), LOC(@"StickyNavbarDesc"), @"stickyNavbar", &kStickyNavbar, selfObject); YTSettingsSectionItem *addStickyNavbar = createSwitchItem(@"StickyNavbar", @"stickyNavbar", &kStickyNavbar, selfObject);
rows = [rows arrayByAddingObject:addStickyNavbar]; rows = [rows arrayByAddingObject:addStickyNavbar];
YTSettingsSectionItem *addNoSubbar = createSwitchItem(LOC(@"NoSubbar"), LOC(@"NoSubbarDesc"), @"noSubbar", &kNoSubbar, selfObject); YTSettingsSectionItem *addNoSubbar = createSwitchItem(@"NoSubbar", @"noSubbar", &kNoSubbar, selfObject);
rows = [rows arrayByAddingObject:addNoSubbar]; rows = [rows arrayByAddingObject:addNoSubbar];
YTSettingsSectionItem *addNoYTLogo = createSwitchItem(LOC(@"NoYTLogo"), LOC(@"NoYTLogoDesc"), @"noYTLogo", &kNoYTLogo, selfObject); YTSettingsSectionItem *addNoYTLogo = createSwitchItem(@"NoYTLogo", @"noYTLogo", &kNoYTLogo, selfObject);
rows = [rows arrayByAddingObject:addNoYTLogo]; rows = [rows arrayByAddingObject:addNoYTLogo];
} }
@@ -158,24 +174,24 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
if (kAdvancedMode) { if (kAdvancedMode) {
YTSettingsSectionItem *overlay = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Overlay") YTSettingsSectionItem *overlay = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Overlay")
accessibilityIdentifier:nil accessibilityIdentifier:@"YTLiteSectionItem"
detailTextBlock:^NSString *() { detailTextBlock:^NSString *() {
return @"‣"; return @"‣";
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ NSArray <YTSettingsSectionItem *> *rows = @[
createSwitchItem(LOC(@"HideAutoplay"), LOC(@"HideAutoplayDesc"), @"hideAutoplay", &kHideAutoplay, selfObject), createSwitchItem(@"HideAutoplay", @"hideAutoplay", &kHideAutoplay, selfObject),
createSwitchItem(LOC(@"HideSubs"), LOC(@"HideSubsDesc"), @"hideSubs", &kHideSubs, selfObject), createSwitchItem(@"HideSubs", @"hideSubs", &kHideSubs, selfObject),
createSwitchItem(LOC(@"NoHUDMsgs"), LOC(@"NoHUDMsgsDesc"), @"noHUDMsgs", &kNoHUDMsgs, selfObject), createSwitchItem(@"NoHUDMsgs", @"noHUDMsgs", &kNoHUDMsgs, selfObject),
createSwitchItem(LOC(@"HidePrevNext"), LOC(@"HidePrevNextDesc"), @"hidePrevNext", &kHidePrevNext, selfObject), createSwitchItem(@"HidePrevNext", @"hidePrevNext", &kHidePrevNext, selfObject),
createSwitchItem(LOC(@"ReplacePrevNext"), LOC(@"ReplacePrevNextDesc"), @"replacePrevNext", &kReplacePrevNext, selfObject), createSwitchItem(@"ReplacePrevNext", @"replacePrevNext", &kReplacePrevNext, selfObject),
createSwitchItem(LOC(@"NoDarkBg"), LOC(@"NoDarkBgDesc"), @"noDarkBg", &kNoDarkBg, selfObject), createSwitchItem(@"NoDarkBg", @"noDarkBg", &kNoDarkBg, selfObject),
createSwitchItem(LOC(@"NoEndScreenCards"), LOC(@"NoEndScreenCardsDesc"), @"endScreenCards", &kEndScreenCards, selfObject), createSwitchItem(@"NoEndScreenCards", @"endScreenCards", &kEndScreenCards, selfObject),
createSwitchItem(LOC(@"NoFullscreenActions"), LOC(@"NoFullscreenActionsDesc"), @"noFullscreenActions", &kNoFullscreenActions, selfObject), createSwitchItem(@"NoFullscreenActions", @"noFullscreenActions", &kNoFullscreenActions, selfObject),
createSwitchItem(LOC(@"PersistentProgressBar"), LOC(@"PersistentProgressBarDesc"), @"persistentProgressBar", &kPersistentProgressBar, selfObject), createSwitchItem(@"PersistentProgressBar", @"persistentProgressBar", &kPersistentProgressBar, selfObject),
createSwitchItem(LOC(@"NoRelatedVids"), LOC(@"NoRelatedVidsDesc"), @"noRelatedVids", &kNoRelatedVids, selfObject), createSwitchItem(@"NoRelatedVids", @"noRelatedVids", &kNoRelatedVids, selfObject),
createSwitchItem(LOC(@"NoPromotionCards"), LOC(@"NoPromotionCardsDesc"), @"noPromotionCards", &kNoPromotionCards, selfObject), createSwitchItem(@"NoPromotionCards", @"noPromotionCards", &kNoPromotionCards, selfObject),
createSwitchItem(LOC(@"NoWatermarks"), LOC(@"NoWatermarksDesc"), @"noWatermarks", &kNoWatermarks, selfObject) createSwitchItem(@"NoWatermarks", @"noWatermarks", &kNoWatermarks, selfObject)
]; ];
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Overlay") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Overlay") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
@@ -185,27 +201,30 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
[sectionItems addObject:overlay]; [sectionItems addObject:overlay];
YTSettingsSectionItem *player = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Player") YTSettingsSectionItem *player = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Player")
accessibilityIdentifier:nil accessibilityIdentifier:@"YTLiteSectionItem"
detailTextBlock:^NSString *() { detailTextBlock:^NSString *() {
return @"‣"; return @"‣";
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ NSArray <YTSettingsSectionItem *> *rows = @[
createSwitchItem(LOC(@"Miniplayer"), LOC(@"MiniplayerDesc"), @"miniplayer", &kMiniplayer, selfObject), createSwitchItem(@"Miniplayer", @"miniplayer", &kMiniplayer, selfObject),
createSwitchItem(LOC(@"PortraitFullscreen"), LOC(@"PortraitFullscreenDesc"), @"portraitFullscreen", &kPortraitFullscreen, selfObject), createSwitchItem(@"PortraitFullscreen", @"portraitFullscreen", &kPortraitFullscreen, selfObject),
createSwitchItem(LOC(@"CopyWithTimestamp"), LOC(@"CopyWithTimestampDesc"), @"copyWithTimestamp", &kCopyWithTimestamp, selfObject), createSwitchItem(@"CopyWithTimestamp", @"copyWithTimestamp", &kCopyWithTimestamp, selfObject),
createSwitchItem(LOC(@"DisableAutoplay"), LOC(@"DisableAutoplayDesc"), @"disableAutoplay", &kDisableAutoplay, selfObject), createSwitchItem(@"DisableAutoplay", @"disableAutoplay", &kDisableAutoplay, selfObject),
createSwitchItem(LOC(@"DisableAutoCaptions"), LOC(@"DisableAutoCaptionsDesc"), @"disableAutoCaptions", &kDisableAutoCaptions, selfObject), createSwitchItem(@"DisableAutoCaptions", @"disableAutoCaptions", &kDisableAutoCaptions, selfObject),
createSwitchItem(LOC(@"NoContentWarning"), LOC(@"NoContentWarningDesc"), @"noContentWarning", &kNoContentWarning, selfObject), createSwitchItem(@"NoContentWarning", @"noContentWarning", &kNoContentWarning, selfObject),
createSwitchItem(LOC(@"ClassicQuality"), LOC(@"ClassicQualityDesc"), @"classicQuality", &kClassicQuality, selfObject), createSwitchItem(@"ClassicQuality", @"classicQuality", &kClassicQuality, selfObject),
createSwitchItem(LOC(@"ExtraSpeedOptions"), LOC(@"ExtraSpeedOptionsDesc"), @"extraSpeedOptions", &kExtraSpeedOptions, selfObject), createSwitchItem(@"ExtraSpeedOptions", @"extraSpeedOptions", &kExtraSpeedOptions, selfObject),
createSwitchItem(LOC(@"DontSnap2Chapter"), LOC(@"DontSnap2ChapterDesc"), @"dontSnapToChapter", &kDontSnapToChapter, selfObject), createSwitchItem(@"DontSnap2Chapter", @"dontSnapToChapter", &kDontSnapToChapter, selfObject),
createSwitchItem(LOC(@"RedProgressBar"), LOC(@"RedProgressBarDesc"), @"redProgressBar", &kRedProgressBar, selfObject), createSwitchItem(@"RedProgressBar", @"redProgressBar", &kRedProgressBar, selfObject),
createSwitchItem(LOC(@"NoHints"), LOC(@"NoHintsDesc"), @"noHints", &kNoHints, selfObject), createSwitchItem(@"NoPlayerRemixButton", @"noPlayerRemixButton", &kNoPlayerRemixButton, selfObject),
createSwitchItem(LOC(@"NoFreeZoom"), LOC(@"NoFreeZoomDesc"), @"noFreeZoom", &kNoFreeZoom, selfObject), createSwitchItem(@"NoPlayerClipButton", @"noPlayerClipButton", &kNoPlayerClipButton, selfObject),
createSwitchItem(LOC(@"AutoFullscreen"), LOC(@"AutoFullscreenDesc"), @"autoFullscreen", &kAutoFullscreen, selfObject), createSwitchItem(@"NoPlayerDownloadButton", @"noPlayerDownloadButton", &kNoPlayerDownloadButton, selfObject),
createSwitchItem(LOC(@"ExitFullscreen"), LOC(@"ExitFullscreenDesc"), @"exitFullscreen", &kExitFullscreen, selfObject), createSwitchItem(@"NoHints", @"noHints", &kNoHints, selfObject),
createSwitchItem(LOC(@"NoDoubleTap2Seek"), LOC(@"NoDoubleTap2SeekDesc"), @"noDoubleTapToSeek", &kNoDoubleTapToSeek, selfObject) createSwitchItem(@"NoFreeZoom", @"noFreeZoom", &kNoFreeZoom, selfObject),
createSwitchItem(@"AutoFullscreen", @"autoFullscreen", &kAutoFullscreen, selfObject),
createSwitchItem(@"ExitFullscreen", @"exitFullscreen", &kExitFullscreen, selfObject),
createSwitchItem(@"NoDoubleTap2Seek", @"noDoubleTapToSeek", &kNoDoubleTapToSeek, selfObject)
]; ];
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Player") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Player") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
@@ -215,35 +234,35 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
[sectionItems addObject:player]; [sectionItems addObject:player];
YTSettingsSectionItem *shorts = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Shorts") YTSettingsSectionItem *shorts = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Shorts")
accessibilityIdentifier:nil accessibilityIdentifier:@"YTLiteSectionItem"
detailTextBlock:^NSString *() { detailTextBlock:^NSString *() {
return @"‣"; return @"‣";
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ NSArray <YTSettingsSectionItem *> *rows = @[
createSwitchItem(LOC(@"ShortsOnlyMode"), LOC(@"ShortsOnlyModeDesc"), @"shortsOnlyMode", &kShortsOnlyMode, selfObject), createSwitchItem(@"ShortsOnlyMode", @"shortsOnlyMode", &kShortsOnlyMode, selfObject),
createSwitchItem(LOC(@"HideShorts"), LOC(@"HideShortsDesc"), @"hideShorts", &kHideShorts, selfObject), createSwitchItem(@"HideShorts", @"hideShorts", &kHideShorts, selfObject),
createSwitchItem(LOC(@"ShortsProgress"), LOC(@"ShortsProgressDesc"), @"shortsProgress", &kShortsProgress, selfObject), createSwitchItem(@"ShortsProgress", @"shortsProgress", &kShortsProgress, selfObject),
createSwitchItem(LOC(@"PinchToFullscreenShorts"), LOC(@"PinchToFullscreenShortsDesc"), @"pinchToFullscreenShorts", &kPinchToFullscreenShorts, selfObject), createSwitchItem(@"PinchToFullscreenShorts", @"pinchToFullscreenShorts", &kPinchToFullscreenShorts, selfObject),
createSwitchItem(LOC(@"ShortsToRegular"), LOC(@"ShortsToRegularDesc"), @"shortsToRegular", &kShortsToRegular, selfObject), createSwitchItem(@"ShortsToRegular", @"shortsToRegular", &kShortsToRegular, selfObject),
createSwitchItem(LOC(@"ResumeShorts"), LOC(@"ResumeShortsDesc"), @"resumeShorts", &kResumeShorts, selfObject), createSwitchItem(@"ResumeShorts", @"resumeShorts", &kResumeShorts, selfObject),
createSwitchItem(LOC(@"HideShortsLogo"), LOC(@"HideShortsLogoDesc"), @"hideShortsLogo", &kHideShortsLogo, selfObject), createSwitchItem(@"HideShortsLogo", @"hideShortsLogo", &kHideShortsLogo, selfObject),
createSwitchItem(LOC(@"HideShortsSearch"), LOC(@"HideShortsSearchDesc"), @"hideShortsSearch", &kHideShortsSearch, selfObject), createSwitchItem(@"HideShortsSearch", @"hideShortsSearch", &kHideShortsSearch, selfObject),
createSwitchItem(LOC(@"HideShortsCamera"), LOC(@"HideShortsCameraDesc"), @"hideShortsCamera", &kHideShortsCamera, selfObject), createSwitchItem(@"HideShortsCamera", @"hideShortsCamera", &kHideShortsCamera, selfObject),
createSwitchItem(LOC(@"HideShortsMore"), LOC(@"HideShortsMoreDesc"), @"hideShortsMore", &kHideShortsMore, selfObject), createSwitchItem(@"HideShortsMore", @"hideShortsMore", &kHideShortsMore, selfObject),
createSwitchItem(LOC(@"HideShortsSubscriptions"), LOC(@"HideShortsSubscriptionsDesc"), @"hideShortsSubscriptions", &kHideShortsSubscriptions, selfObject), createSwitchItem(@"HideShortsSubscriptions", @"hideShortsSubscriptions", &kHideShortsSubscriptions, selfObject),
createSwitchItem(LOC(@"HideShortsLike"), LOC(@"HideShortsLikeDesc"), @"hideShortsLike", &kHideShortsLike, selfObject), createSwitchItem(@"HideShortsLike", @"hideShortsLike", &kHideShortsLike, selfObject),
createSwitchItem(LOC(@"HideShortsDislike"), LOC(@"HideShortsDislikeDesc"), @"hideShortsDislike", &kHideShortsDislike, selfObject), createSwitchItem(@"HideShortsDislike", @"hideShortsDislike", &kHideShortsDislike, selfObject),
createSwitchItem(LOC(@"HideShortsComments"), LOC(@"HideShortsCommentsDesc"), @"hideShortsComments", &kHideShortsComments, selfObject), createSwitchItem(@"HideShortsComments", @"hideShortsComments", &kHideShortsComments, selfObject),
createSwitchItem(LOC(@"HideShortsRemix"), LOC(@"HideShortsRemixDesc"), @"hideShortsRemix", &kHideShortsRemix, selfObject), createSwitchItem(@"HideShortsRemix", @"hideShortsRemix", &kHideShortsRemix, selfObject),
createSwitchItem(LOC(@"HideShortsShare"), LOC(@"HideShortsShareDesc"), @"hideShortsShare", &kHideShortsShare, selfObject), createSwitchItem(@"HideShortsShare", @"hideShortsShare", &kHideShortsShare, selfObject),
createSwitchItem(LOC(@"HideShortsAvatars"), LOC(@"HideShortsAvatarsDesc"), @"hideShortsAvatars", &kHideShortsAvatars, selfObject), createSwitchItem(@"HideShortsAvatars", @"hideShortsAvatars", &kHideShortsAvatars, selfObject),
createSwitchItem(LOC(@"HideShortsThanks"), LOC(@"HideShortsThanksDesc"), @"hideShortsThanks", &kHideShortsThanks, selfObject), createSwitchItem(@"HideShortsThanks", @"hideShortsThanks", &kHideShortsThanks, selfObject),
createSwitchItem(LOC(@"HideShortsSource"), LOC(@"HideShortsSourceDesc"), @"hideShortsSource", &kHideShortsSource, selfObject), createSwitchItem(@"HideShortsSource", @"hideShortsSource", &kHideShortsSource, selfObject),
createSwitchItem(LOC(@"HideShortsChannelName"), LOC(@"HideShortsChannelNameDesc"), @"hideShortsChannelName", &kHideShortsChannelName, selfObject), createSwitchItem(@"HideShortsChannelName", @"hideShortsChannelName", &kHideShortsChannelName, selfObject),
createSwitchItem(LOC(@"HideShortsDescription"), LOC(@"HideShortsDescriptionDesc"), @"hideShortsDescription", &kHideShortsDescription, selfObject), createSwitchItem(@"HideShortsDescription", @"hideShortsDescription", &kHideShortsDescription, selfObject),
createSwitchItem(LOC(@"HideShortsAudioTrack"), LOC(@"HideShortsAudioTrackDesc"), @"hideShortsAudioTrack", &kHideShortsAudioTrack, selfObject), createSwitchItem(@"HideShortsAudioTrack", @"hideShortsAudioTrack", &kHideShortsAudioTrack, selfObject),
createSwitchItem(LOC(@"NoPromotionCards"), LOC(@"NoPromotionCardsDesc"), @"hideShortsPromoCards", &kHideShortsPromoCards, selfObject) createSwitchItem(@"NoPromotionCards", @"hideShortsPromoCards", &kHideShortsPromoCards, selfObject)
]; ];
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Shorts") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Shorts") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
[settingsViewController pushViewController:picker]; [settingsViewController pushViewController:picker];
@@ -253,20 +272,20 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
} }
YTSettingsSectionItem *tabbar = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Tabbar") YTSettingsSectionItem *tabbar = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Tabbar")
accessibilityIdentifier:nil accessibilityIdentifier:@"YTLiteSectionItem"
detailTextBlock:^NSString *() { detailTextBlock:^NSString *() {
return @"‣"; return @"‣";
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ NSArray <YTSettingsSectionItem *> *rows = @[
createSwitchItem(LOC(@"RemoveLabels"), LOC(@"RemoveLabelsDesc"), @"removeLabels", &kRemoveLabels, selfObject), createSwitchItem(@"RemoveLabels", @"removeLabels", &kRemoveLabels, selfObject),
createSwitchItem(LOC(@"RemoveIndicators"), LOC(@"RemoveIndicatorsDesc"), @"removeIndicators", &kRemoveIndicators, selfObject), createSwitchItem(@"RemoveIndicators", @"removeIndicators", &kRemoveIndicators, selfObject),
createSwitchItem(LOC(@"ReExplore"), LOC(@"ReExploreDesc"), @"reExplore", &kReExplore, selfObject), createSwitchItem(@"ReExplore", @"reExplore", &kReExplore, selfObject),
createSwitchItem(LOC(@"AddExplore"), LOC(@"AddExploreDesc"), @"addExplore", &kAddExplore, selfObject), createSwitchItem(@"AddExplore", @"addExplore", &kAddExplore, selfObject),
createSwitchItem(LOC(@"HideShortsTab"), LOC(@"HideShortsTabDesc"), @"removeShorts", &kRemoveShorts, selfObject), createSwitchItem(@"HideShortsTab", @"removeShorts", &kRemoveShorts, selfObject),
createSwitchItem(LOC(@"HideSubscriptionsTab"), LOC(@"HideSubscriptionsTabDesc"), @"removeSubscriptions", &kRemoveSubscriptions, selfObject), createSwitchItem(@"HideSubscriptionsTab", @"removeSubscriptions", &kRemoveSubscriptions, selfObject),
createSwitchItem(LOC(@"HideUploadButton"), LOC(@"HideUploadButtonDesc"), @"removeUploads", &kRemoveUploads, selfObject), createSwitchItem(@"HideUploadButton", @"removeUploads", &kRemoveUploads, selfObject),
createSwitchItem(LOC(@"HideLibraryTab"), LOC(@"HideLibraryTabDesc"), @"removeLibrary", &kRemoveLibrary, selfObject) createSwitchItem(@"HideLibraryTab", @"removeLibrary", &kRemoveLibrary, selfObject)
]; ];
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]];
@@ -277,26 +296,32 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
if (kAdvancedMode) { if (kAdvancedMode) {
YTSettingsSectionItem *other = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Other") YTSettingsSectionItem *other = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Other")
accessibilityIdentifier:nil accessibilityIdentifier:@"YTLiteSectionItem"
detailTextBlock:^NSString *() { detailTextBlock:^NSString *() {
return @"‣"; return @"‣";
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ NSArray <YTSettingsSectionItem *> *rows = @[
createSwitchItem(LOC(@"CopyVideoInfo"), LOC(@"CopyVideoInfoDesc"), @"copyVideoInfo", &kCopyVideoInfo, selfObject), createSwitchItem(@"CopyVideoInfo", @"copyVideoInfo", &kCopyVideoInfo, selfObject),
createSwitchItem(LOC(@"PostManager"), LOC(@"PostManagerDesc"), @"postManager", &kPostManager, selfObject), createSwitchItem(@"PostManager", @"postManager", &kPostManager, selfObject),
createSwitchItem(LOC(@"SavePostImage"), LOC(@"SavePostImageDesc"), @"savePostImage", &kSavePostImage, selfObject), createSwitchItem(@"SaveProfilePhoto", @"saveProfilePhoto", &kSaveProfilePhoto, selfObject),
createSwitchItem(LOC(@"SaveProfilePhoto"), LOC(@"SaveProfilePhotoDesc"), @"saveProfilePhoto", &kSaveProfilePhoto, selfObject), createSwitchItem(@"CommentManager", @"commentManager", &kCommentManager, selfObject),
createSwitchItem(LOC(@"CommentManager"), LOC(@"CommentManagerDesc"), @"commentManager", &kCommentManager, selfObject), createSwitchItem(@"FixAlbums", @"fixAlbums", &kFixAlbums, selfObject),
createSwitchItem(LOC(@"FixAlbums"), LOC(@"FixAlbumsDesc"), @"fixAlbums", &kFixAlbums, selfObject), createSwitchItem(@"RemovePlayNext", @"removePlayNext", &kRemovePlayNext, selfObject),
createSwitchItem(LOC(@"RemovePlayNext"), LOC(@"RemovePlayNextDesc"), @"removePlayNext", &kRemovePlayNext, selfObject), createSwitchItem(@"RemoveDownloadMenu", @"removeDownloadMenu", &kRemoveDownloadMenu, selfObject),
createSwitchItem(LOC(@"NoContinueWatching"), LOC(@"NoContinueWatchingDesc"), @"noContinueWatching", &kNoContinueWatching, selfObject), createSwitchItem(@"RemoveWatchLaterMenu", @"removeWatchLaterMenu", &kRemoveWatchLaterMenu, selfObject),
createSwitchItem(LOC(@"NoSearchHistory"), LOC(@"NoSearchHistoryDesc"), @"noSearchHistory", &kNoSearchHistory, selfObject), createSwitchItem(@"RemoveSaveToPlaylistMenu", @"removeSaveToPlaylistMenu", &kRemoveSaveToPlaylistMenu, selfObject),
createSwitchItem(LOC(@"NoRelatedWatchNexts"), LOC(@"NoRelatedWatchNextsDesc"), @"noRelatedWatchNexts", &kNoRelatedWatchNexts, selfObject), createSwitchItem(@"RemoveShareMenu", @"removeShareMenu", &kRemoveShareMenu, selfObject),
createSwitchItem(LOC(@"StickSortComments"), LOC(@"StickSortCommentsDesc"), @"stickSortComments", &kStickSortComments, selfObject), createSwitchItem(@"RemoveNotInterestedMenu", @"removeNotInterestedMenu", &kRemoveNotInterestedMenu, selfObject),
createSwitchItem(LOC(@"HideSortComments"), LOC(@"HideSortCommentsDesc"), @"hideSortComments", &kHideSortComments, selfObject), createSwitchItem(@"RemoveDontRecommendMenu", @"removeDontRecommendMenu", &kRemoveDontRecommendMenu, selfObject),
createSwitchItem(LOC(@"PlaylistOldMinibar"), LOC(@"PlaylistOldMinibarDesc"), @"playlistOldMinibar", &kPlaylistOldMinibar, selfObject), createSwitchItem(@"RemoveReportMenu", @"removeReportMenu", &kRemoveReportMenu, selfObject),
createSwitchItem(LOC(@"DisableRTL"), LOC(@"DisableRTLDesc"), @"disableRTL", &kDisableRTL, selfObject) createSwitchItem(@"NoContinueWatching", @"noContinueWatching", &kNoContinueWatching, selfObject),
createSwitchItem(@"NoSearchHistory", @"noSearchHistory", &kNoSearchHistory, selfObject),
createSwitchItem(@"NoRelatedWatchNexts", @"noRelatedWatchNexts", &kNoRelatedWatchNexts, selfObject),
createSwitchItem(@"StickSortComments", @"stickSortComments", &kStickSortComments, selfObject),
createSwitchItem(@"HideSortComments", @"hideSortComments", &kHideSortComments, selfObject),
createSwitchItem(@"PlaylistOldMinibar", @"playlistOldMinibar", &kPlaylistOldMinibar, selfObject),
createSwitchItem(@"DisableRTL", @"disableRTL", &kDisableRTL, selfObject)
]; ];
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Other") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]]; YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Other") pickerSectionTitle:nil rows:rows selectedItemIndex:NSNotFound parentResponder:[self parentResponder]];
@@ -307,88 +332,121 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
[sectionItems addObject:space]; [sectionItems addObject:space];
YTSettingsSectionItem *startup = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Startup") YTSettingsSectionItem *wifiQuality = [YTSettingsSectionItemClass itemWithTitle:LOC(@"PlaybackQualityOnWiFi")
accessibilityIdentifier:nil accessibilityIdentifier:@"YTLiteSectionItem"
detailTextBlock:^NSString *() { detailTextBlock:^NSString *() {
switch (kPivotIndex) { NSString *qualityLabel = kWiFiQualityIndex == 1 ? LOC(@"Best") :
case 1: kWiFiQualityIndex == 2 ? @"2160p60" :
return LOC(@"Explore"); kWiFiQualityIndex == 3 ? @"2160p" :
case 2: kWiFiQualityIndex == 4 ? @"1440p60" :
return LOC(@"ShortsTab"); kWiFiQualityIndex == 5 ? @"1440p" :
case 3: kWiFiQualityIndex == 6 ? @"1080p60" :
return LOC(@"Subscriptions"); kWiFiQualityIndex == 7 ? @"1080p" :
case 4: kWiFiQualityIndex == 8 ? @"720p60" :
return LOC(@"Library"); kWiFiQualityIndex == 9 ? @"720p" :
case 0: kWiFiQualityIndex == 10 ? @"480p" :
default: kWiFiQualityIndex == 11 ? @"360p" :
return LOC(@"Home"); LOC(@"Default");
}
return qualityLabel;
} }
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSArray <YTSettingsSectionItem *> *rows = @[ NSMutableArray <YTSettingsSectionItem *> *rows = [NSMutableArray array];
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"Home") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *home, NSUInteger arg1) { NSArray *qualityTitles = @[LOC(@"Default"), LOC(@"Best"), @"2160p60", @"2160p", @"1440p60", @"1440p", @"1080p60", @"1080p", @"720p60", @"720p", @"480p", @"360p"];
kPivotIndex = 0;
for (NSUInteger i = 0; i < qualityTitles.count; i++) {
NSString *title = qualityTitles[i];
YTSettingsSectionItem *item = [YTSettingsSectionItemClass checkmarkItemWithTitle:title titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
kWiFiQualityIndex = (int)arg1;
[settingsViewController reloadData]; [settingsViewController reloadData];
[self updateIntegerPrefsForKey:@"pivotIndex" intValue:kPivotIndex]; [self updateIntegerPrefsForKey:@"wifiQualityIndex" intValue:kWiFiQualityIndex];
return YES; return YES;
}], }];
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"Explore") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *library, NSUInteger arg1) { [rows addObject:item];
if (!kReExplore && !kAddExplore) { }
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"SelectQuality") pickerSectionTitle:nil rows:rows selectedItemIndex:kWiFiQualityIndex parentResponder:[self parentResponder]];
[settingsViewController pushViewController:picker];
return YES;
}];
[sectionItems addObject:wifiQuality];
YTSettingsSectionItem *cellQuality = [YTSettingsSectionItemClass itemWithTitle:LOC(@"PlaybackQualityOnCellular")
accessibilityIdentifier:@"YTLiteSectionItem"
detailTextBlock:^NSString *() {
NSString *qualityLabel = kCellQualityIndex == 1 ? LOC(@"Best") :
kCellQualityIndex == 2 ? @"2160p60" :
kCellQualityIndex == 3 ? @"2160p" :
kCellQualityIndex == 4 ? @"1440p60" :
kCellQualityIndex == 5 ? @"1440p" :
kCellQualityIndex == 6 ? @"1080p60" :
kCellQualityIndex == 7 ? @"1080p" :
kCellQualityIndex == 8 ? @"720p60" :
kCellQualityIndex == 9 ? @"720p" :
kCellQualityIndex == 10 ? @"480p" :
kCellQualityIndex == 11 ? @"360p" :
LOC(@"Default");
return qualityLabel;
}
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSMutableArray <YTSettingsSectionItem *> *rows = [NSMutableArray array];
NSArray *qualityTitles = @[LOC(@"Default"), LOC(@"Best"), @"2160p60", @"2160p", @"1440p60", @"1440p", @"1080p60", @"1080p", @"720p60", @"720p", @"480p", @"360p"];
for (NSUInteger i = 0; i < qualityTitles.count; i++) {
NSString *title = qualityTitles[i];
YTSettingsSectionItem *item = [YTSettingsSectionItemClass checkmarkItemWithTitle:title titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
kCellQualityIndex = (int)arg1;
[settingsViewController reloadData];
[self updateIntegerPrefsForKey:@"cellQualityIndex" intValue:kCellQualityIndex];
return YES;
}];
[rows addObject:item];
}
YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"SelectQuality") pickerSectionTitle:nil rows:rows selectedItemIndex:kCellQualityIndex parentResponder:[self parentResponder]];
[settingsViewController pushViewController:picker];
return YES;
}];
[sectionItems addObject:cellQuality];
YTSettingsSectionItem *startup = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Startup")
accessibilityIdentifier:@"YTLiteSectionItem"
detailTextBlock:^NSString *() {
NSString *tabLabel = kPivotIndex == 1 ? LOC(@"Explore") :
kPivotIndex == 2 ? LOC(@"ShortsTab") :
kPivotIndex == 3 ? LOC(@"Subscriptions") :
kPivotIndex == 4 ? LOC(@"Library") :
LOC(@"Home");
return tabLabel;
}
selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
NSMutableArray <YTSettingsSectionItem *> *rows = [NSMutableArray array];
NSArray *tabTitles = @[LOC(@"Home"), LOC(@"Explore"), LOC(@"ShortsTab"), LOC(@"Subscriptions"), LOC(@"Library")];
for (NSUInteger i = 0; i < tabTitles.count; i++) {
NSString *title = tabTitles[i];
YTSettingsSectionItem *item = [YTSettingsSectionItemClass checkmarkItemWithTitle:title titleDescription:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
if (([title isEqualToString:LOC(@"Explore")] && !kReExplore && !kAddExplore) ||
([title isEqualToString:LOC(@"ShortsTab")] && kRemoveShorts) ||
([title isEqualToString:LOC(@"Subscriptions")] && kRemoveSubscriptions) ||
([title isEqualToString:LOC(@"Library")] && kRemoveLibrary)) {
YTAlertView *alertView = [%c(YTAlertView) infoDialog]; YTAlertView *alertView = [%c(YTAlertView) infoDialog];
alertView.title = LOC(@"Warning"); alertView.title = LOC(@"Warning");
alertView.subtitle = LOC(@"TabIsHidden"); alertView.subtitle = LOC(@"TabIsHidden");
[alertView show]; [alertView show];
return NO; return NO;
} else { } else {
kPivotIndex = 1; kPivotIndex = (int)arg1;
[settingsViewController reloadData]; [settingsViewController reloadData];
[self updateIntegerPrefsForKey:@"pivotIndex" intValue:kPivotIndex]; [self updateIntegerPrefsForKey:@"pivotIndex" intValue:kPivotIndex];
return YES; return YES;
} }
}], }];
[YTSettingsSectionItemClass checkmarkItemWithTitle:LOC(@"ShortsTab") titleDescription:nil selectBlock:^BOOL (YTSettingsCell *shorts, NSUInteger arg1) { [rows addObject:item];
if (kRemoveShorts) {
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(@"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 = 3;
[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 = 4;
[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]]; YTSettingsPickerViewController *picker = [[%c(YTSettingsPickerViewController) alloc] initWithNavTitle:LOC(@"Startup") pickerSectionTitle:nil rows:rows selectedItemIndex:kPivotIndex parentResponder:[self parentResponder]];
[settingsViewController pushViewController:picker]; [settingsViewController pushViewController:picker];
return YES; return YES;
@@ -398,55 +456,72 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
[sectionItems addObject:space]; [sectionItems addObject:space];
YTSettingsSectionItem *ps = [%c(YTSettingsSectionItem) itemWithTitle:@"PoomSmart" titleDescription:@"YouTube-X, YTNoPremium, YTClassicVideoQuality, YTShortsProgress, YTReExplore, SkipContentWarning, YTAutoFullscreen, YouTubeHeaders" accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *ps = [%c(YTSettingsSectionItem) itemWithTitle:@"PoomSmart" titleDescription:@"YouTube-X, YTNoPremium, YTClassicVideoQuality, YTShortsProgress, YTReExplore, SkipContentWarning, YTAutoFullscreen, YouTubeHeaders" accessibilityIdentifier:@"YTLiteSectionItem" 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) { YTSettingsSectionItem *miro = [%c(YTSettingsSectionItem) itemWithTitle:@"MiRO92" titleDescription:@"YTNoShorts" accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/MiRO92/"]]; return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/MiRO92/"]];
}]; }];
YTSettingsSectionItem *lillie = [%c(YTSettingsSectionItem) itemWithTitle:@"Lillie" titleDescription:@"ExtraSpeedOptions" accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *tonymillion = [%c(YTSettingsSectionItem) itemWithTitle:@"Tony Million" titleDescription:@"Reachability" accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/LillieH1000"]]; return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/tonymillion/Reachability"]];
}]; }];
YTSettingsSectionItem *stalker = [%c(YTSettingsSectionItem) itemWithTitle:@"Stalker" titleDescription:LOC(@"ChineseSimplified") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *stalker = [%c(YTSettingsSectionItem) itemWithTitle:@"Stalker" titleDescription:LOC(@"ChineseSimplified") accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/xiangfeidexiaohuo"]]; return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/xiangfeidexiaohuo"]];
}]; }];
YTSettingsSectionItem *clement = [%c(YTSettingsSectionItem) itemWithTitle:@"Clement" titleDescription:LOC(@"ChineseTraditional") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *clement = [%c(YTSettingsSectionItem) itemWithTitle:@"Clement" titleDescription:LOC(@"ChineseTraditional") accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://twitter.com/a100900900"]]; return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://twitter.com/a100900900"]];
}]; }];
YTSettingsSectionItem *balackburn = [%c(YTSettingsSectionItem) itemWithTitle:@"Balackburn" titleDescription:LOC(@"French") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *balackburn = [%c(YTSettingsSectionItem) itemWithTitle:@"Balackburn" titleDescription:LOC(@"French") accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/Balackburn"]]; return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/Balackburn"]];
}]; }];
YTSettingsSectionItem *decibelios = [%c(YTSettingsSectionItem) itemWithTitle:@"DeciBelioS" titleDescription:LOC(@"Spanish") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *decibelios = [%c(YTSettingsSectionItem) itemWithTitle:@"DeciBelioS" titleDescription:LOC(@"Spanish") accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/Deci8BelioS"]]; return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/Deci8BelioS"]];
}]; }];
YTSettingsSectionItem *skeids = [%c(YTSettingsSectionItem) itemWithTitle:@"SKEIDs" titleDescription:LOC(@"Japanese") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *skeids = [%c(YTSettingsSectionItem) itemWithTitle:@"SKEIDs" titleDescription:LOC(@"Japanese") accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/SKEIDs"]]; return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/SKEIDs"]];
}]; }];
YTSettingsSectionItem *hiepvk = [%c(YTSettingsSectionItem) itemWithTitle:@"Hiepvk" titleDescription:LOC(@"Vietnamese") accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *hiepvk = [%c(YTSettingsSectionItem) itemWithTitle:@"Hiepvk" titleDescription:LOC(@"Vietnamese") accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/hiepvk"]]; return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/hiepvk"]];
}]; }];
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:@"YTLiteSectionItem" 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 *paypal = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"DonateViaPayPal") titleDescription:nil accessibilityIdentifier:nil detailTextBlock:^NSString *() { return @"♡"; } selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *support = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"SupportDevelopment") accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:^NSString *() { return @"♡"; } selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://paypal.me/Dayanch96/"]]; YTDefaultSheetController *sheetController = [%c(YTDefaultSheetController) sheetControllerWithMessage:LOC(@"SupportDevelopment") subMessage:LOC(@"SupportDevelopmentDesc") delegate:nil parentResponder:nil];
YTActionSheetHeaderView *headerView = [sheetController valueForKey:@"_headerView"];
YTFormattedStringLabel *subtitle = [headerView valueForKey:@"_subtitleLabel"];
subtitle.numberOfLines = 0;
[headerView showHeaderDivider];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:@"PayPal" iconImage:[self resizedImageNamed:@"paypal"] secondaryIconImage:nil accessibilityIdentifier:nil handler:^ {
[%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://paypal.me/dayanch96"]];
}]];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:@"Github Sponsors" iconImage:[self resizedImageNamed:@"github"] secondaryIconImage:nil accessibilityIdentifier:nil handler:^ {
[%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/sponsors/dayanch96"]];
}]];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:@"Buy Me a Coffee" iconImage:[self resizedImageNamed:@"coffee"] secondaryIconImage:nil accessibilityIdentifier:nil handler:^ {
[%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://www.buymeacoffee.com/dayanch96"]];
}]];
UIViewController *currentController = UIApplication.sharedApplication.windows.firstObject.rootViewController;
[sheetController presentFromViewController:currentController.presentedViewController animated:YES completion:nil];
return YES;
}]; }];
YTSettingsSectionItem *ghSponsors = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"SupportViaGhSponsors") titleDescription:nil accessibilityIdentifier:nil detailTextBlock:^NSString *() { return @"♡"; } selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *cache = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"ClearCache") titleDescription:nil accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:^NSString *() { return GetCacheSize(); } selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
return [%c(YTUIUtils) openURL:[NSURL URLWithString:@"https://github.com/sponsors/dayanch96"]];
}];
YTSettingsSectionItem *cache = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"ClearCache") titleDescription:nil accessibilityIdentifier:nil detailTextBlock:^NSString *() { return GetCacheSize(); } selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject; NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
[[NSFileManager defaultManager] removeItemAtPath:cachePath error:nil]; [[NSFileManager defaultManager] removeItemAtPath:cachePath error:nil];
@@ -455,7 +530,7 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
return YES; return YES;
}]; }];
YTSettingsSectionItem *reset = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"ResetSettings") titleDescription:nil accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *reset = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"ResetSettings") titleDescription:nil accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
YTAlertView *alertView = [%c(YTAlertView) confirmationDialogWithAction:^{ YTAlertView *alertView = [%c(YTAlertView) confirmationDialogWithAction:^{
NSString *prefsPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YTLite.plist"]; NSString *prefsPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YTLite.plist"];
[[NSFileManager defaultManager] removeItemAtPath:prefsPath error:nil]; [[NSFileManager defaultManager] removeItemAtPath:prefsPath error:nil];
@@ -473,19 +548,18 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
}]; }];
YTSettingsSectionItem *version = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Version") YTSettingsSectionItem *version = [YTSettingsSectionItemClass itemWithTitle:LOC(@"Version")
accessibilityIdentifier:nil accessibilityIdentifier:@"YTLiteSectionItem"
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, miro, lillie, dayanch96, stalker, clement, balackburn, decibelios, skeids, hiepvk, space, createSwitchItem(LOC(@"Advanced"), nil, @"advancedMode", &kAdvancedMode, selfObject), cache, reset]; NSArray <YTSettingsSectionItem *> *rows = @[ps, miro, tonymillion, dayanch96, stalker, clement, balackburn, decibelios, skeids, hiepvk, space, createSwitchItem(@"Advanced", @"advancedMode", &kAdvancedMode, selfObject), cache, 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];
return YES; return YES;
}]; }];
[sectionItems addObject:paypal]; [sectionItems addObject:support];
[sectionItems addObject:ghSponsors];
[sectionItems addObject:version]; [sectionItems addObject:version];
BOOL isNew = [settingsViewController respondsToSelector:@selector(setSectionItems:forCategory:title:icon:titleDescription:headerHidden:)]; BOOL isNew = [settingsViewController respondsToSelector:@selector(setSectionItems:forCategory:title:icon:titleDescription:headerHidden:)];
@@ -500,27 +574,22 @@ static YTSettingsSectionItem *createSwitchItem(NSString *title, NSString *titleD
return; return;
} %orig; } %orig;
} }
%end
%ctor { %new
if (!kAdvancedModeReminder && !kAdvancedMode) { - (UIImage *)resizedImageNamed:(NSString *)iconName {
NSString *prefsPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"YTLite.plist"];
NSMutableDictionary *prefs = [NSMutableDictionary dictionaryWithContentsOfFile:prefsPath];
[prefs setObject:@(YES) forKey:@"advancedModeReminder"];
[prefs writeToFile:prefsPath atomically:NO];
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.dvntm.ytlite.prefschanged"), NULL, NULL, YES);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:CGSizeMake(32, 32)];
YTAlertView *alertView = [%c(YTAlertView) confirmationDialogWithAction:^{ UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
[prefs setObject:@(YES) forKey:@"advancedMode"]; UIView *imageView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
[prefs writeToFile:prefsPath atomically:NO]; UIImageView *iconImageView = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[YTLiteBundle() pathForResource:iconName ofType:@"png"]]];
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.dvntm.ytlite.prefschanged"), NULL, NULL, YES); iconImageView.contentMode = UIViewContentModeScaleAspectFit;
} iconImageView.clipsToBounds = YES;
actionTitle:LOC(@"Yes") iconImageView.frame = imageView.bounds;
cancelTitle:LOC(@"No")];
alertView.title = @"YTLite"; [imageView addSubview:iconImageView];
alertView.subtitle = [NSString stringWithFormat:LOC(@"AdvancedModeReminder"), @"YTLite", LOC(@"Version"), LOC(@"Advanced")]; [imageView.layer renderInContext:rendererContext.CGContext];
[alertView show]; }];
});
} return image;
} }
%end
+103 -40
View File
@@ -2,28 +2,8 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <rootless.h> #import <rootless.h>
#import <Photos/Photos.h> #import <Photos/Photos.h>
#import "../YouTubeHeader/YTAlertView.h" #import "Reachability.h"
#import "../YouTubeHeader/YTIGuideResponse.h" #import "YouTubeHeaders.h"
#import "../YouTubeHeader/YTIGuideResponseSupportedRenderers.h"
#import "../YouTubeHeader/YTIPivotBarSupportedRenderers.h"
#import "../YouTubeHeader/YTIPivotBarRenderer.h"
#import "../YouTubeHeader/YTIBrowseRequest.h"
#import "../YouTubeHeader/YTISectionListRenderer.h"
#import "../YouTubeHeader/YTQTMButton.h"
#import "../YouTubeHeader/YTIButtonRenderer.h"
#import "../YouTubeHeader/YTVideoQualitySwitchOriginalController.h"
#import "../YouTubeHeader/YTPlayerViewController.h"
#import "../YouTubeHeader/YTWatchController.h"
#import "../YouTubeHeader/YTPlayerOverlay.h"
#import "../YouTubeHeader/YTPlayerOverlayProvider.h"
#import "../YouTubeHeader/YTSettingsViewController.h"
#import "../YouTubeHeader/YTSettingsSectionItem.h"
#import "../YouTubeHeader/YTSettingsSectionItemManager.h"
#import "../YouTubeHeader/YTSettingsPickerViewController.h"
#import "../YouTubeHeader/YTUIUtils.h"
#import "../YouTubeHeader/YTIMenuConditionalServiceItemRenderer.h"
#import "../YouTubeHeader/YTToastResponderEvent.h"
#import "../YouTubeHeader/YTPageStyleController.h"
static inline NSBundle *YTLiteBundle() { static inline NSBundle *YTLiteBundle() {
static NSBundle *bundle = nil; static NSBundle *bundle = nil;
@@ -74,6 +54,9 @@ BOOL kClassicQuality;
BOOL kExtraSpeedOptions; BOOL kExtraSpeedOptions;
BOOL kDontSnapToChapter; BOOL kDontSnapToChapter;
BOOL kRedProgressBar; BOOL kRedProgressBar;
BOOL kNoPlayerRemixButton;
BOOL kNoPlayerClipButton;
BOOL kNoPlayerDownloadButton;
BOOL kNoHints; BOOL kNoHints;
BOOL kNoFreeZoom; BOOL kNoFreeZoom;
BOOL kAutoFullscreen; BOOL kAutoFullscreen;
@@ -112,12 +95,18 @@ BOOL kRemoveUploads;
BOOL kRemoveLibrary; BOOL kRemoveLibrary;
BOOL kCopyVideoInfo; BOOL kCopyVideoInfo;
BOOL kPostManager; BOOL kPostManager;
BOOL kSavePostImage;
BOOL kSaveProfilePhoto; BOOL kSaveProfilePhoto;
BOOL kCommentManager; BOOL kCommentManager;
BOOL kSavePost; BOOL kSavePost;
BOOL kFixAlbums; BOOL kFixAlbums;
BOOL kRemovePlayNext; BOOL kRemovePlayNext;
BOOL kRemoveDownloadMenu;
BOOL kRemoveWatchLaterMenu;
BOOL kRemoveSaveToPlaylistMenu;
BOOL kRemoveShareMenu;
BOOL kRemoveNotInterestedMenu;
BOOL kRemoveDontRecommendMenu;
BOOL kRemoveReportMenu;
BOOL kNoContinueWatching; BOOL kNoContinueWatching;
BOOL kNoSearchHistory; BOOL kNoSearchHistory;
BOOL kNoRelatedWatchNexts; BOOL kNoRelatedWatchNexts;
@@ -127,16 +116,28 @@ BOOL kPlaylistOldMinibar;
BOOL kDisableRTL; BOOL kDisableRTL;
BOOL kAdvancedMode; BOOL kAdvancedMode;
BOOL kAdvancedModeReminder; BOOL kAdvancedModeReminder;
int kWiFiQualityIndex;
int kCellQualityIndex;
int kPivotIndex; int kPivotIndex;
@interface YTTouchFeedbackController : YTCollectionViewCell
@property (nonatomic, strong, readwrite) UIColor *feedbackColor;
@end
@interface ABCSwitch : UIControl
@property (nonatomic, strong, readwrite) UIColor *onTintColor;
@end
@interface YTSettingsCell ()
- (void)setIndicatorIcon:(int)icon;
@end
@interface YTSettingsSectionItemManager (Custom) @interface YTSettingsSectionItemManager (Custom)
@property (nonatomic, strong) NSMutableDictionary *prefs; @property (nonatomic, strong) NSMutableDictionary *prefs;
@property (nonatomic, strong) NSString *prefsPath; @property (nonatomic, strong) NSString *prefsPath;
- (void)updatePrefsForKey:(NSString *)key enabled:(BOOL)enabled; - (void)updatePrefsForKey:(NSString *)key enabled:(BOOL)enabled;
- (void)updateIntegerPrefsForKey:(NSString *)key intValue:(NSInteger)intValue; - (void)updateIntegerPrefsForKey:(NSString *)key intValue:(NSInteger)intValue;
@end - (UIImage *)resizedImageNamed:(NSString *)iconName;
@interface YTPivotBarView : UIView
@end @end
@interface YTLightweightQTMButton () @interface YTLightweightQTMButton ()
@@ -148,10 +149,6 @@ int kPivotIndex;
- (void)setSizeWithPaddingAndInsets:(BOOL)sizeWithPaddingAndInsets; - (void)setSizeWithPaddingAndInsets:(BOOL)sizeWithPaddingAndInsets;
@end @end
@interface YTPivotBarItemView : UIView
@property (nonatomic, strong, readwrite) YTQTMButton *navigationButton;
@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;
@@ -171,11 +168,22 @@ int kPivotIndex;
- (void)showPivotBar; - (void)showPivotBar;
@end @end
@interface YTPivotBarView : UIView
- (void)selectItemWithPivotIdentifier:(id)pivotIndentifier;
@end
@interface YTPivotBarViewController : UIViewController @interface YTPivotBarViewController : UIViewController
@property (nonatomic, weak, readwrite) YTAppViewController *parentViewController; @property (nonatomic, weak, readwrite) YTAppViewController *parentViewController;
- (YTPivotBarView *)pivotBarView;
- (void)selectItemWithPivotIdentifier:(id)pivotIndentifier; - (void)selectItemWithPivotIdentifier:(id)pivotIndentifier;
@end @end
@interface YTPivotBarItemView : UIView
@property (nonatomic, strong, readwrite) YTIPivotBarItemRenderer *renderer;
@property (nonatomic, weak, readwrite) YTPivotBarViewController *delegate;
@property (nonatomic, strong, readwrite) YTQTMButton *navigationButton;
@end
@interface YTScrollableNavigationController : UINavigationController @interface YTScrollableNavigationController : UINavigationController
@property (nonatomic, weak, readwrite) YTAppViewController *parentViewController; @property (nonatomic, weak, readwrite) YTAppViewController *parentViewController;
@end @end
@@ -199,19 +207,43 @@ int kPivotIndex;
@property (nonatomic, weak, readwrite) YTScrollableNavigationController *navigationController; @property (nonatomic, weak, readwrite) YTScrollableNavigationController *navigationController;
@end @end
@interface YTIVideoDetails () @interface YTIVideoDetails : NSObject
@property (nonatomic, copy, readwrite) NSString *title; @property (nonatomic, copy, readwrite) NSString *title;
@property (nonatomic, copy, readwrite) NSString *shortDescription; @property (nonatomic, copy, readwrite) NSString *shortDescription;
@end @end
@interface YTPlayerViewController (YTAFS) @interface YTIPlayerResponse : NSObject
@property (nonatomic, assign, readonly) YTIVideoDetails *videoDetails;
@end
@interface YTPlayerResponse : NSObject
@property (nonatomic, assign, readonly) YTIPlayerResponse *playerData;
@end
@interface MLQuickMenuVideoQualitySettingFormatConstraint : NSObject
- (instancetype)initWithVideoQualitySetting:(int)settings formatSelectionReason:(NSInteger)reason qualityLabel:(NSString *)label;
@end
@interface MLFormat : NSObject
@property (nonatomic, assign, readonly) NSString *qualityLabel;
@property (nonatomic, assign, readonly) int singleDimensionResolution;
@end
@interface YTSingleVideoController : NSObject
@property (nonatomic, assign, readonly) NSArray *selectableVideoFormats;
- (void)setVideoFormatConstraint:(MLQuickMenuVideoQualitySettingFormatConstraint *)formatConstraint;
@end
@interface YTPlayerViewController : UIViewController
@property (nonatomic, assign, readonly) YTPlayerResponse *playerResponse; @property (nonatomic, assign, readonly) YTPlayerResponse *playerResponse;
@property (nonatomic, assign, readonly) YTSingleVideoController *activeVideo;
@property (nonatomic, weak, readwrite) UIViewController *parentViewController; @property (nonatomic, weak, readwrite) UIViewController *parentViewController;
@property (readonly, nonatomic) NSString *contentVideoID; @property (readonly, nonatomic) NSString *contentVideoID;
- (void)setActiveCaptionTrack:(id)arg1; - (void)setActiveCaptionTrack:(id)arg1;
- (void)shortsToRegular; - (void)shortsToRegular;
- (void)autoFullscreen; - (void)autoFullscreen;
- (void)turnOffCaptions; - (void)turnOffCaptions;
- (void)autoQuality;
@end @end
@interface YTPlayerView : UIView @interface YTPlayerView : UIView
@@ -288,15 +320,16 @@ int kPivotIndex;
@property (atomic, assign, readonly) NSMutableArray *allObjects; @property (atomic, assign, readonly) NSMutableArray *allObjects;
@end @end
@interface ASDisplayNode : NSObject @interface ASDisplayNode ()
@property (nonatomic, assign, readonly) UIViewController *closestViewController; @property (nonatomic, assign, readonly) UIViewController *closestViewController;
@property (atomic, assign, readonly) ASNodeAncestryEnumerator *supernodes; @property (atomic, assign, readonly) ASNodeAncestryEnumerator *supernodes;
@property (atomic, copy, readwrite) NSArray *yogaChildren; // @property (atomic, copy, readwrite) NSArray *yogaChildren;
@property (atomic) CALayer *layer; @property (atomic) CALayer *layer;
@end @end
@interface ELMContainerNode : ASDisplayNode @interface ELMContainerNode : ASDisplayNode
@property (nonatomic, strong, readwrite) NSString *copiedComment; @property (nonatomic, strong, readwrite) NSString *copiedComment;
@property (nonatomic, strong, readwrite) NSURL *copiedURL;
@end @end
@interface ELMExpandableTextNode : ASDisplayNode @interface ELMExpandableTextNode : ASDisplayNode
@@ -307,6 +340,9 @@ int kPivotIndex;
@property (atomic, copy, readwrite) NSURL *URL; @property (atomic, copy, readwrite) NSURL *URL;
@end @end
@interface YTImageZoomNode : ASNetworkImageNode
@end
@interface ASTextNode : ASDisplayNode @interface ASTextNode : ASDisplayNode
@property (atomic, copy, readwrite) NSAttributedString *attributedText; @property (atomic, copy, readwrite) NSAttributedString *attributedText;
@end @end
@@ -314,18 +350,21 @@ int kPivotIndex;
@interface _ASDisplayView : UIView @interface _ASDisplayView : UIView
@property (nonatomic, strong, readwrite) ASDisplayNode *keepalive_node; @property (nonatomic, strong, readwrite) ASDisplayNode *keepalive_node;
- (void)postManager:(UILongPressGestureRecognizer *)sender; - (void)postManager:(UILongPressGestureRecognizer *)sender;
- (void)saveImage:(UILongPressGestureRecognizer *)sender;
- (void)savePFP:(UILongPressGestureRecognizer *)sender; - (void)savePFP:(UILongPressGestureRecognizer *)sender;
- (void)commentManager:(UILongPressGestureRecognizer *)sender; - (void)commentManager:(UILongPressGestureRecognizer *)sender;
@end @end
@interface MLHAMQueuePlayer : NSObject // @interface MLHAMQueuePlayer : NSObject
@property id playerEventCenter; // @property id playerEventCenter;
-(void)setRate:(float)rate; // -(void)setRate:(float)rate;
@end // @end
@interface YTVarispeedSwitchControllerOption : NSObject @interface YTVarispeedSwitchControllerOption : NSObject
- (id)initWithTitle:(id)title rate:(float)rate; - (id)initWithTitle:(NSString *)title rate:(float)rate;
@end
@interface YTVarispeedSwitchController : NSObject
- (void)addActionForOption:(YTVarispeedSwitchControllerOption *)option;
@end @end
@interface HAMPlayerInternal : NSObject @interface HAMPlayerInternal : NSObject
@@ -340,3 +379,27 @@ int kPivotIndex;
@property (readonly, nonatomic) CGFloat mediaTime; @property (readonly, nonatomic) CGFloat mediaTime;
@property (readonly, nonatomic) NSString *videoID; @property (readonly, nonatomic) NSString *videoID;
@end @end
@interface YTFormattedStringLabel : UILabel
@end
@interface YTActionSheetHeaderView : UIView
- (void)showHeaderDivider;
@end
@interface YTActionSheetAction : NSObject
+ (instancetype)actionWithTitle:(NSString *)title iconImage:(UIImage *)image style:(NSInteger)style handler:(void (^)(void))handler;
+ (instancetype)actionWithTitle:(NSString *)title iconImage:(UIImage *)image secondaryIconImage:(UIImage *)secondaryIconImage accessibilityIdentifier:(NSString *)identifier handler:(void (^)(void))handler;
+ (instancetype)actionWithTitle:(NSString *)title titleColor:(UIColor *)titleColor iconImage:(UIImage *)image iconColor:(UIColor *)iconColor disableAutomaticButtonColor:(BOOL)autoColor accessibilityIdentifier:(NSString *)identifier handler:(void (^)(void))handler;
@end
@interface YTDefaultSheetController : NSObject
- (void)addAction:(YTActionSheetAction *)action;
- (void)presentFromView:(UIView *)view animated:(BOOL)animated completion:(void(^)(void))completion;
- (void)presentFromViewController:(UIViewController *)vc animated:(BOOL)animated completion:(void(^)(void))completion;
+ (instancetype)sheetControllerWithParentResponder:(id)parentResponder;
+ (instancetype)sheetControllerWithParentResponder:(id)parentResponder forcedSheetStyle:(NSInteger)style;
+ (instancetype)sheetControllerWithMessage:(NSString *)message delegate:(id)delegate parentResponder:(id)parentResponder;
+ (instancetype)sheetControllerWithMessage:(NSString *)message subMessage:(NSString *)subMessage delegate:(id)delegate parentResponder:(id)parentResponder;
@end
+314 -138
View File
@@ -1,5 +1,9 @@
#import "YTLite.h" #import "YTLite.h"
static UIImage *YTImageNamed(NSString *imageName) {
return [UIImage imageNamed:imageName inBundle:[NSBundle mainBundle] compatibleWithTraitCollection:nil];
}
// YouTube-X (https://github.com/PoomSmart/YouTube-X/) // YouTube-X (https://github.com/PoomSmart/YouTube-X/)
// Background Playback // Background Playback
%hook YTIPlayabilityStatus %hook YTIPlayabilityStatus
@@ -284,44 +288,22 @@
} }
%end %end
// Extra Speed Options (https://github.com/LillieH1000/YouTube-Reborn/blob/v4/Tweak.xm#L853) - Same code but for .x
// Extra Speed Options
%hook YTVarispeedSwitchController %hook YTVarispeedSwitchController
- (void *)init { - (void)setDelegate:(id)arg1 {
void *ret = (void *)%orig; NSMutableArray *optionsCopy = [[self valueForKey:@"_options"] mutableCopy];
if (kExtraSpeedOptions) { NSArray *speedOptions = @[@"2.5", @"3", @"3.5", @"4", @"5"];
NSArray *speedOptions = @[@"0.1x", @"0.25x", @"0.5x", @"0.75x", @"1x", @"1.25x", @"1.5x", @"1.75x", @"2x", @"2.5x", @"3x", @"3.5x", @"4x", @"5x"];
NSMutableArray *speedOptionsCopy = [NSMutableArray new];
for (NSString *title in speedOptions) { for (NSString *title in speedOptions) {
float rate = [title floatValue]; float rate = [title floatValue];
[speedOptionsCopy addObject:[[objc_lookUpClass("YTVarispeedSwitchControllerOption") alloc] initWithTitle:title rate:rate]]; YTVarispeedSwitchControllerOption *option = [[%c(YTVarispeedSwitchControllerOption) alloc] initWithTitle:title rate:rate];
[optionsCopy addObject:option];
} }
Ivar optionsIvar = class_getInstanceVariable(object_getClass(self), "_options"); if (kExtraSpeedOptions) [self setValue:[optionsCopy copy] forKey:@"_options"];
object_setIvar(self, optionsIvar, [speedOptionsCopy copy]);
} return ret; return %orig;
}
%end
%hook MLHAMQueuePlayer
- (void)setRate:(float)rate {
if (kExtraSpeedOptions) {
Ivar rateIvar = class_getInstanceVariable([self class], "_rate");
if (rateIvar) {
float* ratePtr = (float *)((__bridge void *)self + ivar_getOffset(rateIvar));
*ratePtr = rate;
}
id ytPlayer = object_getIvar(self, class_getInstanceVariable([self class], "_player"));
if ([ytPlayer respondsToSelector:@selector(setRate:)]) {
[ytPlayer setRate:rate];
}
[self.playerEventCenter broadcastRateChange:rate];
} else {
%orig(rate);
}
} }
%end %end
@@ -377,6 +359,7 @@
- (void)loadWithPlayerTransition:(id)arg1 playbackConfig:(id)arg2 { - (void)loadWithPlayerTransition:(id)arg1 playbackConfig:(id)arg2 {
%orig; %orig;
if (kWiFiQualityIndex != 0 || kCellQualityIndex != 0) [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(autoQuality) userInfo:nil repeats:NO];
if (kAutoFullscreen) [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(autoFullscreen) userInfo:nil repeats:NO]; if (kAutoFullscreen) [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(autoFullscreen) userInfo:nil repeats:NO];
if (kShortsToRegular) [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(shortsToRegular) userInfo:nil repeats:NO]; if (kShortsToRegular) [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(shortsToRegular) userInfo:nil repeats:NO];
if (kDisableAutoCaptions) [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(turnOffCaptions) userInfo:nil repeats:NO]; if (kDisableAutoCaptions) [NSTimer scheduledTimerWithTimeInterval:0.75 target:self selector:@selector(turnOffCaptions) userInfo:nil repeats:NO];
@@ -402,6 +385,76 @@
- (void)turnOffCaptions { - (void)turnOffCaptions {
[self setActiveCaptionTrack:nil]; [self setActiveCaptionTrack:nil];
} }
%new
- (void)autoQuality {
if (![self.view.superview isKindOfClass:NSClassFromString(@"YTWatchView")]) {
return;
}
NetworkStatus status = [[Reachability reachabilityForInternetConnection] currentReachabilityStatus];
NSInteger kQualityIndex = status == ReachableViaWiFi ? kWiFiQualityIndex : kCellQualityIndex;
NSString *bestQualityLabel;
int highestResolution = 0;
for (MLFormat *format in self.activeVideo.selectableVideoFormats) {
int reso = format.singleDimensionResolution;
if (reso > highestResolution) {
highestResolution = reso;
bestQualityLabel = format.qualityLabel;
}
}
NSString *qualityLabel = kQualityIndex == 1 ? bestQualityLabel :
kQualityIndex == 2 ? @"2160p60" :
kQualityIndex == 3 ? @"2160p" :
kQualityIndex == 4 ? @"1440p60" :
kQualityIndex == 5 ? @"1440p" :
kQualityIndex == 6 ? @"1080p60" :
kQualityIndex == 7 ? @"1080p" :
kQualityIndex == 8 ? @"720p60" :
kQualityIndex == 9 ? @"720p" :
kQualityIndex == 10 ? @"480p" :
kQualityIndex == 11 ? @"360p" :
nil;
if (![qualityLabel isEqualToString:bestQualityLabel]) {
BOOL exactMatch = NO;
NSString *closestQualityLabel = qualityLabel;
for (MLFormat *format in self.activeVideo.selectableVideoFormats) {
if ([format.qualityLabel isEqualToString:qualityLabel]) {
exactMatch = YES;
break;
}
}
if (!exactMatch) {
NSInteger bestQualityDifference = NSIntegerMax;
for (MLFormat *format in self.activeVideo.selectableVideoFormats) {
NSArray *formatСomponents = [format.qualityLabel componentsSeparatedByString:@"p"];
NSArray *targetComponents = [qualityLabel componentsSeparatedByString:@"p"];
if (formatСomponents.count == 2) {
NSInteger formatQuality = [formatСomponents.firstObject integerValue];
NSInteger targetQuality = [targetComponents.firstObject integerValue];
NSInteger difference = labs(formatQuality - targetQuality);
if (difference < bestQualityDifference) {
bestQualityDifference = difference;
closestQualityLabel = format.qualityLabel;
}
}
}
qualityLabel = closestQualityLabel;
}
}
MLQuickMenuVideoQualitySettingFormatConstraint *fc = [[%c(MLQuickMenuVideoQualitySettingFormatConstraint) alloc] init];
if ([fc respondsToSelector:@selector(initWithVideoQualitySetting:formatSelectionReason:qualityLabel:)]) {
[self.activeVideo setVideoFormatConstraint:[fc initWithVideoQualitySetting:3 formatSelectionReason:2 qualityLabel:qualityLabel]];
}
}
%end %end
// Exit Fullscreen on Finish // Exit Fullscreen on Finish
@@ -468,6 +521,79 @@
} }
%end %end
// Remove Download button from the menu
%hook YTDefaultSheetController
- (void)addAction:(YTActionSheetAction *)action {
NSString *identifier = [action valueForKey:@"_accessibilityIdentifier"];
NSDictionary *actionsToRemove = @{
@"7": @(kRemoveDownloadMenu),
@"1": @(kRemoveWatchLaterMenu),
@"3": @(kRemoveSaveToPlaylistMenu),
@"5": @(kRemoveShareMenu),
@"12": @(kRemoveNotInterestedMenu),
@"31": @(kRemoveDontRecommendMenu),
@"58": @(kRemoveReportMenu)
};
if (![actionsToRemove[identifier] boolValue]) {
%orig;
}
}
%end
// Hide buttons under the video player (@PoomSmart)
static BOOL findCell(ASNodeController *nodeController, NSArray <NSString *> *identifiers) {
for (id child in [nodeController children]) {
if ([child isKindOfClass:%c(ELMNodeController)]) {
NSArray <ELMComponent *> *elmChildren = [(ELMNodeController *)child children];
for (ELMComponent *elmChild in elmChildren) {
for (NSString *identifier in identifiers) {
if ([[elmChild description] containsString:identifier])
return YES;
}
}
}
if ([child isKindOfClass:%c(ASNodeController)]) {
ASDisplayNode *childNode = ((ASNodeController *)child).node; // ELMContainerNode
NSArray *yogaChildren = childNode.yogaChildren;
for (ASDisplayNode *displayNode in yogaChildren) {
if ([identifiers containsObject:displayNode.accessibilityIdentifier])
return YES;
}
return findCell(child, identifiers);
}
return NO;
}
return NO;
}
%hook ASCollectionView
- (CGSize)sizeForElement:(ASCollectionElement *)element {
if ([self.accessibilityIdentifier isEqualToString:@"id.video.scrollable_action_bar"]) {
ASCellNode *node = [element node];
ASNodeController *nodeController = [node controller];
if (kNoPlayerRemixButton && findCell(nodeController, @[@"id.video.remix.button"])) {
return CGSizeZero;
}
if (kNoPlayerClipButton && findCell(nodeController, @[@"clip_button.eml"])) {
return CGSizeZero;
}
if (kNoPlayerDownloadButton && findCell(nodeController, @[@"id.ui.add_to.offline.button"])) {
return CGSizeZero;
}
}
return %orig;
}
%end
// Remove Premium Pop-up, Horizontal Video Carousel and Shorts (https://github.com/MiRO92/YTNoShorts) // Remove Premium Pop-up, Horizontal Video Carousel and Shorts (https://github.com/MiRO92/YTNoShorts)
%hook YTAsyncCollectionView %hook YTAsyncCollectionView
- (id)cellForItemAtIndexPath:(NSIndexPath *)indexPath { - (id)cellForItemAtIndexPath:(NSIndexPath *)indexPath {
@@ -538,6 +664,7 @@
- (void)setRemixButton:(id)arg1 { if (!kHideShortsRemix) %orig; } - (void)setRemixButton:(id)arg1 { if (!kHideShortsRemix) %orig; }
- (void)setShareButton:(id)arg1 { if (!kHideShortsShare) %orig; } - (void)setShareButton:(id)arg1 { if (!kHideShortsShare) %orig; }
- (void)setNativePivotButton:(id)arg1 { if (!kHideShortsAvatars) %orig; } - (void)setNativePivotButton:(id)arg1 { if (!kHideShortsAvatars) %orig; }
- (void)setPivotButtonElementRenderer:(id)arg1 { if (!kHideShortsAvatars) %orig; }
%end %end
%hook YTReelHeaderView %hook YTReelHeaderView
@@ -637,8 +764,61 @@ static BOOL isOverlayShown = YES;
} }
%end %end
static void downloadImageFromURL(UIResponder *responder, NSURL *URL, BOOL download) {
NSString *URLString = URL.absoluteString;
if (kFixAlbums && [URLString hasPrefix:@"https://yt3."]) {
URLString = [URLString stringByReplacingOccurrencesOfString:@"https://yt3." withString:@"https://yt4."];
}
NSURL *downloadURL = nil;
if ([URLString containsString:@"c-fcrop"]) {
NSRange croppedURL = [URLString rangeOfString:@"c-fcrop"];
if (croppedURL.location != NSNotFound) {
NSString *newURL = [URLString stringByReplacingOccurrencesOfString:[URLString substringFromIndex:croppedURL.location] withString:@"nd-v1"];
downloadURL = [NSURL URLWithString:newURL];
}
} else {
downloadURL = URL;
}
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:downloadURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data) {
if (download) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
[request addResourceWithType:PHAssetResourceTypePhoto data:data options:nil];
} completionHandler:^(BOOL success, NSError *error) {
[[%c(YTToastResponderEvent) eventWithMessage:success ? LOC(@"Saved") : [NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription] firstResponder:responder] send];
}];
} else {
[UIPasteboard generalPasteboard].image = [UIImage imageWithData:data];
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:responder] send];
}
} else {
[[%c(YTToastResponderEvent) eventWithMessage:[NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription] firstResponder:responder] send];
}
}] resume];
}
static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^completionHandler)(UIImage *)) {
UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
CGContextFillRect(context, CGRectMake(0, 0, layer.frame.size.width, layer.frame.size.height));
[layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (completionHandler) {
completionHandler(image);
}
}
%hook ELMContainerNode %hook ELMContainerNode
%property (nonatomic, strong) NSString *copiedComment; %property (nonatomic, strong) NSString *copiedComment;
%property (nonatomic, strong) NSURL *copiedURL;
%end %end
%hook ASDisplayNode %hook ASDisplayNode
@@ -674,52 +854,26 @@ static BOOL isOverlayShown = YES;
} }
%end %end
static void downloadImageFromURL(UIResponder *responder, NSURL *URL) { %hook YTImageZoomNode
NSString *URLString = URL.absoluteString; - (BOOL)gestureRecognizer:(id)arg1 shouldRecognizeSimultaneouslyWithGestureRecognizer:(id)arg2 {
BOOL isImageLoaded = [self valueForKey:@"_didLoadImage"];
if (kPostManager && isImageLoaded) {
ASDisplayNode *displayNode = (ASDisplayNode *)self;
ASNetworkImageNode *imageNode = (ASNetworkImageNode *)self;
NSURL *URL = imageNode.URL;
if (kFixAlbums && [URLString hasPrefix:@"https://yt3."]) { NSMutableArray *allObjects = displayNode.supernodes.allObjects;
URLString = [URLString stringByReplacingOccurrencesOfString:@"https://yt3." withString:@"https://yt4."]; for (ELMContainerNode *containerNode in allObjects) {
if ([containerNode.description containsString:@"id.ui.backstage.original_post"]) {
containerNode.copiedURL = URL;
break;
}
}
} }
NSURL *downloadURL = nil; return %orig;
if ([URLString containsString:@"c-fcrop"]) {
NSRange croppedURL = [URLString rangeOfString:@"c-fcrop"];
if (croppedURL.location != NSNotFound) {
NSString *newURL = [URLString stringByReplacingOccurrencesOfString:[URLString substringFromIndex:croppedURL.location] withString:@"nd-v1"];
downloadURL = [NSURL URLWithString:newURL];
}
} else {
downloadURL = URL;
}
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:downloadURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
[request addResourceWithType:PHAssetResourceTypePhoto data:data options:nil];
} completionHandler:^(BOOL success, NSError *error) {
[[%c(YTToastResponderEvent) eventWithMessage:success ? LOC(@"Saved") : [NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription] firstResponder:responder] send];
}];
} else {
[[%c(YTToastResponderEvent) eventWithMessage:[NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription] firstResponder:responder] send];
}
}] resume];
}
static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^completionHandler)(UIImage *)) {
UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
CGContextFillRect(context, CGRectMake(0, 0, layer.frame.size.width, layer.frame.size.height));
[layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (completionHandler) {
completionHandler(image);
}
} }
%end
%hook _ASDisplayView %hook _ASDisplayView
- (void)setKeepalive_node:(id)arg1 { - (void)setKeepalive_node:(id)arg1 {
@@ -727,7 +881,6 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
NSArray *gesturesInfo = @[ NSArray *gesturesInfo = @[
@{@"selector": @"postManager:", @"text": @"id.ui.backstage.original_post", @"key": @(kPostManager)}, @{@"selector": @"postManager:", @"text": @"id.ui.backstage.original_post", @"key": @(kPostManager)},
@{@"selector": @"saveImage:", @"text": @"YTImageZoomNode-View", @"key": @(kSavePostImage)},
@{@"selector": @"savePFP:", @"text": @"ELMImageNode-View", @"key": @(kSaveProfilePhoto)}, @{@"selector": @"savePFP:", @"text": @"ELMImageNode-View", @"key": @(kSaveProfilePhoto)},
@{@"selector": @"commentManager:", @"text": @"id.ui.comment_cell", @"key": @(kCommentManager)} @{@"selector": @"commentManager:", @"text": @"id.ui.comment_cell", @"key": @(kCommentManager)}
]; ];
@@ -760,11 +913,20 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:PFPURL]]; UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:PFPURL]];
if (image) { if (image) {
YTDefaultSheetController *sheetController = [%c(YTDefaultSheetController) sheetControllerWithParentResponder:nil];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"SaveProfilePicture") iconImage:YTImageNamed(@"yt_outline_image_24pt") style:0 handler:^ {
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
UIResponder *responder = self.nextResponder; [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Saved") firstResponder:self.keepalive_node.closestViewController] send];
while (responder && ![responder isKindOfClass:[UIViewController class]]) responder = responder.nextResponder; }]];
if (responder) [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Saved") firstResponder:responder] send];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyProfilePicture") iconImage:YTImageNamed(@"yt_outline_library_image_24pt") style:0 handler:^ {
[UIPasteboard generalPasteboard].image = image;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:self.keepalive_node.closestViewController] send];
}]];
[sheetController presentFromViewController:self.keepalive_node.closestViewController animated:YES completion:nil];
} }
} }
} }
@@ -778,20 +940,30 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
ELMContainerNode *nodeForLayer = (ELMContainerNode *)self.keepalive_node.yogaChildren[0]; ELMContainerNode *nodeForLayer = (ELMContainerNode *)self.keepalive_node.yogaChildren[0];
ELMContainerNode *containerNode = (ELMContainerNode *)self.keepalive_node; ELMContainerNode *containerNode = (ELMContainerNode *)self.keepalive_node;
NSString *text = containerNode.copiedComment; NSString *text = containerNode.copiedComment;
NSURL *URL = containerNode.copiedURL;
CALayer *layer = nodeForLayer.layer; CALayer *layer = nodeForLayer.layer;
UIColor *backgroundColor = containerNode.closestViewController.view.backgroundColor; UIColor *backgroundColor = containerNode.closestViewController.view.backgroundColor;
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:LOC(@"SelectAction") message:nil preferredStyle:UIAlertControllerStyleActionSheet]; YTDefaultSheetController *sheetController = [%c(YTDefaultSheetController) sheetControllerWithParentResponder:nil];
alertController.view.tintColor = [UIColor labelColor];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyPostText") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyPostText") iconImage:YTImageNamed(@"yt_outline_message_bubble_right_24pt") style:0 handler:^ {
if (text) { if (text) {
[UIPasteboard generalPasteboard].string = text; [UIPasteboard generalPasteboard].string = text;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send]; [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send];
} }
}]]; }]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"SavePostAsImage") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { if (URL) {
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"SaveCurrentImage") iconImage:YTImageNamed(@"yt_outline_image_24pt") style:0 handler:^ {
downloadImageFromURL(containerNode.closestViewController, URL, YES);
}]];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyCurrentImage") iconImage:YTImageNamed(@"yt_outline_library_image_24pt") style:0 handler:^ {
downloadImageFromURL(containerNode.closestViewController, URL, NO);
}]];
}
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"SavePostAsImage") titleColor:[[UIColor redColor] colorWithAlphaComponent:0.7f] iconImage:YTImageNamed(@"yt_outline_image_24pt") iconColor:[[UIColor redColor] colorWithAlphaComponent:0.7f] disableAutomaticButtonColor:YES accessibilityIdentifier:nil handler:^ {
genImageFromLayer(layer, backgroundColor, ^(UIImage *image) { genImageFromLayer(layer, backgroundColor, ^(UIImage *image) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image]; PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
@@ -803,30 +975,14 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
}); });
}]]; }]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyPostAsImage") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyPostAsImage") titleColor:[[UIColor redColor] colorWithAlphaComponent:0.7f] iconImage:YTImageNamed(@"yt_outline_library_image_24pt") iconColor:[[UIColor redColor] colorWithAlphaComponent:0.7f] disableAutomaticButtonColor:YES accessibilityIdentifier:nil handler:^ {
genImageFromLayer(layer, backgroundColor, ^(UIImage *image) { genImageFromLayer(layer, backgroundColor, ^(UIImage *image) {
[UIPasteboard generalPasteboard].image = image; [UIPasteboard generalPasteboard].image = image;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send]; [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send];
}); });
}]]; }]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"Cancel") style:UIAlertActionStyleCancel handler:nil]]; [sheetController presentFromViewController:containerNode.closestViewController animated:YES completion:nil];
[containerNode.closestViewController presentViewController:alertController animated:YES completion:nil];
}
}
%new
- (void)saveImage:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
ASNetworkImageNode *imageNode = (ASNetworkImageNode *)self.keepalive_node;
NSURL *imageURL = imageNode.URL;
UIResponder *responder = self.nextResponder;
while (responder && ![responder isKindOfClass:[UIViewController class]]) responder = responder.nextResponder;
if (imageURL) downloadImageFromURL(responder, imageURL);
} }
} }
@@ -839,17 +995,16 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
CALayer *layer = self.layer; CALayer *layer = self.layer;
UIColor *backgroundColor = containerNode.closestViewController.view.backgroundColor; UIColor *backgroundColor = containerNode.closestViewController.view.backgroundColor;
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:LOC(@"SelectAction") message:nil preferredStyle:UIAlertControllerStyleActionSheet]; YTDefaultSheetController *sheetController = [%c(YTDefaultSheetController) sheetControllerWithParentResponder:nil];
alertController.view.tintColor = [UIColor labelColor];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyCommentText") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyCommentText") iconImage:YTImageNamed(@"yt_outline_message_bubble_right_24pt") style:0 handler:^ {
if (comment) { if (comment) {
[UIPasteboard generalPasteboard].string = comment; [UIPasteboard generalPasteboard].string = comment;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send]; [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send];
} }
}]]; }]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"SaveCommentAsImage") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"SaveCommentAsImage") iconImage:YTImageNamed(@"yt_outline_image_24pt") style:0 handler:^ {
genImageFromLayer(layer, backgroundColor, ^(UIImage *image) { genImageFromLayer(layer, backgroundColor, ^(UIImage *image) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image]; PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
@@ -861,16 +1016,14 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
}); });
}]]; }]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyCommentAsImage") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyCommentAsImage") iconImage:YTImageNamed(@"yt_outline_library_image_24pt") style:0 handler:^ {
genImageFromLayer(layer, backgroundColor, ^(UIImage *image) { genImageFromLayer(layer, backgroundColor, ^(UIImage *image) {
[UIPasteboard generalPasteboard].image = image; [UIPasteboard generalPasteboard].image = image;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send]; [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send];
}); });
}]]; }]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"Cancel") style:UIAlertActionStyleCancel handler:nil]]; [sheetController presentFromViewController:containerNode.closestViewController animated:YES completion:nil];
[containerNode.closestViewController presentViewController:alertController animated:YES completion:nil];
} }
} }
%end %end
@@ -942,26 +1095,12 @@ BOOL isTabSelected = NO;
%orig; %orig;
if (!isTabSelected && !kShortsOnlyMode) { if (!isTabSelected && !kShortsOnlyMode) {
NSString *pivotIdentifier; NSString *pivotIdentifier = kPivotIndex == 1 ? @"FEexplore" :
switch (kPivotIndex) { kPivotIndex == 2 ? @"FEshorts" :
case 0: kPivotIndex == 3 ? @"FEsubscriptions" :
pivotIdentifier = @"FEwhat_to_watch"; kPivotIndex == 4 ? @"FElibrary" :
break; @"FEwhat_to_watch";
case 1:
pivotIdentifier = @"FEexplore";
break;
case 2:
pivotIdentifier = @"FEshorts";
break;
case 3:
pivotIdentifier = @"FEsubscriptions";
break;
case 4:
pivotIdentifier = @"FElibrary";
break;
default:
return;
}
[self selectItemWithPivotIdentifier:pivotIdentifier]; [self selectItemWithPivotIdentifier:pivotIdentifier];
isTabSelected = YES; isTabSelected = YES;
} }
@@ -1008,7 +1147,7 @@ BOOL isTabSelected = NO;
copyInfoButton.accessibilityLabel = LOC(@"CopyVideoInfo"); copyInfoButton.accessibilityLabel = LOC(@"CopyVideoInfo");
[copyInfoButton setTag:999]; [copyInfoButton setTag:999];
[copyInfoButton enableNewTouchFeedback]; [copyInfoButton enableNewTouchFeedback];
[copyInfoButton setImage:[UIImage imageNamed:@"yt_outline_copy_24pt" inBundle:[NSBundle mainBundle] compatibleWithTraitCollection:nil] forState:UIControlStateNormal]; [copyInfoButton setImage:YTImageNamed(@"yt_outline_copy_24pt") forState:UIControlStateNormal];
[copyInfoButton setTintColor:[UIColor labelColor]]; [copyInfoButton setTintColor:[UIColor labelColor]];
[copyInfoButton setTranslatesAutoresizingMaskIntoConstraints:false]; [copyInfoButton setTranslatesAutoresizingMaskIntoConstraints:false];
[copyInfoButton addTarget:self action:@selector(didTapCopyInfoButton:) forControlEvents:UIControlEventTouchUpInside]; [copyInfoButton addTarget:self action:@selector(didTapCopyInfoButton:) forControlEvents:UIControlEventTouchUpInside];
@@ -1032,22 +1171,19 @@ BOOL isTabSelected = NO;
NSString *title = playerVC.playerResponse.playerData.videoDetails.title; NSString *title = playerVC.playerResponse.playerData.videoDetails.title;
NSString *shortDescription = playerVC.playerResponse.playerData.videoDetails.shortDescription; NSString *shortDescription = playerVC.playerResponse.playerData.videoDetails.shortDescription;
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:LOC(@"SelectAction") message:nil preferredStyle:UIAlertControllerStyleActionSheet]; YTDefaultSheetController *sheetController = [%c(YTDefaultSheetController) sheetControllerWithParentResponder:nil];
alertController.view.tintColor = [UIColor labelColor];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyTitle") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyTitle") iconImage:YTImageNamed(@"yt_outline_text_box_24pt") style:0 handler:^ {
[UIPasteboard generalPasteboard].string = title; [UIPasteboard generalPasteboard].string = title;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:self.resizeDelegate] send]; [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:self.resizeDelegate] send];
}]]; }]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyDescription") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyDescription") iconImage:YTImageNamed(@"yt_outline_message_bubble_right_24pt") style:0 handler:^ {
[UIPasteboard generalPasteboard].string = shortDescription; [UIPasteboard generalPasteboard].string = shortDescription;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:self.resizeDelegate] send]; [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:self.resizeDelegate] send];
}]]; }]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"Cancel") style:UIAlertActionStyleCancel handler:nil]]; [sheetController presentFromViewController:self.resizeDelegate animated:YES completion:nil];
[self.resizeDelegate presentViewController:alertController animated:YES completion:nil];
} }
%end %end
@@ -1121,6 +1257,9 @@ static void reloadPrefs() {
kExtraSpeedOptions = [prefs[@"extraSpeedOptions"] boolValue] ?: NO; kExtraSpeedOptions = [prefs[@"extraSpeedOptions"] boolValue] ?: NO;
kDontSnapToChapter = [prefs[@"dontSnapToChapter"] boolValue] ?: NO; kDontSnapToChapter = [prefs[@"dontSnapToChapter"] boolValue] ?: NO;
kRedProgressBar = [prefs[@"redProgressBar"] boolValue] ?: NO; kRedProgressBar = [prefs[@"redProgressBar"] boolValue] ?: NO;
kNoPlayerRemixButton = [prefs[@"noPlayerRemixButton"] boolValue] ?: NO;
kNoPlayerClipButton = [prefs[@"noPlayerClipButton"] boolValue] ?: NO;
kNoPlayerDownloadButton = [prefs[@"noPlayerDownloadButton"] boolValue] ?: NO;
kNoHints = [prefs[@"noHints"] boolValue] ?: NO; kNoHints = [prefs[@"noHints"] boolValue] ?: NO;
kNoFreeZoom = [prefs[@"noFreeZoom"] boolValue] ?: NO; kNoFreeZoom = [prefs[@"noFreeZoom"] boolValue] ?: NO;
kAutoFullscreen = [prefs[@"autoFullscreen"] boolValue] ?: NO; kAutoFullscreen = [prefs[@"autoFullscreen"] boolValue] ?: NO;
@@ -1159,11 +1298,17 @@ static void reloadPrefs() {
kRemoveLibrary = [prefs[@"removeLibrary"] boolValue] ?: NO; kRemoveLibrary = [prefs[@"removeLibrary"] boolValue] ?: NO;
kCopyVideoInfo = [prefs[@"copyVideoInfo"] boolValue] ?: NO; kCopyVideoInfo = [prefs[@"copyVideoInfo"] boolValue] ?: NO;
kPostManager = [prefs[@"postManager"] boolValue] ?: NO; kPostManager = [prefs[@"postManager"] boolValue] ?: NO;
kSavePostImage = [prefs[@"savePostImage"] boolValue] ?: NO; kSaveProfilePhoto = [prefs[@"saveProfilePhoto"] boolValue] ?: NO;
kSaveProfilePhoto = [prefs[@"savePostImage"] boolValue] ?: NO;
kCommentManager = [prefs[@"commentManager"] boolValue] ?: NO; kCommentManager = [prefs[@"commentManager"] boolValue] ?: NO;
kFixAlbums = [prefs[@"fixAlbums"] boolValue] ?: NO; kFixAlbums = [prefs[@"fixAlbums"] boolValue] ?: NO;
kRemovePlayNext = [prefs[@"removePlayNext"] boolValue] ?: NO; kRemovePlayNext = [prefs[@"removePlayNext"] boolValue] ?: NO;
kRemoveDownloadMenu = [prefs[@"removeDownloadMenu"] boolValue] ?: NO;
kRemoveWatchLaterMenu = [prefs[@"removeWatchLaterMenu"] boolValue] ?: NO;
kRemoveSaveToPlaylistMenu = [prefs[@"removeSaveToPlaylistMenu"] boolValue] ?: NO;
kRemoveShareMenu = [prefs[@"removeShareMenu"] boolValue] ?: NO;
kRemoveNotInterestedMenu = [prefs[@"removeNotInterestedMenu"] boolValue] ?: NO;
kRemoveDontRecommendMenu = [prefs[@"removeDontRecommendMenu"] boolValue] ?: NO;
kRemoveReportMenu = [prefs[@"removeReportMenu"] boolValue] ?: NO;
kNoContinueWatching = [prefs[@"noContinueWatching"] boolValue] ?: NO; kNoContinueWatching = [prefs[@"noContinueWatching"] boolValue] ?: NO;
kNoSearchHistory = [prefs[@"noSearchHistory"] boolValue] ?: NO; kNoSearchHistory = [prefs[@"noSearchHistory"] boolValue] ?: NO;
kNoRelatedWatchNexts = [prefs[@"noRelatedWatchNexts"] boolValue] ?: NO; kNoRelatedWatchNexts = [prefs[@"noRelatedWatchNexts"] boolValue] ?: NO;
@@ -1171,6 +1316,8 @@ static void reloadPrefs() {
kHideSortComments = [prefs[@"hideSortComments"] boolValue] ?: NO; kHideSortComments = [prefs[@"hideSortComments"] boolValue] ?: NO;
kPlaylistOldMinibar = [prefs[@"playlistOldMinibar"] boolValue] ?: NO; kPlaylistOldMinibar = [prefs[@"playlistOldMinibar"] boolValue] ?: NO;
kDisableRTL = [prefs[@"disableRTL"] boolValue] ?: NO; kDisableRTL = [prefs[@"disableRTL"] boolValue] ?: NO;
kWiFiQualityIndex = (prefs[@"wifiQualityIndex"] != nil) ? [prefs[@"wifiQualityIndex"] intValue] : 0;
kCellQualityIndex = (prefs[@"cellQualityIndex"] != nil) ? [prefs[@"cellQualityIndex"] intValue] : 0;
kPivotIndex = (prefs[@"pivotIndex"] != nil) ? [prefs[@"pivotIndex"] intValue] : 0; kPivotIndex = (prefs[@"pivotIndex"] != nil) ? [prefs[@"pivotIndex"] intValue] : 0;
kAdvancedMode = [prefs[@"advancedMode"] boolValue] ?: NO; kAdvancedMode = [prefs[@"advancedMode"] boolValue] ?: NO;
kAdvancedModeReminder = [prefs[@"advancedModeReminder"] boolValue] ?: NO; kAdvancedModeReminder = [prefs[@"advancedModeReminder"] boolValue] ?: NO;
@@ -1207,6 +1354,9 @@ static void reloadPrefs() {
@"extraSpeedOptions" : @(kExtraSpeedOptions), @"extraSpeedOptions" : @(kExtraSpeedOptions),
@"dontSnapToChapter" : @(kDontSnapToChapter), @"dontSnapToChapter" : @(kDontSnapToChapter),
@"redProgressBar" : @(kRedProgressBar), @"redProgressBar" : @(kRedProgressBar),
@"noPlayerRemixButton" : @(kNoPlayerRemixButton),
@"noPlayerClipButton" : @(kNoPlayerClipButton),
@"noPlayerDownloadButton" : @(kNoPlayerDownloadButton),
@"noHints" : @(kNoHints), @"noHints" : @(kNoHints),
@"noFreeZoom" : @(kNoFreeZoom), @"noFreeZoom" : @(kNoFreeZoom),
@"autoFullscreen" : @(kAutoFullscreen), @"autoFullscreen" : @(kAutoFullscreen),
@@ -1245,11 +1395,17 @@ static void reloadPrefs() {
@"removeLibrary" : @(kRemoveLibrary), @"removeLibrary" : @(kRemoveLibrary),
@"copyVideoInfo" : @(kCopyVideoInfo), @"copyVideoInfo" : @(kCopyVideoInfo),
@"postManager" : @(kPostManager), @"postManager" : @(kPostManager),
@"savePostImage" : @(kSavePostImage),
@"saveProfilePhoto" : @(kSaveProfilePhoto), @"saveProfilePhoto" : @(kSaveProfilePhoto),
@"commentManager" : @(kCommentManager), @"commentManager" : @(kCommentManager),
@"fixAlbums" : @(kFixAlbums), @"fixAlbums" : @(kFixAlbums),
@"removePlayNext" : @(kRemovePlayNext), @"removePlayNext" : @(kRemovePlayNext),
@"removeDownloadMenu" : @(kRemoveDownloadMenu),
@"removeWatchLaterMenu" : @(kRemoveWatchLaterMenu),
@"removeSaveToPlaylistMenu" : @(kRemoveSaveToPlaylistMenu),
@"removeShareMenu" : @(kRemoveShareMenu),
@"removeNotInterestedMenu" : @(kRemoveNotInterestedMenu),
@"removeDontRecommendMenu" : @(kRemoveDontRecommendMenu),
@"removeReportMenu" : @(kRemoveReportMenu),
@"noContinueWatching" : @(kNoContinueWatching), @"noContinueWatching" : @(kNoContinueWatching),
@"noSearchHistory" : @(kNoSearchHistory), @"noSearchHistory" : @(kNoSearchHistory),
@"noRelatedWatchNexts" : @(kNoRelatedWatchNexts), @"noRelatedWatchNexts" : @(kNoRelatedWatchNexts),
@@ -1257,6 +1413,8 @@ static void reloadPrefs() {
@"hideSortComments" : @(kHideSortComments), @"hideSortComments" : @(kHideSortComments),
@"playlistOldMinibar" : @(kPlaylistOldMinibar), @"playlistOldMinibar" : @(kPlaylistOldMinibar),
@"disableRTL" : @(kDisableRTL), @"disableRTL" : @(kDisableRTL),
@"wifiQualityIndex" : @(kWiFiQualityIndex),
@"cellQualityIndex" : @(kCellQualityIndex),
@"pivotIndex" : @(kPivotIndex), @"pivotIndex" : @(kPivotIndex),
@"advancedMode" : @(kAdvancedMode), @"advancedMode" : @(kAdvancedMode),
@"advancedModeReminder" : @(kAdvancedModeReminder) @"advancedModeReminder" : @(kAdvancedModeReminder)
@@ -1279,6 +1437,24 @@ static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStrin
[prefs writeToFile:path atomically:NO]; [prefs writeToFile:path atomically:NO];
} }
if (![prefs[@"advancedMode"] boolValue] && ![prefs[@"advancedModeReminder"] boolValue]) {
[prefs setObject:@(YES) forKey:@"advancedModeReminder"];
[prefs writeToFile:path atomically:NO];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
YTAlertView *alertView = [%c(YTAlertView) confirmationDialogWithAction:^{
[prefs setObject:@(YES) forKey:@"advancedMode"];
[prefs writeToFile:path atomically:NO];
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), CFSTR("com.dvntm.ytlite.prefschanged"), NULL, NULL, YES);
}
actionTitle:LOC(@"Yes")
cancelTitle:LOC(@"No")];
alertView.title = @"YTLite";
alertView.subtitle = [NSString stringWithFormat:LOC(@"AdvancedModeReminder"), @"YTLite", LOC(@"Version"), LOC(@"Advanced")];
[alertView show];
});
}
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();
} }
+24
View File
@@ -0,0 +1,24 @@
#import "../YouTubeHeader/YTAlertView.h"
#import "../YouTubeHeader/YTIGuideResponse.h"
#import "../YouTubeHeader/YTIGuideResponseSupportedRenderers.h"
#import "../YouTubeHeader/YTIPivotBarSupportedRenderers.h"
#import "../YouTubeHeader/YTIPivotBarRenderer.h"
#import "../YouTubeHeader/YTIBrowseRequest.h"
#import "../YouTubeHeader/YTISectionListRenderer.h"
#import "../YouTubeHeader/YTQTMButton.h"
#import "../YouTubeHeader/YTIButtonRenderer.h"
#import "../YouTubeHeader/YTVideoQualitySwitchOriginalController.h"
#import "../YouTubeHeader/YTWatchController.h"
#import "../YouTubeHeader/YTPlayerOverlay.h"
#import "../YouTubeHeader/YTPlayerOverlayProvider.h"
#import "../YouTubeHeader/YTSettingsViewController.h"
#import "../YouTubeHeader/YTSettingsSectionItem.h"
#import "../YouTubeHeader/YTSettingsSectionItemManager.h"
#import "../YouTubeHeader/YTSettingsPickerViewController.h"
#import "../YouTubeHeader/YTUIUtils.h"
#import "../YouTubeHeader/YTIMenuConditionalServiceItemRenderer.h"
#import "../YouTubeHeader/YTToastResponderEvent.h"
#import "../YouTubeHeader/YTPageStyleController.h"
#import "../YouTubeHeader/ASCollectionElement.h"
#import "../YouTubeHeader/ASCollectionView.h"
#import "../YouTubeHeader/ELMNodeController.h"
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

@@ -67,6 +67,12 @@
"DontSnap2ChapterDesc" = "Disables skipping to the next episode by double-tap gesture."; "DontSnap2ChapterDesc" = "Disables skipping to the next episode by double-tap gesture.";
"RedProgressBar" = "Red progress bar"; "RedProgressBar" = "Red progress bar";
"RedProgressBarDesc" = "Brings back red progress bar."; "RedProgressBarDesc" = "Brings back red progress bar.";
"NoPlayerRemixButton" = "Remove remix button";
"NoPlayerRemixButtonDesc" = "Removes remix button under the player.";
"NoPlayerClipButton" = "Remove clip button";
"NoPlayerClipButtonDesc" = "Removes clip button under the player.";
"NoPlayerDownloadButton" = "Remove download button";
"NoPlayerDownloadButtonDesc" = "Removes download button under the player.";
"NoHints" = "Disable hints"; "NoHints" = "Disable hints";
"NoHintsDesc" = "Disables hints by author which appears at the top-right corner during playback."; "NoHintsDesc" = "Disables hints by author which appears at the top-right corner during playback.";
"NoFreeZoom" = "Disable free zoom gesture"; "NoFreeZoom" = "Disable free zoom gesture";
@@ -147,8 +153,6 @@
"CopyVideoInfoDesc" = "Adds button to copy video title and description into Video Description panel."; "CopyVideoInfoDesc" = "Adds button to copy video title and description into Video Description panel.";
"PostManager" = "Save post information"; "PostManager" = "Save post information";
"PostManagerDesc" = "Allows to copy post text and save post as image by long tap."; "PostManagerDesc" = "Allows to copy post text and save post as image by long tap.";
"SavePostImage" = "Save image from community posts";
"SavePostImageDesc" = "Saves community post image to the Photos app by long tap.";
"SaveProfilePhoto" = "Save profile picture"; "SaveProfilePhoto" = "Save profile picture";
"SaveProfilePhotoDesc" = "Saves profile picture to the Photos app by long tap."; "SaveProfilePhotoDesc" = "Saves profile picture to the Photos app by long tap.";
"CommentManager" = "Save comment information"; "CommentManager" = "Save comment information";
@@ -157,6 +161,20 @@
"FixAlbumsDesc" = "Fixes the display of covers for users from Russia."; "FixAlbumsDesc" = "Fixes the display of covers for users from Russia.";
"RemovePlayNext" = "Remove \"Play next in queue\""; "RemovePlayNext" = "Remove \"Play next in queue\"";
"RemovePlayNextDesc" = "Removes \"Play next in queue\" option from menu."; "RemovePlayNextDesc" = "Removes \"Play next in queue\" option from menu.";
"RemoveDownloadMenu" = "Remove \"Download\"";
"RemoveDownloadMenuDesc" = "Removes \"Download\" option from menu.";
"RemoveWatchLaterMenu" = "Remove \"Save to Watch Later\"";
"RemoveWatchLaterMenuDesc" = "Removes \"Save to Watch Later\" option from menu.";
"RemoveSaveToPlaylistMenu" = "Remove \"Save to playlist\"";
"RemoveSaveToPlaylistMenuDesc" = "Removes \"Save to playlist\" option from menu.";
"RemoveShareMenu" = "Remove \"Share\"";
"RemoveShareMenuDesc" = "Removes \"Share\" option from menu.";
"RemoveNotInterestedMenu" = "Remove \"Not interested\"";
"RemoveNotInterestedMenuDesc" = "Removes \"Not interested\" option from menu.";
"RemoveDontRecommendMenu" = "Remove \"Don't recommend channel\"";
"RemoveDontRecommendMenuDesc" = "Removes \"Don't recommend channel\" option from menu.";
"RemoveReportMenu" = "Remove \"Report\"";
"RemoveReportMenuDesc" = "Removes \"Report\" option from menu.";
"NoContinueWatching" = "Remove \"Continue watching\""; "NoContinueWatching" = "Remove \"Continue watching\"";
"NoContinueWatchingDesc" = "Removes the \"Continue watching\" section containing unfinished videos from the Home page."; "NoContinueWatchingDesc" = "Removes the \"Continue watching\" section containing unfinished videos from the Home page.";
"NoSearchHistory" = "Hide search history"; "NoSearchHistory" = "Hide search history";
@@ -172,6 +190,12 @@
"DisableRTL" = "Disable RTL formatting"; "DisableRTL" = "Disable RTL formatting";
"DisableRTLDesc" = "Forcefully displays text in left-to-right (LTR) format for languages that are initially displayed in right-to-left (RTL)."; "DisableRTLDesc" = "Forcefully displays text in left-to-right (LTR) format for languages that are initially displayed in right-to-left (RTL).";
"PlaybackQualityOnWiFi" = "Playback quality on WiFi";
"PlaybackQualityOnCellular" = "Playback quality on Cellular";
"SelectQuality" = "Select Quality";
"Default" = "Default";
"Best" = "Best";
"Startup" = "Startup page"; "Startup" = "Startup page";
"Home" = "Home"; "Home" = "Home";
"Explore" = "Explore"; "Explore" = "Explore";
@@ -181,8 +205,8 @@
"Warning" = "Warning"; "Warning" = "Warning";
"TabIsHidden" = "Hidden tab cannot be selected as startup page"; "TabIsHidden" = "Hidden tab cannot be selected as startup page";
"DonateViaPayPal" = "Donate via PayPal"; "SupportDevelopment" = "Support development";
"SupportViaGhSponsors" = "Support development via Github Sponsors"; "SupportDevelopmentDesc" = "If you like YTLite and would like to support its development, you can do it using any of convenient ways below.\nThanks❤";
"Version" = "Version"; "Version" = "Version";
"About" = "About"; "About" = "About";
"Credits" = "Credits"; "Credits" = "Credits";
@@ -194,6 +218,7 @@
"Japanese" = "Japanese localization"; "Japanese" = "Japanese localization";
"Vietnamese" = "Vietnamese localization"; "Vietnamese" = "Vietnamese localization";
"Advanced" = "Advanced mode"; "Advanced" = "Advanced mode";
"AdvancedDesc" = "More customizable mode";
"AdvancedModeReminder" = "Would you like to activate Advanced mode for YTLite?\n\nThis mode provides more than 50 additional options to customize and optimize your YouTube experience. You can enable/disable it later from Settings → %@ → %@ → %@."; "AdvancedModeReminder" = "Would you like to activate Advanced mode for YTLite?\n\nThis mode provides more than 50 additional options to customize and optimize your YouTube experience. You can enable/disable it later from Settings → %@ → %@ → %@.";
"ClearCache" = "Clear cache"; "ClearCache" = "Clear cache";
"ResetSettings" = "Reset YTLite settings"; "ResetSettings" = "Reset YTLite settings";
@@ -207,11 +232,15 @@
"CopyTitle" = "Copy title"; "CopyTitle" = "Copy title";
"CopyDescription" = "Copy description"; "CopyDescription" = "Copy description";
"CopyPostText" = "Copy post text"; "CopyPostText" = "Copy post text";
"SaveCurrentImage" = "Save current image";
"CopyCurrentImage" = "Copy current image";
"SavePostAsImage" = "Save post as image"; "SavePostAsImage" = "Save post as image";
"CopyPostAsImage" = "Copy post as image"; "CopyPostAsImage" = "Copy post as image";
"CopyCommentText" = "Copy comment text"; "CopyCommentText" = "Copy comment text";
"SaveCommentAsImage" = "Save comment as image"; "SaveCommentAsImage" = "Save comment as image";
"CopyCommentAsImage" = "Copy comment as image"; "CopyCommentAsImage" = "Copy comment as image";
"SaveProfilePicture" = "Save profile picture";
"CopyProfilePicture" = "Copy profile picture";
"Cancel" = "Cancel"; "Cancel" = "Cancel";
"Copied" = "Copied to clipboard"; "Copied" = "Copied to clipboard";
"Saved" = "Saved to Photos"; "Saved" = "Saved to Photos";
@@ -67,6 +67,12 @@
"DontSnap2ChapterDesc" = "Desactiva el salto al siguiente episodio mediante el gesto de doble toque."; "DontSnap2ChapterDesc" = "Desactiva el salto al siguiente episodio mediante el gesto de doble toque.";
"RedProgressBar" = "Barra de progreso roja"; "RedProgressBar" = "Barra de progreso roja";
"RedProgressBarDesc" = "Devuelve la barra de progreso roja."; "RedProgressBarDesc" = "Devuelve la barra de progreso roja.";
"NoPlayerRemixButton" = "Quitar botón Remix";
"NoPlayerRemixButtonDesc" = "Elimina el botón Remix situado debajo del reproductor.";
"NoPlayerClipButton" = "Elimina el botón de clip";
"NoPlayerClipButtonDesc" = "Elimina botón de clip debajo del reproductor";
"NoPlayerDownloadButton" = "Elimina el botón de descarga";
"NoPlayerDownloadButtonDesc" = "Elimina el botón de descarga situado bajo el reproductor";
"NoHints" = "Desactivar sugerencias"; "NoHints" = "Desactivar sugerencias";
"NoHintsDesc" = "Desactiva las sugerencias del autor que aparecen en la esquina superior derecha durante la reproducción."; "NoHintsDesc" = "Desactiva las sugerencias del autor que aparecen en la esquina superior derecha durante la reproducción.";
"NoFreeZoom" = "Desactivar gesto de zoom libre"; "NoFreeZoom" = "Desactivar gesto de zoom libre";
@@ -143,20 +149,32 @@
"HideShortsAudioTrackDesc" = "Oculta la pista de audio debajo de la descripción de Shorts."; "HideShortsAudioTrackDesc" = "Oculta la pista de audio debajo de la descripción de Shorts.";
"Other" = "Otro"; "Other" = "Otro";
"CopyVideoInfo" = "Copy video information"; "CopyVideoInfo" = "Copia la información del vídeo";
"CopyVideoInfoDesc" = "Adds button to copy video title and description into Video Description panel."; "CopyVideoInfoDesc" = "Añade un botón para copiar el título y la descripción del vídeo en el panel de descripción del vídeo.";
"PostManager" = "Save post information"; "PostManager" = "Guardar información de post";
"PostManagerDesc" = "Allows to copy post text and save post as image by long tap."; "PostManagerDesc" = "Permite copiar el texto de la entrada y guardarla como imagen pulsando prolongadamente";
"SavePostImage" = "Guardar imagen de las entradas de la comunidad";
"SavePostImageDesc" = "Guarda la imagen de las publicaciones de la comunidad en la aplicación Fotos con un toque prolongado";
"SaveProfilePhoto" = "Guardar foto de perfil"; "SaveProfilePhoto" = "Guardar foto de perfil";
"SaveProfilePhotoDesc" = "Guarda la imagen de perfil en la aplicación Fotos con un toque prolongado"; "SaveProfilePhotoDesc" = "Guarda la imagen de perfil en la aplicación Fotos con un toque prolongado";
"CommentManager" = "Save comment information"; "CommentManager" = "Guardar información de comentarios";
"CommentManagerDesc" = "Allows to copy comment text and save comment as image by long tap."; "CommentManagerDesc" = "Permite copiar texto de comentario y guardar comentario como imagen mediante pulsación larga".;
"FixAlbums" = "Arreglar portadas"; "FixAlbums" = "Arreglar portadas";
"FixAlbumsDesc" = "Corrige la visualización de portadas para usuarios de Rusia"; "FixAlbumsDesc" = "Corrige la visualización de portadas para usuarios de Rusia";
"RemovePlayNext" = "Eliminar \"Reproducir siguiente en cola\""; "RemovePlayNext" = "Eliminar \"Reproducir siguiente en cola\"";
"RemovePlayNextDesc" = "Elimina la opción \"Reproducir siguiente en cola\" del menú."; "RemovePlayNextDesc" = "Elimina la opción \"Reproducir siguiente en cola\" del menú.";
"RemoveDownloadMenu" = "Quitar \"Descargar\"";
"RemoveDownloadMenuDesc" = "Elimina la opción \"Descargar\" del menú.";
"RemoveWatchLaterMenu" = "Eliminar \"Guardar para ver después\"";
"RemoveWatchLaterMenuDesc" = "Elimina del menú la opción \"Guardar para ver más tarde\"";
"RemoveSaveToPlaylistMenu" = "Quitar \"Guardar en lista de reproducción\"";
"RemoveSaveToPlaylistMenuDesc" = "Elimina la opción \"Guardar en lista de reproducción\" del menú.";
"RemoveShareMenu" = "Eliminar \"Compartir\"";
"RemoveShareMenuDesc" = "Elimina la opción \"Compartir\" del menú.";
"RemoveNotInterestedMenu" = "Eliminar \"No me interesa\"";
"RemoveNotInterestedMenuDesc" = "Elimina la opción \"No me interesa\" del menú.";
"RemoveDontRecommendMenu" = "Quitar \"No recomiendo canal\"";
"RemoveDontRecommendMenuDesc" = "Elimina del menú la opción \"No recomiendo canal\"";
"RemoveReportMenu" = "Eliminar \"Reportar\"";
"RemoveReportMenuDesc" = "Elimina la opción \"Reportar\" del menú.";
"NoContinueWatching" = "Eliminar \"Continuar viendo\""; "NoContinueWatching" = "Eliminar \"Continuar viendo\"";
"NoContinueWatchingDesc" = "Elimina la sección \"Continuar viendo\" que contiene videos sin terminar de la página de inicio."; "NoContinueWatchingDesc" = "Elimina la sección \"Continuar viendo\" que contiene videos sin terminar de la página de inicio.";
"NoSearchHistory" = "Ocultar el historial de búsqueda"; "NoSearchHistory" = "Ocultar el historial de búsqueda";
@@ -172,6 +190,12 @@
"DisableRTL" = "Desactivar el formato RTL"; "DisableRTL" = "Desactivar el formato RTL";
"DisableRTLDesc" = "Muestra forzosamente el texto en formato de izquierda a derecha (LTR) para los idiomas que se muestran inicialmente en formato de derecha a izquierda (RTL)."; "DisableRTLDesc" = "Muestra forzosamente el texto en formato de izquierda a derecha (LTR) para los idiomas que se muestran inicialmente en formato de derecha a izquierda (RTL).";
"PlaybackQualityOnWiFi" = "Calidad de reproducción en WiFi";
"PlaybackQualityOnCellular" = "Calidad de reproducción en Cellular";
"SelectQuality" = "Seleccionar calidad";
"Default" = "Por defecto";
"Best" = "Mejor";
"Startup" = "Página de inicio"; "Startup" = "Página de inicio";
"Home" = "Inicio"; "Home" = "Inicio";
"Explore" = "Explorar"; "Explore" = "Explorar";
@@ -181,8 +205,8 @@
"Warning" = "Advertencia"; "Warning" = "Advertencia";
"TabIsHidden" = "No se puede seleccionar una pestaña oculta como página de inicio"; "TabIsHidden" = "No se puede seleccionar una pestaña oculta como página de inicio";
"DonateViaPayPal" = "Donate via PayPal"; "SupportDevelopment" = "Apoya el desarrollo";
"SupportViaGhSponsors" = "Support development via Github Sponsors"; "SupportDevelopmentDesc" = "Si le gusta YTLite y quiere apoyar su desarrollo, puede hacerlo de cualquiera de las formas que se indican a continuación.\nGracias❤";
"Version" = "Versión"; "Version" = "Versión";
"About" = "Acerca de"; "About" = "Acerca de";
"Credits" = "Créditos"; "Credits" = "Créditos";
@@ -194,6 +218,7 @@
"Japanese" = "Traducción: Japonés"; "Japanese" = "Traducción: Japonés";
"Vietnamese" = "Vietnamese localization"; "Vietnamese" = "Vietnamese localization";
"Advanced" = "Modo avanzado"; "Advanced" = "Modo avanzado";
"AdvancedDesc" = "More customizable mode";
"AdvancedModeReminder" = "¿Desea activar el modo Avanzado para YTLite?\n\nEste modo ofrece más de 50 opciones adicionales para personalizar y optimizar tu experiencia en YouTube. Puedes activarlo/desactivarlo más tarde desde Ajustes → %@ → %@ → %@."; "AdvancedModeReminder" = "¿Desea activar el modo Avanzado para YTLite?\n\nEste modo ofrece más de 50 opciones adicionales para personalizar y optimizar tu experiencia en YouTube. Puedes activarlo/desactivarlo más tarde desde Ajustes → %@ → %@ → %@.";
"ClearCache" = "Clear cache"; "ClearCache" = "Clear cache";
"ResetSettings" = "Restablecer configuración de YTLite"; "ResetSettings" = "Restablecer configuración de YTLite";
@@ -203,17 +228,21 @@
"Yes" = "Sí"; "Yes" = "Sí";
"No" = "No"; "No" = "No";
"SelectAction" = "Select action"; "SelectAction" = "Seleccionar acción";
"CopyTitle" = "Copy title"; "CopyTitle" = "Copiar título";
"CopyDescription" = "Copy description"; "CopyDescription" = "Copiar descripción";
"CopyPostText" = "Copy post text"; "CopyPostText" = "Copiar texto de post";
"SavePostAsImage" = "Save post as image"; "SaveCurrentImage" = "Guardar imagen actual";
"CopyPostAsImage" = "Copy post as image"; "CopyCurrentImage" = "Copiar imagen actual";
"CopyCommentText" = "Copy comment text"; "SavePostAsImage" = "Guardar post como imagen";
"SaveCommentAsImage" = "Save comment as image"; "CopyPostAsImage" = "Copiar post como imagen";
"CopyCommentAsImage" = "Copy comment as image"; "CopyCommentText" = "Copiar texto de comentario";
"Cancel" = "Cancel"; "SaveCommentAsImage" = "Guardar comentario como imagen";
"CopyCommentAsImage" = "Copiar comentario como imagen";
"SaveProfilePicture" = "Guardar imagen de perfil";
"CopyProfilePicture" = "Copiar imagen de perfil";
"Cancel" = "Cancelar";
"Copied" = "Copiado al portapapeles"; "Copied" = "Copiado al portapapeles";
"Done" = "Done";
"Saved" = "Guardado en Fotos"; "Saved" = "Guardado en Fotos";
"Done" = "Hecho";
"Error" = "Error"; "Error" = "Error";
@@ -67,6 +67,12 @@
"DontSnap2ChapterDesc" = "Désactive le passage à l'épisode suivant en double tapant."; "DontSnap2ChapterDesc" = "Désactive le passage à l'épisode suivant en double tapant.";
"RedProgressBar" = "Barre de progression rouge"; "RedProgressBar" = "Barre de progression rouge";
"RedProgressBarDesc" = "Ramène la barre de progression rouge."; "RedProgressBarDesc" = "Ramène la barre de progression rouge.";
"NoPlayerRemixButton" = "Supprimer le bouton de remix";
"NoPlayerRemixButtonDesc" = "Supprime le bouton de remix sous le lecteur.";
"NoPlayerClipButton" = "Supprimer le bouton de clip";
"NoPlayerClipButtonDesc" = "Supprime le bouton de clip sous le lecteur.";
"NoPlayerDownloadButton" = "Supprimer le bouton de téléchargement";
"NoPlayerDownloadButtonDesc" = "Supprime le bouton de téléchargement sous le lecteur.";
"NoHints" = "Désactiver les indices"; "NoHints" = "Désactiver les indices";
"NoHintsDesc" = "Désactive les indices de l'auteur qui apparaissent dans le coin supérieur droit pendant la lecture."; "NoHintsDesc" = "Désactive les indices de l'auteur qui apparaissent dans le coin supérieur droit pendant la lecture.";
"NoFreeZoom" = "Désactiver le geste de zoom libre"; "NoFreeZoom" = "Désactiver le geste de zoom libre";
@@ -145,18 +151,30 @@
"Other" = "Autre"; "Other" = "Autre";
"CopyVideoInfo" = "Copier les informations vidéo"; "CopyVideoInfo" = "Copier les informations vidéo";
"CopyVideoInfoDesc" = "Ajout d'un bouton permettant de copier le titre et la description de la vidéo dans le panneau Description de la vidéo."; "CopyVideoInfoDesc" = "Ajout d'un bouton permettant de copier le titre et la description de la vidéo dans le panneau Description de la vidéo.";
"PostManager" = "Save post information"; "PostManager" = "Gérer les publications";
"PostManagerDesc" = "Allows to copy post text and save post as image by long tap."; "PostManagerDesc" = "Permet de copier le texte de la publication et de sauvegarder la publication en tant qu'image en maintenant le toucher.";
"SavePostImage" = "Enregistrer l'image des publications de la communauté";
"SavePostImageDesc" = "Enregistre l'image des publications de la communauté dans l'application Photos en appuyant longuement.";
"SaveProfilePhoto" = "Enregistrer la photo de profil"; "SaveProfilePhoto" = "Enregistrer la photo de profil";
"SaveProfilePhotoDesc" = "Enregistre la photo de profil dans l'application Photos en appuyant longuement."; "SaveProfilePhotoDesc" = "Enregistre la photo de profil dans l'application Photos en appuyant longuement.";
"CommentManager" = "Save comment information"; "CommentManager" = "Gérer les commentaires";
"CommentManagerDesc" = "Allows to copy comment text and save comment as image by long tap."; "CommentManagerDesc" = "Permet de copier le texte des commentaires et de sauvegarder le commentaire en tant qu'image en maintenant une pression prolongée.";
"FixAlbums" = "Réparer les couvertures"; "FixAlbums" = "Réparer les vignettes";
"FixAlbumsDesc" = "Répare l'affichage des couvertures pour les utilisateurs de Russie."; "FixAlbumsDesc" = "Répare l'affichage des vignettes pour les utilisateurs de Russie.";
"RemovePlayNext" = "Supprimer \"Placer en première position dans la file d'attente\""; "RemovePlayNext" = "Supprimer \"Placer en première position dans la file d'attente\"";
"RemovePlayNextDesc" = "Supprime l'option \"Placer en première position dans la file d'attente\" du menu."; "RemovePlayNextDesc" = "Supprime l'option \"Placer en première position dans la file d'attente\" du menu.";
"RemoveDownloadMenu" = "Supprimer \"Télécharger\"";
"RemoveDownloadMenuDesc" = "Supprime l'option \"Télécharger\" du menu.";
"RemoveWatchLaterMenu" = "Supprimer \"Enregistrer pour plus tard\"";
"RemoveWatchLaterMenuDesc" = "Supprime l'option \"Enregistrer pour plus tard\" du menu.";
"RemoveSaveToPlaylistMenu" = "Supprimer \"Enregistrer dans une playlist\"";
"RemoveSaveToPlaylistMenuDesc" = "Supprime l'option \"Enregistrer dans une playlist\" du menu.";
"RemoveShareMenu" = "Supprimer \"Partager\"";
"RemoveShareMenuDesc" = "Supprime l'option \"Partager\" du menu.";
"RemoveNotInterestedMenu" = "Supprimer \"Pas intéressé\"";
"RemoveNotInterestedMenuDesc" = "Supprime l'option \"Pas intéressé\" du menu.";
"RemoveDontRecommendMenu" = "Supprimer \"Ne pas recommander la chaîne\"";
"RemoveDontRecommendMenuDesc" = "Supprime l'option \"Ne pas recommander la chaîne\" du menu.";
"RemoveReportMenu" = "Supprimer \"Signaler\"";
"RemoveReportMenuDesc" = "Supprime l'option \"Signaler\" du menu.";
"NoContinueWatching" = "Supprimer \"Continuer à regarder\""; "NoContinueWatching" = "Supprimer \"Continuer à regarder\"";
"NoContinueWatchingDesc" = "Supprime la section \"Continuer à regarder\" contenant les vidéos inachevées de la page d'accueil."; "NoContinueWatchingDesc" = "Supprime la section \"Continuer à regarder\" contenant les vidéos inachevées de la page d'accueil.";
"NoSearchHistory" = "Masquer l'historique de recherche"; "NoSearchHistory" = "Masquer l'historique de recherche";
@@ -172,6 +190,12 @@
"DisableRTL" = "Désactiver le formatage de droite à gauche"; "DisableRTL" = "Désactiver le formatage de droite à gauche";
"DisableRTLDesc" = "Affiche le texte de force en format de gauche à droite (LTR) pour les langues qui sont initialement affichées de droite à gauche (RTL)."; "DisableRTLDesc" = "Affiche le texte de force en format de gauche à droite (LTR) pour les langues qui sont initialement affichées de droite à gauche (RTL).";
"PlaybackQualityOnWiFi" = "Qualité de lecture sur WiFi";
"PlaybackQualityOnCellular" = "Qualité de lecture sur réseau cellulaire";
"SelectQuality" = "Sélectionner la qualité";
"Default" = "Par défaut";
"Best" = "Meilleure";
"Startup" = "Page de démarrage"; "Startup" = "Page de démarrage";
"Home" = "Accueil"; "Home" = "Accueil";
"Explore" = "Explorer"; "Explore" = "Explorer";
@@ -181,8 +205,8 @@
"Warning" = "Avertissement"; "Warning" = "Avertissement";
"TabIsHidden" = "L'onglet masqué ne peut pas être sélectionné comme page de démarrage"; "TabIsHidden" = "L'onglet masqué ne peut pas être sélectionné comme page de démarrage";
"DonateViaPayPal" = "Faire un don via PayPal"; "SupportDevelopment" = "Soutenir le développement";
"SupportViaGhSponsors" = "Soutenir le développement via les sponsors Github"; "SupportDevelopmentDesc" = "Si vous aimez YTLite et souhaitez soutenir son développement, vous pouvez le faire en utilisant l'une des méthodes pratiques ci-dessous.\nMerci❤";
"Version" = "Version"; "Version" = "Version";
"About" = "À propos"; "About" = "À propos";
"Credits" = "Crédits"; "Credits" = "Crédits";
@@ -194,6 +218,7 @@
"Japanese" = "Localisation japonaise"; "Japanese" = "Localisation japonaise";
"Vietnamese" = "Localisation vietnamienne"; "Vietnamese" = "Localisation vietnamienne";
"Advanced" = "Mode avancé"; "Advanced" = "Mode avancé";
"AdvancedDesc" = "Mode plus personnalisable";
"AdvancedModeReminder" = "Voulez-vous activer le mode avancé pour YTLite ?\n\nCe mode offre plus de 50 options supplémentaires pour personnaliser et optimiser votre expérience YouTube. Vous pouvez l'activer/désactiver ultérieurement depuis Paramètres → %@ → %@ → %@."; "AdvancedModeReminder" = "Voulez-vous activer le mode avancé pour YTLite ?\n\nCe mode offre plus de 50 options supplémentaires pour personnaliser et optimiser votre expérience YouTube. Vous pouvez l'activer/désactiver ultérieurement depuis Paramètres → %@ → %@ → %@.";
"ClearCache" = "Effacer le cache"; "ClearCache" = "Effacer le cache";
"ResetSettings" = "Réinitialiser les paramètres YTLite"; "ResetSettings" = "Réinitialiser les paramètres YTLite";
@@ -206,12 +231,14 @@
"SelectAction" = "Sélectionner une action"; "SelectAction" = "Sélectionner une action";
"CopyTitle" = "Copier le titre"; "CopyTitle" = "Copier le titre";
"CopyDescription" = "Copier la description"; "CopyDescription" = "Copier la description";
"CopyPostText" = "Copy post text"; "CopyPostText" = "Copier le texte de la publication";
"SavePostAsImage" = "Save post as image"; "SavePostAsImage" = "Enregistrer la publication en tant qu'image";
"CopyPostAsImage" = "Copy post as image"; "CopyPostAsImage" = "Copier la publication en tant qu'image";
"CopyCommentText" = "Copy comment text"; "CopyCommentText" = "Copier le texte du commentaire";
"SaveCommentAsImage" = "Save comment as image"; "SaveCommentAsImage" = "Enregistrer le commentaire en tant qu'image";
"CopyCommentAsImage" = "Copy comment as image"; "CopyCommentAsImage" = "Copier le commentaire en tant qu'image";
"SaveProfilePicture" = "Enregistrer la photo de profil";
"CopyProfilePicture" = "Copier la photo de profil";
"Cancel" = "Annuler"; "Cancel" = "Annuler";
"Copied" = "Copié dans le presse-papiers"; "Copied" = "Copié dans le presse-papiers";
"Saved" = "Enregistré dans Photos"; "Saved" = "Enregistré dans Photos";
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

@@ -67,6 +67,12 @@
"DontSnap2ChapterDesc" = "ダブルタップジェスチャーで次のエピソードへスキップするのを無効にします"; "DontSnap2ChapterDesc" = "ダブルタップジェスチャーで次のエピソードへスキップするのを無効にします";
"RedProgressBar" = "赤いプログレスバー"; "RedProgressBar" = "赤いプログレスバー";
"RedProgressBarDesc" = "赤いプログレスバーを復元します"; "RedProgressBarDesc" = "赤いプログレスバーを復元します";
"NoPlayerRemixButton" = "Remove remix button";
"NoPlayerRemixButtonDesc" = "Removes remix button under the player.";
"NoPlayerClipButton" = "Remove clip button";
"NoPlayerClipButtonDesc" = "Removes clip button under the player.";
"NoPlayerDownloadButton" = "Remove download button";
"NoPlayerDownloadButtonDesc" = "Removes download button under the player.";
"NoHints" = "ヒントを無効化"; "NoHints" = "ヒントを無効化";
"NoHintsDesc" = "再生中に右上に表示される投稿者のヒントを無効にします"; "NoHintsDesc" = "再生中に右上に表示される投稿者のヒントを無効にします";
"NoFreeZoom" = "フリーズームジェスチャーを無効化"; "NoFreeZoom" = "フリーズームジェスチャーを無効化";
@@ -147,8 +153,6 @@
"CopyVideoInfoDesc" = "Adds button to copy video title and description into Video Description panel."; "CopyVideoInfoDesc" = "Adds button to copy video title and description into Video Description panel.";
"PostManager" = "Save post information"; "PostManager" = "Save post information";
"PostManagerDesc" = "Allows to copy post text and save post as image by long tap."; "PostManagerDesc" = "Allows to copy post text and save post as image by long tap.";
"SavePostImage" = "Save community posts image";
"SavePostImageDesc" = "Saves community posts image to the Photos app by long tap.";
"SaveProfilePhoto" = "Save profile picture"; "SaveProfilePhoto" = "Save profile picture";
"SaveProfilePhotoDesc" = "Saves profile picture to the Photos app by long tap."; "SaveProfilePhotoDesc" = "Saves profile picture to the Photos app by long tap.";
"CommentManager" = "Save comment information"; "CommentManager" = "Save comment information";
@@ -157,6 +161,20 @@
"FixAlbumsDesc" = "Fixes the display of covers for users from Russia."; "FixAlbumsDesc" = "Fixes the display of covers for users from Russia.";
"RemovePlayNext" = "\"次に再生\"を削除"; "RemovePlayNext" = "\"次に再生\"を削除";
"RemovePlayNextDesc" = "メニューから\"次に再生\"オプションを削除します"; "RemovePlayNextDesc" = "メニューから\"次に再生\"オプションを削除します";
"RemoveDownloadMenu" = "Remove \"Download\"";
"RemoveDownloadMenuDesc" = "Removes \"Download\" option from menu.";
"RemoveWatchLaterMenu" = "Remove \"Save to Watch Later\"";
"RemoveWatchLaterMenuDesc" = "Removes \"Save to Watch Later\" option from menu.";
"RemoveSaveToPlaylistMenu" = "Remove \"Save to playlist\"";
"RemoveSaveToPlaylistMenuDesc" = "Removes \"Save to playlist\" option from menu.";
"RemoveShareMenu" = "Remove \"Share\"";
"RemoveShareMenuDesc" = "Removes \"Share\" option from menu.";
"RemoveNotInterestedMenu" = "Remove \"Not interested\"";
"RemoveNotInterestedMenuDesc" = "Removes \"Not interested\" option from menu.";
"RemoveDontRecommendMenu" = "Remove \"Don't recommend channel\"";
"RemoveDontRecommendMenuDesc" = "Removes \"Don't recommend channel\" option from menu.";
"RemoveReportMenu" = "Remove \"Report\"";
"RemoveReportMenuDesc" = "Removes \"Report\" option from menu.";
"NoContinueWatching" = "\"続きを見る\"を削除"; "NoContinueWatching" = "\"続きを見る\"を削除";
"NoContinueWatchingDesc" = "ホームページに未完成の動画を含む\"続きを見る\"セクションを削除します"; "NoContinueWatchingDesc" = "ホームページに未完成の動画を含む\"続きを見る\"セクションを削除します";
"NoSearchHistory" = "検索履歴を非表示"; "NoSearchHistory" = "検索履歴を非表示";
@@ -172,6 +190,12 @@
"DisableRTL" = "RTLフォーマットを無効化"; "DisableRTL" = "RTLフォーマットを無効化";
"DisableRTLDesc" = "RTLで表示される言語を左から右(LTR)の形式で表示するように強制します"; "DisableRTLDesc" = "RTLで表示される言語を左から右(LTR)の形式で表示するように強制します";
"PlaybackQualityOnWiFi" = "Playback quality on WiFi";
"PlaybackQualityOnCellular" = "Playback quality on Cellular";
"SelectQuality" = "Select Quality";
"Default" = "Default";
"Best" = "Best";
"Startup" = "スタートアップページ"; "Startup" = "スタートアップページ";
"Home" = "ホーム"; "Home" = "ホーム";
"Explore" = "探索"; "Explore" = "探索";
@@ -181,8 +205,8 @@
"Warning" = "警告"; "Warning" = "警告";
"TabIsHidden" = "非表示のタブはスタートアップページとして選択できません"; "TabIsHidden" = "非表示のタブはスタートアップページとして選択できません";
"DonateViaPayPal" = "Donate via PayPal"; "SupportDevelopment" = "Support development";
"SupportViaGhSponsors" = "Support development via Github Sponsors"; "SupportDevelopmentDesc" = "If you like YTLite and would like to support its development, you can do it using any of convenient ways below.\nThanks❤";
"Version" = "バージョン"; "Version" = "バージョン";
"About" = "About"; "About" = "About";
"Credits" = "クレジット"; "Credits" = "クレジット";
@@ -194,6 +218,7 @@
"Japanese" = "日本語翻訳"; "Japanese" = "日本語翻訳";
"Vietnamese" = "Vietnamese localization"; "Vietnamese" = "Vietnamese localization";
"Advanced" = "アドバンスモード"; "Advanced" = "アドバンスモード";
"AdvancedDesc" = "More customizable mode";
"AdvancedModeReminder" = "YTLiteでアドバンスモードを有効にしますか?\n\nこのモードでは50以上の追加オプションを使用してYouTubeのカスタマイズと最適化が可能です。後で、設定 → %@ → %@ → %@から変更できます"; "AdvancedModeReminder" = "YTLiteでアドバンスモードを有効にしますか?\n\nこのモードでは50以上の追加オプションを使用してYouTubeのカスタマイズと最適化が可能です。後で、設定 → %@ → %@ → %@から変更できます";
"ClearCache" = "Clear cache"; "ClearCache" = "Clear cache";
"ResetSettings" = "YTLiteの設定をリセット"; "ResetSettings" = "YTLiteの設定をリセット";
@@ -212,6 +237,8 @@
"CopyCommentText" = "Copy comment text"; "CopyCommentText" = "Copy comment text";
"SaveCommentAsImage" = "Save comment as image"; "SaveCommentAsImage" = "Save comment as image";
"CopyCommentAsImage" = "Copy comment as image"; "CopyCommentAsImage" = "Copy comment as image";
"SaveProfilePicture" = "Save profile picture";
"CopyProfilePicture" = "Copy profile picture";
"Cancel" = "Cancel"; "Cancel" = "Cancel";
"Copied" = "Copied to clipboard"; "Copied" = "Copied to clipboard";
"Saved" = "Saved to Photos"; "Saved" = "Saved to Photos";
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

@@ -67,6 +67,12 @@
"DontSnap2ChapterDesc" = "Отключает жест перемотки к следующему эпизоду двойным нажатием."; "DontSnap2ChapterDesc" = "Отключает жест перемотки к следующему эпизоду двойным нажатием.";
"RedProgressBar" = "Красный прогресс-бар"; "RedProgressBar" = "Красный прогресс-бар";
"RedProgressBarDesc" = "Возвращает красный прогресс-бар вместо нового, серого цвета."; "RedProgressBarDesc" = "Возвращает красный прогресс-бар вместо нового, серого цвета.";
"NoPlayerRemixButton" = "Убрать кнопку «Ремикс»";
"NoPlayerRemixButtonDesc" = "Убирает кнопку «Ремикс» под плеером.";
"NoPlayerClipButton" = "Убрать кнопку «Создать клип»";
"NoPlayerClipButtonDesc" = "Убирает кнопку «Создать клип» под плеером.";
"NoPlayerDownloadButton" = "Убрать кнопку «Скачать»";
"NoPlayerDownloadButtonDesc" = "Убирает кнопку «Скачать» под плеером.";
"NoHints" = "Отключить подсказки"; "NoHints" = "Отключить подсказки";
"NoHintsDesc" = "Скрывает подсказки от авторов видео, появляющиеся в правом верхнем углу."; "NoHintsDesc" = "Скрывает подсказки от авторов видео, появляющиеся в правом верхнем углу.";
"NoFreeZoom" = "Отключить жесты для зума"; "NoFreeZoom" = "Отключить жесты для зума";
@@ -147,8 +153,6 @@
"CopyVideoInfoDesc" = "Добавляет кнопку для копирования названия и описания видео в панель описания видео."; "CopyVideoInfoDesc" = "Добавляет кнопку для копирования названия и описания видео в панель описания видео.";
"PostManager" = "Сохранять информацию с постов"; "PostManager" = "Сохранять информацию с постов";
"PostManagerDesc" = "Позволяет скопировать текст из поста или сохранить пост как фото долгим нажатием по нему."; "PostManagerDesc" = "Позволяет скопировать текст из поста или сохранить пост как фото долгим нажатием по нему.";
"SavePostImage" = "Сохранять изображения постов";
"SavePostImageDesc" = "Сохраняет изображения постов в «Фото» долгим нажатием по ним.";
"SaveProfilePhoto" = "Сохранять фото профиля"; "SaveProfilePhoto" = "Сохранять фото профиля";
"SaveProfilePhotoDesc" = "Сохраняет фото профиля в «Фото» долгим нажатием по нему."; "SaveProfilePhotoDesc" = "Сохраняет фото профиля в «Фото» долгим нажатием по нему.";
"CopyCommentText" = "Копировать текст комментариев"; "CopyCommentText" = "Копировать текст комментариев";
@@ -159,6 +163,20 @@
"FixAlbumsDesc" = "Исправляет отображение обложек в том случае, если вы из России."; "FixAlbumsDesc" = "Исправляет отображение обложек в том случае, если вы из России.";
"RemovePlayNext" = "Убрать «Добавить в начало очереди»"; "RemovePlayNext" = "Убрать «Добавить в начало очереди»";
"RemovePlayNextDesc" = "Убирает опцию «Добавить в начало очереди» из меню видео."; "RemovePlayNextDesc" = "Убирает опцию «Добавить в начало очереди» из меню видео.";
"RemoveDownloadMenu" = "Убрать «Скачать»";
"RemoveDownloadMenuDesc" = "Убирает «Скачать» из меню видео.";
"RemoveWatchLaterMenu" = "Убрать «Смотреть позже»";
"RemoveWatchLaterMenuDesc" = "Убирает «Смотреть позже» из меню видео.";
"RemoveSaveToPlaylistMenu" = "Убрать «Добавить в плейлист»";
"RemoveSaveToPlaylistMenuDesc" = "Убирает «Добавить в плейлист» из меню видео.";
"RemoveShareMenu" = "Убрать «Поделиться»";
"RemoveShareMenuDesc" = "Убирает «Поделиться» из меню видео.";
"RemoveNotInterestedMenu" = "Убрать «Не интересует»";
"RemoveNotInterestedMenuDesc" = "Убирает «Не интересует» из меню видео.";
"RemoveDontRecommendMenu" = "Убрать «Не рекомендовать»";
"RemoveDontRecommendMenuDesc" = "Убирает «Не рекомендовать видео с этого канала» из меню видео.";
"RemoveReportMenu" = "Убрать «Пожаловаться»";
"RemoveReportMenuDesc" = "Убирает «Пожаловаться» из меню видео.";
"NoContinueWatching" = "Отключить «Продолжить просмотр»"; "NoContinueWatching" = "Отключить «Продолжить просмотр»";
"NoContinueWatchingDesc" = "Удаляет блок «Продолжить просмотр» содержащий недосмотренные видео с Главной страницы."; "NoContinueWatchingDesc" = "Удаляет блок «Продолжить просмотр» содержащий недосмотренные видео с Главной страницы.";
"NoSearchHistory" = "Скрыть историю поиска"; "NoSearchHistory" = "Скрыть историю поиска";
@@ -174,6 +192,12 @@
"DisableRTL" = "Запретить формат «справа налево»"; "DisableRTL" = "Запретить формат «справа налево»";
"DisableRTLDesc" = "Принудительно отображает текст в формате слева направо для языков, изначально отображающихся в формате справа налево."; "DisableRTLDesc" = "Принудительно отображает текст в формате слева направо для языков, изначально отображающихся в формате справа налево.";
"PlaybackQualityOnWiFi" = "Качество по WiFi";
"PlaybackQualityOnCellular" = "Качество по мобильной сети";
"SelectQuality" = "Выберите качество";
"Default" = "По умолчанию";
"Best" = "Лучшее";
"Startup" = "Начальная страница"; "Startup" = "Начальная страница";
"Home" = "Главная"; "Home" = "Главная";
"Explore" = "Навигация"; "Explore" = "Навигация";
@@ -183,8 +207,8 @@
"Warning" = "Внимание"; "Warning" = "Внимание";
"TabIsHidden" = "Скрытая вкладка не может быть выбрана в качестве начальной страницы"; "TabIsHidden" = "Скрытая вкладка не может быть выбрана в качестве начальной страницы";
"DonateViaPayPal" = "Задонатить на PayPal"; "SupportDevelopment" = "Помочь с развитием проекта";
"SupportViaGhSponsors" = "Поддержать разработку в Github Sponsors"; "SupportDevelopmentDesc" = "Если вам понравился YTLite и вы хотели бы поддержать проект, то можете сделать это любым подходящим ниже способом.\nСпасибо❤";
"Version" = "Версия"; "Version" = "Версия";
"About" = "О твике"; "About" = "О твике";
"Credits" = "Авторы"; "Credits" = "Авторы";
@@ -196,6 +220,7 @@
"Japanese" = "Японская локализация"; "Japanese" = "Японская локализация";
"Vietnamese" = "Вьетнамская локализация"; "Vietnamese" = "Вьетнамская локализация";
"Advanced" = "Расширенный режим"; "Advanced" = "Расширенный режим";
"AdvancedDesc" = "Более настраиваемый режим";
"AdvancedModeReminder" = "Хотите ли вы активировать расширенный режим настроек YTLite?\n\nДанный режим добавляет более 50 опций для тонкой настройки YouTube. Вы всегда сможете включить/отключить расширенный режим перейдя в Настройки → %@ → %@ → %@."; "AdvancedModeReminder" = "Хотите ли вы активировать расширенный режим настроек YTLite?\n\nДанный режим добавляет более 50 опций для тонкой настройки YouTube. Вы всегда сможете включить/отключить расширенный режим перейдя в Настройки → %@ → %@ → %@.";
"ClearCache" = "Очистить кеш"; "ClearCache" = "Очистить кеш";
"ResetSettings" = "Сбросить настройки твика"; "ResetSettings" = "Сбросить настройки твика";
@@ -209,11 +234,15 @@
"CopyTitle" = "Скопировать название"; "CopyTitle" = "Скопировать название";
"CopyDescription" = "Скопировать описание"; "CopyDescription" = "Скопировать описание";
"CopyPostText" = "Скопировать текст поста"; "CopyPostText" = "Скопировать текст поста";
"SaveCurrentImage" = "Сохранить данное фото";
"CopyCurrentImage" = "Скопировать данное фото";
"SavePostAsImage" = "Сохранить пост как фото"; "SavePostAsImage" = "Сохранить пост как фото";
"CopyPostAsImage" = "Скопировать пост как фото"; "CopyPostAsImage" = "Скопировать пост как фото";
"CopyCommentText" = "Скопировать текст комментария"; "CopyCommentText" = "Скопировать текст комментария";
"SaveCommentAsImage" = "Сохранить комментарий как фото"; "SaveCommentAsImage" = "Сохранить комментарий как фото";
"CopyCommentAsImage" = "Скопировать комментарий как фото"; "CopyCommentAsImage" = "Скопировать комментарий как фото";
"SaveProfilePicture" = "Сохранить фото профиля";
"CopyProfilePicture" = "Скопировать фото профиля";
"Cancel" = "Отмена"; "Cancel" = "Отмена";
"Copied" = "Скопировано в буфер обмена"; "Copied" = "Скопировано в буфер обмена";
"Saved" = "Сохранено в Фото"; "Saved" = "Сохранено в Фото";
@@ -67,6 +67,12 @@
"DontSnap2ChapterDesc" = "Tắt tính năng tự động chuyển tới chương gần nhất khi tua video."; "DontSnap2ChapterDesc" = "Tắt tính năng tự động chuyển tới chương gần nhất khi tua video.";
"RedProgressBar" = "Thanh tiến trình màu đỏ"; "RedProgressBar" = "Thanh tiến trình màu đỏ";
"RedProgressBarDesc" = "Mang lại thanh tiến trình màu đỏ."; "RedProgressBarDesc" = "Mang lại thanh tiến trình màu đỏ.";
"NoPlayerRemixButton" = "Xóa nút phối lại";
"NoPlayerRemixButtonDesc" = "Xóa nút phối lại bên dưới trình phát.";
"NoPlayerClipButton" = "Xóa nút clip";
"NoPlayerClipButtonDesc" = "Xóa nút clip bên dưới trình phát.";
"NoPlayerDownloadButton" = "Xóa nút tải xuống";
"NoPlayerDownloadButtonDesc" = "Xóa nút tải xuống dưới trình phát.";
"NoHints" = "Tắt gợi ý"; "NoHints" = "Tắt gợi ý";
"NoHintsDesc" = "Tắt gợi ý của tác giả xuất hiện ở góc trên bên phải trong khi phát lại."; "NoHintsDesc" = "Tắt gợi ý của tác giả xuất hiện ở góc trên bên phải trong khi phát lại.";
"NoFreeZoom" = "Tắt tính năng chạm để thu phóng"; "NoFreeZoom" = "Tắt tính năng chạm để thu phóng";
@@ -145,18 +151,30 @@
"Other" = "Khác"; "Other" = "Khác";
"CopyVideoInfo" = "Sao chép thông tin video"; "CopyVideoInfo" = "Sao chép thông tin video";
"CopyVideoInfoDesc" = "Thêm nút để sao chép tiêu đề và mô tả video vào bảng Mô tả Video."; "CopyVideoInfoDesc" = "Thêm nút để sao chép tiêu đề và mô tả video vào bảng Mô tả Video.";
"PostManager" = "Lưu bài viết"; "PostManager" = "Lưu bài đăng";
"PostManagerDesc" = "Cho phép sao chép văn bản bài viết và lưu bài viết dưới dạng hình ảnh bằng cách nhấn giữ."; "PostManagerDesc" = "Cho phép sao chép văn bản bài đăng và lưu bài đăng dưới dạng hình ảnh bằng cách nhấn giữ.";
"SavePostImage" = "Lưu hình ảnh từ bài viết trên cộng đồng";
"SavePostImageDesc" = "Lưu hình ảnh bài viết của cộng đồng vào ứng dụng Ảnh bằng cách nhấn giữ.";
"SaveProfilePhoto" = "Lưu ảnh hồ sơ"; "SaveProfilePhoto" = "Lưu ảnh hồ sơ";
"SaveProfilePhotoDesc" = "Lưu ảnh hồ sơ vào ứng dụng Ảnh bằng cách nhấn và giữ."; "SaveProfilePhotoDesc" = "Lưu ảnh hồ sơ vào ứng dụng Ảnh bằng cách nhấn và giữ.";
"CommentManager" = "Save comment information"; "CommentManager" = "Lưu bình luận";
"CommentManagerDesc" = "Allows to copy comment text and save comment as image by long tap."; "CommentManagerDesc" = "Cho phép sao chép văn bản bình luận và lưu bình luận dưới dạng hình ảnh bằng cách nhấn giữ.";
"FixAlbums" = "Sửa Albums"; "FixAlbums" = "Sửa Albums";
"FixAlbumsDesc" = "Sửa lỗi hiển thị Albums cho người dùng Nga."; "FixAlbumsDesc" = "Sửa lỗi hiển thị Albums cho người dùng Nga.";
"RemovePlayNext" = "Xóa \"Phát tiếp theo trong danh sách chờ\""; "RemovePlayNext" = "Xóa \"Phát tiếp theo trong danh sách chờ\"";
"RemovePlayNextDesc" = "Xóa tùy chọn \"Phát tiếp theo trong danh sách chờ\" khỏi menu."; "RemovePlayNextDesc" = "Xóa tùy chọn \"Phát tiếp theo trong danh sách chờ\" khỏi menu.";
"RemoveDownloadMenu" = "Xóa \"Tải video xuống\"";
"RemoveDownloadMenuDesc" = "Xóa tùy chọn \"Tải video xuống\" khỏi menu.";
"RemoveWatchLaterMenu" = "Xóa \"Lưu vào danh sách Xem sau\"";
"RemoveWatchLaterMenuDesc" = "Xóa tùy chọn \"Lưu vào danh sách Xem sau\" khỏi menu.";
"RemoveSaveToPlaylistMenu" = "Xóa \"Lưu vào danh sách phát\"";
"RemoveSaveToPlaylistMenuDesc" = "Xóa tùy chọn \"Lưu vào danh sách phát\" khỏi menu.";
"RemoveShareMenu" = "Xóa \"Chia sẻ\"";
"RemoveShareMenuDesc" = "Xóa tùy chọn \"Chia sẻ\" khỏi menu.";
"RemoveNotInterestedMenu" = "Xóa \"Không quan tâm\"";
"RemoveNotInterestedMenuDesc" = "Xóa tùy chọn \"Không quan tâm\" khỏi menu.";
"RemoveDontRecommendMenu" = "Xóa \"Không đề xuất kênh này\"";
"RemoveDontRecommendMenuDesc" = "Xóa tùy chọn \"Không đề xuất kênh này\" khỏi menu.";
"RemoveReportMenu" = "Xóa \"Báo vi phạm\"";
"RemoveReportMenuDesc" = "Xóa tùy chọn \"Báo vi phạm\" khỏi menu.";
"NoContinueWatching" = "Xóa \"Tiếp tục xem\""; "NoContinueWatching" = "Xóa \"Tiếp tục xem\"";
"NoContinueWatchingDesc" = "Xóa phần \"Tiếp tục xem\" chứa các video chưa xem hết khỏi Trang chủ."; "NoContinueWatchingDesc" = "Xóa phần \"Tiếp tục xem\" chứa các video chưa xem hết khỏi Trang chủ.";
"NoSearchHistory" = "Ẩn lịch sử tìm kiếm"; "NoSearchHistory" = "Ẩn lịch sử tìm kiếm";
@@ -172,6 +190,12 @@
"DisableRTL" = "Tắt định dạng RTL"; "DisableRTL" = "Tắt định dạng RTL";
"DisableRTLDesc" = "Hiển thị mạnh mẽ văn bản ở định dạng từ trái sang phải (LTR) cho các ngôn ngữ ban đầu được hiển thị ở định dạng từ phải sang trái (RTL)."; "DisableRTLDesc" = "Hiển thị mạnh mẽ văn bản ở định dạng từ trái sang phải (LTR) cho các ngôn ngữ ban đầu được hiển thị ở định dạng từ phải sang trái (RTL).";
"PlaybackQualityOnWiFi" = "Chất lượng Video trên mạng Wi-Fi";
"PlaybackQualityOnCellular" = "Chất lượng Video trên mạng di động";
"SelectQuality" = "Chọn chất lượng";
"Default" = "Mặc định";
"Best" = "Tốt nhất";
"Startup" = "Trang khởi động"; "Startup" = "Trang khởi động";
"Home" = "Trang chủ"; "Home" = "Trang chủ";
"Explore" = "Khám phá"; "Explore" = "Khám phá";
@@ -181,8 +205,8 @@
"Warning" = "Cảnh báo"; "Warning" = "Cảnh báo";
"TabIsHidden" = "Không thể chọn Tab ẩn làm trang khởi động"; "TabIsHidden" = "Không thể chọn Tab ẩn làm trang khởi động";
"DonateViaPayPal" = "Quyên góp qua PayPal"; "SupportDevelopment" = "Hỗ trợ phát triển";
"SupportViaGhSponsors" = "Hỗ trợ phát triển thông qua Github"; "SupportDevelopmentDesc" = "Nếu bạn thích YTLite và muốn hỗ trợ sự phát triển của nó, bạn có thể thực hiện bằng bất kỳ cách thuận tiện nào dưới đây.\nCảm ơn❤";
"Version" = "Phiên bản"; "Version" = "Phiên bản";
"About" = "Giới thiệu"; "About" = "Giới thiệu";
"Credits" = "Credits"; "Credits" = "Credits";
@@ -194,6 +218,7 @@
"Japanese" = "Tiếng Nhật"; "Japanese" = "Tiếng Nhật";
"Vietnamese" = "Tiếng Việt"; "Vietnamese" = "Tiếng Việt";
"Advanced" = "Chế độ nâng cao"; "Advanced" = "Chế độ nâng cao";
"AdvancedDesc" = "Chế độ tùy chỉnh";
"AdvancedModeReminder" = "Bạn có muốn kích hoạt Chế độ nâng cao cho YTLite không?\n\nChế độ này cung cấp hơn 50 tùy chọn bổ sung để tùy chỉnh và tối ưu hóa trải nghiệm YouTube của bạn. Bạn có thể Bật/Tắt nó sau từ Cài đặt → %@ → %@ → %@."; "AdvancedModeReminder" = "Bạn có muốn kích hoạt Chế độ nâng cao cho YTLite không?\n\nChế độ này cung cấp hơn 50 tùy chọn bổ sung để tùy chỉnh và tối ưu hóa trải nghiệm YouTube của bạn. Bạn có thể Bật/Tắt nó sau từ Cài đặt → %@ → %@ → %@.";
"ClearCache" = "Xóa bộ nhớ đệm"; "ClearCache" = "Xóa bộ nhớ đệm";
"ResetSettings" = "Đặt lại cài đặt YTLite"; "ResetSettings" = "Đặt lại cài đặt YTLite";
@@ -206,12 +231,14 @@
"SelectAction" = "Chọn hành động"; "SelectAction" = "Chọn hành động";
"CopyTitle" = "Sao chép tiêu đề"; "CopyTitle" = "Sao chép tiêu đề";
"CopyDescription" = "Sao chép mô tả"; "CopyDescription" = "Sao chép mô tả";
"CopyPostText" = "Sao chép văn bản bài viết"; "CopyPostText" = "Sao chép văn bản bài đăng";
"SavePostAsImage" = "Lưu bài viết dưới dạng hình ảnh"; "SavePostAsImage" = "Lưu bài đăng dưới dạng hình ảnh";
"CopyPostAsImage" = "Sao chép bài viết dưới dạng hình ảnh"; "CopyPostAsImage" = "Sao chép bài đăng dưới dạng hình ảnh";
"CopyCommentText" = "Copy comment text"; "CopyCommentText" = "Sao chép văn bản bình luận";
"SaveCommentAsImage" = "Save comment as image"; "SaveCommentAsImage" = "Lưu bình luận dưới dạng hình ảnh";
"CopyCommentAsImage" = "Copy comment as image"; "CopyCommentAsImage" = "Sao chép bình luận dưới dạng hình ảnh";
"SaveProfilePicture" = "Lưu ảnh hồ sơ";
"CopyProfilePicture" = "Sao chép ảnh hồ sơ";
"Cancel" = "Hủy bỏ"; "Cancel" = "Hủy bỏ";
"Copied" = "Sao chép vào clipboard"; "Copied" = "Sao chép vào clipboard";
"Saved" = "Đã lưu vào Ảnh"; "Saved" = "Đã lưu vào Ảnh";
@@ -67,6 +67,12 @@
"DontSnap2ChapterDesc" = "禁用通过双击手势跳到下一集。"; "DontSnap2ChapterDesc" = "禁用通过双击手势跳到下一集。";
"RedProgressBar" = "红色进度条"; "RedProgressBar" = "红色进度条";
"RedProgressBarDesc" = "加回红色进度条。"; "RedProgressBarDesc" = "加回红色进度条。";
"NoPlayerRemixButton" = "移除混剪按钮";
"NoPlayerRemixButtonDesc" = "移除播放器下方的混剪按钮。";
"NoPlayerClipButton" = "移除剪辑按钮";
"NoPlayerClipButtonDesc" = "移除播放器下方的剪辑按钮。";
"NoPlayerDownloadButton" = "移除下载按钮";
"NoPlayerDownloadButtonDesc" = "移除播放器下方的下载按钮。";
"NoHints" = "禁用提示"; "NoHints" = "禁用提示";
"NoHintsDesc" = "禁用播放期间出现在右上角的作者提示。"; "NoHintsDesc" = "禁用播放期间出现在右上角的作者提示。";
"NoFreeZoom" = "禁用自由缩放手势"; "NoFreeZoom" = "禁用自由缩放手势";
@@ -147,16 +153,28 @@
"CopyVideoInfoDesc" = "添加按钮从“视频说明”面板中复制视频的标题和描述。"; "CopyVideoInfoDesc" = "添加按钮从“视频说明”面板中复制视频的标题和描述。";
"PostManager" = "保存帖子信息"; "PostManager" = "保存帖子信息";
"PostManagerDesc" = "允许通过长按复制帖子文本并将帖子另存为图片。"; "PostManagerDesc" = "允许通过长按复制帖子文本并将帖子另存为图片。";
"SavePostImage" = "保存社区帖子图片";
"SavePostImageDesc" = "长按社区帖子图片保存到照片应用程序。";
"SaveProfilePhoto" = "保存个人资料图片"; "SaveProfilePhoto" = "保存个人资料图片";
"SaveProfilePhotoDesc" = "长按个人资料图片保存到照片应用程序。"; "SaveProfilePhotoDesc" = "长按个人资料图片保存到照片应用程序。";
"CommentManager" = "Save comment information"; "CommentManager" = "保存评论信息";
"CommentManagerDesc" = "Allows to copy comment text and save comment as image by long tap."; "CommentManagerDesc" = "允许通过长按复制评论文本并将评论保存为图片。";
"FixAlbums" = "修复封面"; "FixAlbums" = "修复封面";
"FixAlbumsDesc" = "修复来自俄罗斯用户的封面显示问题。"; "FixAlbumsDesc" = "修复来自俄罗斯用户的封面显示问题。";
"RemovePlayNext" = "删除“播放队列中的下一个”"; "RemovePlayNext" = "删除“播放队列中的下一个”";
"RemovePlayNextDesc" = "从菜单中删除“播放队列中的下一个”选项。"; "RemovePlayNextDesc" = "从菜单中删除“播放队列中的下一个”选项。";
"RemoveDownloadMenu" = "删除“下载”";
"RemoveDownloadMenuDesc" = "从菜单中删除“下载”选项。";
"RemoveWatchLaterMenu" = "删除“保存到稍后观看”";
"RemoveWatchLaterMenuDesc" = "从菜单中删除“保存到稍后观看”选项。";
"RemoveSaveToPlaylistMenu" = "删除“保存到播放列表”";
"RemoveSaveToPlaylistMenuDesc" = "从菜单中删除“保存到播放列表”选项。";
"RemoveShareMenu" = "删除“分享”";
"RemoveShareMenuDesc" = "从菜单中删除“分享”选项。";
"RemoveNotInterestedMenu" = "删除“不感兴趣”";
"RemoveNotInterestedMenuDesc" = "从菜单中删除“不感兴趣”选项。";
"RemoveDontRecommendMenu" = "删除“不推荐此频道”";
"RemoveDontRecommendMenuDesc" = "从菜单中删除“不推荐此频道”选项。";
"RemoveReportMenu" = "删除“举报”";
"RemoveReportMenuDesc" = "从菜单中删除“举报”选项。";
"NoContinueWatching" = "删除“继续观看”"; "NoContinueWatching" = "删除“继续观看”";
"NoContinueWatchingDesc" = "从首页中删除包含未完成视频的“继续观看”部分。"; "NoContinueWatchingDesc" = "从首页中删除包含未完成视频的“继续观看”部分。";
"NoSearchHistory" = "隐藏搜索历史记录"; "NoSearchHistory" = "隐藏搜索历史记录";
@@ -170,7 +188,13 @@
"PlaylistOldMinibar" = "旧播放列表"; "PlaylistOldMinibar" = "旧播放列表";
"PlaylistOldMinibarDesc" = "将新的浮动播放列表面板替换为旧的浮动播放列表面板。"; "PlaylistOldMinibarDesc" = "将新的浮动播放列表面板替换为旧的浮动播放列表面板。";
"DisableRTL" = "禁用 RTL 格式"; "DisableRTL" = "禁用 RTL 格式";
"DisableRTLDesc" = "对于最初以从右到左 (RTL) 显示的语言,强制以从左到右 (LTR) 格式显示文本。"; "DisableRTLDesc" = "对于最初以从右到左(RTL)显示的语言,强制以从左到右(LTR)格式显示文本。";
"PlaybackQualityOnWiFi" = "WiFi网络播放质量";
"PlaybackQualityOnCellular" = "蜂窝网络播放质量";
"SelectQuality" = "选择质量";
"Default" = "默认";
"Best" = "最好";
"Startup" = "启动页"; "Startup" = "启动页";
"Home" = "首页"; "Home" = "首页";
@@ -181,8 +205,8 @@
"Warning" = "警告"; "Warning" = "警告";
"TabIsHidden" = "无法选择隐藏选项卡作为启动页。"; "TabIsHidden" = "无法选择隐藏选项卡作为启动页。";
"DonateViaPayPal" = "PayPal 赞助"; "SupportDevelopment" = "支持开发";
"SupportViaGhSponsors" = "通过 Github 赞助支持开发"; "SupportDevelopmentDesc" = "如果您喜欢YTLite并愿意支持开发,可以使用以下任何便捷的方式来赞助。\n感谢❤";
"Version" = "版本"; "Version" = "版本";
"About" = "关于"; "About" = "关于";
"Credits" = "信息"; "Credits" = "信息";
@@ -194,6 +218,7 @@
"Japanese" = "日语本地化"; "Japanese" = "日语本地化";
"Vietnamese" = "越南语本地化"; "Vietnamese" = "越南语本地化";
"Advanced" = "高级模式"; "Advanced" = "高级模式";
"AdvancedDesc" = "更多自定义的功能";
"AdvancedModeReminder" = "想为YTLite激活高级模式吗?\n\n此模式提供了50多个额外的选项来自定义和优化您的YouTube体验。\n可以稍后从设置中启用/禁用它 → %@ → %@ → %@。"; "AdvancedModeReminder" = "想为YTLite激活高级模式吗?\n\n此模式提供了50多个额外的选项来自定义和优化您的YouTube体验。\n可以稍后从设置中启用/禁用它 → %@ → %@ → %@。";
"ClearCache" = "清除缓存"; "ClearCache" = "清除缓存";
"ResetSettings" = "重置YTLite设置"; "ResetSettings" = "重置YTLite设置";
@@ -209,9 +234,11 @@
"CopyPostText" = "复制帖子文本"; "CopyPostText" = "复制帖子文本";
"SavePostAsImage" = "帖子另存为图片"; "SavePostAsImage" = "帖子另存为图片";
"CopyPostAsImage" = "帖子作为图片复制"; "CopyPostAsImage" = "帖子作为图片复制";
"CopyCommentText" = "Copy comment text"; "CopyCommentText" = "复制评论文本";
"SaveCommentAsImage" = "Save comment as image"; "SaveCommentAsImage" = "评论另存为图片";
"CopyCommentAsImage" = "Copy comment as image"; "CopyCommentAsImage" = "评论作为图片复制";
"SaveProfilePicture" = "保存个人资料图片";
"CopyProfilePicture" = "复制个人资料图片";
"Cancel" = "取消"; "Cancel" = "取消";
"Copied" = "已复制到剪贴板"; "Copied" = "已复制到剪贴板";
"Saved" = "已保存到照片"; "Saved" = "已保存到照片";
@@ -67,6 +67,12 @@
"DontSnap2ChapterDesc" = "停用點兩下手勢跳轉到下一集"; "DontSnap2ChapterDesc" = "停用點兩下手勢跳轉到下一集";
"RedProgressBar" = "紅色進度條"; "RedProgressBar" = "紅色進度條";
"RedProgressBarDesc" = "恢復紅色的進度條"; "RedProgressBarDesc" = "恢復紅色的進度條";
"NoPlayerRemixButton" = "移除Remix按鈕";
"NoPlayerRemixButtonDesc" = "移除播放器下方的Remix按鈕";
"NoPlayerClipButton" = "移除剪輯片段按鈕";
"NoPlayerClipButtonDesc" = "移除播放器下方的剪輯片段按鈕";
"NoPlayerDownloadButton" = "移除下載按鈕";
"NoPlayerDownloadButtonDesc" = "移除播放器下方的下載按鈕";
"NoHints" = "停用提示"; "NoHints" = "停用提示";
"NoHintsDesc" = "在播放過程中出現在右上角的作者提示"; "NoHintsDesc" = "在播放過程中出現在右上角的作者提示";
"NoFreeZoom" = "停用自由縮放手勢"; "NoFreeZoom" = "停用自由縮放手勢";
@@ -147,16 +153,28 @@
"CopyVideoInfoDesc" = "新增按鈕將影片標題和說明,複製到影片說明欄"; "CopyVideoInfoDesc" = "新增按鈕將影片標題和說明,複製到影片說明欄";
"PostManager" = "儲存貼文資訊"; "PostManager" = "儲存貼文資訊";
"PostManagerDesc" = "長按可以複製貼文內容或將貼文儲存為圖片"; "PostManagerDesc" = "長按可以複製貼文內容或將貼文儲存為圖片";
"SavePostImage" = "儲存社群貼文圖片";
"SavePostImageDesc" = "長按社群貼文圖片儲存到照片應用";
"SaveProfilePhoto" = "儲存個人檔案照片"; "SaveProfilePhoto" = "儲存個人檔案照片";
"SaveProfilePhotoDesc" = "長按個人檔案照片儲存到照片應用"; "SaveProfilePhotoDesc" = "長按個人檔案照片儲存到照片應用";
"CommentManager" = "Save comment information"; "CommentManager" = "儲存留言資訊";
"CommentManagerDesc" = "Allows to copy comment text and save comment as image by long tap."; "CommentManagerDesc" = "長按可以複製留言內容或將留言儲存為圖片";
"FixAlbums" = "修復封面"; "FixAlbums" = "修復封面";
"FixAlbumsDesc" = "為俄羅斯使用者修復封面顯示問題"; "FixAlbumsDesc" = "為俄羅斯使用者修復封面顯示問題";
"RemovePlayNext" = "移除「播放下一個」"; "RemovePlayNext" = "移除「播放下一個」";
"RemovePlayNextDesc" = "從選單移除「播放下一個」"; "RemovePlayNextDesc" = "從選單移除「播放下一個」";
"RemoveDownloadMenu" = "移除「下載影片」";
"RemoveDownloadMenuDesc" = "從選單移除「下載影片」選項";
"RemoveWatchLaterMenu" = "移除「儲存至稍後觀看清單」";
"RemoveWatchLaterMenuDesc" = "從選單移除「儲存至稍後觀看清單」選項";
"RemoveSaveToPlaylistMenu" = "移除「儲存至播放清單」";
"RemoveSaveToPlaylistMenuDesc" = "從選單移除「儲存至播放清單」選項";
"RemoveShareMenu" = "移除「分享」";
"RemoveShareMenuDesc" = "從選單中移除「分享」選項";
"RemoveNotInterestedMenu" = "移除「不感興趣」";
"RemoveNotInterestedMenuDesc" = "從選單移除「不感興趣」選項";
"RemoveDontRecommendMenu" = "移除「不要推薦這個頻道」";
"RemoveDontRecommendMenuDesc" = "從選單移除「不要推薦這個頻道」選項";
"RemoveReportMenu" = "移除「檢舉」";
"RemoveReportMenuDesc" = "從選單移除「檢舉」選項";
"NoContinueWatching" = "移除「繼續觀看」"; "NoContinueWatching" = "移除「繼續觀看」";
"NoContinueWatchingDesc" = "從首頁中移除包含未完成影片的「繼續觀看」部分"; "NoContinueWatchingDesc" = "從首頁中移除包含未完成影片的「繼續觀看」部分";
"NoSearchHistory" = "隱藏搜尋記錄"; "NoSearchHistory" = "隱藏搜尋記錄";
@@ -172,6 +190,12 @@
"DisableRTL" = "停用RTL格式"; "DisableRTL" = "停用RTL格式";
"DisableRTLDesc" = "強制將初始顯示從右到左(RTL)格式的語言,改為從左到右(LTR)顯示"; "DisableRTLDesc" = "強制將初始顯示從右到左(RTL)格式的語言,改為從左到右(LTR)顯示";
"PlaybackQualityOnWiFi" = "使用Wi-Fi時的影片畫質";
"PlaybackQualityOnCellular" = "使用行動網路時的影片畫質";
"SelectQuality" = "選擇畫質";
"Default" = "預設";
"Best" = "最佳";
"Startup" = "啟動頁面"; "Startup" = "啟動頁面";
"Home" = "首頁"; "Home" = "首頁";
"Explore" = "探索"; "Explore" = "探索";
@@ -181,8 +205,8 @@
"Warning" = "警告"; "Warning" = "警告";
"TabIsHidden" = "無法將隱藏的標籤選為啟動頁面"; "TabIsHidden" = "無法將隱藏的標籤選為啟動頁面";
"DonateViaPayPal" = "透過PayPal贊助"; "SupportDevelopment" = "支持開發";
"SupportViaGhSponsors" = "透過Github贊助支持開發"; "SupportDevelopmentDesc" = "如果您喜歡 YTLite 並且願意支持開發,可以使用以下任何方便的方式支持。\n感謝❤";
"Version" = "版本"; "Version" = "版本";
"About" = "關於"; "About" = "關於";
"Credits" = "貢獻"; "Credits" = "貢獻";
@@ -194,6 +218,7 @@
"Japanese" = "日本語在地化"; "Japanese" = "日本語在地化";
"Vietnamese" = "越南語在地化"; "Vietnamese" = "越南語在地化";
"Advanced" = "進階模式"; "Advanced" = "進階模式";
"AdvancedDesc" = "更多自訂功能";
"AdvancedModeReminder" = "您是否想啟用YTLite的進階模式?\n\n這個模式提供了50多個額外的選項,可以自訂義和優化您的YouTube使用體驗。您稍後可以在「設定」中 → %@ → %@ → %@ 啟用或停用它。"; "AdvancedModeReminder" = "您是否想啟用YTLite的進階模式?\n\n這個模式提供了50多個額外的選項,可以自訂義和優化您的YouTube使用體驗。您稍後可以在「設定」中 → %@ → %@ → %@ 啟用或停用它。";
"ClearCache" = "清除快取"; "ClearCache" = "清除快取";
"ResetSettings" = "重置YTLite設定"; "ResetSettings" = "重置YTLite設定";
@@ -209,9 +234,13 @@
"CopyPostText" = "複製貼文內容"; "CopyPostText" = "複製貼文內容";
"SavePostAsImage" = "貼文儲存為圖片"; "SavePostAsImage" = "貼文儲存為圖片";
"CopyPostAsImage" = "複製貼文為圖片"; "CopyPostAsImage" = "複製貼文為圖片";
"CopyCommentText" = "Copy comment text"; "SaveCurrentImage" = "儲存當前圖片";
"SaveCommentAsImage" = "Save comment as image"; "CopyCurrentImage" = "複製當前圖片";
"CopyCommentAsImage" = "Copy comment as image"; "CopyCommentText" = "複製留言內容";
"SaveCommentAsImage" = "留言儲存為圖片";
"CopyCommentAsImage" = "儲存留言為圖片";
"SaveProfilePicture" = "儲存個人檔案照片";
"CopyProfilePicture" = "複製個人檔案照片";
"Cancel" = "取消"; "Cancel" = "取消";
"Copied" = "已複製到剪貼簿"; "Copied" = "已複製到剪貼簿";
"Saved" = "已儲存到照片應用"; "Saved" = "已儲存到照片應用";
Binary file not shown.
Binary file not shown.