Skip to content

Commit

Permalink
[MC-1563] File downloading (#339)
Browse files Browse the repository at this point in the history
* Adds CTFileDownloadManager class for file downloading
Adds callback for each file and all files download

* Added unit tests for CTFileDownloadManager

* Added unit tests for CTFileDownloadDelegate protocol callback methods.

* Updated callback approach to use completion block.
Updated unit tests.

* - Added class CTFileDownloader to handle file downloading from inapps, file variables.
- Added expiry logic for files downloaded.
- Added unit tests.

* Added public method to get file downloaded path.

* Added some unit tests for clearFileAssets method.

* - Added logic for handling url download in progress, only one request to the url to download the file.
- Added methods for image preloading cases.
- Added unit test cases.

* - Added thread safety check for updating active and inactive dictionary.
- Added changes for CS InApps to use the new CTFileDownloader class for image preloading.
- Removed previous usage of CTInAppImagePrefetchManager class for image preloading.

* Added callback for File variables only, and code cleanup.

* Address comments and improvements

* Rename methods

* Move duplicate methods to test helper

* Move tests to group

* Move tests headers and mocks to separate files

* Use longer resource timeout

* Improve tests

* Improve clear expired files

* Fix clear expired assets

* Save files to directory inside documents
Remove all files removes the files inside the directory
Add Unit tests

* Move to group

---------

Co-authored-by: Nikola Zagorchev <[email protected]>
  • Loading branch information
nishant-clevertap and nzagorchev authored Jun 25, 2024
1 parent 40f069d commit 6a94ad3
Show file tree
Hide file tree
Showing 36 changed files with 2,140 additions and 669 deletions.
90 changes: 74 additions & 16 deletions CleverTapSDK.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions CleverTapSDK.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions CleverTapSDK/CTConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ extern NSString *const kSessionId;
#define CLTAP_NOTIFICATION_TAG @"W$"
#define CLTAP_DATE_FORMAT @"yyyyMMdd"

#pragma mark Constants for File Assets
#define CLTAP_FILE_URLS_EXPIRY_DICT @"file_urls_expiry_dict"
#define CLTAP_FILE_ASSETS_LAST_DELETED_TS @"cs_file_assets_last_deleted_timestamp"
#define CLTAP_FILE_EXPIRY_OFFSET (60 * 60 * 24 * 7 * 2) // 2 weeks
#define CLTAP_FILE_RESOURCE_TIME_OUT_INTERVAL 15
#define CLTAP_FILES_DIRECTORY_NAME @"CleverTap_Files"

#pragma mark Constants for App fields
#define CLTAP_APP_VERSION @"Version"
#define CLTAP_LATITUDE @"Latitude"
Expand Down
4 changes: 2 additions & 2 deletions CleverTapSDK/CTInAppNotification.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#import "CTInAppUtils.h"
#import "CTNotificationButton.h"
#if !CLEVERTAP_NO_INAPP_SUPPORT
#import "CTInAppImagePrefetchManager.h"
#import "CTFileDownloader.h"
#endif

@interface CTInAppNotification : NSObject
Expand Down Expand Up @@ -66,7 +66,7 @@
- (instancetype)init __unavailable;
#if !CLEVERTAP_NO_INAPP_SUPPORT
- (instancetype)initWithJSON:(NSDictionary*)json
imagePrefetchManager:(CTInAppImagePrefetchManager *)imagePrefetchManager;
fileDownloader:(CTFileDownloader *)fileDownloader;
#endif

- (void)prepareWithCompletionHandler: (void (^)(void))completionHandler;
Expand Down
8 changes: 4 additions & 4 deletions CleverTapSDK/CTInAppNotification.m
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ @interface CTInAppNotification() {

@property (nonatomic, readwrite) NSString *error;

@property (nonatomic, strong) CTInAppImagePrefetchManager *imagePrefetchManager;
@property (nonatomic, strong) CTFileDownloader *fileDownloader;

@end

Expand All @@ -78,10 +78,10 @@ @implementation CTInAppNotification: NSObject
@synthesize mediaIsVideo=_mediaIsVideo;

- (instancetype)initWithJSON:(NSDictionary *)jsonObject
imagePrefetchManager:(CTInAppImagePrefetchManager *)imagePrefetchManager {
fileDownloader:(CTFileDownloader *)fileDownloader {
if (self = [super init]) {
@try {
self.imagePrefetchManager = imagePrefetchManager;
self.fileDownloader = fileDownloader;
self.inAppType = CTInAppTypeUnknown;
self.jsonDescription = jsonObject;
self.campaignId = (NSString*) jsonObject[CLTAP_NOTIFICATION_ID_TAG];
Expand Down Expand Up @@ -434,7 +434,7 @@ - (BOOL)isKeyValidInDictionary:(NSDictionary *)d forKey:(NSString *)key ofClass:

- (UIImage *)loadImageIfPresentInDiskCache:(NSURL *)imageURL {
NSString *imageURLString = [imageURL absoluteString];
UIImage *image = [self.imagePrefetchManager loadImageFromDisk:imageURLString];
UIImage *image = [self.fileDownloader loadImageFromDisk:imageURLString];
if (image) return image;
return nil;
}
Expand Down
15 changes: 7 additions & 8 deletions CleverTapSDK/CleverTap.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#import "CTDispatchQueueManager.h"
#import "CTMultiDelegateManager.h"
#import "CTSessionManager.h"
#import "CTFileDownloader.h"

#if !CLEVERTAP_NO_INAPP_SUPPORT
#import "CTInAppFCManager.h"
Expand All @@ -56,7 +57,6 @@
#import "CleverTap+InAppsResponseHandler.h"
#import "CTInAppEvaluationManager.h"
#import "CTInAppTriggerManager.h"
#import "CTInAppImagePrefetchManager.h"
#endif

#if !CLEVERTAP_NO_INBOX_SUPPORT
Expand Down Expand Up @@ -242,7 +242,7 @@ @interface CleverTap () <UIApplicationDelegate> {
@property (nonatomic, strong, readwrite) CTInAppEvaluationManager *inAppEvaluationManager;
@property (nonatomic, strong, readwrite) CTInAppDisplayManager *inAppDisplayManager;
@property (nonatomic, strong, readwrite) CTImpressionManager *impressionManager;
@property (nonatomic, strong, readwrite) CTInAppImagePrefetchManager *imagePrefetchManager;
@property (nonatomic, strong, readwrite) CTFileDownloader *fileDownloader;
@property (nonatomic, strong, readwrite) CTInAppStore * _Nullable inAppStore;
#endif

Expand Down Expand Up @@ -477,6 +477,8 @@ - (instancetype)initWithConfig:(CleverTapInstanceConfig*)config andCleverTapID:(
[self initNetworking];
[self inflateQueuesAsync];
[self addObservers];

self.fileDownloader = [[CTFileDownloader alloc] initWithConfig:self.config];
#if !CLEVERTAP_NO_INAPP_SUPPORT
if (!_config.analyticsOnly && ![CTUIUtils runningInsideAppExtension]) {
[self initializeInAppSupport];
Expand Down Expand Up @@ -506,12 +508,9 @@ - (instancetype)initWithConfig:(CleverTapInstanceConfig*)config andCleverTapID:(

#if !CLEVERTAP_NO_INAPP_SUPPORT
- (void)initializeInAppSupport {
CTInAppImagePrefetchManager *imagePrefetchManager = [[CTInAppImagePrefetchManager alloc] initWithConfig:self.config];
self.imagePrefetchManager = imagePrefetchManager;

CTInAppStore *inAppStore = [[CTInAppStore alloc] initWithConfig:self.config
delegateManager:self.delegateManager
imagePrefetchManager:self.imagePrefetchManager
fileDownloader:self.fileDownloader
deviceId:self.deviceInfo.deviceId];
self.inAppStore = inAppStore;

Expand All @@ -525,7 +524,7 @@ - (void)initializeInAppSupport {
inAppFCManager:inAppFCManager
impressionManager:impressionManager
inAppStore:inAppStore
imagePrefetchManager:self.imagePrefetchManager];
fileDownloader:self.fileDownloader];

CTInAppEvaluationManager *evaluationManager = [[CTInAppEvaluationManager alloc] initWithAccountId:self.config.accountId deviceId:self.deviceInfo.deviceId delegateManager:self.delegateManager impressionManager:impressionManager inAppDisplayManager:displayManager inAppStore:inAppStore inAppTriggerManager:triggerManager];

Expand Down Expand Up @@ -1563,7 +1562,7 @@ - (void)resumeInAppNotifications {
}

- (void)clearInAppResources:(BOOL)expiredOnly {
[self.imagePrefetchManager _clearImageAssets:expiredOnly];
[self.fileDownloader clearFileAssets:expiredOnly];
}
#endif

Expand Down
68 changes: 68 additions & 0 deletions CleverTapSDK/FileDownload/CTFileDownloadManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#import <Foundation/Foundation.h>

@class CleverTapInstanceConfig;

NS_ASSUME_NONNULL_BEGIN

typedef void(^CTFilesDownloadCompletedBlock)(NSDictionary<NSString *, NSNumber *> *status);
typedef void(^CTFilesDeleteCompletedBlock)(NSDictionary<NSString *, NSNumber *> *status);
typedef void(^CTFilesRemoveCompletedBlock)(NSDictionary<NSString *, NSNumber *> *status);
typedef void (^DownloadCompletionHandler)(NSURL *url, BOOL success);

@interface CTFileDownloadManager : NSObject

+ (instancetype)sharedInstanceWithConfig:(CleverTapInstanceConfig *)config;
- (instancetype)init NS_UNAVAILABLE;

/*!
@method
@discussion
This method accepts file urls as NSArray of NSURLs and downloads each file to directory inside NSDocumentDirectory directory.
@param completion the completion block to be executed when all files are downloaded. `status` dictionary will
contain file download status of each file as {url,success}. The completion block is executed on background queue.
*/
- (void)downloadFiles:(NSArray<NSURL *> *)urls withCompletionBlock:(CTFilesDownloadCompletedBlock)completion;

/*!
@method
@discussion
This method checks if file is already present in the directory or not.
*/
- (BOOL)isFileAlreadyPresent:(NSURL *)url;

/*!
@method
@discussion
This method returns the file path to the file. This method does *not* check if the file exists.
*/
- (NSString *)filePath:(NSURL *)url;

/*!
@method
@discussion
This method deletes the files from the directory if present.
@param completion the completion block to be executed when all files are deleted. `status` dictionary will
contain file delete status of each file as {url,success}. The completion block is executed on background queue.
*/
- (void)deleteFiles:(NSArray<NSString *> *)urls withCompletionBlock:(CTFilesDeleteCompletedBlock)completion;

/*!
@method
@discussion
This method deletes all files from the directory.
@param completion the completion block to be executed when all files are deleted. `status` dictionary will
contain file download status of each file as {file path,success}. The completion block is executed on background queue.
*/
- (void)removeAllFilesWithCompletionBlock:(CTFilesRemoveCompletedBlock)completion;

@end

NS_ASSUME_NONNULL_END
Loading

0 comments on commit 6a94ad3

Please sign in to comment.