Compare commits

...
45 Commits
Author SHA1 Message Date
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
dayanch96 fe3a942de0 Merge branch 'main' of https://github.com/dayanch96/YTLite 2024-02-22 16:24:22 +03:00
dayanch96 123215f372 v2.6.3 2024-02-22 16:23:13 +03:00
Dan 07fc0b98c3 Merge pull request #61 from mumuisdog/main
Update zh-Hant Localizable
2024-02-21 18:37:01 +03:00
mumuisdog 537f828731 Update Localizable.strings 2024-02-21 22:50:23 +08:00
Dan 8218578734 Merge pull request #60 from xiangfeidexiaohuo/main
update zh-Hans
2024-02-21 15:05:59 +03:00
xiangfeidexiaohuo fe6b509b3b update zh-Hans
Signed-off-by: xiangfeidexiaohuo <jsjson@163.com>
2024-02-21 20:01:15 +08:00
Dan 8f72d70029 Merge pull request #59 from hiepvk/main
Update Localizable.strings
2024-02-21 09:45:42 +03:00
Hiệpvk 07a13df097 Update Localizable.strings 2024-02-21 13:41:30 +07:00
dayanch96 9a43e1b9b3 Merge branch 'main' of https://github.com/dayanch96/YTLite 2024-02-21 05:09:00 +03:00
dayanch96 f7d567bf5d v2.6.2 2024-02-21 05:08:56 +03:00
Dan 4921d95073 Merge pull request #58 from xiangfeidexiaohuo/main
update zh-Hans
2024-02-20 17:32:46 +03:00
xiangfeidexiaohuo 87cdca4867 update zh-Hans
Signed-off-by: xiangfeidexiaohuo <jsjson@163.com>
2024-02-20 22:28:42 +08:00
dayanch96 f96d397f3b Merge branch 'main' of https://github.com/dayanch96/YTLite 2024-02-20 15:52:39 +03:00
dayanch96 74baf844be 2.6.1 2024-02-20 15:52:36 +03:00
Dan df95227b88 Merge pull request #57 from Balackburn/main
updated french localization
2024-02-20 10:29:26 +03:00
Balackburn 66e7e35798 updated french localization 2024-02-20 08:24:52 +01:00
Dan 3e67c85de9 Merge pull request #56 from mumuisdog/main
Update zh-Hant Localizable
2024-02-20 03:04:49 +03:00
mumuisdog dae1714bcc Update Localizable.strings 2024-02-20 07:16:34 +08:00
Dan 343f40dac3 Merge pull request #54 from hiepvk/main
Add Vietnamese localization
2024-02-19 20:24:27 +03:00
Hiệpvk 7eafc3de7d Add Vietnamese localization 2024-02-20 00:20:20 +07:00
Dan 33b0125e9b Merge pull request #53 from xiangfeidexiaohuo/main
update zh-Hans
2024-02-19 18:03:51 +03:00
xiangfeidexiaohuo 9d8f74c8cb update zh-Hans
Signed-off-by: xiangfeidexiaohuo <jsjson@163.com>
2024-02-19 22:38:09 +08:00
Dan 6bb405092d Merge pull request #52 from Balackburn/main
Fix typo error in french localization
2024-02-19 17:33:44 +03:00
Balackburn 8da024261d Merge branch 'dayanch96:main' into main 2024-02-19 13:11:53 +01:00
Balackburn a2771e7d52 typo 2024-02-19 13:10:59 +01:00
Dan e3b1507e7a Merge pull request #51 from Balackburn/main
updated fr localization
2024-02-19 14:06:30 +03:00
Balackburn d4bc6a5859 updated fr localization 2024-02-19 11:31:54 +01:00
dayanch96 256c9f54cd v2.6 2024-02-19 05:44:16 +03:00
Dan 44436a0d1c Merge pull request #48 from Balackburn/main
Updated french localization
2024-02-17 20:58:23 +03:00
Balackburn cccd5adb58 Merge branch 'dayanch96:main' into main 2024-02-17 18:26:27 +01:00
Balackburn db8cf75f07 Updated fr localization 2024-02-17 18:26:10 +01:00
Dan 43af06cf1b Merge pull request #47 from mumuisdog/main
Update zh-Hant Localizable
2024-02-17 20:15:25 +03:00
mumuisdog 6cadf005c0 Update Localizable.strings 2024-02-18 01:12:33 +08:00
Dan 8f272f567d Merge pull request #46 from xiangfeidexiaohuo/main
update zh-Hans
2024-02-17 18:59:36 +03:00
xiangfeidexiaohuo 7ea704af46 update zh-Hans
Signed-off-by: xiangfeidexiaohuo <jsjson@163.com>
2024-02-17 23:28:48 +08:00
Dan 6efa3c74c9 Merge pull request #44 from Deci8BelioS/main
Update Localizable.strings Spanish
2024-02-17 16:44:32 +03:00
DeciBelioS 3337bd2dd4 Update Localizable.strings Spanish 2024-02-17 14:42:43 +01:00
28 changed files with 2306 additions and 492 deletions
+4 -4
View File
@@ -5,14 +5,14 @@ endif
DEBUG=0 DEBUG=0
FINALPACKAGE=1 FINALPACKAGE=1
ARCHS = arm64 ARCHS = arm64
PACKAGE_VERSION = 2.5 PACKAGE_VERSION = 2.7
TARGET := iphone:clang:latest:11.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
+302 -191
View File
@@ -6,6 +6,23 @@
static const NSInteger YTLiteSection = 789; static const NSInteger YTLiteSection = 789;
static NSString *GetCacheSize() {
NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:cachePath error:nil];
unsigned long long int folderSize = 0;
for (NSString *fileName in filesArray) {
NSString *filePath = [cachePath stringByAppendingPathComponent:fileName];
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
folderSize += [fileAttributes fileSize];
}
NSByteCountFormatter *formatter = [[NSByteCountFormatter alloc] init];
formatter.countStyle = NSByteCountFormatterCountStyleFile;
return [formatter stringFromByteCount:folderSize];
}
// Settings // Settings
%hook YTAppSettingsPresentationData %hook YTAppSettingsPresentationData
+ (NSArray *)settingsCategoryOrder { + (NSArray *)settingsCategoryOrder {
@@ -24,6 +41,21 @@ static const NSInteger YTLiteSection = 789;
} }
%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 {
@@ -51,12 +83,13 @@ static const NSInteger YTLiteSection = 789;
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"]) {
@@ -90,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]];
@@ -110,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];
} }
@@ -141,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]];
@@ -168,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]];
@@ -198,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];
@@ -236,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]];
@@ -260,24 +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(@"CopyPostText"), LOC(@"CopyPostTextDesc"), @"copyPostText", &kCopyPostText, selfObject), createSwitchItem(@"CopyVideoInfo", @"copyVideoInfo", &kCopyVideoInfo, selfObject),
createSwitchItem(LOC(@"SavePostImage"), LOC(@"SavePostImageDesc"), @"savePostImage", &kSavePostImage, selfObject), createSwitchItem(@"PostManager", @"postManager", &kPostManager, selfObject),
createSwitchItem(LOC(@"SaveProfilePhoto"), LOC(@"SaveProfilePhotoDesc"), @"saveProfilePhoto", &kSaveProfilePhoto, selfObject), createSwitchItem(@"SaveProfilePhoto", @"saveProfilePhoto", &kSaveProfilePhoto, selfObject),
createSwitchItem(LOC(@"FixAlbums"), LOC(@"FixAlbumsDesc"), @"fixAlbums", &kFixAlbums, selfObject), createSwitchItem(@"CommentManager", @"commentManager", &kCommentManager, selfObject),
createSwitchItem(LOC(@"RemovePlayNext"), LOC(@"RemovePlayNextDesc"), @"removePlayNext", &kRemovePlayNext, selfObject), createSwitchItem(@"FixAlbums", @"fixAlbums", &kFixAlbums, selfObject),
createSwitchItem(LOC(@"NoContinueWatching"), LOC(@"NoContinueWatchingDesc"), @"noContinueWatching", &kNoContinueWatching, selfObject), createSwitchItem(@"RemovePlayNext", @"removePlayNext", &kRemovePlayNext, selfObject),
createSwitchItem(LOC(@"NoSearchHistory"), LOC(@"NoSearchHistoryDesc"), @"noSearchHistory", &kNoSearchHistory, selfObject), createSwitchItem(@"RemoveDownloadMenu", @"removeDownloadMenu", &kRemoveDownloadMenu, selfObject),
createSwitchItem(LOC(@"NoRelatedWatchNexts"), LOC(@"NoRelatedWatchNextsDesc"), @"noRelatedWatchNexts", &kNoRelatedWatchNexts, selfObject), createSwitchItem(@"RemoveWatchLaterMenu", @"removeWatchLaterMenu", &kRemoveWatchLaterMenu, selfObject),
createSwitchItem(LOC(@"StickSortComments"), LOC(@"StickSortCommentsDesc"), @"stickSortComments", &kStickSortComments, selfObject), createSwitchItem(@"RemoveSaveToPlaylistMenu", @"removeSaveToPlaylistMenu", &kRemoveSaveToPlaylistMenu, selfObject),
createSwitchItem(LOC(@"HideSortComments"), LOC(@"HideSortCommentsDesc"), @"hideSortComments", &kHideSortComments, selfObject), createSwitchItem(@"RemoveShareMenu", @"removeShareMenu", &kRemoveShareMenu, selfObject),
createSwitchItem(LOC(@"PlaylistOldMinibar"), LOC(@"PlaylistOldMinibarDesc"), @"playlistOldMinibar", &kPlaylistOldMinibar, selfObject), createSwitchItem(@"RemoveNotInterestedMenu", @"removeNotInterestedMenu", &kRemoveNotInterestedMenu, selfObject),
createSwitchItem(LOC(@"DisableRTL"), LOC(@"DisableRTLDesc"), @"disableRTL", &kDisableRTL, selfObject) createSwitchItem(@"RemoveDontRecommendMenu", @"removeDontRecommendMenu", &kRemoveDontRecommendMenu, selfObject),
createSwitchItem(@"RemoveReportMenu", @"removeReportMenu", &kRemoveReportMenu, 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]];
@@ -288,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;
@@ -379,43 +456,81 @@ 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 *dayanch96 = [%c(YTSettingsSectionItem) itemWithTitle:@"Dayanch96" titleDescription:LOC(@"Developer") 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"]];
}];
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 *reset = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"ResetSettings") titleDescription:nil accessibilityIdentifier:nil detailTextBlock:nil selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) { YTSettingsSectionItem *support = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"SupportDevelopment") accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:^NSString *() { return @"♡"; } selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
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 *cache = [%c(YTSettingsSectionItem) itemWithTitle:LOC(@"ClearCache") titleDescription:nil accessibilityIdentifier:@"YTLiteSectionItem" detailTextBlock:^NSString *() { return GetCacheSize(); } selectBlock:^BOOL (YTSettingsCell *cell, NSUInteger arg1) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
[[NSFileManager defaultManager] removeItemAtPath:cachePath error:nil];
});
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Done") firstResponder:[self parentResponder]] send];
return YES;
}];
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];
@@ -433,17 +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, space, createSwitchItem(LOC(@"Advanced"), nil, @"advancedMode", &kAdvancedMode, selfObject), 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:support];
[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:)];
@@ -458,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
+170 -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;
@@ -110,12 +93,20 @@ BOOL kRemoveShorts;
BOOL kRemoveSubscriptions; BOOL kRemoveSubscriptions;
BOOL kRemoveUploads; BOOL kRemoveUploads;
BOOL kRemoveLibrary; BOOL kRemoveLibrary;
BOOL kCopyPostText; BOOL kCopyVideoInfo;
BOOL kSavePostImage; BOOL kPostManager;
BOOL kSaveProfilePhoto; BOOL kSaveProfilePhoto;
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;
@@ -125,16 +116,32 @@ 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;
- (UIImage *)resizedImageNamed:(NSString *)iconName;
@end @end
@interface YTPivotBarView : UIView @interface YTLightweightQTMButton ()
@property (nonatomic, assign, readwrite, getter=isShouldRaiseOnTouch) BOOL shouldRaiseOnTouch;
@end @end
@interface YTQTMButton () @interface YTQTMButton ()
@@ -142,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;
@@ -165,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
@@ -193,13 +207,43 @@ int kPivotIndex;
@property (nonatomic, weak, readwrite) YTScrollableNavigationController *navigationController; @property (nonatomic, weak, readwrite) YTScrollableNavigationController *navigationController;
@end @end
@interface YTPlayerViewController (YTAFS) @interface YTIVideoDetails : NSObject
@property (nonatomic, copy, readwrite) NSString *title;
@property (nonatomic, copy, readwrite) NSString *shortDescription;
@end
@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) 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
@@ -207,6 +251,37 @@ int kPivotIndex;
- (void)turnShortsOnlyModeOff:(UILongPressGestureRecognizer *)gesture; - (void)turnShortsOnlyModeOff:(UILongPressGestureRecognizer *)gesture;
@end @end
@interface YTEngagementPanelIdentifier : NSObject
@property (nonatomic, copy, readonly) NSString *identifierString;
@end
@interface YTEngagementPanelHeaderView : UIView
@property (nonatomic, assign, readonly) YTQTMButton *closeButton;
@end
@interface YTWatchViewController : UIViewController
@property (nonatomic, weak, readwrite) YTPlayerViewController *playerViewController;
@end
@interface YTEngagementPanelContainerController : UIViewController
@property (nonatomic, weak, readwrite) YTWatchViewController *parentViewController;
@end
@interface YTEngagementPanelNavigationController : UIViewController
@property (nonatomic, weak, readwrite) YTEngagementPanelContainerController *parentViewController;
@end
@interface YTMainAppEngagementPanelViewController : UIViewController
@property (nonatomic, weak, readwrite) YTEngagementPanelNavigationController *parentViewController;
@end
@interface YTEngagementPanelView : UIView
@property (nonatomic, weak, readwrite) YTMainAppEngagementPanelViewController *resizeDelegate;
@property (nonatomic, copy, readwrite) YTEngagementPanelIdentifier *panelIdentifier;
@property (nonatomic, assign, readonly) YTEngagementPanelHeaderView *headerView;
- (void)didTapCopyInfoButton:(UIButton *)sender;
@end
@interface YTSegmentableInlinePlayerBarView @interface YTSegmentableInlinePlayerBarView
@property (nonatomic, assign, readwrite) BOOL enableSnapToChapter; @property (nonatomic, assign, readwrite) BOOL enableSnapToChapter;
@end @end
@@ -241,24 +316,55 @@ int kPivotIndex;
@interface YTELMView : UIView @interface YTELMView : UIView
@end @end
@interface ASNetworkImageNode : NSObject @interface ASNodeAncestryEnumerator : NSEnumerator
@property (atomic, assign, readonly) NSMutableArray *allObjects;
@end
@interface ASDisplayNode ()
@property (nonatomic, assign, readonly) UIViewController *closestViewController;
@property (atomic, assign, readonly) ASNodeAncestryEnumerator *supernodes;
// @property (atomic, copy, readwrite) NSArray *yogaChildren;
@property (atomic) CALayer *layer;
@end
@interface ELMContainerNode : ASDisplayNode
@property (nonatomic, strong, readwrite) NSString *copiedComment;
@property (nonatomic, strong, readwrite) NSURL *copiedURL;
@end
@interface ELMExpandableTextNode : ASDisplayNode
@property (atomic, assign, readonly) ASDisplayNode *currentTextNode;
@end
@interface ASNetworkImageNode : ASDisplayNode
@property (atomic, copy, readwrite) NSURL *URL; @property (atomic, copy, readwrite) NSURL *URL;
@end @end
@interface _ASDisplayView : UIView @interface YTImageZoomNode : ASNetworkImageNode
@property (nonatomic, strong, readwrite) ASNetworkImageNode *keepalive_node;
- (void)copyText:(UILongPressGestureRecognizer *)sender;
- (void)saveImage:(UILongPressGestureRecognizer *)sender;
- (void)savePFP:(UILongPressGestureRecognizer *)sender;
@end @end
@interface MLHAMQueuePlayer : NSObject @interface ASTextNode : ASDisplayNode
@property id playerEventCenter; @property (atomic, copy, readwrite) NSAttributedString *attributedText;
-(void)setRate:(float)rate;
@end @end
@interface _ASDisplayView : UIView
@property (nonatomic, strong, readwrite) ASDisplayNode *keepalive_node;
- (void)postManager:(UILongPressGestureRecognizer *)sender;
- (void)savePFP:(UILongPressGestureRecognizer *)sender;
- (void)commentManager:(UILongPressGestureRecognizer *)sender;
@end
// @interface MLHAMQueuePlayer : NSObject
// @property id playerEventCenter;
// -(void)setRate:(float)rate;
// @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
@@ -273,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
+499 -135
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
@@ -280,49 +284,26 @@
%hook YTVideoQualitySwitchControllerFactory %hook YTVideoQualitySwitchControllerFactory
- (id)videoQualitySwitchControllerWithParentResponder:(id)responder { - (id)videoQualitySwitchControllerWithParentResponder:(id)responder {
Class originalClass = %c(YTVideoQualitySwitchOriginalController); Class originalClass = %c(YTVideoQualitySwitchOriginalController);
if (kClassicQuality) return originalClass ? [[originalClass alloc] initWithParentResponder:responder] : %orig; return kClassicQuality && originalClass ? [[originalClass alloc] initWithParentResponder:responder] : %orig;
return %orig;
} }
%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
@@ -378,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];
@@ -403,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
@@ -469,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 {
@@ -539,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
@@ -638,76 +764,8 @@ static BOOL isOverlayShown = YES;
} }
%end %end
%hook _ASDisplayView static void downloadImageFromURL(UIResponder *responder, NSURL *URL, BOOL download) {
- (void)setKeepalive_node:(id)arg1 { NSString *URLString = URL.absoluteString;
%orig;
NSString *description = [self description];
if (kCopyPostText && [description containsString:@"ELMExpandableTextNode-View"]) {
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(copyText:)];
longPress.minimumPressDuration = 0.3;
[self addGestureRecognizer:longPress];
}
if (kSavePostImage && [description containsString:@"YTImageZoomNode-View"]) {
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(saveImage:)];
longPress.minimumPressDuration = 0.3;
[self addGestureRecognizer:longPress];
}
if (kSaveProfilePhoto && [description containsString:@"ELMImageNode-View"] && [description containsString:@"eml.avatar"]) {
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(savePFP:)];
longPress.minimumPressDuration = 0.3;
[self addGestureRecognizer:longPress];
}
}
%new
- (void)savePFP:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
NSString *URLString = self.keepalive_node.URL.absoluteString;
if (URLString) {
NSRange sizeRange = [URLString rangeOfString:@"=s"];
if (sizeRange.location != NSNotFound) {
NSRange dashRange = [URLString rangeOfString:@"-" options:0 range:NSMakeRange(sizeRange.location, URLString.length - sizeRange.location)];
if (dashRange.location != NSNotFound) {
NSString *newURLString = [URLString stringByReplacingCharactersInRange:NSMakeRange(sizeRange.location + 2, dashRange.location - sizeRange.location - 2) withString:@"1024"];
NSURL *PFPURL = [NSURL URLWithString:newURLString];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:PFPURL]];
if (image) {
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
UIResponder *responder = self.nextResponder;
while (responder && ![responder isKindOfClass:[UIViewController class]]) responder = responder.nextResponder;
if (responder) [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Saved") firstResponder:responder] send];
}
}
}
}
}
}
%new
- (void)copyText:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = self.accessibilityLabel;
UIResponder *responder = self.nextResponder;
while (responder && ![responder isKindOfClass:[UIViewController class]]) responder = responder.nextResponder;
if (responder) [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:responder] send];
}
}
%new
- (void)saveImage:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
NSURL *imageURL = self.keepalive_node.URL;
if (imageURL) {
NSString *URLString = imageURL.absoluteString;
if (kFixAlbums && [URLString hasPrefix:@"https://yt3."]) { if (kFixAlbums && [URLString hasPrefix:@"https://yt3."]) {
URLString = [URLString stringByReplacingOccurrencesOfString:@"https://yt3." withString:@"https://yt4."]; URLString = [URLString stringByReplacingOccurrencesOfString:@"https://yt3." withString:@"https://yt4."];
@@ -721,26 +779,251 @@ static BOOL isOverlayShown = YES;
downloadURL = [NSURL URLWithString:newURL]; downloadURL = [NSURL URLWithString:newURL];
} }
} else { } else {
downloadURL = imageURL; downloadURL = URL;
} }
UIResponder *responder = self.nextResponder;
while (responder && ![responder isKindOfClass:[UIViewController class]]) responder = responder.nextResponder;
NSURLSession *session = [NSURLSession sharedSession]; NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:downloadURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { [[session dataTaskWithURL:downloadURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data) { if (data) {
if (download) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset]; PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
[request addResourceWithType:PHAssetResourceTypePhoto data:data options:nil]; [request addResourceWithType:PHAssetResourceTypePhoto data:data options:nil];
} completionHandler:^(BOOL success, NSError *error) { } completionHandler:^(BOOL success, NSError *error) {
if (responder) [[%c(YTToastResponderEvent) eventWithMessage:success ? LOC(@"Saved") : [NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription] firstResponder:responder] send]; [[%c(YTToastResponderEvent) eventWithMessage:success ? LOC(@"Saved") : [NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription] firstResponder:responder] send];
}]; }];
} else { } else {
if (responder) [[%c(YTToastResponderEvent) eventWithMessage:[NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription] firstResponder:responder] send]; [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]; }] 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
%property (nonatomic, strong) NSString *copiedComment;
%property (nonatomic, strong) NSURL *copiedURL;
%end
%hook ASDisplayNode
- (void)setFrame:(CGRect)frame {
%orig;
if (kCommentManager && [[self valueForKey:@"_accessibilityIdentifier"] isEqualToString:@"id.comment.content.label"]) {
ASTextNode *textNode = (ASTextNode *)self;
NSString *comment = textNode.attributedText.string;
NSMutableArray *allObjects = self.supernodes.allObjects;
for (ELMContainerNode *containerNode in allObjects) {
if ([containerNode.description containsString:@"id.ui.comment_cell"] && comment) {
containerNode.copiedComment = comment;
break;
}
}
}
if (kPostManager && [self isKindOfClass:NSClassFromString(@"ELMExpandableTextNode")]) {
ELMExpandableTextNode *expandableTextNode = (ELMExpandableTextNode *)self;
ASTextNode *textNode = (ASTextNode *)expandableTextNode.currentTextNode;
NSString *text = textNode.attributedText.string;
NSMutableArray *allObjects = self.supernodes.allObjects;
for (ELMContainerNode *containerNode in allObjects) {
if ([containerNode.description containsString:@"id.ui.backstage.original_post"] && text) {
containerNode.copiedComment = text;
break;
}
}
}
}
%end
%hook YTImageZoomNode
- (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;
NSMutableArray *allObjects = displayNode.supernodes.allObjects;
for (ELMContainerNode *containerNode in allObjects) {
if ([containerNode.description containsString:@"id.ui.backstage.original_post"]) {
containerNode.copiedURL = URL;
break;
}
}
}
return %orig;
}
%end
%hook _ASDisplayView
- (void)setKeepalive_node:(id)arg1 {
%orig;
NSArray *gesturesInfo = @[
@{@"selector": @"postManager:", @"text": @"id.ui.backstage.original_post", @"key": @(kPostManager)},
@{@"selector": @"savePFP:", @"text": @"ELMImageNode-View", @"key": @(kSaveProfilePhoto)},
@{@"selector": @"commentManager:", @"text": @"id.ui.comment_cell", @"key": @(kCommentManager)}
];
for (NSDictionary *gestureInfo in gesturesInfo) {
SEL selector = NSSelectorFromString(gestureInfo[@"selector"]);
if ([gestureInfo[@"key"] boolValue] && [[self description] containsString:gestureInfo[@"text"]]) {
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:selector];
longPress.minimumPressDuration = 0.3;
[self addGestureRecognizer:longPress];
break;
}
}
}
%new
- (void)savePFP:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
ASNetworkImageNode *imageNode = (ASNetworkImageNode *)self.keepalive_node;
NSString *URLString = imageNode.URL.absoluteString;
if (URLString) {
NSRange sizeRange = [URLString rangeOfString:@"=s"];
if (sizeRange.location != NSNotFound) {
NSRange dashRange = [URLString rangeOfString:@"-" options:0 range:NSMakeRange(sizeRange.location, URLString.length - sizeRange.location)];
if (dashRange.location != NSNotFound) {
NSString *newURLString = [URLString stringByReplacingCharactersInRange:NSMakeRange(sizeRange.location + 2, dashRange.location - sizeRange.location - 2) withString:@"1024"];
NSURL *PFPURL = [NSURL URLWithString:newURLString];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:PFPURL]];
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);
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Saved") firstResponder:self.keepalive_node.closestViewController] 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];
}
}
}
}
}
}
%new
- (void)postManager:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
ELMContainerNode *nodeForLayer = (ELMContainerNode *)self.keepalive_node.yogaChildren[0];
ELMContainerNode *containerNode = (ELMContainerNode *)self.keepalive_node;
NSString *text = containerNode.copiedComment;
NSURL *URL = containerNode.copiedURL;
CALayer *layer = nodeForLayer.layer;
UIColor *backgroundColor = containerNode.closestViewController.view.backgroundColor;
YTDefaultSheetController *sheetController = [%c(YTDefaultSheetController) sheetControllerWithParentResponder:nil];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyPostText") iconImage:YTImageNamed(@"yt_outline_message_bubble_right_24pt") style:0 handler:^ {
if (text) {
[UIPasteboard generalPasteboard].string = text;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send];
}
}]];
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) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
request.creationDate = [NSDate date];
} completionHandler:^(BOOL success, NSError *error) {
NSString *message = success ? LOC(@"Saved") : [NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription];
[[%c(YTToastResponderEvent) eventWithMessage:message firstResponder:containerNode.closestViewController] send];
}];
});
}]];
[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) {
[UIPasteboard generalPasteboard].image = image;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send];
});
}]];
[sheetController presentFromViewController:containerNode.closestViewController animated:YES completion:nil];
}
}
%new
- (void)commentManager:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
ELMContainerNode *containerNode = (ELMContainerNode *)self.keepalive_node;
NSString *comment = containerNode.copiedComment;
CALayer *layer = self.layer;
UIColor *backgroundColor = containerNode.closestViewController.view.backgroundColor;
YTDefaultSheetController *sheetController = [%c(YTDefaultSheetController) sheetControllerWithParentResponder:nil];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyCommentText") iconImage:YTImageNamed(@"yt_outline_message_bubble_right_24pt") style:0 handler:^ {
if (comment) {
[UIPasteboard generalPasteboard].string = comment;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send];
}
}]];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"SaveCommentAsImage") iconImage:YTImageNamed(@"yt_outline_image_24pt") style:0 handler:^ {
genImageFromLayer(layer, backgroundColor, ^(UIImage *image) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
request.creationDate = [NSDate date];
} completionHandler:^(BOOL success, NSError *error) {
NSString *message = success ? LOC(@"Saved") : [NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription];
[[%c(YTToastResponderEvent) eventWithMessage:message firstResponder:containerNode.closestViewController] send];
}];
});
}]];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyCommentAsImage") iconImage:YTImageNamed(@"yt_outline_library_image_24pt") style:0 handler:^ {
genImageFromLayer(layer, backgroundColor, ^(UIImage *image) {
[UIPasteboard generalPasteboard].image = image;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send];
});
}]];
[sheetController presentFromViewController:containerNode.closestViewController animated:YES completion:nil];
} }
} }
%end %end
@@ -812,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;
} }
@@ -847,6 +1116,8 @@ BOOL isTabSelected = NO;
- (void)viewDidAppear:(BOOL)animated { - (void)viewDidAppear:(BOOL)animated {
%orig; %orig;
isOverlayShown = YES;
if (kShortsOnlyMode) { if (kShortsOnlyMode) {
[self.navigationController.parentViewController hidePivotBar]; [self.navigationController.parentViewController hidePivotBar];
} }
@@ -854,7 +1125,7 @@ BOOL isTabSelected = NO;
%end %end
%hook YTAppViewController %hook YTAppViewController
- (void)showPivotBar { if (!kShortsOnlyMode) %orig;} ; - (void)showPivotBar { if (!kShortsOnlyMode) %orig; }
%end %end
%hook YTReelWatchRootViewController %hook YTReelWatchRootViewController
@@ -867,6 +1138,55 @@ BOOL isTabSelected = NO;
} }
%end %end
%hook YTEngagementPanelView
- (void)layoutSubviews {
%orig;
if (kCopyVideoInfo && [self.panelIdentifier.identifierString isEqualToString:@"video-description-ep-identifier"]) {
YTQTMButton *copyInfoButton = [%c(YTQTMButton) iconButton];
copyInfoButton.accessibilityLabel = LOC(@"CopyVideoInfo");
[copyInfoButton setTag:999];
[copyInfoButton enableNewTouchFeedback];
[copyInfoButton setImage:YTImageNamed(@"yt_outline_copy_24pt") forState:UIControlStateNormal];
[copyInfoButton setTintColor:[UIColor labelColor]];
[copyInfoButton setTranslatesAutoresizingMaskIntoConstraints:false];
[copyInfoButton addTarget:self action:@selector(didTapCopyInfoButton:) forControlEvents:UIControlEventTouchUpInside];
if (self.headerView && ![self.headerView viewWithTag:999]) {
[self.headerView addSubview:copyInfoButton];
[NSLayoutConstraint activateConstraints:@[
[copyInfoButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-48],
[copyInfoButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
[copyInfoButton.widthAnchor constraintEqualToConstant:40.0],
[copyInfoButton.heightAnchor constraintEqualToConstant:40.0],
]];
}
}
}
%new
- (void)didTapCopyInfoButton:(UIButton *)sender {
YTPlayerViewController *playerVC = self.resizeDelegate.parentViewController.parentViewController.parentViewController.playerViewController;
NSString *title = playerVC.playerResponse.playerData.videoDetails.title;
NSString *shortDescription = playerVC.playerResponse.playerData.videoDetails.shortDescription;
YTDefaultSheetController *sheetController = [%c(YTDefaultSheetController) sheetControllerWithParentResponder:nil];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyTitle") iconImage:YTImageNamed(@"yt_outline_text_box_24pt") style:0 handler:^ {
[UIPasteboard generalPasteboard].string = title;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:self.resizeDelegate] send];
}]];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyDescription") iconImage:YTImageNamed(@"yt_outline_message_bubble_right_24pt") style:0 handler:^ {
[UIPasteboard generalPasteboard].string = shortDescription;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:self.resizeDelegate] send];
}]];
[sheetController presentFromViewController:self.resizeDelegate animated:YES completion:nil];
}
%end
// Disable Right-To-Left Formatting // Disable Right-To-Left Formatting
%hook NSParagraphStyle %hook NSParagraphStyle
+ (NSWritingDirection)defaultWritingDirectionForLanguage:(id)lang { return kDisableRTL ? NSWritingDirectionLeftToRight : %orig; } + (NSWritingDirection)defaultWritingDirectionForLanguage:(id)lang { return kDisableRTL ? NSWritingDirectionLeftToRight : %orig; }
@@ -937,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;
@@ -973,11 +1296,19 @@ static void reloadPrefs() {
kRemoveSubscriptions = [prefs[@"removeSubscriptions"] boolValue] ?: NO; kRemoveSubscriptions = [prefs[@"removeSubscriptions"] boolValue] ?: NO;
kRemoveUploads = (prefs[@"removeUploads"] != nil) ? [prefs[@"removeUploads"] boolValue] : YES; kRemoveUploads = (prefs[@"removeUploads"] != nil) ? [prefs[@"removeUploads"] boolValue] : YES;
kRemoveLibrary = [prefs[@"removeLibrary"] boolValue] ?: NO; kRemoveLibrary = [prefs[@"removeLibrary"] boolValue] ?: NO;
kCopyPostText = [prefs[@"copyPostText"] boolValue] ?: NO; kCopyVideoInfo = [prefs[@"copyVideoInfo"] boolValue] ?: NO;
kSavePostImage = [prefs[@"savePostImage"] boolValue] ?: NO; kPostManager = [prefs[@"postManager"] boolValue] ?: NO;
kSaveProfilePhoto = [prefs[@"savePostImage"] boolValue] ?: NO; kSaveProfilePhoto = [prefs[@"saveProfilePhoto"] 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;
@@ -985,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;
@@ -1021,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),
@@ -1057,11 +1393,19 @@ static void reloadPrefs() {
@"removeSubscriptions" : @(kRemoveSubscriptions), @"removeSubscriptions" : @(kRemoveSubscriptions),
@"removeUploads" : @(kRemoveUploads), @"removeUploads" : @(kRemoveUploads),
@"removeLibrary" : @(kRemoveLibrary), @"removeLibrary" : @(kRemoveLibrary),
@"copyPostText" : @(kCopyPostText), @"copyVideoInfo" : @(kCopyVideoInfo),
@"savePostImage" : @(kSavePostImage), @"postManager" : @(kPostManager),
@"saveProfilePhoto" : @(kSaveProfilePhoto), @"saveProfilePhoto" : @(kSaveProfilePhoto),
@"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),
@@ -1069,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)
@@ -1091,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";
@@ -143,16 +149,32 @@
"HideShortsAudioTrackDesc" = "Hides AudioTrack under Shorts description."; "HideShortsAudioTrackDesc" = "Hides AudioTrack under Shorts description.";
"Other" = "Other"; "Other" = "Other";
"CopyPostText" = "Copy community posts text"; "CopyVideoInfo" = "Copy video information";
"CopyPostTextDesc" = "Copies community posts text to the clipboard by long tap."; "CopyVideoInfoDesc" = "Adds button to copy video title and description into Video Description panel.";
"SavePostImage" = "Save image from community posts"; "PostManager" = "Save post information";
"SavePostImageDesc" = "Saves community post image to the Photos app by long tap."; "PostManagerDesc" = "Allows to copy post text and save post as image 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";
"CommentManagerDesc" = "Allows to copy comment text and save comment as image by long tap.";
"FixAlbums" = "Fix covers"; "FixAlbums" = "Fix covers";
"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";
@@ -168,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";
@@ -177,6 +205,8 @@
"Warning" = "Warning"; "Warning" = "Warning";
"TabIsHidden" = "Hidden tab cannot be selected as startup page"; "TabIsHidden" = "Hidden tab cannot be selected as startup page";
"SupportDevelopment" = "Support development";
"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";
@@ -186,8 +216,11 @@
"French" = "French localization"; "French" = "French localization";
"Spanish" = "Spanish localization"; "Spanish" = "Spanish localization";
"Japanese" = "Japanese localization"; "Japanese" = "Japanese 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";
"ResetSettings" = "Reset YTLite settings"; "ResetSettings" = "Reset YTLite settings";
"ResetMessage" = "This option will reset YTLite settings to default and close YouTube.\n\nAre you sure you want to continue?"; "ResetMessage" = "This option will reset YTLite settings to default and close YouTube.\n\nAre you sure you want to continue?";
"ShortsOnlyWarning" = "Are you sure you want to activate this mode?\n\nIn this mode, you will only be able to watch Shorts videos and won't be able to do anything else.\n\nYou can disable Shorts Only Mode by long pressing with two fingers in the Shorts player."; "ShortsOnlyWarning" = "Are you sure you want to activate this mode?\n\nIn this mode, you will only be able to watch Shorts videos and won't be able to do anything else.\n\nYou can disable Shorts Only Mode by long pressing with two fingers in the Shorts player.";
@@ -195,6 +228,21 @@
"Yes" = "Yes"; "Yes" = "Yes";
"No" = "No"; "No" = "No";
"SelectAction" = "Select action";
"CopyTitle" = "Copy title";
"CopyDescription" = "Copy description";
"CopyPostText" = "Copy post text";
"SaveCurrentImage" = "Save current image";
"CopyCurrentImage" = "Copy current image";
"SavePostAsImage" = "Save post as image";
"CopyPostAsImage" = "Copy post as image";
"CopyCommentText" = "Copy comment text";
"SaveCommentAsImage" = "Save comment as image";
"CopyCommentAsImage" = "Copy comment as image";
"SaveProfilePicture" = "Save profile picture";
"CopyProfilePicture" = "Copy profile picture";
"Cancel" = "Cancel";
"Copied" = "Copied to clipboard"; "Copied" = "Copied to clipboard";
"Saved" = "Saved to Photos"; "Saved" = "Saved to Photos";
"Done" = "Done";
"Error" = "Error"; "Error" = "Error";
@@ -37,8 +37,8 @@
"NoEndScreenCardsDesc" = "Oculta las tarjetas emergentes de fin de pantalla (miniaturas) al final de los vídeos."; "NoEndScreenCardsDesc" = "Oculta las tarjetas emergentes de fin de pantalla (miniaturas) al final de los vídeos.";
"NoFullscreenActions" = "Desactivar acciones en pantalla completa"; "NoFullscreenActions" = "Desactivar acciones en pantalla completa";
"NoFullscreenActionsDesc" = "Desactiva el panel de acciones en el modo de pantalla completa."; "NoFullscreenActionsDesc" = "Desactiva el panel de acciones en el modo de pantalla completa.";
"PersistentProgressBar" = "Persistent progress bar"; "PersistentProgressBar" = "Barra de progreso persistente";
"PersistentProgressBarDesc" = "Always shows progress bar in the player."; "PersistentProgressBarDesc" = "Muestra siempre la barra de progreso en el reproductor.";
"NoRelatedVids" = "Sin vídeos relacionados en la superposición"; "NoRelatedVids" = "Sin vídeos relacionados en la superposición";
"NoRelatedVidsDesc" = "Elimina los vídeos relacionados que se muestran en la superposición al deslizar hacia arriba."; "NoRelatedVidsDesc" = "Elimina los vídeos relacionados que se muestran en la superposición al deslizar hacia arriba.";
"NoPromotionCards" = "Ocultar tarjetas de promoción pagada"; "NoPromotionCards" = "Ocultar tarjetas de promoción pagada";
@@ -55,8 +55,8 @@
"CopyWithTimestampDesc" = "Permite copiar el enlace con marca de tiempo en el portapapeles pulsando el botón de pausa."; "CopyWithTimestampDesc" = "Permite copiar el enlace con marca de tiempo en el portapapeles pulsando el botón de pausa.";
"DisableAutoplay" = "Desactivar reproducción automática"; "DisableAutoplay" = "Desactivar reproducción automática";
"DisableAutoplayDesc" = "Evita la reproducción automática de vídeos después de abrirlos."; "DisableAutoplayDesc" = "Evita la reproducción automática de vídeos después de abrirlos.";
"DisableAutoCaptions" = "Disable auto captions"; "DisableAutoCaptions" = "Desactivar subtítulos automáticos";
"DisableAutoCaptionsDesc" = "Prevents automatic activation of captions."; "DisableAutoCaptionsDesc" = "Evita la activación automática de subtítulos.";
"NoContentWarning" = "Omitir advertencia de contenido"; "NoContentWarning" = "Omitir advertencia de contenido";
"NoContentWarningDesc" = "Omite el mensaje de advertencia de contenido sensible."; "NoContentWarningDesc" = "Omite el mensaje de advertencia de contenido sensible.";
"ClassicQuality" = "Calidad de vídeo clásica"; "ClassicQuality" = "Calidad de vídeo clásica";
@@ -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" = "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" = "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";
@@ -85,8 +91,8 @@
"RemoveIndicatorsDesc" = "Elimina los indicadores de pestaña."; "RemoveIndicatorsDesc" = "Elimina los indicadores de pestaña.";
"ReExplore" = "Reemplazar pestaña Shorts con pestaña Explorar"; "ReExplore" = "Reemplazar pestaña Shorts con pestaña Explorar";
"ReExploreDesc" = "Muestra la pestaña Explorar en lugar de la pestaña Shorts como en versiones antiguas de YouTube."; "ReExploreDesc" = "Muestra la pestaña Explorar en lugar de la pestaña Shorts como en versiones antiguas de YouTube.";
"AddExplore" = "Add Explore tab"; "AddExplore" = "Añadir pestaña Explorar";
"AddExploreDesc" = "Adds Explore tab to the Tab bar."; "AddExploreDesc" = "Añade la pestaña Explorar a la barra de pestañas.";
"HideShortsTab" = "Ocultar pestaña Shorts"; "HideShortsTab" = "Ocultar pestaña Shorts";
"HideShortsTabDesc" = "Oculta la pestaña Shorts de la barra de pestañas."; "HideShortsTabDesc" = "Oculta la pestaña Shorts de la barra de pestañas.";
"HideSubscriptionsTab" = "Ocultar pestaña Suscripciones"; "HideSubscriptionsTab" = "Ocultar pestaña Suscripciones";
@@ -97,16 +103,16 @@
"HideLibraryTabDesc" = "Oculta la pestaña Biblioteca de la barra de pestañas."; "HideLibraryTabDesc" = "Oculta la pestaña Biblioteca de la barra de pestañas.";
"Shorts" = "Shorts"; "Shorts" = "Shorts";
"ShortsOnlyMode" = "Shorts Only Mode"; "ShortsOnlyMode" = "Modo sólo Shorts";
"ShortsOnlyModeDesc" = "Limits YouTube functionality to viewing Shorts only."; "ShortsOnlyModeDesc" = "Limita la funcionalidad de YouTube únicamente a la visualización de Shorts.";
"HideShorts" = "Ocultar vídeos Shorts"; "HideShorts" = "Ocultar vídeos Shorts";
"HideShortsDesc" = "Oculta los vídeos Shorts de la página de inicio, Recomendados, etc. (No se aplica al historial de reproducciones)"; "HideShortsDesc" = "Oculta los vídeos Shorts de la página de inicio, Recomendados, etc. (No se aplica al historial de reproducciones)";
"ShortsProgress" = "Activar barra de progreso"; "ShortsProgress" = "Activar barra de progreso";
"ShortsProgressDesc" = "Muestra una barra de progreso en la superposición de Shorts."; "ShortsProgressDesc" = "Muestra una barra de progreso en la superposición de Shorts.";
"PinchToFullscreenShorts" = "Pinch to Fullscreen"; "PinchToFullscreenShorts" = "Pellizcar para pantalla completa";
"PinchToFullscreenShortsDesc" = "Manages visibility of the overlay with pinch in and pinch out gestures, displaying Shorts in fullscreen mode."; "PinchToFullscreenShortsDesc" = "Gestiona la visibilidad de la superposición con gestos de pellizcar para acercar y pellizcar para alejar, mostrando Shorts en modo de pantalla completa.";
"ShortsToRegular" = "Shorts to regular videos"; "ShortsToRegular" = "De Shorts a vídeos normales";
"ShortsToRegularDesc" = "Opens Shorts videos as regular videos."; "ShortsToRegularDesc" = "Abre los Shorts como vídeos normales.";
"ResumeShorts" = "No empezar desde la pestaña Shorts"; "ResumeShorts" = "No empezar desde la pestaña Shorts";
"ResumeShortsDesc" = "Evita empezar desde los vídeos Shorts al abrir la aplicación, lo cual ocurre si YouTube se cerró mientras se veían Shorts."; "ResumeShortsDesc" = "Evita empezar desde los vídeos Shorts al abrir la aplicación, lo cual ocurre si YouTube se cerró mientras se veían Shorts.";
"HideShortsLogo" = "Ocultar el logo de Shorts"; "HideShortsLogo" = "Ocultar el logo de Shorts";
@@ -133,8 +139,8 @@
"HideShortsAvatarsDesc" = "Oculta la imagen de perfil en la esquina inferior derecha."; "HideShortsAvatarsDesc" = "Oculta la imagen de perfil en la esquina inferior derecha.";
"HideShortsThanks" = "Ocultar botón de Supergracias"; "HideShortsThanks" = "Ocultar botón de Supergracias";
"HideShortsThanksDesc" = "Oculta el botón de Supergracias (Donar) en la superposición de Shorts."; "HideShortsThanksDesc" = "Oculta el botón de Supergracias (Donar) en la superposición de Shorts.";
"HideShortsSource" = "Hide Shorts Source"; "HideShortsSource" = "Ocultar fuente de Shorts";
"HideShortsSourceDesc" = "Hides the Shorts sources under the channel name."; "HideShortsSourceDesc" = "Oculta las fuentes Shorts bajo el nombre del canal.";
"HideShortsChannelName" = "Ocultar nombre del canal"; "HideShortsChannelName" = "Ocultar nombre del canal";
"HideShortsChannelNameDesc" = "Oculta el nombre del canal y el botón de Suscribirse en la superposición de Shorts."; "HideShortsChannelNameDesc" = "Oculta el nombre del canal y el botón de Suscribirse en la superposición de Shorts.";
"HideShortsDescription" = "Ocultar descripción"; "HideShortsDescription" = "Ocultar descripción";
@@ -143,16 +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";
"CopyPostText" = "Copy community posts text"; "CopyVideoInfo" = "Copy video information";
"CopyPostTextDesc" = "Copies community posts text to the clipboard by long tap."; "CopyVideoInfoDesc" = "Adds button to copy video title and description into Video Description panel.";
"SavePostImage" = "Save community posts image"; "PostManager" = "Save post information";
"SavePostImageDesc" = "Saves community posts image to the Photos app by long tap."; "PostManagerDesc" = "Allows to copy post text and save post as image by long tap.";
"SaveProfilePhoto" = "Save profile picture"; "SaveProfilePhoto" = "Guardar foto de perfil";
"SaveProfilePhotoDesc" = "Saves profile picture to the Photos app by long tap."; "SaveProfilePhotoDesc" = "Guarda la imagen de perfil en la aplicación Fotos con un toque prolongado";
"FixAlbums" = "Fix covers"; "CommentManager" = "Save comment information";
"FixAlbumsDesc" = "Fixes the display of covers for users from Russia."; "CommentManagerDesc" = "Allows to copy comment text and save comment as image by long tap.";
"FixAlbums" = "Arreglar portadas";
"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" = "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" = "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";
@@ -168,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" = "Playback quality on WiFi";
"PlaybackQualityOnCellular" = "Playback quality on Cellular";
"SelectQuality" = "Select Quality";
"Default" = "Default";
"Best" = "Best";
"Startup" = "Página de inicio"; "Startup" = "Página de inicio";
"Home" = "Inicio"; "Home" = "Inicio";
"Explore" = "Explorar"; "Explore" = "Explorar";
@@ -177,6 +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";
"SupportDevelopment" = "Support development";
"SupportDevelopmentDesc" = "If you like YTLite and would like to support its development, you can do it using any of convenient ways below.\nThanks❤";
"Version" = "Versión"; "Version" = "Versión";
"About" = "Acerca de"; "About" = "Acerca de";
"Credits" = "Créditos"; "Credits" = "Créditos";
@@ -186,15 +216,31 @@
"French" = "Traducción: Frances"; "French" = "Traducción: Frances";
"Spanish" = "Traducción: Español"; "Spanish" = "Traducción: Español";
"Japanese" = "Traducción: Japonés"; "Japanese" = "Traducción: Japonés";
"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";
"ResetSettings" = "Restablecer configuración de YTLite"; "ResetSettings" = "Restablecer configuración de YTLite";
"ResetMessage" = "Esta opción restablecerá la configuración de YTLite a los valores predeterminados y cerrará YouTube.\n\n¿Estás seguro de que deseas continuar?"; "ResetMessage" = "Esta opción restablecerá la configuración de YTLite a los valores predeterminados y cerrará YouTube.\n\n¿Estás seguro de que deseas continuar?";
"ShortsOnlyWarning" = "Are you sure you want to activate this mode?\n\nIn this mode, you will only be able to watch Shorts videos and won't be able to do anything else.\n\nYou can disable Shorts Only Mode by long pressing with two fingers in the Shorts player."; "ShortsOnlyWarning" = "¿Estás seguro de que quieres activar este modo?\n\nEn este modo, sólo podrás ver Shorts y no podrás hacer nada más.\n\nPuedes desactivar el modo sólo Shorts realizando una pulsación larga con dos dedos en el reproductor de Shorts.";
"ShortsModeTurnedOff" = "Shorts Only Mode has been turned off"; "ShortsModeTurnedOff" = "Se ha desactivado el modo de sólo Shorts";
"Yes" = "Sí"; "Yes" = "Sí";
"No" = "No"; "No" = "No";
"Copied" = "Copied to clipboard"; "SelectAction" = "Select action";
"Saved" = "Saved to Photos"; "CopyTitle" = "Copy title";
"CopyDescription" = "Copy description";
"CopyPostText" = "Copy post text";
"SavePostAsImage" = "Save post as image";
"CopyPostAsImage" = "Copy post as image";
"CopyCommentText" = "Copy comment text";
"SaveCommentAsImage" = "Save comment as image";
"CopyCommentAsImage" = "Copy comment as image";
"SaveProfilePicture" = "Save profile picture";
"CopyProfilePicture" = "Copy profile picture";
"Cancel" = "Cancel";
"Copied" = "Copiado al portapapeles";
"Done" = "Done";
"Saved" = "Guardado en Fotos";
"Error" = "Error"; "Error" = "Error";
@@ -37,8 +37,8 @@
"NoEndScreenCardsDesc" = "Masque les cartes de fin d'écran (vignettes) à la fin des vidéos."; "NoEndScreenCardsDesc" = "Masque les cartes de fin d'écran (vignettes) à la fin des vidéos.";
"NoFullscreenActions" = "Désactiver les actions en plein écran"; "NoFullscreenActions" = "Désactiver les actions en plein écran";
"NoFullscreenActionsDesc" = "Désactive le panneau d'actions en mode plein écran."; "NoFullscreenActionsDesc" = "Désactive le panneau d'actions en mode plein écran.";
"PersistentProgressBar" = "Persistent progress bar"; "PersistentProgressBar" = "Barre de progression persistante";
"PersistentProgressBarDesc" = "Always shows progress bar in the player."; "PersistentProgressBarDesc" = " Affiche toujours la barre de progression dans le lecteur ";
"NoRelatedVids" = "Pas de vidéos associées dans l'overlay"; "NoRelatedVids" = "Pas de vidéos associées dans l'overlay";
"NoRelatedVidsDesc" = "Supprime les vidéos associées affichées dans l'overlay en faisant glisser vers le haut."; "NoRelatedVidsDesc" = "Supprime les vidéos associées affichées dans l'overlay en faisant glisser vers le haut.";
"NoPromotionCards" = "Masquer les cartes de promotion payante"; "NoPromotionCards" = "Masquer les cartes de promotion payante";
@@ -51,12 +51,12 @@
"MiniplayerDesc" = "Active le mini-lecteur pour les vidéos qui n'étaient pas initialement conçues pour cela, comme les vidéos destinées aux enfants."; "MiniplayerDesc" = "Active le mini-lecteur pour les vidéos qui n'étaient pas initialement conçues pour cela, comme les vidéos destinées aux enfants.";
"PortraitFullscreen" = "Mode plein écran en portrait"; "PortraitFullscreen" = "Mode plein écran en portrait";
"PortraitFullscreenDesc" = "Active la prise en charge du mode plein écran en portrait."; "PortraitFullscreenDesc" = "Active la prise en charge du mode plein écran en portrait.";
"CopyWithTimestamp" = "Copy timestamped links"; "CopyWithTimestamp" = "Copier les liens avec horodatage";
"CopyWithTimestampDesc" = "Allows to copy timestamped link to the clipboard by pressing pause button."; "CopyWithTimestampDesc" = "Permet de copier les liens avec horodatage dans le presse-papiers en appuyant sur le bouton de pause.";
"DisableAutoplay" = "Désactiver la lecture automatique des vidéos"; "DisableAutoplay" = "Désactiver la lecture automatique des vidéos";
"DisableAutoplayDesc" = "Empêche la lecture des vidéos après ouverture."; "DisableAutoplayDesc" = "Empêche la lecture des vidéos après ouverture.";
"DisableAutoCaptions" = "Disable auto captions"; "DisableAutoCaptions" = "Désactiver les sous-titres automatiques";
"DisableAutoCaptionsDesc" = "Prevents automatic activation of captions."; "DisableAutoCaptionsDesc" = "Empêche l'activation des sous-titres automatique.";
"NoContentWarning" = "Passer l'avertissement de contenu"; "NoContentWarning" = "Passer l'avertissement de contenu";
"NoContentWarningDesc" = "Ignore le message d'avertissement de contenu sensible."; "NoContentWarningDesc" = "Ignore le message d'avertissement de contenu sensible.";
"ClassicQuality" = "Qualité vidéo classique"; "ClassicQuality" = "Qualité vidéo classique";
@@ -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" = "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" = "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";
@@ -81,12 +87,12 @@
"Tabbar" = "Barre d'onglets"; "Tabbar" = "Barre d'onglets";
"RemoveLabels" = "Supprimer les sous-titres"; "RemoveLabels" = "Supprimer les sous-titres";
"RemoveLabelsDesc" = "Supprime les sous-titres des onglets."; "RemoveLabelsDesc" = "Supprime les sous-titres des onglets.";
"RemoveIndicators" = "Remove indicators"; "RemoveIndicators" = "Supprimer les indicateurs";
"RemoveIndicatorsDesc" = "Removes tab indicators."; "RemoveIndicatorsDesc" = "Supprime les indicateurs d'onglets.";
"ReExplore" = "Remplacer l'onglet Shorts par l'onglet Explorer"; "ReExplore" = "Remplacer l'onglet Shorts par l'onglet Explorer";
"ReExploreDesc" = "Affiche l'onglet Explorer à la place de l'onglet Shorts comme dans les anciennes versions de YouTube."; "ReExploreDesc" = "Affiche l'onglet Explorer à la place de l'onglet Shorts comme dans les anciennes versions de YouTube.";
"AddExplore" = "Add Explore tab"; "AddExplore" = "Ajouter l'onglet Explorer";
"AddExploreDesc" = "Adds Explore tab to the Tab bar."; "AddExploreDesc" = "Ajoute l'onglet Explorer à la barre d'onglets.";
"HideShortsTab" = "Masquer l'onglet Shorts"; "HideShortsTab" = "Masquer l'onglet Shorts";
"HideShortsTabDesc" = "Masque l'onglet Shorts de la barre d'onglets"; "HideShortsTabDesc" = "Masque l'onglet Shorts de la barre d'onglets";
"HideSubscriptionsTab" = "Masquer l'onglet Abonnements"; "HideSubscriptionsTab" = "Masquer l'onglet Abonnements";
@@ -97,16 +103,16 @@
"HideLibraryTabDesc" = "Masque l'onglet Bibliothèque de la barre d'onglets"; "HideLibraryTabDesc" = "Masque l'onglet Bibliothèque de la barre d'onglets";
"Shorts" = "Shorts"; "Shorts" = "Shorts";
"ShortsOnlyMode" = "Shorts Only Mode"; "ShortsOnlyMode" = "Mode Shorts uniquement";
"ShortsOnlyModeDesc" = "Limits YouTube functionality to viewing Shorts only."; "ShortsOnlyModeDesc" = "Limite les fonctionnalités de YouTube à la visualisation des Shorts uniquement.";
"HideShorts" = "Masquer les vidéos Shorts"; "HideShorts" = "Masquer les vidéos Shorts";
"HideShortsDesc" = "Masque les vidéos Shorts de la page d'accueil, des recommandations, etc. (Non appliqué à l'historique de visionnage)"; "HideShortsDesc" = "Masque les vidéos Shorts de la page d'accueil, des recommandations, etc. (Non appliqué à l'historique de visionnage)";
"ShortsProgress" = "Activer la barre de progression"; "ShortsProgress" = "Activer la barre de progression";
"ShortsProgressDesc" = "Affiche la barre de progression dans l'overlay Shorts."; "ShortsProgressDesc" = "Affiche la barre de progression dans l'overlay Shorts.";
"PinchToFullscreenShorts" = "Pinch to Fullscreen"; "PinchToFullscreenShorts" = "Pincer pour plein écran";
"PinchToFullscreenShortsDesc" = "Manages visibility of the overlay with pinch in and pinch out gestures, displaying Shorts in fullscreen mode."; "PinchToFullscreenShortsDesc" = "Gère la visibilité de l'overlay avec les gestes de pincement, affichant les Shorts en mode plein écran.";
"ShortsToRegular" = "Shorts to regular videos"; "ShortsToRegular" = "Shorts vers vidéos normales";
"ShortsToRegularDesc" = "Opens Shorts videos as regular videos."; "ShortsToRegularDesc" = "Ouvre les vidéos Shorts en tant que vidéos normales.";
"ResumeShorts" = "Ne pas démarrer depuis l'onglet Shorts"; "ResumeShorts" = "Ne pas démarrer depuis l'onglet Shorts";
"ResumeShortsDesc" = "Empêche de démarrer depuis les vidéos Shorts lors de l'ouverture de l'application, ce qui se produit si YouTube était fermé pendant la lecture des Shorts."; "ResumeShortsDesc" = "Empêche de démarrer depuis les vidéos Shorts lors de l'ouverture de l'application, ce qui se produit si YouTube était fermé pendant la lecture des Shorts.";
"HideShortsLogo" = "Masquer le logo Shorts"; "HideShortsLogo" = "Masquer le logo Shorts";
@@ -133,8 +139,8 @@
"HideShortsAvatarsDesc" = "Masque la photo de profil dans le coin inférieur droit."; "HideShortsAvatarsDesc" = "Masque la photo de profil dans le coin inférieur droit.";
"HideShortsThanks" = "Masquer le bouton Superthanks"; "HideShortsThanks" = "Masquer le bouton Superthanks";
"HideShortsThanksDesc" = "Masque le bouton Superthanks (Don) de l'overlay Shorts."; "HideShortsThanksDesc" = "Masque le bouton Superthanks (Don) de l'overlay Shorts.";
"HideShortsSource" = "Hide Shorts Source"; "HideShortsSource" = "Cacher la source des Shorts";
"HideShortsSourceDesc" = "Hides the Shorts sources under the channel name."; "HideShortsSourceDesc" = "Masque les sources des Shorts sous le nom de la chaîne.";
"HideShortsChannelName" = "Masquer le nom de la chaîne"; "HideShortsChannelName" = "Masquer le nom de la chaîne";
"HideShortsChannelNameDesc" = "Masque le nom de la chaîne et le bouton S'abonner de l'overlay Shorts."; "HideShortsChannelNameDesc" = "Masque le nom de la chaîne et le bouton S'abonner de l'overlay Shorts.";
"HideShortsDescription" = "Masquer la description"; "HideShortsDescription" = "Masquer la description";
@@ -143,23 +149,39 @@
"HideShortsAudioTrackDesc" = "Masque la piste audio sous la description des Shorts."; "HideShortsAudioTrackDesc" = "Masque la piste audio sous la description des Shorts.";
"Other" = "Autre"; "Other" = "Autre";
"CopyPostText" = "Copy community posts text"; "CopyVideoInfo" = "Copier les informations vidéo";
"CopyPostTextDesc" = "Copies community posts text to the clipboard by long tap."; "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.";
"SavePostImage" = "Save community posts image"; "PostManager" = "Save post information";
"SavePostImageDesc" = "Saves community posts image to the Photos app by long tap."; "PostManagerDesc" = "Allows to copy post text and save post as image by long tap.";
"SaveProfilePhoto" = "Save profile picture"; "SaveProfilePhoto" = "Enregistrer la photo de profil";
"SaveProfilePhotoDesc" = "Saves profile picture to the Photos app by long tap."; "SaveProfilePhotoDesc" = "Enregistre la photo de profil dans l'application Photos en appuyant longuement.";
"FixAlbums" = "Fix covers"; "CommentManager" = "Save comment information";
"FixAlbumsDesc" = "Fixes the display of covers for users from Russia."; "CommentManagerDesc" = "Allows to copy comment text and save comment as image by long tap.";
"FixAlbums" = "Réparer les couvertures";
"FixAlbumsDesc" = "Répare l'affichage des couvertures 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" = "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" = "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";
"NoSearchHistoryDesc" = "Masque visuellement l'historique de recherche et les suggestions. Note : Votre historique de recherche sera toujours accessible dans vos autres clients YouTube."; "NoSearchHistoryDesc" = "Masque visuellement l'historique de recherche et les suggestions. Note : Votre historique de recherche sera toujours accessible dans vos autres clients YouTube.";
"NoRelatedWatchNexts" = "Masquer toutes les vidéos sous le lecteur"; "NoRelatedWatchNexts" = "Masquer toutes les vidéos sous le lecteur";
"NoRelatedWatchNextsDesc" = "Masque toutes les vidéos sous le lecteur, ne laissant que les informations sur la vidéo et la section des commentaires."; "NoRelatedWatchNextsDesc" = "Masque toutes les vidéos sous le lecteur, ne laissant que les informations sur la vidéo et la section des commentaires.";
"StickSortComments" = "Épingler l'en-tête des commentaires";\ "StickSortComments" = "Épingler l'en-tête des commentaires";
"StickSortCommentsDesc" = "Épingle l'en-tête de tri des commentaires (Meilleurs, Plus récents) pour qu'il ne disparaisse pas pendant le défilement."; "StickSortCommentsDesc" = "Épingle l'en-tête de tri des commentaires (Meilleurs, Plus récents) pour qu'il ne disparaisse pas pendant le défilement.";
"HideSortComments" = "Masquer l'en-tête des commentaires"; "HideSortComments" = "Masquer l'en-tête des commentaires";
"HideSortCommentsDesc" = "Masque l'en-tête de tri des commentaires (Meilleurs, Plus récents) pour qu'il n'apparaisse jamais."; "HideSortCommentsDesc" = "Masque l'en-tête de tri des commentaires (Meilleurs, Plus récents) pour qu'il n'apparaisse jamais.";
@@ -168,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" = "Playback quality on WiFi";
"PlaybackQualityOnCellular" = "Playback quality on Cellular";
"SelectQuality" = "Select Quality";
"Default" = "Default";
"Best" = "Best";
"Startup" = "Page de démarrage"; "Startup" = "Page de démarrage";
"Home" = "Accueil"; "Home" = "Accueil";
"Explore" = "Explorer"; "Explore" = "Explorer";
@@ -177,6 +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";
"SupportDevelopment" = "Support development";
"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" = "À propos"; "About" = "À propos";
"Credits" = "Crédits"; "Credits" = "Crédits";
@@ -186,15 +216,31 @@
"French" = "Localisation française"; "French" = "Localisation française";
"Spanish" = "Localisation espagnole"; "Spanish" = "Localisation espagnole";
"Japanese" = "Localisation japonaise"; "Japanese" = "Localisation japonaise";
"Vietnamese" = "Localisation vietnamienne";
"Advanced" = "Mode avancé"; "Advanced" = "Mode avancé";
"AdvancedDesc" = "More customizable mode";
"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";
"ResetSettings" = "Réinitialiser les paramètres YTLite"; "ResetSettings" = "Réinitialiser les paramètres YTLite";
"ResetMessage" = "Cette option réinitialisera les paramètres YTLite par défaut et fermera YouTube.\n\nÊtes-vous sûr de vouloir continuer ?"; "ResetMessage" = "Cette option réinitialisera les paramètres YTLite par défaut et fermera YouTube.\n\nÊtes-vous sûr de vouloir continuer ?";
"ShortsOnlyWarning" = "Are you sure you want to activate this mode?\n\nIn this mode, you will only be able to watch Shorts videos and won't be able to do anything else.\n\nYou can disable Shorts Only Mode by long pressing with two fingers in the Shorts player."; "ShortsOnlyWarning" = "Êtes-vous sûr de vouloir activer ce mode?\n\nDans ce mode, vous ne pourrez regarder que des vidéos Shorts et vous ne pourrez rien d'autre faire.\n\nVous pouvez désactiver le mode Shorts Only en appuyant longuement avec deux doigts dans le lecteur Shorts.";
"ShortsModeTurnedOff" = "Shorts Only Mode has been turned off"; "ShortsModeTurnedOff" = "Le mode Shorts uniquement a été désactivé";
"Yes" = "Oui"; "Yes" = "Oui";
"No" = "Non"; "No" = "Non";
"Copied" = "Copied to clipboard"; "SelectAction" = "Sélectionner une action";
"Saved" = "Saved to Photos"; "CopyTitle" = "Copier le titre";
"Error" = "Error"; "CopyDescription" = "Copier la description";
"CopyPostText" = "Copy post text";
"SavePostAsImage" = "Save post as image";
"CopyPostAsImage" = "Copy post as image";
"CopyCommentText" = "Copy comment text";
"SaveCommentAsImage" = "Save comment as image";
"CopyCommentAsImage" = "Copy comment as image";
"SaveProfilePicture" = "Save profile picture";
"CopyProfilePicture" = "Copy profile picture";
"Cancel" = "Annuler";
"Copied" = "Copié dans le presse-papiers";
"Saved" = "Enregistré dans Photos";
"Done" = "Terminé";
"Error" = "Erreur";
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" = "フリーズームジェスチャーを無効化";
@@ -143,16 +149,32 @@
"HideShortsAudioTrackDesc" = "ショートの説明の下に表示されるオーディオトラックを非表示にします"; "HideShortsAudioTrackDesc" = "ショートの説明の下に表示されるオーディオトラックを非表示にします";
"Other" = "その他"; "Other" = "その他";
"CopyPostText" = "Copy community posts text"; "CopyVideoInfo" = "Copy video information";
"CopyPostTextDesc" = "Copies community posts text to the clipboard by long tap."; "CopyVideoInfoDesc" = "Adds button to copy video title and description into Video Description panel.";
"SavePostImage" = "Save community posts image"; "PostManager" = "Save post information";
"SavePostImageDesc" = "Saves community posts image to the Photos app by long tap."; "PostManagerDesc" = "Allows to copy post text and save post as image 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";
"CommentManagerDesc" = "Allows to copy comment text and save comment as image by long tap.";
"FixAlbums" = "Fix covers"; "FixAlbums" = "Fix covers";
"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" = "検索履歴を非表示";
@@ -168,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" = "探索";
@@ -177,6 +205,8 @@
"Warning" = "警告"; "Warning" = "警告";
"TabIsHidden" = "非表示のタブはスタートアップページとして選択できません"; "TabIsHidden" = "非表示のタブはスタートアップページとして選択できません";
"SupportDevelopment" = "Support development";
"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" = "クレジット";
@@ -186,8 +216,11 @@
"French" = "フランス語翻訳"; "French" = "フランス語翻訳";
"Spanish" = "スペイン語翻訳"; "Spanish" = "スペイン語翻訳";
"Japanese" = "日本語翻訳"; "Japanese" = "日本語翻訳";
"Vietnamese" = "Vietnamese localization";
"Advanced" = "アドバンスモード"; "Advanced" = "アドバンスモード";
"AdvancedDesc" = "More customizable mode";
"AdvancedModeReminder" = "YTLiteでアドバンスモードを有効にしますか?\n\nこのモードでは50以上の追加オプションを使用してYouTubeのカスタマイズと最適化が可能です。後で、設定 → %@ → %@ → %@から変更できます"; "AdvancedModeReminder" = "YTLiteでアドバンスモードを有効にしますか?\n\nこのモードでは50以上の追加オプションを使用してYouTubeのカスタマイズと最適化が可能です。後で、設定 → %@ → %@ → %@から変更できます";
"ClearCache" = "Clear cache";
"ResetSettings" = "YTLiteの設定をリセット"; "ResetSettings" = "YTLiteの設定をリセット";
"ResetMessage" = "このオプションを選択するとYTLiteの設定がデフォルトにリセットされ、アプリが終了します。\n\n続行してもよろしいですか?"; "ResetMessage" = "このオプションを選択するとYTLiteの設定がデフォルトにリセットされ、アプリが終了します。\n\n続行してもよろしいですか?";
"ShortsOnlyWarning" = "Are you sure you want to activate this mode?\n\nIn this mode, you will only be able to watch Shorts videos and won't be able to do anything else.\n\nYou can disable Shorts Only Mode by long pressing with two fingers in the Shorts player."; "ShortsOnlyWarning" = "Are you sure you want to activate this mode?\n\nIn this mode, you will only be able to watch Shorts videos and won't be able to do anything else.\n\nYou can disable Shorts Only Mode by long pressing with two fingers in the Shorts player.";
@@ -195,6 +228,19 @@
"Yes" = "はい"; "Yes" = "はい";
"No" = "いいえ"; "No" = "いいえ";
"SelectAction" = "Select action";
"CopyTitle" = "Copy title";
"CopyDescription" = "Copy description";
"CopyPostText" = "Copy post text";
"SavePostAsImage" = "Save post as image";
"CopyPostAsImage" = "Copy post as image";
"CopyCommentText" = "Copy comment text";
"SaveCommentAsImage" = "Save comment as image";
"CopyCommentAsImage" = "Copy comment as image";
"SaveProfilePicture" = "Save profile picture";
"CopyProfilePicture" = "Copy profile picture";
"Cancel" = "Cancel";
"Copied" = "Copied to clipboard"; "Copied" = "Copied to clipboard";
"Saved" = "Saved to Photos"; "Saved" = "Saved to Photos";
"Done" = "Done";
"Error" = "Error"; "Error" = "Error";
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" = "Отключить жесты для зума";
@@ -143,16 +149,34 @@
"HideShortsAudioTrackDesc" = "Скрывает информацию об аудиодорожке в нижней части плеера."; "HideShortsAudioTrackDesc" = "Скрывает информацию об аудиодорожке в нижней части плеера.";
"Other" = "Другие настройки"; "Other" = "Другие настройки";
"CopyPostText" = "Копировать текст постов"; "CopyVideoInfo" = "Копировать информацию о видео";
"CopyPostTextDesc" = "Копирует текст постов в буфер обмена долгим нажатием."; "CopyVideoInfoDesc" = "Добавляет кнопку для копирования названия и описания видео в панель описания видео.";
"SavePostImage" = "Сохранять изображения постов"; "PostManager" = "Сохранять информацию с постов";
"SavePostImageDesc" = "Сохраняет изображения постов в «Фото» долгим нажатием по ним."; "PostManagerDesc" = "Позволяет скопировать текст из поста или сохранить пост как фото долгим нажатием по нему.";
"SaveProfilePhoto" = "Сохранять фото профиля"; "SaveProfilePhoto" = "Сохранять фото профиля";
"SaveProfilePhotoDesc" = "Сохраняет фото профиля в «Фото» долгим нажатием по нему."; "SaveProfilePhotoDesc" = "Сохраняет фото профиля в «Фото» долгим нажатием по нему.";
"CopyCommentText" = "Копировать текст комментариев";
"CopyCommentTextDesc" = "Копирует текст комментариев в буфер обмена долгим нажатием.";
"CommentManager" = "Сохранять информацию с комментариев";
"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" = "Скрыть историю поиска";
@@ -168,6 +192,12 @@
"DisableRTL" = "Запретить формат «справа налево»"; "DisableRTL" = "Запретить формат «справа налево»";
"DisableRTLDesc" = "Принудительно отображает текст в формате слева направо для языков, изначально отображающихся в формате справа налево."; "DisableRTLDesc" = "Принудительно отображает текст в формате слева направо для языков, изначально отображающихся в формате справа налево.";
"PlaybackQualityOnWiFi" = "Качество по WiFi";
"PlaybackQualityOnCellular" = "Качество по мобильной сети";
"SelectQuality" = "Выберите качество";
"Default" = "По умолчанию";
"Best" = "Лучшее";
"Startup" = "Начальная страница"; "Startup" = "Начальная страница";
"Home" = "Главная"; "Home" = "Главная";
"Explore" = "Навигация"; "Explore" = "Навигация";
@@ -177,6 +207,8 @@
"Warning" = "Внимание"; "Warning" = "Внимание";
"TabIsHidden" = "Скрытая вкладка не может быть выбрана в качестве начальной страницы"; "TabIsHidden" = "Скрытая вкладка не может быть выбрана в качестве начальной страницы";
"SupportDevelopment" = "Помочь с развитием проекта";
"SupportDevelopmentDesc" = "Если вам понравился YTLite и вы хотели бы поддержать проект, то можете сделать это любым подходящим ниже способом.\nСпасибо❤";
"Version" = "Версия"; "Version" = "Версия";
"About" = "О твике"; "About" = "О твике";
"Credits" = "Авторы"; "Credits" = "Авторы";
@@ -186,8 +218,11 @@
"French" = "Французская локализация"; "French" = "Французская локализация";
"Spanish" = "Испанская локализация"; "Spanish" = "Испанская локализация";
"Japanese" = "Японская локализация"; "Japanese" = "Японская локализация";
"Vietnamese" = "Вьетнамская локализация";
"Advanced" = "Расширенный режим"; "Advanced" = "Расширенный режим";
"AdvancedDesc" = "Более настраиваемый режим";
"AdvancedModeReminder" = "Хотите ли вы активировать расширенный режим настроек YTLite?\n\nДанный режим добавляет более 50 опций для тонкой настройки YouTube. Вы всегда сможете включить/отключить расширенный режим перейдя в Настройки → %@ → %@ → %@."; "AdvancedModeReminder" = "Хотите ли вы активировать расширенный режим настроек YTLite?\n\nДанный режим добавляет более 50 опций для тонкой настройки YouTube. Вы всегда сможете включить/отключить расширенный режим перейдя в Настройки → %@ → %@ → %@.";
"ClearCache" = "Очистить кеш";
"ResetSettings" = "Сбросить настройки твика"; "ResetSettings" = "Сбросить настройки твика";
"ResetMessage" = "Данное действие сбросит настройки YTLite к значениям по умолчанию и закроет YouTube.\n\nУверены, что хотите продолжить?"; "ResetMessage" = "Данное действие сбросит настройки YTLite к значениям по умолчанию и закроет YouTube.\n\nУверены, что хотите продолжить?";
"ShortsOnlyWarning" = "Вы уверены, что хотите активировать данный режим?\n\nВ данном режиме вы не сможете ничего делать, кроме как смотреть видеоролики Shorts.\n\nРежим Shorts можно будет отключить зажав в плеере двумя пальцами."; "ShortsOnlyWarning" = "Вы уверены, что хотите активировать данный режим?\n\nВ данном режиме вы не сможете ничего делать, кроме как смотреть видеоролики Shorts.\n\nРежим Shorts можно будет отключить зажав в плеере двумя пальцами.";
@@ -195,6 +230,21 @@
"Yes" = "Да"; "Yes" = "Да";
"No" = "Нет"; "No" = "Нет";
"SelectAction" = "Выберите действие";
"CopyTitle" = "Скопировать название";
"CopyDescription" = "Скопировать описание";
"CopyPostText" = "Скопировать текст поста";
"SaveCurrentImage" = "Сохранить данное фото";
"CopyCurrentImage" = "Скопировать данное фото";
"SavePostAsImage" = "Сохранить пост как фото";
"CopyPostAsImage" = "Скопировать пост как фото";
"CopyCommentText" = "Скопировать текст комментария";
"SaveCommentAsImage" = "Сохранить комментарий как фото";
"CopyCommentAsImage" = "Скопировать комментарий как фото";
"SaveProfilePicture" = "Сохранить фото профиля";
"CopyProfilePicture" = "Скопировать фото профиля";
"Cancel" = "Отмена";
"Copied" = "Скопировано в буфер обмена"; "Copied" = "Скопировано в буфер обмена";
"Saved" = "Сохранено в Фото"; "Saved" = "Сохранено в Фото";
"Done" = "Готово";
"Error" = "Ошибка"; "Error" = "Ошибка";
@@ -0,0 +1,246 @@
"General" = "Chung";
"RemoveAds" = "Loại bỏ các quảng cáo";
"RemoveAdsDesc" = "Loại bỏ quảng cáo trong ứng dụng.";
"BackgroundPlayback" = "Phát lại ở chế độ nền";
"BackgroundPlaybackDesc" = "Cho phép phát lại ở chế độ nền.";
"Navbar" = "Thanh điều hướng";
"RemoveCast" = "Ẩn nút Cast";
"RemoveCastDesc" = "Ẩn nút Cast khỏi thanh Điều hướng.";
"RemoveNotifications" = "Ẩn nút Thông báo";
"RemoveNotificationsDesc" = "Ẩn nút Thông báo khỏi thanh Điều hướng.";
"RemoveSearch" = "Ẩn nút Tìm kiếm";
"RemoveSearchDesc" = "Ẩn nút Tìm kiếm khỏi thanh Điều hướng.";
"RemoveVoiceSearch" = "Ẩn nút tìm kiếm bằng giọng nói";
"RemoveVoiceSearchDesc" = "Ẩn nút tìm kiếm bằng giọng nói khỏi thanh Điều hướng.";
"StickyNavbar" = "Thanh điều hướng cố định";
"StickyNavbarDesc" = "Ghim thanh Điều hướng để nó vẫn hiển thị khi cuộn xuống.";
"NoSubbar" = "Ẩn thanh phụ";
"NoSubbarDesc" = "Ẩn Thanh phụ (Tất cả, Mới đối với bạn, Trực tiếp, v.v.) dưới thanh Điều hướng.";
"NoYTLogo" = "Xóa biểu tượng YouTube";
"NoYTLogoDesc" = "Xóa logo YouTube trong thanh Điều hướng.";
"Overlay" = "Lớp phủ";
"HideAutoplay" = "Ẩn nút Tự động phát";
"HideAutoplayDesc" = "Ẩn nút Tự động phát trong trình phát video.";
"HideSubs" = "Ẩn nút phụ đề";
"HideSubsDesc" = "Ẩn nút Phụ đề khỏi lớp phủ.";
"NoHUDMsgs" = "Ẩn thông báo HUD";
"NoHUDMsgsDesc" = "Ẩn tất cả các thông báo tính năng từ người chơi. Ví dụ: CC được bật/tắt, Vòng lặp video được bật, v.v.";
"HidePrevNext" = "Ẩn nút Trước và Tiếp theo";
"HidePrevNextDesc" = "Ẩn các nút Trước và Tiếp theo khỏi lớp phủ video.";
"ReplacePrevNext" = "Nút tua đi và tua lại nhanh";
"ReplacePrevNextDesc" = "Thay thế các nút Trước và Tiếp theo thành nút tua đi và tua lại nhanh trong lớp phủ video.";
"NoDarkBg" = "Xóa nền tối";
"NoDarkBgDesc" = "Loại bỏ nền tối của lớp phủ.";
"NoEndScreenCards" = "Ẩn video dạng thumbnails";
"NoEndScreenCardsDesc" = "Ẩn thumbnail của các video đề xuất, xuất hiện ở cuối video.";
"NoFullscreenActions" = "Vô hiệu hóa các hành động toàn màn hình";
"NoFullscreenActionsDesc" = "Vô hiệu hóa bảng hành động ở chế độ toàn màn hình.";
"PersistentProgressBar" = "Thanh tiến trình liên tục";
"PersistentProgressBarDesc" = "Luôn hiển thị thanh tiến trình trong trình phát.";
"NoRelatedVids" = "Không có video liên quan trong lớp phủ";
"NoRelatedVidsDesc" = "Xóa các video liên quan được hiển thị trong lớp phủ bằng cách vuốt lên.";
"NoPromotionCards" = "Ẩn thẻ Quảng cáo trả phí";
"NoPromotionCardsDesc" = "Ẩn thẻ \"Bao gồm quảng cáo trả phí\" trong các video có quảng cáo.";
"NoWatermarks" = "Ẩn watermark của kênh";
"NoWatermarksDesc" = "Ẩn watermark của kênh trong video. Yêu cầu khởi động lại ứng dụng.";
"Player" = "Trình phát";
"Miniplayer" = "Cho phép sử dụng trình phát thu nhỏ với mọi video";
"MiniplayerDesc" = "Cho phép sử dụng trình phát thu nhỏ với mọi video ban đầu không được thiết kế cho trình phát đó, chẳng hạn như các video dành cho trẻ em.";
"PortraitFullscreen" = "Chế độ toàn màn hình dọc";
"PortraitFullscreenDesc" = "Cho phép hỗ trợ chế độ toàn màn hình dọc.";
"CopyWithTimestamp" = "Sao chép các liên kết có dấu thời gian";
"CopyWithTimestampDesc" = "Cho phép sao chép liên kết có dấu thời gian vào bảng tạm bằng cách nhấn nút tạm dừng.";
"DisableAutoplay" = "Tắt video Tự động phát";
"DisableAutoplayDesc" = "Ngăn chặn phát lại video sau khi mở.";
"DisableAutoCaptions" = "Tắt chú thích tự động";
"DisableAutoCaptionsDesc" = "Ngăn chặn việc tự động kích hoạt chú thích.";
"NoContentWarning" = "Bỏ qua cảnh báo nội dung";
"NoContentWarningDesc" = "Bỏ qua thông báo cảnh báo nội dung nhạy cảm.";
"ClassicQuality" = "Chất lượng video cổ điển";
"ClassicQualityDesc" = "Mang lại menu lựa chọn chất lượng video cổ điển.";
"ExtraSpeedOptions" = "Bổ sung tùy chọn tốc độ";
"ExtraSpeedOptionsDesc" = "Thêm nhiều tùy chọn tốc độ phát video vào menu trình phát.";
"DontSnap2Chapter" = "Tắt tự động chuyển tới chương";
"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 đỏ";
"RedProgressBarDesc" = "Mang lại thanh tiến trình màu đỏ.";
"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" = "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.";
"NoFreeZoom" = "Tắt tính năng chạm để thu phóng";
"NoFreeZoomDesc" = "Tắt tính năng chạm để thu phóng";
"AutoFullscreen" = "Phát video ở chế độ toàn màn hình";
"AutoFullscreenDesc" = "Tự động phát video ở chế độ toàn màn hình.";
"ExitFullscreen" = "Thoát chế độ toàn màn hình khi hoàn tất";
"ExitFullscreenDesc" = "Thoát khỏi chế độ toàn màn hình khi kết thúc phát video.";
"NoDoubleTap2Seek" = "Tắt tình năng chạm 2 lần để tua";
"NoDoubleTap2SeekDesc" = "Tắt tình năng chạm 2 lần để tua";
"Tabbar" = "Thanh tab";
"RemoveLabels" = "Xóa nhãn";
"RemoveLabelsDesc" = "Loại bỏ nhãn tab.";
"RemoveIndicators" = "Xóa chỉ báo";
"RemoveIndicatorsDesc" = "Loại bỏ các chỉ báo tab.";
"ReExplore" = "Thay thế tab Shorts bằng tab Khám phá";
"ReExploreDesc" = "Hiển thị tab Khám phá thay vì tab Shorts như trên các phiên bản YouTube cũ.";
"AddExplore" = "Thêm tab Khám phá";
"AddExploreDesc" = "Thêm tab Khám phá vào thanh Tab.";
"HideShortsTab" = "Ẩn tab Shorts";
"HideShortsTabDesc" = "Ẩn tab Shorts khỏi thanh Tab.";
"HideSubscriptionsTab" = "Ẩn tab Đăng ký";
"HideSubscriptionsTabDesc" = "Ẩn tab Đăng ký khỏi thanh Tab.";
"HideUploadButton" = "Ẩn nút Tải lên";
"HideUploadButtonDesc" = "Ẩn nút Tải lên khỏi thanh Tab.";
"HideLibraryTab" = "Ẩn tab Thư viện";
"HideLibraryTabDesc" = "Ẩn tab Thư viện khỏi thanh Tab.";
"Shorts" = "Shorts";
"ShortsOnlyMode" = "Chế độ chỉ dành cho Short";
"ShortsOnlyModeDesc" = "Giới hạn chức năng của YouTube chỉ ở chế độ Short.";
"HideShorts" = "Ẩn Shorts";
"HideShortsDesc" = "Ẩn Shorts khỏi Trang chủ, Được đề xuất, v.v. (Không áp dụng cho Lịch sử xem)";
"ShortsProgress" = "Bật thanh tiến trình";
"ShortsProgressDesc" = "Hiển thị thanh tiến trình trong lớp phủ Shorts.";
"PinchToFullscreenShorts" = "Chụm vào toàn màn hình";
"PinchToFullscreenShortsDesc" = "Quản lý khả năng hiển thị của lớp phủ bằng cử chỉ chụm vào và kéo ra, hiển thị Shorts ở chế độ toàn màn hình.";
"ShortsToRegular" = "Từ Shorts đến video thông thường";
"ShortsToRegularDesc" = "Mở Shorts như video thông thường.";
"ResumeShorts" = "Tắt tính năng tự động tiếp tục Shorts";
"ResumeShortsDesc" = "Nếu bạn thoát YouTube trong khi đang xem video Shorts, video Shorts đó sẽ không tự động phát khi bạn mở lại YouTube.";
"HideShortsLogo" = "Ẩn biểu tượng Shorts";
"HideShortsLogoDesc" = "Ẩn biểu tượng Shorts ở góc trên cùng bên trái.";
"HideShortsSearch" = "Ẩn nút Tìm kiếm";
"HideShortsSearchDesc" = "Ẩn nút Tìm kiếm khỏi lớp phủ Shorts.";
"HideShortsCamera" = "Ẩn nút Máy ảnh";
"HideShortsCameraDesc" = "Ẩn nút Máy ảnh khỏi lớp phủ Shorts.";
"HideShortsMore" = "Ẩn nút Thêm (⋮)";
"HideShortsMoreDesc" = "Ẩn nút Thêm (⋮) khỏi lớp phủ Shorts. Nó cũng có thể truy cập được bằng cách nhấn và giữ màn hình.";
"HideShortsSubscriptions" = "Ẩn nút Đăng ký";
"HideShortsSubscriptionsDesc" = "Ẩn nút Đăng ký xuất hiện khi Shorts bị tạm dừng.";
"HideShortsLike" = "Ẩn nút Thích";
"HideShortsLikeDesc" = "Ẩn nút Thích khỏi lớp phủ Shorts.";
"HideShortsDislike" = "Ẩn nút Không thích";
"HideShortsDislikeDesc" = "Ẩn nút Không thích khỏi lớp phủ Shorts.";
"HideShortsComments" = "Ẩn nút bình luận";
"HideShortsCommentsDesc" = "Ẩn nút bình luận khỏi lớp phủ Shorts.";
"HideShortsRemix" = "Ẩn nút phối lại";
"HideShortsRemixDesc" = "Ẩn nút Phối lại khỏi lớp phủ Shorts.";
"HideShortsShare" = "Ẩn nút Chia sẻ";
"HideShortsShareDesc" = "Ẩn nút Chia sẻ khỏi lớp phủ Shorts.";
"HideShortsAvatars" = "Ẩn hình đại diện kênh";
"HideShortsAvatarsDesc" = "Ẩn hình đại diện kênh ở góc dưới bên phải.";
"HideShortsThanks" = "Ẩn nút Superthanks";
"HideShortsThanksDesc" = "Ẩn nút Superthanks (Quyên góp) khỏi lớp phủ Shorts.";
"HideShortsSource" = "Ẩn nguồn Shorts";
"HideShortsSourceDesc" = "Ẩn nguồn Shorts dưới tên kênh.";
"HideShortsChannelName" = "Ẩn tên kênh";
"HideShortsChannelNameDesc" = "Ẩn tên kênh và nút đăng ký khỏi lớp phủ Shorts.";
"HideShortsDescription" = "Ẩn mô tả";
"HideShortsDescriptionDesc" = "Ẩn phần mô tả Shorts dưới tên kênh.";
"HideShortsAudioTrack" = "Ẩn AudioTrack";
"HideShortsAudioTrackDesc" = "Ẩn AudioTrack trong phần mô tả Shorts.";
"Other" = "Khác";
"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.";
"PostManager" = "Lưu bài đăng";
"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ữ.";
"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ữ.";
"CommentManager" = "Lưu bình luận";
"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";
"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ờ\"";
"RemovePlayNextDesc" = "Xóa tùy chọn \"Phát tiếp theo trong danh sách chờ\" khỏi 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" = "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ủ.";
"NoSearchHistory" = "Ẩn lịch sử tìm kiếm";
"NoSearchHistoryDesc" = "Ẩn lịch sử tìm kiếm và đề xuất một cách trực quan. Lưu ý: Lịch sử tìm kiếm của bạn vẫn có thể truy cập được trong các ứng dụng YouTube khác.";
"NoRelatedWatchNexts" = "Ẩn tất cả video dưới trình phát";
"NoRelatedWatchNextsDesc" = "Ẩn tất cả video bên dưới trình phát, chỉ để lại phần thông tin video và nhận xét.";
"StickSortComments" = "Dán tiêu đề bình luận";
"StickSortCommentsDesc" = "Ghim sắp xếp tiêu đề nhận xét (Hàng đầu, Mới nhất) để nó không biến mất khi cuộn.";
"HideSortComments" = "Ẩn bình luận";
"HideSortCommentsDesc" = "Ẩn bình luận Short, sắp xếp (Hàng đầu, Mới nhất) để nó không bao giờ xuất hiện.";
"PlaylistOldMinibar" = "Danh sách phát mini bar cũ";
"PlaylistOldMinibarDesc" = "Thay thế bảng điều khiển danh sách phát nổi mới bằng bảng điều khiển cũ.";
"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).";
"PlaybackQualityOnWiFi" = "Playback quality on WiFi";
"PlaybackQualityOnCellular" = "Playback quality on Cellular";
"SelectQuality" = "Select Quality";
"Default" = "Default";
"Best" = "Best";
"Startup" = "Trang khởi động";
"Home" = "Trang chủ";
"Explore" = "Khám phá";
"ShortsTab" = "Shorts";
"Subscriptions" = "Đăng ký";
"Library" = "Thư viện";
"Warning" = "Cảnh báo";
"TabIsHidden" = "Không thể chọn Tab ẩn làm trang khởi động";
"SupportDevelopment" = "Support development";
"SupportDevelopmentDesc" = "If you like YTLite and would like to support its development, you can do it using any of convenient ways below.\nThanks❤";
"Version" = "Phiên bản";
"About" = "Giới thiệu";
"Credits" = "Credits";
"Developer" = "Nhà phát triển YTLite";
"ChineseSimplified" = "Tiếng Trung (giản thể)";
"ChineseTraditional" = "Tiếng Trung (phồn thể)";
"French" = "Tiếng Pháp";
"Spanish" = "Tiếng Tây Ban Nha";
"Japanese" = "Tiếng Nhật";
"Vietnamese" = "Tiếng Việt";
"Advanced" = "Chế độ nâng cao";
"AdvancedDesc" = "More customizable mode";
"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";
"ResetSettings" = "Đặt lại cài đặt YTLite";
"ResetMessage" = "Tùy chọn này sẽ đặt lại cài đặt YTLite về mặc định và đóng YouTube.\n\nBạn có chắc chắn muốn tiếp tục không?";
"ShortsOnlyWarning" = "Bạn có chắc chắn muốn kích hoạt chế độ này?\n\nỞ chế độ này, bạn sẽ chỉ có thể xem video Shorts và không thể làm gì khác.\n\nBạn có thể tắt Chế độ chỉ Shorts bằng cách nhấn và giữ bằng hai ngón tay trong trình phát Shorts.";
"ShortsModeTurnedOff" = "Chế độ chỉ dành cho Shorts đã bị tắt";
"Yes" = "Có";
"No" = "Không";
"SelectAction" = "Chọn hành động";
"CopyTitle" = "Sao chép tiêu đề";
"CopyDescription" = "Sao chép mô tả";
"CopyPostText" = "Sao chép văn bản bài đăng";
"SavePostAsImage" = "Lưu bài đăng dưới dạng hình ảnh";
"CopyPostAsImage" = "Sao chép bài đăng dưới dạng hình ảnh";
"CopyCommentText" = "Sao chép văn bản bình luận";
"SaveCommentAsImage" = "Lưu bình luận dưới dạng hình ảnh";
"CopyCommentAsImage" = "Sao chép bình luận dưới dạng hình ảnh";
"SaveProfilePicture" = "Save profile picture";
"CopyProfilePicture" = "Copy profile picture";
"Cancel" = "Hủy bỏ";
"Copied" = "Sao chép vào clipboard";
"Saved" = "Đã lưu vào Ảnh";
"Done" = "Xong";
"Error" = "Lỗi";
@@ -37,8 +37,8 @@
"NoEndScreenCardsDesc" = "隐藏视频结尾处的片尾屏幕(缩略图)。"; "NoEndScreenCardsDesc" = "隐藏视频结尾处的片尾屏幕(缩略图)。";
"NoFullscreenActions" = "禁用全屏操作"; "NoFullscreenActions" = "禁用全屏操作";
"NoFullscreenActionsDesc" = "在全屏模式下禁用操作面板。"; "NoFullscreenActionsDesc" = "在全屏模式下禁用操作面板。";
"PersistentProgressBar" = "Persistent progress bar"; "PersistentProgressBar" = "持续进度条";
"PersistentProgressBarDesc" = "Always shows progress bar in the player."; "PersistentProgressBarDesc" = "始终在播放器中显示进度条。";
"NoRelatedVids" = "没有相关视频"; "NoRelatedVids" = "没有相关视频";
"NoRelatedVidsDesc" = "通过向上滑动删除播放界面中显示的相关视频。"; "NoRelatedVidsDesc" = "通过向上滑动删除播放界面中显示的相关视频。";
"NoPromotionCards" = "隐藏付费"; "NoPromotionCards" = "隐藏付费";
@@ -55,8 +55,8 @@
"CopyWithTimestampDesc" = "允许通过按下暂停按钮将带有时间戳的链接复制到剪贴板。"; "CopyWithTimestampDesc" = "允许通过按下暂停按钮将带有时间戳的链接复制到剪贴板。";
"DisableAutoplay" = "禁用自动播放视频"; "DisableAutoplay" = "禁用自动播放视频";
"DisableAutoplayDesc" = "打开后防止视频自动播放。"; "DisableAutoplayDesc" = "打开后防止视频自动播放。";
"DisableAutoCaptions" = "Disable auto captions"; "DisableAutoCaptions" = "禁用自动字幕";
"DisableAutoCaptionsDesc" = "Prevents automatic activation of captions."; "DisableAutoCaptionsDesc" = "防止自动激活字幕。";
"NoContentWarning" = "跳过内容警告"; "NoContentWarning" = "跳过内容警告";
"NoContentWarningDesc" = "跳过敏感内容警告消息。"; "NoContentWarningDesc" = "跳过敏感内容警告消息。";
"ClassicQuality" = "经典视频质量"; "ClassicQuality" = "经典视频质量";
@@ -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" = "禁用自由缩放手势";
@@ -85,8 +91,8 @@
"RemoveIndicatorsDesc" = "删除选项卡“红点”指示。"; "RemoveIndicatorsDesc" = "删除选项卡“红点”指示。";
"ReExplore" = "“短视频”替换为“探索”"; "ReExplore" = "“短视频”替换为“探索”";
"ReExploreDesc" = "在旧版本 YouTube 中将“短视频”选项卡替换为“探索”。"; "ReExploreDesc" = "在旧版本 YouTube 中将“短视频”选项卡替换为“探索”。";
"AddExplore" = "Add Explore tab"; "AddExplore" = "添加“探索”选项卡";
"AddExploreDesc" = "Adds Explore tab to the Tab bar."; "AddExploreDesc" = "将“探索”选项卡添加到底部选项卡栏。";
"HideShortsTab" = "隐藏短视频"; "HideShortsTab" = "隐藏短视频";
"HideShortsTabDesc" = "从选项卡栏中隐藏短视频。"; "HideShortsTabDesc" = "从选项卡栏中隐藏短视频。";
"HideSubscriptionsTab" = "隐藏订阅内容"; "HideSubscriptionsTab" = "隐藏订阅内容";
@@ -97,16 +103,16 @@
"HideLibraryTabDesc" = "从选项卡栏中隐藏媒体库。"; "HideLibraryTabDesc" = "从选项卡栏中隐藏媒体库。";
"Shorts" = "短视频"; "Shorts" = "短视频";
"ShortsOnlyMode" = "Shorts Only Mode"; "ShortsOnlyMode" = "仅短视频模式";
"ShortsOnlyModeDesc" = "Limits YouTube functionality to viewing Shorts only."; "ShortsOnlyModeDesc" = " YouTube 功能限制为只能观看短视频。";
"HideShorts" = "隐藏短视频"; "HideShorts" = "隐藏短视频";
"HideShortsDesc" = "从首页、推荐等隐藏短视频(不适用于观看历史记录)。"; "HideShortsDesc" = "从首页、推荐等隐藏短视频(不适用于观看历史记录)。";
"ShortsProgress" = "启用进度条"; "ShortsProgress" = "启用进度条";
"ShortsProgressDesc" = "在短视频播放器中显示进度条。"; "ShortsProgressDesc" = "在短视频播放器中显示进度条。";
"PinchToFullscreenShorts" = "Pinch to Fullscreen"; "PinchToFullscreenShorts" = "捏合至全屏";
"PinchToFullscreenShortsDesc" = "Manages visibility of the overlay with pinch in and pinch out gestures, displaying Shorts in fullscreen mode."; "PinchToFullscreenShortsDesc" = "通过捏合和捏合手势管理播放界面,以全屏模式显示短视频。";
"ShortsToRegular" = "Shorts to regular videos"; "ShortsToRegular" = "常规短视频";
"ShortsToRegularDesc" = "Opens Shorts videos as regular videos."; "ShortsToRegularDesc" = "像打开普通视频一样打开短视频。";
"ResumeShorts" = "不要从短视频开始"; "ResumeShorts" = "不要从短视频开始";
"ResumeShortsDesc" = "防止在打开应用程序时首先启动短视频,如果在观看短视频时关闭,就会发生这种情况。"; "ResumeShortsDesc" = "防止在打开应用程序时首先启动短视频,如果在观看短视频时关闭,就会发生这种情况。";
"HideShortsLogo" = "隐藏短视频Logo"; "HideShortsLogo" = "隐藏短视频Logo";
@@ -133,8 +139,8 @@
"HideShortsAvatarsDesc" = "隐藏右下角的发布者个人资料头像。"; "HideShortsAvatarsDesc" = "隐藏右下角的发布者个人资料头像。";
"HideShortsThanks" = "隐藏捐赠按钮"; "HideShortsThanks" = "隐藏捐赠按钮";
"HideShortsThanksDesc" = "从短视频播放器中隐藏捐赠按钮。"; "HideShortsThanksDesc" = "从短视频播放器中隐藏捐赠按钮。";
"HideShortsSource" = "Hide Shorts Source"; "HideShortsSource" = "隐藏短视频来源";
"HideShortsSourceDesc" = "Hides the Shorts sources under the channel name."; "HideShortsSourceDesc" = "在频道名称下隐藏短视频来源。";
"HideShortsChannelName" = "隐藏发布者名称"; "HideShortsChannelName" = "隐藏发布者名称";
"HideShortsChannelNameDesc" = "从短视频播放器中隐藏发布者名称和订阅按钮。"; "HideShortsChannelNameDesc" = "从短视频播放器中隐藏发布者名称和订阅按钮。";
"HideShortsDescription" = "隐藏文案"; "HideShortsDescription" = "隐藏文案";
@@ -143,16 +149,32 @@
"HideShortsAudioTrackDesc" = "隐藏短视频文案下方的音轨。"; "HideShortsAudioTrackDesc" = "隐藏短视频文案下方的音轨。";
"Other" = "其他"; "Other" = "其他";
"CopyPostText" = "Copy community posts text"; "CopyVideoInfo" = "复制视频信息";
"CopyPostTextDesc" = "Copies community posts text to the clipboard by long tap."; "CopyVideoInfoDesc" = "添加按钮从“视频说明”面板中复制视频的标题和描述。";
"SavePostImage" = "Save community posts image"; "PostManager" = "保存帖子信息";
"SavePostImageDesc" = "Saves community posts image to the Photos app by long tap."; "PostManagerDesc" = "允许通过长按复制帖子文本并将帖子另存为图片。";
"SaveProfilePhoto" = "Save profile picture"; "SaveProfilePhoto" = "保存个人资料图片";
"SaveProfilePhotoDesc" = "Saves profile picture to the Photos app by long tap."; "SaveProfilePhotoDesc" = "长按个人资料图片保存到照片应用程序。";
"FixAlbums" = "Fix covers"; "CommentManager" = "保存评论信息";
"FixAlbumsDesc" = "Fixes the display of covers for users from Russia."; "CommentManagerDesc" = "允许通过长按复制评论文本并将评论保存为图片。";
"FixAlbums" = "修复封面";
"FixAlbumsDesc" = "修复来自俄罗斯用户的封面显示问题。";
"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" = "隐藏搜索历史记录";
@@ -168,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" = "探索";
@@ -177,6 +205,8 @@
"Warning" = "警告"; "Warning" = "警告";
"TabIsHidden" = "无法选择隐藏选项卡作为启动页。"; "TabIsHidden" = "无法选择隐藏选项卡作为启动页。";
"SupportDevelopment" = "Support development";
"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" = "关于";
"Credits" = "信息"; "Credits" = "信息";
@@ -186,15 +216,31 @@
"French" = "法语本地化"; "French" = "法语本地化";
"Spanish" = "西班牙语本地化"; "Spanish" = "西班牙语本地化";
"Japanese" = "日语本地化"; "Japanese" = "日语本地化";
"Vietnamese" = "越南语本地化";
"Advanced" = "高级模式"; "Advanced" = "高级模式";
"AdvancedDesc" = "More customizable mode";
"AdvancedModeReminder" = "想为YTLite激活高级模式吗?\n\n此模式提供了50多个额外的选项来自定义和优化您的YouTube体验。\n可以稍后从设置中启用/禁用它 → %@ → %@ → %@。"; "AdvancedModeReminder" = "想为YTLite激活高级模式吗?\n\n此模式提供了50多个额外的选项来自定义和优化您的YouTube体验。\n可以稍后从设置中启用/禁用它 → %@ → %@ → %@。";
"ClearCache" = "清除缓存";
"ResetSettings" = "重置YTLite设置"; "ResetSettings" = "重置YTLite设置";
"ResetMessage" = "此选项会将YTLite设置重置为默认值并关闭YouTube。\n\n确定要继续吗?"; "ResetMessage" = "此选项会将YTLite设置重置为默认值并关闭YouTube。\n\n确定要继续吗?";
"ShortsOnlyWarning" = "Are you sure you want to activate this mode?\n\nIn this mode, you will only be able to watch Shorts videos and won't be able to do anything else.\n\nYou can disable Shorts Only Mode by long pressing with two fingers in the Shorts player."; "ShortsOnlyWarning" = "确定要激活此模式吗?\n\n在此模式下,将只能观看短视频,且无法执行任何其他操作。\n\n可以通过双指长按禁用“仅短视频模式”。";
"ShortsModeTurnedOff" = "Shorts Only Mode has been turned off"; "ShortsModeTurnedOff" = "仅短视频模式已关闭";
"Yes" = "是"; "Yes" = "是";
"No" = "不"; "No" = "不";
"Copied" = "Copied to clipboard"; "SelectAction" = "选择操作";
"Saved" = "Saved to Photos"; "CopyTitle" = "复制标题";
"Error" = "Error"; "CopyDescription" = "复制描述";
"CopyPostText" = "复制帖子文本";
"SavePostAsImage" = "帖子另存为图片";
"CopyPostAsImage" = "帖子作为图片复制";
"CopyCommentText" = "复制评论文本";
"SaveCommentAsImage" = "评论另存为图片";
"CopyCommentAsImage" = "评论作为图片复制";
"SaveProfilePicture" = "Save profile picture";
"CopyProfilePicture" = "Copy profile picture";
"Cancel" = "取消";
"Copied" = "已复制到剪贴板";
"Saved" = "已保存到照片";
"Done" = "完成";
"Error" = "错误";
@@ -37,8 +37,8 @@
"NoEndScreenCardsDesc" = "隱藏當影片結束時的懸停影片(縮圖)"; "NoEndScreenCardsDesc" = "隱藏當影片結束時的懸停影片(縮圖)";
"NoFullscreenActions" = "停用全螢幕操作"; "NoFullscreenActions" = "停用全螢幕操作";
"NoFullscreenActionsDesc" = "在全螢幕模式下停用操作面板"; "NoFullscreenActionsDesc" = "在全螢幕模式下停用操作面板";
"PersistentProgressBar" = "Persistent progress bar"; "PersistentProgressBar" = "固定進度條";
"PersistentProgressBarDesc" = "Always shows progress bar in the player."; "PersistentProgressBarDesc" = "總是在播放器中顯示進度條";
"NoRelatedVids" = "隱藏相關影片"; "NoRelatedVids" = "隱藏相關影片";
"NoRelatedVidsDesc" = "移除全螢幕模式向上滑動時所出現的相關影片"; "NoRelatedVidsDesc" = "移除全螢幕模式向上滑動時所出現的相關影片";
"NoPromotionCards" = "隱藏付費推廣"; "NoPromotionCards" = "隱藏付費推廣";
@@ -55,8 +55,8 @@
"CopyWithTimestampDesc" = "透過按下暫停按鈕,將帶有時間標記的連結複製到剪貼簿"; "CopyWithTimestampDesc" = "透過按下暫停按鈕,將帶有時間標記的連結複製到剪貼簿";
"DisableAutoplay" = "停用自動播放"; "DisableAutoplay" = "停用自動播放";
"DisableAutoplayDesc" = "在打開應用程式後防止自動播放影片"; "DisableAutoplayDesc" = "在打開應用程式後防止自動播放影片";
"DisableAutoCaptions" = "Disable auto captions"; "DisableAutoCaptions" = "停用自動字幕";
"DisableAutoCaptionsDesc" = "Prevents automatic activation of captions."; "DisableAutoCaptionsDesc" = "防止字幕自動啟用";
"NoContentWarning" = "略過內容警告"; "NoContentWarning" = "略過內容警告";
"NoContentWarningDesc" = "略過敏感內容警告訊息"; "NoContentWarningDesc" = "略過敏感內容警告訊息";
"ClassicQuality" = "舊版本影片畫質"; "ClassicQuality" = "舊版本影片畫質";
@@ -65,8 +65,14 @@
"ExtraSpeedOptionsDesc" = "在播放速度選單中添加更多選項"; "ExtraSpeedOptionsDesc" = "在播放速度選單中添加更多選項";
"DontSnap2Chapter" = "停用跳轉到章節"; "DontSnap2Chapter" = "停用跳轉到章節";
"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" = "停用自由縮放手勢";
@@ -85,8 +91,8 @@
"RemoveIndicatorsDesc" = "刪除標籤通知標記"; "RemoveIndicatorsDesc" = "刪除標籤通知標記";
"ReExplore" = "用探索取代Shorts分頁"; "ReExplore" = "用探索取代Shorts分頁";
"ReExploreDesc" = "如同舊版YouTube一樣顯示「探索」而非「Shorts」"; "ReExploreDesc" = "如同舊版YouTube一樣顯示「探索」而非「Shorts」";
"AddExplore" = "Add Explore tab"; "AddExplore" = "新增探索標籤";
"AddExploreDesc" = "Adds Explore tab to the Tab bar."; "AddExploreDesc" = "在下方標籤欄新增探索標籤";
"HideShortsTab" = "隱藏Shorts"; "HideShortsTab" = "隱藏Shorts";
"HideShortsTabDesc" = "從標籤欄中隱藏Shorts標籤"; "HideShortsTabDesc" = "從標籤欄中隱藏Shorts標籤";
"HideSubscriptionsTab" = "隱藏訂閱內容"; "HideSubscriptionsTab" = "隱藏訂閱內容";
@@ -97,16 +103,16 @@
"HideLibraryTabDesc" = "從標籤欄中隱藏媒體庫標籤"; "HideLibraryTabDesc" = "從標籤欄中隱藏媒體庫標籤";
"Shorts" = "Shorts"; "Shorts" = "Shorts";
"ShortsOnlyMode" = "Shorts Only Mode"; "ShortsOnlyMode" = "只看Shorts模式";
"ShortsOnlyModeDesc" = "Limits YouTube functionality to viewing Shorts only."; "ShortsOnlyModeDesc" = "限制YouTube功能只能觀看Shorts影片";
"HideShorts" = "隱藏Shorts影片"; "HideShorts" = "隱藏Shorts影片";
"HideShortsDesc" = "從首頁、推薦...等,隱藏Shorts影片(不適用於觀看紀錄)"; "HideShortsDesc" = "從首頁、推薦...等,隱藏Shorts影片(不適用於觀看紀錄)";
"ShortsProgress" = "啟用時間進度條"; "ShortsProgress" = "啟用時間進度條";
"ShortsProgressDesc" = "在Shorts底部顯示進度條"; "ShortsProgressDesc" = "在Shorts底部顯示進度條";
"PinchToFullscreenShorts" = "Pinch to Fullscreen"; "PinchToFullscreenShorts" = "捏合切換全螢幕";
"PinchToFullscreenShortsDesc" = "Manages visibility of the overlay with pinch in and pinch out gestures, displaying Shorts in fullscreen mode."; "PinchToFullscreenShortsDesc" = "透過兩指縮放手勢,控制覆蓋層的顯示,讓Shorts以全螢幕模式播放";
"ShortsToRegular" = "Shorts to regular videos"; "ShortsToRegular" = "Shorts轉為一般影片";
"ShortsToRegularDesc" = "Opens Shorts videos as regular videos."; "ShortsToRegularDesc" = "將Shorts作為一般影片開啟";
"ResumeShorts" = "不要從Shorts開始"; "ResumeShorts" = "不要從Shorts開始";
"ResumeShortsDesc" = "防止重新開啟應用程式時從Shorts開始播放,如果在觀看Shorts時關閉,就會發生這種情況"; "ResumeShortsDesc" = "防止重新開啟應用程式時從Shorts開始播放,如果在觀看Shorts時關閉,就會發生這種情況";
"HideShortsLogo" = "隱藏Shorts圖示"; "HideShortsLogo" = "隱藏Shorts圖示";
@@ -133,8 +139,8 @@
"HideShortsAvatarsDesc" = "隱藏右下角的頻道圖片"; "HideShortsAvatarsDesc" = "隱藏右下角的頻道圖片";
"HideShortsThanks" = "隱藏超級感謝按鈕"; "HideShortsThanks" = "隱藏超級感謝按鈕";
"HideShortsThanksDesc" = "從Shorts中隱藏超級感謝 (贊助) 按鈕"; "HideShortsThanksDesc" = "從Shorts中隱藏超級感謝 (贊助) 按鈕";
"HideShortsSource" = "Hide Shorts Source"; "HideShortsSource" = "隱藏Shorts來源";
"HideShortsSourceDesc" = "Hides the Shorts sources under the channel name."; "HideShortsSourceDesc" = "在頻道名稱下隱藏Shorts來源";
"HideShortsChannelName" = "隱藏頻道名稱"; "HideShortsChannelName" = "隱藏頻道名稱";
"HideShortsChannelNameDesc" = "從Shorts中隱藏頻道名稱和訂閱按鈕"; "HideShortsChannelNameDesc" = "從Shorts中隱藏頻道名稱和訂閱按鈕";
"HideShortsDescription" = "隱藏描述"; "HideShortsDescription" = "隱藏描述";
@@ -143,20 +149,36 @@
"HideShortsAudioTrackDesc" = "隱藏Shorts描述下的原始音效"; "HideShortsAudioTrackDesc" = "隱藏Shorts描述下的原始音效";
"Other" = "其它"; "Other" = "其它";
"CopyPostText" = "Copy community posts text"; "CopyVideoInfo" = "複製影片資訊";
"CopyPostTextDesc" = "Copies community posts text to the clipboard by long tap."; "CopyVideoInfoDesc" = "新增按鈕將影片標題和說明,複製到影片說明欄";
"SavePostImage" = "Save community posts image"; "PostManager" = "儲存貼文資訊";
"SavePostImageDesc" = "Saves community posts image to the Photos app by long tap."; "PostManagerDesc" = "長按可以複製貼文內容或將貼文儲存為圖片";
"SaveProfilePhoto" = "Save profile picture"; "SaveProfilePhoto" = "儲存個人檔案照片";
"SaveProfilePhotoDesc" = "Saves profile picture to the Photos app by long tap."; "SaveProfilePhotoDesc" = "長按個人檔案照片儲存到照片應用";
"FixAlbums" = "Fix covers"; "CommentManager" = "儲存留言資訊";
"FixAlbumsDesc" = "Fixes the display of covers for users from Russia."; "CommentManagerDesc" = "長按可以複製留言內容或將留言儲存為圖片";
"FixAlbums" = "修復封面";
"FixAlbumsDesc" = "為俄羅斯使用者修復封面顯示問題";
"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" = "隱藏搜尋記錄";
"NoSearchHistoryDesc" = "視覺上隱藏搜尋歷史紀錄和建議。注意:您的搜尋紀錄仍然可在其它 YouTube 客戶端中存取"; "NoSearchHistoryDesc" = "視覺上隱藏搜尋歷史紀錄和建議。注意:您的搜尋紀錄仍然可在其它YouTube客戶端中存取";
"NoRelatedWatchNexts" = "隱藏播放器下的所有影片"; "NoRelatedWatchNexts" = "隱藏播放器下的所有影片";
"NoRelatedWatchNextsDesc" = "只留下影片資訊和留言區域"; "NoRelatedWatchNextsDesc" = "只留下影片資訊和留言區域";
"StickSortComments" = "固定留言排序"; "StickSortComments" = "固定留言排序";
@@ -168,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" = "探索";
@@ -177,6 +205,8 @@
"Warning" = "警告"; "Warning" = "警告";
"TabIsHidden" = "無法將隱藏的標籤選為啟動頁面"; "TabIsHidden" = "無法將隱藏的標籤選為啟動頁面";
"SupportDevelopment" = "Support development";
"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" = "關於";
"Credits" = "貢獻"; "Credits" = "貢獻";
@@ -185,16 +215,32 @@
"ChineseTraditional" = "繁體中文在地化"; "ChineseTraditional" = "繁體中文在地化";
"French" = "法文在地化"; "French" = "法文在地化";
"Spanish" = "西班牙文在地化"; "Spanish" = "西班牙文在地化";
"Japanese" = "日本語地化"; "Japanese" = "日本語地化";
"Vietnamese" = "越南語在地化";
"Advanced" = "進階模式"; "Advanced" = "進階模式";
"AdvancedDesc" = "More customizable mode";
"AdvancedModeReminder" = "您是否想啟用YTLite的進階模式?\n\n這個模式提供了50多個額外的選項,可以自訂義和優化您的YouTube使用體驗。您稍後可以在「設定」中 → %@ → %@ → %@ 啟用或停用它。"; "AdvancedModeReminder" = "您是否想啟用YTLite的進階模式?\n\n這個模式提供了50多個額外的選項,可以自訂義和優化您的YouTube使用體驗。您稍後可以在「設定」中 → %@ → %@ → %@ 啟用或停用它。";
"ClearCache" = "清除快取";
"ResetSettings" = "重置YTLite設定"; "ResetSettings" = "重置YTLite設定";
"ResetMessage" = "這個選項會將YTLite重置為預設值,並關閉Youtube\n\n您確定要繼續嗎?"; "ResetMessage" = "這個選項會將YTLite重置為預設值,並關閉Youtube\n\n您確定要繼續嗎?";
"ShortsOnlyWarning" = "Are you sure you want to activate this mode?\n\nIn this mode, you will only be able to watch Shorts videos and won't be able to do anything else.\n\nYou can disable Shorts Only Mode by long pressing with two fingers in the Shorts player."; "ShortsOnlyWarning" = "您確定要開啟此模式嗎?\n\n在此模式下,您只能觀看Shorts影片,無法進行其它操作。\n\n您可以在Shorts播放器中使用兩指長按來停用只看Shorts模式。";
"ShortsModeTurnedOff" = "Shorts Only Mode has been turned off"; "ShortsModeTurnedOff" = "已關閉「只看Shorts模式」";
"Yes" = "是"; "Yes" = "是";
"No" = "否"; "No" = "否";
"Copied" = "Copied to clipboard"; "SelectAction" = "選擇動作";
"Saved" = "Saved to Photos"; "CopyTitle" = "複製標題";
"Error" = "Error"; "CopyDescription" = "複製說明";
"CopyPostText" = "複製貼文內容";
"SavePostAsImage" = "儲存貼文為圖片";
"CopyPostAsImage" = "複製貼文為圖片";
"CopyCommentText" = "複製留言內容";
"SaveCommentAsImage" = "留言儲存為圖片";
"CopyCommentAsImage" = "複製留言為圖片";
"SaveProfilePicture" = "Save profile picture";
"CopyProfilePicture" = "Copy profile picture";
"Cancel" = "取消";
"Copied" = "已複製到剪貼簿";
"Saved" = "已儲存到照片應用";
"Done" = "Done";
"Error" = "發生錯誤";
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.