Skip to content

Commit

Permalink
Merge pull request #368 from Countly/staging
Browse files Browse the repository at this point in the history
Staging 7.9
  • Loading branch information
turtledreams authored Dec 4, 2024
2 parents fa92c8f + a19d604 commit 7a99289
Show file tree
Hide file tree
Showing 17 changed files with 94 additions and 35 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## 24.7.9
* Improved view tracking capabilities

## 24.7.8
* Added support for localization of content blocks.

* Mitigated an issue where visibility could have been wrongly assigned if a view was closed while going to background. (Experimental!)
* Mitigated an issue where the user provided URLSessionConfiguration was not applied to direct requests
* Mitigated an issue where a concurrent modification error could have happen when starting multiple stopped views
* Mitigated an issue that parsing internal content event segmentation.

## 24.7.7
* Changed the visibility tracking segmentation values to binary

## 24.7.6
* Mitigated an issue with experimental visibility tracking and previous name recording, ensuring they’re included even when no segmentation is provided in event or view recording.

Expand Down
2 changes: 1 addition & 1 deletion Countly-PL.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Countly-PL'
s.version = '24.7.6'
s.version = '24.7.9'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.summary = 'Countly is an innovative, real-time, open source mobile analytics platform.'
s.homepage = 'https://github.com/Countly/countly-sdk-ios'
Expand Down
25 changes: 16 additions & 9 deletions Countly.m
Original file line number Diff line number Diff line change
Expand Up @@ -932,19 +932,26 @@ - (void)recordEvent:(NSString *)key segmentation:(NSDictionary *)segmentation co
[CountlyPersistency.sharedInstance recordEvent:event];
}

