modded scinsta with additional features and fixes for recent instagram version

This commit is contained in:
faroukbmiled
2026-03-28 23:57:15 +01:00
commit 3d133ac333
105 changed files with 11916 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "../../modules/JGProgressHUD/JGProgressHUD.h"
#import "../InstagramHeaders.h"
#import "../Utils.h"
#import "Manager.h"
@interface SCIDownloadPillView : UIView
@property (nonatomic, strong) UIProgressView *progressRing;
@property (nonatomic, strong) UILabel *textLabel;
@property (nonatomic, strong) UILabel *subtitleLabel;
@property (nonatomic, strong) UIButton *cancelButton;
@property (nonatomic, copy) void (^onCancel)(void);
- (void)showInView:(UIView *)view;
- (void)dismiss;
- (void)dismissAfterDelay:(NSTimeInterval)delay;
- (void)setProgress:(float)progress;
- (void)setText:(NSString *)text;
@end
@interface SCIDownloadDelegate : NSObject <SCIDownloadDelegateProtocol>
typedef NS_ENUM(NSUInteger, DownloadAction) {
share,
quickLook,
saveToPhotos
};
@property (nonatomic, readonly) DownloadAction action;
@property (nonatomic, readonly) BOOL showProgress;
@property (nonatomic, strong) SCIDownloadManager *downloadManager;
@property (nonatomic, strong) SCIDownloadPillView *pill;
- (instancetype)initWithAction:(DownloadAction)action showProgress:(BOOL)showProgress;
- (void)downloadFileWithURL:(NSURL *)url fileExtension:(NSString *)fileExtension hudLabel:(NSString *)hudLabel;
@end
+261
View File
@@ -0,0 +1,261 @@
#import "Download.h"
#import <Photos/Photos.h>
#pragma mark - SCIDownloadPillView
@implementation SCIDownloadPillView
- (instancetype)init {
self = [super initWithFrame:CGRectZero];
if (self) {
self.backgroundColor = [UIColor colorWithWhite:0.1 alpha:0.92];
self.layer.cornerRadius = 20;
self.clipsToBounds = YES;
self.alpha = 0;
// Circular progress (using a small CAShapeLayer ring)
_progressRing = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
_progressRing.progressTintColor = [UIColor systemBlueColor];
_progressRing.trackTintColor = [UIColor colorWithWhite:0.3 alpha:1.0];
_progressRing.translatesAutoresizingMaskIntoConstraints = NO;
_progressRing.layer.cornerRadius = 2;
_progressRing.clipsToBounds = YES;
[self addSubview:_progressRing];
// Text
_textLabel = [[UILabel alloc] init];
_textLabel.text = @"Downloading 0%";
_textLabel.textColor = [UIColor whiteColor];
_textLabel.font = [UIFont systemFontOfSize:13 weight:UIFontWeightSemibold];
_textLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_textLabel];
// Subtitle
_subtitleLabel = [[UILabel alloc] init];
_subtitleLabel.text = @"Tap to cancel";
_subtitleLabel.textColor = [UIColor colorWithWhite:0.6 alpha:1.0];
_subtitleLabel.font = [UIFont systemFontOfSize:10 weight:UIFontWeightRegular];
_subtitleLabel.textAlignment = NSTextAlignmentCenter;
_subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_subtitleLabel];
// Tap gesture for cancel
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap)];
[self addGestureRecognizer:tap];
// Layout: [progress bar]
// [text centered]
// [subtitle centered]
[NSLayoutConstraint activateConstraints:@[
[_progressRing.topAnchor constraintEqualToAnchor:self.topAnchor constant:12],
[_progressRing.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:16],
[_progressRing.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-16],
[_progressRing.heightAnchor constraintEqualToConstant:4],
[_textLabel.topAnchor constraintEqualToAnchor:_progressRing.bottomAnchor constant:6],
[_textLabel.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
[_subtitleLabel.topAnchor constraintEqualToAnchor:_textLabel.bottomAnchor constant:2],
[_subtitleLabel.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
[_subtitleLabel.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-10],
]];
}
return self;
}
- (void)handleTap {
if (self.onCancel) self.onCancel();
}
- (void)showInView:(UIView *)view {
[self removeFromSuperview];
self.translatesAutoresizingMaskIntoConstraints = NO;
[view addSubview:self];
[NSLayoutConstraint activateConstraints:@[
[self.topAnchor constraintEqualToAnchor:view.safeAreaLayoutGuide.topAnchor constant:4],
[self.centerXAnchor constraintEqualToAnchor:view.centerXAnchor],
[self.widthAnchor constraintGreaterThanOrEqualToConstant:160],
[self.widthAnchor constraintLessThanOrEqualToConstant:220],
]];
[UIView animateWithDuration:0.25 animations:^{
self.alpha = 1;
}];
}
- (void)dismiss {
[UIView animateWithDuration:0.2 animations:^{
self.alpha = 0;
} completion:^(BOOL finished) {
[self removeFromSuperview];
}];
}
- (void)dismissAfterDelay:(NSTimeInterval)delay {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self dismiss];
});
}
- (void)setProgress:(float)progress {
[self.progressRing setProgress:progress animated:YES];
}
- (void)setText:(NSString *)text {
self.textLabel.text = text;
}
@end
#pragma mark - SCIDownloadDelegate
@implementation SCIDownloadDelegate
- (instancetype)initWithAction:(DownloadAction)action showProgress:(BOOL)showProgress {
self = [super init];
if (self) {
_action = action;
_showProgress = showProgress;
self.downloadManager = [[SCIDownloadManager alloc] initWithDelegate:self];
}
return self;
}
- (void)downloadFileWithURL:(NSURL *)url fileExtension:(NSString *)fileExtension hudLabel:(NSString *)hudLabel {
// Dismiss any existing pill
[self.pill dismiss];
self.pill = [[SCIDownloadPillView alloc] init];
if (hudLabel) {
[self.pill setText:hudLabel];
}
if (!self.showProgress) {
self.pill.progressRing.hidden = YES;
self.pill.subtitleLabel.text = nil;
}
__weak typeof(self) weakSelf = self;
self.pill.onCancel = ^{
[weakSelf.downloadManager cancelDownload];
};
UIViewController *topVC = topMostController();
UIView *hostView = topVC.view;
if (!hostView) hostView = [UIApplication sharedApplication].keyWindow;
if (!hostView) {
NSLog(@"[SCInsta] Download: No valid view");
return;
}
[self.pill showInView:hostView];
NSLog(@"[SCInsta] Download: Will start download for url \"%@\" with file extension: \".%@\"", url, fileExtension);
[self.downloadManager downloadFileWithURL:url fileExtension:fileExtension];
}
- (void)downloadDidStart {
NSLog(@"[SCInsta] Download: Download started");
}
- (void)downloadDidCancel {
dispatch_async(dispatch_get_main_queue(), ^{
[self.pill setText:@"Cancelled"];
self.pill.subtitleLabel.text = nil;
self.pill.progressRing.hidden = YES;
[self.pill dismissAfterDelay:0.8];
});
NSLog(@"[SCInsta] Download: Download cancelled");
}
- (void)downloadDidProgress:(float)progress {
if (self.showProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.pill setProgress:progress];
[self.pill setText:[NSString stringWithFormat:@"Downloading %d%%", (int)(progress * 100)]];
});
}
}
- (void)downloadDidFinishWithError:(NSError *)error {
dispatch_async(dispatch_get_main_queue(), ^{
if (error && error.code != NSURLErrorCancelled) {
NSLog(@"[SCInsta] Download: Download failed with error: \"%@\"", error);
[self.pill setText:@"Download failed"];
self.pill.subtitleLabel.text = nil;
self.pill.progressRing.hidden = YES;
[self.pill dismissAfterDelay:2.0];
}
});
}
- (void)downloadDidFinishWithFileURL:(NSURL *)fileURL {
dispatch_async(dispatch_get_main_queue(), ^{
[self.pill dismiss];
NSLog(@"[SCInsta] Download: Finished with url: \"%@\"", [fileURL absoluteString]);
switch (self.action) {
case share:
[SCIUtils showShareVC:fileURL];
break;
case quickLook:
[SCIUtils showQuickLookVC:@[fileURL]];
break;
case saveToPhotos: {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status != PHAuthorizationStatusAuthorized) {
dispatch_async(dispatch_get_main_queue(), ^{
[SCIUtils showErrorHUDWithDescription:@"Photo library access denied"];
});
return;
}
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
NSString *ext = [[fileURL pathExtension] lowercaseString];
BOOL isVideo = [@[@"mp4", @"mov", @"m4v"] containsObject:ext];
if (isVideo) {
PHAssetCreationRequest *req = [PHAssetCreationRequest creationRequestForAsset];
PHAssetResourceCreationOptions *opts = [[PHAssetResourceCreationOptions alloc] init];
opts.shouldMoveFile = YES;
[req addResourceWithType:PHAssetResourceTypeVideo fileURL:fileURL options:opts];
req.creationDate = [NSDate date];
} else {
PHAssetCreationRequest *req = [PHAssetCreationRequest creationRequestForAsset];
PHAssetResourceCreationOptions *opts = [[PHAssetResourceCreationOptions alloc] init];
opts.shouldMoveFile = YES;
[req addResourceWithType:PHAssetResourceTypePhoto fileURL:fileURL options:opts];
req.creationDate = [NSDate date];
}
} completionHandler:^(BOOL success, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (success) {
SCIDownloadPillView *donePill = [[SCIDownloadPillView alloc] init];
donePill.progressRing.hidden = YES;
donePill.subtitleLabel.text = nil;
[donePill setText:@"Saved to Photos"];
UIView *hostView = topMostController().view;
if (hostView) {
[donePill showInView:hostView];
[donePill dismissAfterDelay:1.5];
}
} else {
[SCIUtils showErrorHUDWithDescription:@"Failed to save to Photos"];
}
});
}];
}];
break;
}
}
});
}
@end
+32
View File
@@ -0,0 +1,32 @@
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
@protocol SCIDownloadDelegateProtocol <NSObject>
// Methods
- (void)downloadDidStart;
- (void)downloadDidCancel;
- (void)downloadDidProgress:(float)progress;
- (void)downloadDidFinishWithError:(NSError *)error;
- (void)downloadDidFinishWithFileURL:(NSURL *)fileURL;
@end
@interface SCIDownloadManager : NSObject <NSURLSessionDownloadDelegate>
// Properties
@property (nonatomic, weak) id<SCIDownloadDelegateProtocol> delegate;
@property (nonatomic, strong) NSURLSession *session;
@property (nonatomic, strong) NSURLSessionDownloadTask *task;
@property (nonatomic, strong) NSString *fileExtension;
// Methods
- (instancetype)initWithDelegate:(id<SCIDownloadDelegateProtocol>)downloadDelegate;
- (void)downloadFileWithURL:(NSURL *)url fileExtension:(NSString *)fileExtension;
- (void)cancelDownload;
- (NSURL *)moveFileToCacheDir:(NSURL *)oldPath;
@end
+75
View File
@@ -0,0 +1,75 @@
#import "Manager.h"
@implementation SCIDownloadManager
- (instancetype)initWithDelegate:(id<SCIDownloadDelegateProtocol>)downloadDelegate {
self = [super init];
if (self) {
self.delegate = downloadDelegate;
}
return self;
}
- (void)downloadFileWithURL:(NSURL *)url fileExtension:(NSString *)fileExtension {
// Properties
self.session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
self.task = [self.session downloadTaskWithURL:url];
// Default to jpg if no other reasonable length extension is provided
self.fileExtension = [fileExtension length] >= 3 ? fileExtension : @"jpg";
[self.task resume];
[self.delegate downloadDidStart];
}
- (void)cancelDownload {
[self.task cancel];
[self.delegate downloadDidCancel];
}
// URLSession methods
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
NSLog(@"Task wrote %lld bytes of %lld bytes", bytesWritten, totalBytesExpectedToWrite);
float progress = (float)totalBytesWritten / (float)totalBytesExpectedToWrite;
[self.delegate downloadDidProgress:progress];
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
// Move downloaded file to cache directory
NSURL *finalLocation = [self moveFileToCacheDir:location];
[self.delegate downloadDidFinishWithFileURL:finalLocation];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
NSLog(@"Task completed with error: %@", error);
[self.delegate downloadDidFinishWithError:error];
}
// Rename downloaded file & move from documents dir -> cache dir
- (NSURL *)moveFileToCacheDir:(NSURL *)oldPath {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *cacheDirectoryPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
NSURL *newPath = [[NSURL fileURLWithPath:cacheDirectoryPath] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", NSUUID.UUID.UUIDString, self.fileExtension]];
NSLog(@"[SCInsta] Download Handler: Moving file from: %@ to: %@", oldPath.absoluteString, newPath.absoluteString);
// Move file to cache directory
NSError *fileMoveError;
[fileManager moveItemAtURL:oldPath toURL:newPath error:&fileMoveError];
if (fileMoveError) {
NSLog(@"[SCInsta] Download Handler: Error while moving file: %@", oldPath.absoluteString);
NSLog(@"[SCInsta] Download Handler: %@", fileMoveError);
}
return newPath;
}
@end