-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- cleaner code - SOLID principles - clean architecture
- Loading branch information
Showing
14 changed files
with
527 additions
and
504 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#import "BundleUpdater.h" | ||
|
||
@interface BundleUpdater (FileManager) | ||
|
||
- (void)copyFilesFromSource:(NSString *)sourceFolder toDestination:(NSString *)destinationFolder; | ||
- (void)clearDocumentsFolder; | ||
- (NSMutableData *)calculateSHA256Hash:(NSData *)script; | ||
- (NSString *)loadHashFromDisk; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
#import "BundleUpdater+FileManager.h" | ||
#import "CommonCrypto/CommonDigest.h" | ||
|
||
@implementation BundleUpdater (FileManager) | ||
|
||
/*! | ||
* @brief Copy files from source to destination recursively | ||
* | ||
* @param sourceFolder Source folder | ||
* @param destinationFolder Destination folder | ||
*/ | ||
- (void)copyFilesFromSource:(NSString *)sourceFolder toDestination:(NSString *)destinationFolder { | ||
NSFileManager *manager = [NSFileManager defaultManager]; | ||
NSError *error; | ||
NSArray *contents = [manager contentsOfDirectoryAtPath:sourceFolder error:&error]; | ||
|
||
if (error) { | ||
NSLog(@"[BUNDLE UPDATER SDK]: Error reading contents of directory %@: %@", sourceFolder, [error localizedDescription]); | ||
return; | ||
} | ||
|
||
for (NSString *file in contents) { | ||
NSString *sourceFilePath = [sourceFolder stringByAppendingPathComponent:file]; | ||
NSString *destinationFilePath = [destinationFolder stringByAppendingPathComponent:file]; | ||
|
||
BOOL isDir; | ||
BOOL fileExistsAtPath = [manager fileExistsAtPath:sourceFilePath isDirectory:&isDir]; | ||
|
||
if (fileExistsAtPath) { | ||
if (isDir) { | ||
// It's a directory, create it in the destination | ||
[manager createDirectoryAtPath:destinationFilePath withIntermediateDirectories:YES attributes:nil error:nil]; | ||
|
||
// Recursively copy the contents of the subdirectory | ||
[self copyFilesFromSource:sourceFilePath toDestination:[destinationFolder stringByAppendingPathComponent:file]]; | ||
} else { | ||
//NSLog(@"Copying to the destination: %@", destinationFilePath); | ||
// It's a file, copy it to the destination | ||
NSData *fileData = [NSData dataWithContentsOfFile:sourceFilePath]; | ||
[fileData writeToFile:destinationFilePath atomically:YES]; | ||
} | ||
} | ||
} | ||
//Log the content of the destination folder | ||
NSLog(@"[BUNDLE UPDATER SDK]: content of the %@ folder %@", sourceFolder, [manager contentsOfDirectoryAtPath:destinationFolder error:nil]); | ||
} | ||
|
||
/*! | ||
* @brief clear the documents folder from files that are not intended to be there | ||
*/ | ||
- (void)clearDocumentsFolder{ | ||
//TODO - custom method and custom class to interact with the documents folder | ||
NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true); | ||
NSArray *documents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dirs.firstObject error:nil]; | ||
NSString *documentPath = dirs.firstObject; | ||
NSFileManager *defManager = [NSFileManager defaultManager]; | ||
for (NSString *document in documents){ | ||
if([document isEqualToString:@"unzipped"] || [document isEqualToString:@"bundle.zip"]){ | ||
NSString *pathToDoc = [documentPath stringByAppendingPathComponent:document]; | ||
NSError *errorRemoving; | ||
[defManager removeItemAtPath:pathToDoc error:&errorRemoving]; | ||
if(errorRemoving){ | ||
// TODO - understand what to do in this case | ||
NSLog(@"[BUNDLE UPDATER ]: Error removing doc %@", document); | ||
} | ||
} | ||
} | ||
} | ||
|
||
/*! | ||
* @brief get the hash of a file | ||
* | ||
* @param script - data of the bundle | ||
* * | ||
* @return a data hash | ||
*/ | ||
- (NSMutableData *)calculateSHA256Hash:(NSData *)script { | ||
NSMutableData *hash = | ||
[NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH]; | ||
CC_SHA256(script.bytes, (CC_LONG)script.length, | ||
(unsigned char *)hash.mutableBytes); | ||
return hash; | ||
} | ||
|
||
/*! | ||
* @brief load the saved hash of the file from disk | ||
* | ||
* @return a string hash of the file | ||
*/ | ||
- (NSString *)loadHashFromDisk { | ||
NSString *hashPath = [[NSSearchPathForDirectoriesInDomains( | ||
NSDocumentDirectory, NSUserDomainMask, YES) firstObject] | ||
stringByAppendingPathComponent:@"main.jsbundle.sha256"]; | ||
NSString *oldHash = [NSString stringWithContentsOfFile:hashPath | ||
encoding:NSUTF8StringEncoding | ||
error:nil]; | ||
return oldHash; | ||
} | ||
|
||
|
||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#import "BundleUpdater.h" | ||
#import <sys/utsname.h> | ||
|
||
@interface BundleUpdater (Info) | ||
- (NSString *)getDeviceModelName; | ||
- (NSDictionary *)getMetaData; | ||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#import "BundleUpdater+Info.h" | ||
@implementation BundleUpdater (Info) | ||
|
||
/*! | ||
* @brief get the device model info | ||
* | ||
* @return a string with the info of the device | ||
*/ | ||
- (NSString *)getDeviceModelName { | ||
struct utsname systemInfo; | ||
uname(&systemInfo); | ||
return [NSString stringWithCString:systemInfo.machine | ||
encoding:NSUTF8StringEncoding]; | ||
} | ||
|
||
/*! | ||
* @brief get the a list of info as summary for the device | ||
* | ||
* @return a dictionary with the info | ||
*/ | ||
- (NSDictionary *)getMetaData { | ||
UIDevice *device = [UIDevice currentDevice]; | ||
NSString *device_name = device.name; | ||
NSString *device_model = [self getDeviceModelName]; | ||
NSString *systemname = device.systemName; | ||
NSString *systemVersion = device.systemVersion; | ||
NSString *deviceIdentifier = [[device identifierForVendor] UUIDString]; | ||
NSString *bundleID = NSBundle.mainBundle.bundleIdentifier; | ||
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; | ||
NSString *marketingVersion = infoDictionary[@"CFBundleShortVersionString"]; | ||
NSString *projectVersion = infoDictionary[@"CFBundleVersion"]; | ||
|
||
NSString *preferredUserLocale = | ||
[[[NSBundle mainBundle] preferredLocalizations] firstObject]; | ||
NSString *batteryLevel = @"Unknown"; | ||
// TODO NSString *phoneChargingState = [self getPhoneBatteryLevel]; | ||
// if (![phoneChargingState isEqualToString:@"Unknown"]) { | ||
// batteryLevel = [NSString | ||
// stringWithFormat:@"%.f", (float)[device batteryLevel] * 100]; | ||
// } | ||
NSString *lowPowerModeEnabled = | ||
[[NSProcessInfo processInfo] isLowPowerModeEnabled] ? @"true" | ||
: @"false"; | ||
// NSDictionary *diskInfo = [self getDiskInfo]; | ||
NSString *buildMode = @"RELEASE"; | ||
#ifdef DEBUG | ||
buildMode = @"DEBUG"; | ||
#endif | ||
float scaleFactor = [[UIScreen mainScreen] scale]; | ||
CGRect screenRect = [[UIScreen mainScreen] bounds]; | ||
CGFloat screenWidth = screenRect.size.width; | ||
CGFloat screenHeight = screenRect.size.height; | ||
return @{ | ||
@"device_name" : device_name, | ||
@"device_model" : device_model, | ||
@"deviceIdentifier" : deviceIdentifier, | ||
@"bundleID" : bundleID, | ||
@"system_name" : systemname, | ||
@"systemVersion" : systemVersion, | ||
@"buildVersionNumber" : marketingVersion, | ||
@"releaseVersionNumber" : projectVersion, | ||
@"preferredUserLocale" : preferredUserLocale, | ||
@"sdkVersion" : @"ALPHA-1", // SDK_VERSION", | ||
@"buildMode" : buildMode, | ||
@"batteryLevel" : batteryLevel, | ||
// @"phoneChargingStatus" : phoneChargingState, | ||
@"batterySaveMode" : lowPowerModeEnabled, | ||
// @"totalDiskSpace" : [diskInfo objectForKey:@"totalSpace"], | ||
// @"totalFreeDiskSpace" : [diskInfo | ||
// objectForKey:@"totalFreeSpace"], | ||
@"devicePixelRatio" : @(scaleFactor), | ||
@"screenWidth" : @(screenWidth), | ||
@"screenHeight" : @(screenHeight) | ||
}; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
|
||
#import "BundleUpdater.h" | ||
|
||
@interface BundleUpdater (UI) | ||
- (void)showUpdateVC:(NSDictionary *)updateData withNecessaryUpdate:(BOOL)isNecessaryUpdate; | ||
- (void)prepareAndHideBottomSheet; | ||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
#import "BundleUpdater+UI.h" | ||
#import "BundleUpdaterNitificationVC.h" | ||
|
||
@implementation BundleUpdater (UI) | ||
|
||
/*! | ||
* @brief show the update bottomsheet if the config are supplied | ||
* | ||
* @param updateData - dictionary with the sheet config | ||
*/ | ||
- (void)showUpdateVC:(NSDictionary *)updateData withNecessaryUpdate:(BOOL)isNecessaryUpdate{ | ||
NSDictionary *config = updateData[@"configuration"]; | ||
NSDictionary *actionBtn = updateData[@"actionBtn"]; | ||
// Set the data properties of the bottom sheet view controller | ||
self.updaterVC.image = config[@"image"]; | ||
self.updaterVC.titleText = config[@"title"]; | ||
self.updaterVC.message = config[@"message"]; | ||
self.updaterVC.buttonLabel = actionBtn[@"label"]; | ||
self.updaterVC.buttonLink = actionBtn[@"label"]; | ||
self.updaterVC.buttonBackgroundColor = actionBtn[@"color"]; | ||
self.updaterVC.buttonIcon = [UIImage imageNamed:@"button_icon"]; | ||
self.updaterVC.footerLogo = [UIImage imageNamed:@"sdk_logo"]; | ||
if(isNecessaryUpdate){ | ||
self.updaterVC.isNecessaryUpdate = true; | ||
} | ||
NSString *type = config[@"type"]; | ||
if([type isEqualToString:@"notification"]){ | ||
//TODO - pass config to the notification | ||
BundleUpdaterNitificationVC *notificationVC = [BundleUpdaterNitificationVC new]; | ||
notificationVC.isNecessaryUpdate = isNecessaryUpdate; | ||
if([notificationVC isKindOfClass:[UIViewController class]]){ | ||
UIViewController *_notificationVC = (UIViewController *)notificationVC; | ||
_notificationVC.modalPresentationStyle = UIModalPresentationOverCurrentContext; | ||
// present the new viewContoller | ||
dispatch_async(dispatch_get_main_queue(), ^{ | ||
UIWindow *window = [[UIApplication sharedApplication] keyWindow]; | ||
UIViewController *rootViewController = window.rootViewController; | ||
[rootViewController presentViewController:_notificationVC animated:NO completion:nil]; | ||
}); | ||
return; | ||
}else{ | ||
NSLog(@"[BUNDLE UPDATER SDK]: It's NOT an UIViewController, display normal bottomsheet"); | ||
} | ||
}else if([type isEqualToString:@"modal"]){ | ||
self.updaterVC.isModal = true; | ||
} | ||
UIViewController *rootViewController = | ||
[[[UIApplication sharedApplication] keyWindow] rootViewController]; | ||
self.updaterVC.modalPresentationStyle = UIModalPresentationOverFullScreen; | ||
self.updaterVC.transitioningDelegate = self; // TODO | ||
[rootViewController presentViewController:self.updaterVC | ||
animated:YES | ||
completion:nil]; | ||
} | ||
|
||
/*! | ||
* @brief prepare the updaterVC before hiding the | ||
*/ | ||
- (void)prepareAndHideBottomSheet { | ||
dispatch_async(dispatch_get_main_queue(), ^{ | ||
// TODO - weak self | ||
[UIView animateWithDuration:0.2 animations:^{ | ||
self.updaterVC.loadingView.alpha = 0; | ||
self.updaterVC.backgroundView.alpha = 0; | ||
}]; | ||
[self.updaterVC.spinner stopAnimating]; | ||
[NSTimer scheduledTimerWithTimeInterval:0.2 | ||
target:self | ||
selector:@selector(hideBottomSheet) | ||
userInfo:nil | ||
repeats:NO]; | ||
}); | ||
} | ||
|
||
/*! | ||
* @brief hide the bottomsheet* | ||
*/ | ||
- (void)hideBottomSheet { | ||
dispatch_async(dispatch_get_main_queue(), ^{ | ||
[self.updaterVC dismissViewControllerAnimated:YES completion:nil]; | ||
}); | ||
} | ||
|
||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.