- (NSDictionary*) processSegmentation:(NSMutableDictionary *) segmentation eventKey:(NSString *)eventKey
{
if(CountlyViewTrackingInternal.sharedInstance.enablePreviousNameRecording) {
if([eventKey isEqualToString:kCountlyReservedEventView]) {
segmentation[kCountlyPreviousView] = CountlyViewTrackingInternal.sharedInstance.previousViewName ?: @"";
}
- (NSDictionary *)processSegmentation:(NSMutableDictionary *)segmentation eventKey:(NSString *)eventKey {
BOOL isViewEvent = [eventKey isEqualToString:kCountlyReservedEventView];

// Add previous view name if enabled and the event is a view event
if (isViewEvent && CountlyViewTrackingInternal.sharedInstance.enablePreviousNameRecording) {
segmentation[kCountlyPreviousView] = CountlyViewTrackingInternal.sharedInstance.previousViewName ?: @"";
}

if(CountlyCommon.sharedInstance.enableVisibiltyTracking) {
segmentation[kCountlyVisibility] = @([self isAppInForeground]);
// Add visibility tracking information if enabled
if (CountlyCommon.sharedInstance.enableVisibiltyTracking) {
BOOL isViewStart = [segmentation[kCountlyVTKeyVisit] isEqual:@1];

// Add visibility if it's not a view event or it's a view start event
if (!isViewEvent || isViewStart) {
segmentation[kCountlyVisibility] = @([self isAppInForeground] ? 1 : 0);
}
}

return segmentation.count == 0 ? nil : segmentation;
// Return segmentation dictionary if not empty, otherwise return nil
return segmentation.count > 0 ? segmentation : nil;
}

- (BOOL)isAppInForeground {
Expand Down
2 changes: 1 addition & 1 deletion Countly.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Countly'
s.version = '24.7.6'
s.version = '24.7.9'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.summary = 'Countly is an innovative, real-time, open source mobile analytics platform.'
s.homepage = 'https://github.com/Countly/countly-sdk-ios'
Expand Down
4 changes: 2 additions & 2 deletions Countly.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 24.7.6;
MARKETING_VERSION = 24.7.9;
PRODUCT_BUNDLE_IDENTIFIER = ly.count.CountlyiOSSDK;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -770,7 +770,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 24.7.6;
MARKETING_VERSION = 24.7.9;
PRODUCT_BUNDLE_IDENTIFIER = ly.count.CountlyiOSSDK;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
2 changes: 2 additions & 0 deletions CountlyCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ void CountlyPrint(NSString *stringToPrint);
- (void)recordOrientation;

- (BOOL)hasStarted_;

- (NSURLSession *)URLSession;
@end


Expand Down
14 changes: 13 additions & 1 deletion CountlyCommon.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ @interface CountlyCommon ()
#endif
@end

NSString* const kCountlySDKVersion = @"24.7.6";
NSString* const kCountlySDKVersion = @"24.7.9";
NSString* const kCountlySDKName = @"objc-native-ios";

NSString* const kCountlyErrorDomain = @"ly.count.ErrorDomain";
Expand Down Expand Up @@ -317,6 +317,18 @@ - (void)tryPresentingViewController:(UIViewController *)viewController withCompl
}
#endif

- (NSURLSession *)URLSession
{
if (CountlyConnectionManager.sharedInstance.URLSessionConfiguration)
{
return [NSURLSession sessionWithConfiguration:CountlyConnectionManager.sharedInstance.URLSessionConfiguration];
}
else
{
return NSURLSession.sharedSession;
}
}

@end


Expand Down
2 changes: 2 additions & 0 deletions CountlyConnectionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,6 @@ extern const NSInteger kCountlyGETRequestMaxLength;
- (NSString *)queryEssentials;
- (NSString *)appendChecksum:(NSString *)queryString;

- (BOOL)isSessionStarted;

@end
6 changes: 6 additions & 0 deletions CountlyConnectionManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ @interface CountlyConnectionManager ()
@property (nonatomic) NSURLSession* URLSession;

@property (nonatomic, strong) NSDate *startTime;

@end

NSString* const kCountlyQSKeyAppKey = @"app_key";
Expand Down Expand Up @@ -105,6 +106,11 @@ - (instancetype)init
return self;
}


- (BOOL)isSessionStarted {
return isSessionStarted;
}

- (void)resetInstance {
CLY_LOG_I(@"%s", __FUNCTION__);
onceToken = 0;
Expand Down
5 changes: 5 additions & 0 deletions CountlyContentBuilderInternal.m
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ - (NSURLRequest *)fetchContentsRequest

queryString = [CountlyConnectionManager.sharedInstance appendChecksum:queryString];

NSArray *components = [CountlyDeviceInfo.locale componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"_-"]];

queryString = [queryString stringByAppendingFormat:@"&%@=%@",
@"la", components.firstObject];

NSString* URLString = [NSString stringWithFormat:@"%@%@?%@",
CountlyConnectionManager.sharedInstance.host,
kCountlyEndpointContent,
Expand Down
2 changes: 1 addition & 1 deletion CountlyFeedbackWidget.m
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ - (void)getWidgetData:(void (^)(NSDictionary * __nullable widgetData, NSError *
return;
}

NSURLSessionTask* task = [NSURLSession.sharedSession dataTaskWithRequest:[self dataRequest] completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
NSURLSessionTask* task = [CountlyCommon.sharedInstance.URLSession dataTaskWithRequest:[self dataRequest] completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
{
NSDictionary *widgetData = nil;

Expand Down
4 changes: 2 additions & 2 deletions CountlyFeedbacksInternal.m
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ - (void)presentRatingWidgetWithID:(NSString *)widgetID closeButtonText:(NSString
return;

NSURLRequest* feedbackWidgetCheckRequest = [self widgetCheckURLRequest:widgetID];
NSURLSessionTask* task = [NSURLSession.sharedSession dataTaskWithRequest:feedbackWidgetCheckRequest completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
NSURLSessionTask* task = [CountlyCommon.sharedInstance.URLSession dataTaskWithRequest:feedbackWidgetCheckRequest completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
{
NSDictionary* widgetInfo = nil;

Expand Down Expand Up @@ -425,7 +425,7 @@ - (void)getFeedbackWidgets:(void (^)(NSArray <CountlyFeedbackWidget *> *feedback
if (CountlyDeviceInfo.sharedInstance.isDeviceIDTemporary)
return;

NSURLSessionTask* task = [NSURLSession.sharedSession dataTaskWithRequest:[self feedbacksRequest] completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
NSURLSessionTask* task = [CountlyCommon.sharedInstance.URLSession dataTaskWithRequest:[self feedbacksRequest] completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
{
NSDictionary *feedbacksResponse = nil;

Expand Down
8 changes: 4 additions & 4 deletions CountlyRemoteConfigInternal.m
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ - (void)fetchRemoteConfigForKeys:(NSArray *)keys omitKeys:(NSArray *)omitKeys i
return;

NSURLRequest* request = [self remoteConfigRequestForKeys:keys omitKeys:omitKeys isLegacy:isLegacy];
NSURLSessionTask* task = [NSURLSession.sharedSession dataTaskWithRequest:request completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
NSURLSessionTask* task = [CountlyCommon.sharedInstance.URLSession dataTaskWithRequest:request completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
{
NSDictionary* remoteConfig = nil;

Expand Down Expand Up @@ -496,7 +496,7 @@ - (void)testingDownloadAllVariantsInternal:(void (^)(CLYRequestResult response,
return;

NSURLRequest* request = [self downloadVariantsRequest];
NSURLSessionTask* task = [NSURLSession.sharedSession dataTaskWithRequest:request completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
NSURLSessionTask* task = [CountlyCommon.sharedInstance.URLSession dataTaskWithRequest:request completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
{
NSMutableDictionary* variants = NSMutableDictionary.new;

Expand Down Expand Up @@ -607,7 +607,7 @@ - (void)testingEnrollIntoVariantInternal:(NSString *)key variantName:(NSString *
}

NSURLRequest* request = [self enrollInVarianRequestForKey:key variantName:variantName];
NSURLSessionTask* task = [NSURLSession.sharedSession dataTaskWithRequest:request completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
NSURLSessionTask* task = [CountlyCommon.sharedInstance.URLSession dataTaskWithRequest:request completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
{
NSDictionary* variants = nil;
[self clearCachedRemoteConfig];
Expand Down Expand Up @@ -721,7 +721,7 @@ - (void)testingDownloaExperimentInfoInternal:(void (^)(CLYRequestResult response
return;

NSURLRequest* request = [self downloadExperimentInfoRequest];
NSURLSessionTask* task = [NSURLSession.sharedSession dataTaskWithRequest:request completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
NSURLSessionTask* task = [CountlyCommon.sharedInstance.URLSession dataTaskWithRequest:request completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
{

NSMutableDictionary<NSString*, CountlyExperimentInformation*> * experiments = NSMutableDictionary.new;
Expand Down
2 changes: 1 addition & 1 deletion CountlyServerConfig.m
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ - (void)fetchServerConfig
if (CountlyDeviceInfo.sharedInstance.isDeviceIDTemporary)
return;

NSURLSessionTask* task = [NSURLSession.sharedSession dataTaskWithRequest:[self serverConfigRequest] completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
NSURLSessionTask* task = [CountlyCommon.sharedInstance.URLSession dataTaskWithRequest:[self serverConfigRequest] completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
{
NSDictionary *serverConfigResponse = nil;

Expand Down
1 change: 1 addition & 0 deletions CountlyViewTrackingInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extern NSString* const kCountlyReservedEventView;
extern NSString* const kCountlyCurrentView;
extern NSString* const kCountlyPreviousView;
extern NSString* const kCountlyPreviousEventName;
extern NSString* const kCountlyVTKeyVisit;

@interface CountlyViewTrackingInternal : NSObject
@property (nonatomic) BOOL isEnabledOnInitialConfig;
Expand Down
30 changes: 18 additions & 12 deletions CountlyViewTrackingInternal.m
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ - (NSString*)startViewInternal:(NSString *)viewName customSegmentation:(NSDictio
segmentation[kCountlyVTKeySegment] = CountlyDeviceInfo.osName;
segmentation[kCountlyVTKeyVisit] = @1;

if (self.isFirstView)
if (self.isFirstView && [CountlyConnectionManager.sharedInstance isSessionStarted])
{
self.isFirstView = NO;
segmentation[kCountlyVTKeyStart] = @1;
Expand Down Expand Up @@ -545,27 +545,33 @@ - (void)startStoppedViewsInternal
{
// Create an array to store keys for views that need to be removed
NSMutableArray<NSString *> *keysToRemove = [NSMutableArray array];

NSMutableArray<NSString *> *keysToStart = [NSMutableArray array];

// Collect keys without modifying the dictionary
[self.viewDataDictionary enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, CountlyViewData * _Nonnull viewData, BOOL * _Nonnull stop) {
if (viewData.willStartAgain)
{
NSString *viewID = [self startViewInternal:viewData.viewName customSegmentation:viewData.startSegmentation isAutoStoppedView:viewData.isAutoStoppedView];

// Retrieve the newly created viewData for the viewID
CountlyViewData* viewDataNew = self.viewDataDictionary[viewID];

// Copy the segmentation data from the old view to the new view
viewDataNew.segmentation = viewData.segmentation.mutableCopy;

// Add the old view's ID to the array for removal later
[keysToStart addObject:key];
[keysToRemove addObject:viewData.viewID];
}
}];

// Start the collected views after enumeration
for (NSString *key in keysToStart)
{
CountlyViewData *viewData = self.viewDataDictionary[key];
NSString *viewID = [self startViewInternal:viewData.viewName customSegmentation:viewData.startSegmentation isAutoStoppedView:viewData.isAutoStoppedView];

// Retrieve and update the newly created viewData
CountlyViewData *viewDataNew = self.viewDataDictionary[viewID];
viewDataNew.segmentation = viewData.segmentation.mutableCopy;
}

// Remove the entries from the dictionary
[self.viewDataDictionary removeObjectsForKeys:keysToRemove];
}


- (void)stopAllViewsInternal:(NSDictionary *)segmentation
{
// TODO: Should apply all the segmenation operations here at one place instead of doing it for individual view
Expand Down Expand Up @@ -759,7 +765,7 @@ - (void)applicationWillTerminate {

- (void)resetFirstView
{
self.isFirstView = NO;
self.isFirstView = YES;
}


Expand Down
6 changes: 5 additions & 1 deletion CountlyWebViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,15 @@ - (void)recordEventsWithJSONString:(NSString *)jsonString {

for (NSDictionary *event in events) {
NSString *key = event[@"key"];
NSDictionary *segmentation = event[@"sg"];
NSDictionary *segmentation = event[@"segmentation"];
NSDictionary *sg = event[@"sg"];
if(!key) {
CLY_LOG_I(@"Skipping the event due to key is empty or nil");
continue;
}
if(sg) {
segmentation = sg;
}
if(!segmentation) {
CLY_LOG_I(@"Skipping the event due to missing segmentation");
continue;
Expand Down

0 comments on commit 7a99289

Please sign in to comment.