Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MC-1563] File downloading #339

Merged
merged 23 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c2516af
Adds CTFileDownloadManager class for file downloading
nishant-clevertap Apr 10, 2024
7ad5a0a
Added unit tests for CTFileDownloadManager
nishant-clevertap Apr 17, 2024
dff8b2a
Added unit tests for CTFileDownloadDelegate protocol callback methods.
nishant-clevertap Apr 17, 2024
3b053c4
Updated callback approach to use completion block.
nishant-clevertap Apr 22, 2024
ec29da0
- Added class CTFileDownloader to handle file downloading from inapps…
nishant-clevertap May 17, 2024
3a0f869
Added public method to get file downloaded path.
nishant-clevertap May 17, 2024
e2d2a62
Added some unit tests for clearFileAssets method.
nishant-clevertap May 17, 2024
0e86375
- Added logic for handling url download in progress, only one request…
nishant-clevertap Jun 12, 2024
e753d44
Merge branch 'develop' of https://github.com/CleverTap/clevertap-ios-…
nishant-clevertap Jun 14, 2024
2019c1f
- Added thread safety check for updating active and inactive dictionary.
nishant-clevertap Jun 18, 2024
c11698d
Added callback for File variables only, and code cleanup.
nishant-clevertap Jun 21, 2024
fd34972
Address comments and improvements
nzagorchev Jun 21, 2024
734d46b
Merge branch 'file_downloading' of github.com:CleverTap/clevertap-ios…
nzagorchev Jun 21, 2024
ffd61af
Rename methods
nzagorchev Jun 22, 2024
35f428f
Move duplicate methods to test helper
nzagorchev Jun 23, 2024
5cf477c
Move tests to group
nzagorchev Jun 23, 2024
b5ff99c
Move tests headers and mocks to separate files
nzagorchev Jun 23, 2024
ed569b2
Use longer resource timeout
nzagorchev Jun 23, 2024
06270c8
Improve tests
nzagorchev Jun 23, 2024
dd8213d
Improve clear expired files
nzagorchev Jun 23, 2024
c176d16
Fix clear expired assets
nzagorchev Jun 24, 2024
80cb607
Save files to directory inside documents
nzagorchev Jun 24, 2024
9a1b602
Move to group
nzagorchev Jun 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading