This commit is contained in:
dayanch96
2024-02-28 15:02:46 +03:00
parent b6958ac963
commit 5bf8181815
20 changed files with 1593 additions and 430 deletions
+319 -143
View File
@@ -1,5 +1,9 @@
#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/)
// Background Playback
%hook YTIPlayabilityStatus
@@ -284,44 +288,22 @@
}
%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
- (void *)init {
void *ret = (void *)%orig;
if (kExtraSpeedOptions) {
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];
- (void)setDelegate:(id)arg1 {
NSMutableArray *optionsCopy = [[self valueForKey:@"_options"] mutableCopy];
NSArray *speedOptions = @[@"2.5", @"3", @"3.5", @"4", @"5"];
for (NSString *title in speedOptions) {
float rate = [title floatValue];
[speedOptionsCopy addObject:[[objc_lookUpClass("YTVarispeedSwitchControllerOption") alloc] initWithTitle:title rate:rate]];
}
Ivar optionsIvar = class_getInstanceVariable(object_getClass(self), "_options");
object_setIvar(self, optionsIvar, [speedOptionsCopy copy]);
} return ret;
}
%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);
for (NSString *title in speedOptions) {
float rate = [title floatValue];
YTVarispeedSwitchControllerOption *option = [[%c(YTVarispeedSwitchControllerOption) alloc] initWithTitle:title rate:rate];
[optionsCopy addObject:option];
}
if (kExtraSpeedOptions) [self setValue:[optionsCopy copy] forKey:@"_options"];
return %orig;
}
%end
@@ -377,6 +359,7 @@
- (void)loadWithPlayerTransition:(id)arg1 playbackConfig:(id)arg2 {
%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 (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];
@@ -402,6 +385,76 @@
- (void)turnOffCaptions {
[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
// Exit Fullscreen on Finish
@@ -468,6 +521,79 @@
}
%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)
%hook YTAsyncCollectionView
- (id)cellForItemAtIndexPath:(NSIndexPath *)indexPath {
@@ -538,6 +664,7 @@
- (void)setRemixButton:(id)arg1 { if (!kHideShortsRemix) %orig; }
- (void)setShareButton:(id)arg1 { if (!kHideShortsShare) %orig; }
- (void)setNativePivotButton:(id)arg1 { if (!kHideShortsAvatars) %orig; }
- (void)setPivotButtonElementRenderer:(id)arg1 { if (!kHideShortsAvatars) %orig; }
%end
%hook YTReelHeaderView
@@ -637,8 +764,61 @@ static BOOL isOverlayShown = YES;
}
%end
static void downloadImageFromURL(UIResponder *responder, NSURL *URL, BOOL download) {
NSString *URLString = URL.absoluteString;
if (kFixAlbums && [URLString hasPrefix:@"https://yt3."]) {
URLString = [URLString stringByReplacingOccurrencesOfString:@"https://yt3." withString:@"https://yt4."];
}
NSURL *downloadURL = nil;
if ([URLString containsString:@"c-fcrop"]) {
NSRange croppedURL = [URLString rangeOfString:@"c-fcrop"];
if (croppedURL.location != NSNotFound) {
NSString *newURL = [URLString stringByReplacingOccurrencesOfString:[URLString substringFromIndex:croppedURL.location] withString:@"nd-v1"];
downloadURL = [NSURL URLWithString:newURL];
}
} else {
downloadURL = URL;
}
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:downloadURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data) {
if (download) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
[request addResourceWithType:PHAssetResourceTypePhoto data:data options:nil];
} completionHandler:^(BOOL success, NSError *error) {
[[%c(YTToastResponderEvent) eventWithMessage:success ? LOC(@"Saved") : [NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription] firstResponder:responder] send];
}];
} else {
[UIPasteboard generalPasteboard].image = [UIImage imageWithData:data];
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:responder] send];
}
} else {
[[%c(YTToastResponderEvent) eventWithMessage:[NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription] firstResponder:responder] send];
}
}] resume];
}
static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^completionHandler)(UIImage *)) {
UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
CGContextFillRect(context, CGRectMake(0, 0, layer.frame.size.width, layer.frame.size.height));
[layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (completionHandler) {
completionHandler(image);
}
}
%hook ELMContainerNode
%property (nonatomic, strong) NSString *copiedComment;
%property (nonatomic, strong) NSURL *copiedURL;
%end
%hook ASDisplayNode
@@ -674,52 +854,26 @@ static BOOL isOverlayShown = YES;
}
%end
static void downloadImageFromURL(UIResponder *responder, NSURL *URL) {
NSString *URLString = URL.absoluteString;
%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;
if (kFixAlbums && [URLString hasPrefix:@"https://yt3."]) {
URLString = [URLString stringByReplacingOccurrencesOfString:@"https://yt3." withString:@"https://yt4."];
}
NSURL *downloadURL = nil;
if ([URLString containsString:@"c-fcrop"]) {
NSRange croppedURL = [URLString rangeOfString:@"c-fcrop"];
if (croppedURL.location != NSNotFound) {
NSString *newURL = [URLString stringByReplacingOccurrencesOfString:[URLString substringFromIndex:croppedURL.location] withString:@"nd-v1"];
downloadURL = [NSURL URLWithString:newURL];
NSMutableArray *allObjects = displayNode.supernodes.allObjects;
for (ELMContainerNode *containerNode in allObjects) {
if ([containerNode.description containsString:@"id.ui.backstage.original_post"]) {
containerNode.copiedURL = URL;
break;
}
}
} else {
downloadURL = URL;
}
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:downloadURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
[request addResourceWithType:PHAssetResourceTypePhoto data:data options:nil];
} completionHandler:^(BOOL success, NSError *error) {
[[%c(YTToastResponderEvent) eventWithMessage:success ? LOC(@"Saved") : [NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription] firstResponder:responder] send];
}];
} else {
[[%c(YTToastResponderEvent) eventWithMessage:[NSString stringWithFormat:LOC(@"%@: %@"), LOC(@"Error"), error.localizedDescription] firstResponder:responder] send];
}
}] resume];
}
static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^completionHandler)(UIImage *)) {
UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
CGContextFillRect(context, CGRectMake(0, 0, layer.frame.size.width, layer.frame.size.height));
[layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (completionHandler) {
completionHandler(image);
}
return %orig;
}
%end
%hook _ASDisplayView
- (void)setKeepalive_node:(id)arg1 {
@@ -727,7 +881,6 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
NSArray *gesturesInfo = @[
@{@"selector": @"postManager:", @"text": @"id.ui.backstage.original_post", @"key": @(kPostManager)},
@{@"selector": @"saveImage:", @"text": @"YTImageZoomNode-View", @"key": @(kSavePostImage)},
@{@"selector": @"savePFP:", @"text": @"ELMImageNode-View", @"key": @(kSaveProfilePhoto)},
@{@"selector": @"commentManager:", @"text": @"id.ui.comment_cell", @"key": @(kCommentManager)}
];
@@ -760,11 +913,20 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:PFPURL]];
if (image) {
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
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);
UIResponder *responder = self.nextResponder;
while (responder && ![responder isKindOfClass:[UIViewController class]]) responder = responder.nextResponder;
if (responder) [[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Saved") firstResponder:responder] send];
[[%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];
}
}
}
@@ -778,20 +940,30 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
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;
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:LOC(@"SelectAction") message:nil preferredStyle:UIAlertControllerStyleActionSheet];
alertController.view.tintColor = [UIColor labelColor];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyPostText") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
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];
}
}]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"SavePostAsImage") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (URL) {
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"SaveCurrentImage") iconImage:YTImageNamed(@"yt_outline_image_24pt") style:0 handler:^ {
downloadImageFromURL(containerNode.closestViewController, URL, YES);
}]];
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyCurrentImage") iconImage:YTImageNamed(@"yt_outline_library_image_24pt") style:0 handler:^ {
downloadImageFromURL(containerNode.closestViewController, URL, NO);
}]];
}
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"SavePostAsImage") titleColor:[[UIColor redColor] colorWithAlphaComponent:0.7f] iconImage:YTImageNamed(@"yt_outline_image_24pt") iconColor:[[UIColor redColor] colorWithAlphaComponent:0.7f] disableAutomaticButtonColor:YES accessibilityIdentifier:nil handler:^ {
genImageFromLayer(layer, backgroundColor, ^(UIImage *image) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
@@ -803,30 +975,14 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
});
}]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyPostAsImage") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyPostAsImage") titleColor:[[UIColor redColor] colorWithAlphaComponent:0.7f] iconImage:YTImageNamed(@"yt_outline_library_image_24pt") iconColor:[[UIColor redColor] colorWithAlphaComponent:0.7f] disableAutomaticButtonColor:YES accessibilityIdentifier:nil handler:^ {
genImageFromLayer(layer, backgroundColor, ^(UIImage *image) {
[UIPasteboard generalPasteboard].image = image;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send];
});
}]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"Cancel") style:UIAlertActionStyleCancel handler:nil]];
[containerNode.closestViewController presentViewController:alertController animated:YES completion:nil];
}
}
%new
- (void)saveImage:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
ASNetworkImageNode *imageNode = (ASNetworkImageNode *)self.keepalive_node;
NSURL *imageURL = imageNode.URL;
UIResponder *responder = self.nextResponder;
while (responder && ![responder isKindOfClass:[UIViewController class]]) responder = responder.nextResponder;
if (imageURL) downloadImageFromURL(responder, imageURL);
[sheetController presentFromViewController:containerNode.closestViewController animated:YES completion:nil];
}
}
@@ -839,17 +995,16 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
CALayer *layer = self.layer;
UIColor *backgroundColor = containerNode.closestViewController.view.backgroundColor;
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:LOC(@"SelectAction") message:nil preferredStyle:UIAlertControllerStyleActionSheet];
alertController.view.tintColor = [UIColor labelColor];
YTDefaultSheetController *sheetController = [%c(YTDefaultSheetController) sheetControllerWithParentResponder:nil];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyCommentText") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyCommentText") iconImage:YTImageNamed(@"yt_outline_message_bubble_right_24pt") style:0 handler:^ {
if (comment) {
[UIPasteboard generalPasteboard].string = comment;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send];
}
}]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"SaveCommentAsImage") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"SaveCommentAsImage") iconImage:YTImageNamed(@"yt_outline_image_24pt") style:0 handler:^ {
genImageFromLayer(layer, backgroundColor, ^(UIImage *image) {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
@@ -861,16 +1016,14 @@ static void genImageFromLayer(CALayer *layer, UIColor *backgroundColor, void (^c
});
}]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyCommentAsImage") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyCommentAsImage") iconImage:YTImageNamed(@"yt_outline_library_image_24pt") style:0 handler:^ {
genImageFromLayer(layer, backgroundColor, ^(UIImage *image) {
[UIPasteboard generalPasteboard].image = image;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:containerNode.closestViewController] send];
});
}]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"Cancel") style:UIAlertActionStyleCancel handler:nil]];
[containerNode.closestViewController presentViewController:alertController animated:YES completion:nil];
[sheetController presentFromViewController:containerNode.closestViewController animated:YES completion:nil];
}
}
%end
@@ -942,26 +1095,12 @@ BOOL isTabSelected = NO;
%orig;
if (!isTabSelected && !kShortsOnlyMode) {
NSString *pivotIdentifier;
switch (kPivotIndex) {
case 0:
pivotIdentifier = @"FEwhat_to_watch";
break;
case 1:
pivotIdentifier = @"FEexplore";
break;
case 2:
pivotIdentifier = @"FEshorts";
break;
case 3:
pivotIdentifier = @"FEsubscriptions";
break;
case 4:
pivotIdentifier = @"FElibrary";
break;
default:
return;
}
NSString *pivotIdentifier = kPivotIndex == 1 ? @"FEexplore" :
kPivotIndex == 2 ? @"FEshorts" :
kPivotIndex == 3 ? @"FEsubscriptions" :
kPivotIndex == 4 ? @"FElibrary" :
@"FEwhat_to_watch";
[self selectItemWithPivotIdentifier:pivotIdentifier];
isTabSelected = YES;
}
@@ -1008,7 +1147,7 @@ BOOL isTabSelected = NO;
copyInfoButton.accessibilityLabel = LOC(@"CopyVideoInfo");
[copyInfoButton setTag:999];
[copyInfoButton enableNewTouchFeedback];
[copyInfoButton setImage:[UIImage imageNamed:@"yt_outline_copy_24pt" inBundle:[NSBundle mainBundle] compatibleWithTraitCollection:nil] forState:UIControlStateNormal];
[copyInfoButton setImage:YTImageNamed(@"yt_outline_copy_24pt") forState:UIControlStateNormal];
[copyInfoButton setTintColor:[UIColor labelColor]];
[copyInfoButton setTranslatesAutoresizingMaskIntoConstraints:false];
[copyInfoButton addTarget:self action:@selector(didTapCopyInfoButton:) forControlEvents:UIControlEventTouchUpInside];
@@ -1032,22 +1171,19 @@ BOOL isTabSelected = NO;
NSString *title = playerVC.playerResponse.playerData.videoDetails.title;
NSString *shortDescription = playerVC.playerResponse.playerData.videoDetails.shortDescription;
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:LOC(@"SelectAction") message:nil preferredStyle:UIAlertControllerStyleActionSheet];
alertController.view.tintColor = [UIColor labelColor];
YTDefaultSheetController *sheetController = [%c(YTDefaultSheetController) sheetControllerWithParentResponder:nil];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyTitle") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyTitle") iconImage:YTImageNamed(@"yt_outline_text_box_24pt") style:0 handler:^ {
[UIPasteboard generalPasteboard].string = title;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:self.resizeDelegate] send];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"CopyDescription") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[sheetController addAction:[%c(YTActionSheetAction) actionWithTitle:LOC(@"CopyDescription") iconImage:YTImageNamed(@"yt_outline_message_bubble_right_24pt") style:0 handler:^ {
[UIPasteboard generalPasteboard].string = shortDescription;
[[%c(YTToastResponderEvent) eventWithMessage:LOC(@"Copied") firstResponder:self.resizeDelegate] send];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:LOC(@"Cancel") style:UIAlertActionStyleCancel handler:nil]];
[self.resizeDelegate presentViewController:alertController animated:YES completion:nil];
[sheetController presentFromViewController:self.resizeDelegate animated:YES completion:nil];
}
%end
@@ -1121,6 +1257,9 @@ static void reloadPrefs() {
kExtraSpeedOptions = [prefs[@"extraSpeedOptions"] boolValue] ?: NO;
kDontSnapToChapter = [prefs[@"dontSnapToChapter"] 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;
kNoFreeZoom = [prefs[@"noFreeZoom"] boolValue] ?: NO;
kAutoFullscreen = [prefs[@"autoFullscreen"] boolValue] ?: NO;
@@ -1159,11 +1298,17 @@ static void reloadPrefs() {
kRemoveLibrary = [prefs[@"removeLibrary"] boolValue] ?: NO;
kCopyVideoInfo = [prefs[@"copyVideoInfo"] boolValue] ?: NO;
kPostManager = [prefs[@"postManager"] boolValue] ?: NO;
kSavePostImage = [prefs[@"savePostImage"] boolValue] ?: NO;
kSaveProfilePhoto = [prefs[@"savePostImage"] boolValue] ?: NO;
kSaveProfilePhoto = [prefs[@"saveProfilePhoto"] boolValue] ?: NO;
kCommentManager = [prefs[@"commentManager"] boolValue] ?: NO;
kFixAlbums = [prefs[@"fixAlbums"] 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;
kNoSearchHistory = [prefs[@"noSearchHistory"] boolValue] ?: NO;
kNoRelatedWatchNexts = [prefs[@"noRelatedWatchNexts"] boolValue] ?: NO;
@@ -1171,6 +1316,8 @@ static void reloadPrefs() {
kHideSortComments = [prefs[@"hideSortComments"] boolValue] ?: NO;
kPlaylistOldMinibar = [prefs[@"playlistOldMinibar"] 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;
kAdvancedMode = [prefs[@"advancedMode"] boolValue] ?: NO;
kAdvancedModeReminder = [prefs[@"advancedModeReminder"] boolValue] ?: NO;
@@ -1207,6 +1354,9 @@ static void reloadPrefs() {
@"extraSpeedOptions" : @(kExtraSpeedOptions),
@"dontSnapToChapter" : @(kDontSnapToChapter),
@"redProgressBar" : @(kRedProgressBar),
@"noPlayerRemixButton" : @(kNoPlayerRemixButton),
@"noPlayerClipButton" : @(kNoPlayerClipButton),
@"noPlayerDownloadButton" : @(kNoPlayerDownloadButton),
@"noHints" : @(kNoHints),
@"noFreeZoom" : @(kNoFreeZoom),
@"autoFullscreen" : @(kAutoFullscreen),
@@ -1245,11 +1395,17 @@ static void reloadPrefs() {
@"removeLibrary" : @(kRemoveLibrary),
@"copyVideoInfo" : @(kCopyVideoInfo),
@"postManager" : @(kPostManager),
@"savePostImage" : @(kSavePostImage),
@"saveProfilePhoto" : @(kSaveProfilePhoto),
@"commentManager" : @(kCommentManager),
@"fixAlbums" : @(kFixAlbums),
@"removePlayNext" : @(kRemovePlayNext),
@"removeDownloadMenu" : @(kRemoveDownloadMenu),
@"removeWatchLaterMenu" : @(kRemoveWatchLaterMenu),
@"removeSaveToPlaylistMenu" : @(kRemoveSaveToPlaylistMenu),
@"removeShareMenu" : @(kRemoveShareMenu),
@"removeNotInterestedMenu" : @(kRemoveNotInterestedMenu),
@"removeDontRecommendMenu" : @(kRemoveDontRecommendMenu),
@"removeReportMenu" : @(kRemoveReportMenu),
@"noContinueWatching" : @(kNoContinueWatching),
@"noSearchHistory" : @(kNoSearchHistory),
@"noRelatedWatchNexts" : @(kNoRelatedWatchNexts),
@@ -1257,6 +1413,8 @@ static void reloadPrefs() {
@"hideSortComments" : @(kHideSortComments),
@"playlistOldMinibar" : @(kPlaylistOldMinibar),
@"disableRTL" : @(kDisableRTL),
@"wifiQualityIndex" : @(kWiFiQualityIndex),
@"cellQualityIndex" : @(kCellQualityIndex),
@"pivotIndex" : @(kPivotIndex),
@"advancedMode" : @(kAdvancedMode),
@"advancedModeReminder" : @(kAdvancedModeReminder)
@@ -1279,6 +1437,24 @@ static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStrin
[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);
reloadPrefs();
}