Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 25.1.1
* Mitigated an issue while setting zone timer interval for content.

## 25.1.0
* Added dynamic resizing functionality for the content zone
* Added a config option to content (setZoneTimerInterval) to set content zone timer. (Experimental!)

* Improved management of content zone size for better responsiveness
* Fixed an issue where the build UUID and executable name were missing from crash reports

## 24.7.9
* Improved view tracking capabilities

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.9'
s.version = '25.1.1'
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
3 changes: 3 additions & 0 deletions Countly.m
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ - (void)startWithConfig:(CountlyConfig *)config
if(config.content.getGlobalContentCallback) {
CountlyContentBuilderInternal.sharedInstance.contentCallback = config.content.getGlobalContentCallback;
}
if(config.content.getZoneTimerInterval){
CountlyContentBuilderInternal.sharedInstance.zoneTimerInterval = config.content.getZoneTimerInterval;
}
#endif

[CountlyPerformanceMonitoring.sharedInstance startWithConfig:config.apm];
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.9'
s.version = '25.1.1'
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.9;
MARKETING_VERSION = 25.1.1;
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.9;
MARKETING_VERSION = 25.1.1;
PRODUCT_BUNDLE_IDENTIFIER = ly.count.CountlyiOSSDK;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
2 changes: 1 addition & 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.9";
NSString* const kCountlySDKVersion = @"25.1.1";
NSString* const kCountlySDKName = @"objc-native-ios";

NSString* const kCountlyErrorDomain = @"ly.count.ErrorDomain";
Expand Down
2 changes: 1 addition & 1 deletion CountlyContentBuilderInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface CountlyContentBuilderInternal: NSObject
#if (TARGET_OS_IOS)
@property (nonatomic, strong) NSArray<NSString *> *currentTags;
@property (nonatomic, assign) NSTimeInterval requestInterval;
@property (nonatomic, assign) NSTimeInterval zoneTimerInterval;
@property (nonatomic) ContentCallback contentCallback;

+ (instancetype)sharedInstance;
Expand Down
61 changes: 40 additions & 21 deletions CountlyContentBuilderInternal.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ - (instancetype)init
{
if (self = [super init])
{
self.requestInterval = 30.0;
self.zoneTimerInterval = 30.0;
_requestTimer = nil;
}

Expand All @@ -55,7 +55,7 @@ - (void)enterContentZone:(NSArray<NSString *> *)tags {
self.currentTags = tags;

[self fetchContents];;
_requestTimer = [NSTimer scheduledTimerWithTimeInterval:self.requestInterval
_requestTimer = [NSTimer scheduledTimerWithTimeInterval:self.zoneTimerInterval
target:self
selector:@selector(fetchContents)
userInfo:nil
Expand Down Expand Up @@ -151,30 +151,49 @@ - (NSURLRequest *)fetchContentsRequest
return request;
}

- (NSString *)resolutionJson {
//TODO: check why area is not clickable and safearea things
CGRect screenBounds = [UIScreen mainScreen].bounds;
if (@available(iOS 11.0, *)) {
CGFloat top = UIApplication.sharedApplication.keyWindow.safeAreaInsets.top;

if (top) {
screenBounds.origin.y += top + 5;
screenBounds.size.height -= top + 5;
} else {
screenBounds.origin.y += 20.0;
screenBounds.size.height -= 20.0;
- (CGSize)getWindowSize {
CGSize size = CGSizeZero;

// Attempt to retrieve the size from the connected scenes (for modern apps)
if (@available(iOS 13.0, *)) {
NSSet<UIScene *> *scenes = [[UIApplication sharedApplication] connectedScenes];
for (UIScene *scene in scenes) {
if ([scene isKindOfClass:[UIWindowScene class]]) {
UIWindowScene *windowScene = (UIWindowScene *)scene;
UIWindow *window = windowScene.windows.firstObject;
if (window) {
size = window.bounds.size;
return size; // Return immediately if we find a valid size
}
}
}
}

// Fallback for legacy apps using AppDelegate
id<UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
if ([appDelegate respondsToSelector:@selector(window)]) {
UIWindow *legacyWindow = [appDelegate performSelector:@selector(window)];
if (legacyWindow) {
size = legacyWindow.bounds.size;
}
} else {
screenBounds.origin.y += 20.0;
screenBounds.size.height -= 20.0;
}

return size;
}

- (NSString *)resolutionJson {
//TODO: check why area is not clickable and safearea things
CGSize size = [self getWindowSize];

CGFloat width = screenBounds.size.width;
CGFloat height = screenBounds.size.height;
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
BOOL isLandscape = UIInterfaceOrientationIsLandscape(orientation);

CGFloat lHpW = isLandscape ? size.height : size.width;
CGFloat lWpH = isLandscape ? size.width : size.height;

NSDictionary *resolutionDict = @{
@"portrait": @{@"height": @(height), @"width": @(width)},
@"landscape": @{@"height": @(width), @"width": @(height)}
@"portrait": @{@"height": @(lWpH), @"width": @(lHpW)},
@"landscape": @{@"height": @(lHpW), @"width": @(lWpH)}
};

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:resolutionDict options:0 error:nil];
Expand Down
14 changes: 14 additions & 0 deletions CountlyContentConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ typedef void (^ContentCallback)(ContentStatus contentStatus, NSDictionary<NSStri
* Get content callback
*/
- (ContentCallback) getGlobalContentCallback;

/**
* This is an experimental feature and it can have breaking changes
* Set the interval for the automatic content update calls
* @param zoneTimerIntervalSeconds in seconds
*
*/
-(void)setZoneTimerInterval:(NSUInteger)zoneTimerIntervalSeconds;

/**
* This is an experimental feature and it can have breaking changes
* Get zone timer interval
*/
- (NSUInteger) getZoneTimerInterval;
#endif

NS_ASSUME_NONNULL_END
Expand Down
18 changes: 16 additions & 2 deletions CountlyContentConfig.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
@interface CountlyContentConfig ()
#if (TARGET_OS_IOS)
@property (nonatomic) ContentCallback contentCallback;
@property (nonatomic) NSUInteger zoneTimerInterval;
#endif
@end

Expand All @@ -26,12 +27,25 @@ - (instancetype)init
#if (TARGET_OS_IOS)
-(void)setGlobalContentCallback:(ContentCallback) callback
{
self.contentCallback = callback;
_contentCallback = callback;
}

- (ContentCallback) getGlobalContentCallback
{
return self.contentCallback;
return _contentCallback;
}


-(void)setZoneTimerInterval:(NSUInteger)zoneTimerIntervalSeconds
{
if (zoneTimerIntervalSeconds > 15) {
_zoneTimerInterval = zoneTimerIntervalSeconds;
}
}

- (NSUInteger) getZoneTimerInterval
{
return _zoneTimerInterval;
}
#endif

Expand Down
4 changes: 2 additions & 2 deletions CountlyCrashReporter.m
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ void CountlyExceptionHandler(NSException *exception, bool isFatal, bool isAutoDe
NSMutableDictionary* crashReport = [crashData.crashMetrics mutableCopy];
crashReport[kCountlyCRKeyError] = crashData.stackTrace;
crashReport[kCountlyCRKeyBinaryImages] = [CountlyCrashReporter.sharedInstance binaryImagesForStackTrace:stackTrace];
crashReport[kCountlyCRKeyBuildUUID] = CountlyCrashReporter.sharedInstance.buildUUID ?: @"";
crashReport[kCountlyCRKeyExecutableName] = CountlyCrashReporter.sharedInstance.executableName ?: @"";
crashReport[kCountlyCRKeyName] = crashData.crashDescription;
crashReport[kCountlyCRKeyType] = crashData.name;
crashReport[kCountlyCRKeyNonfatal] = @(!crashData.fatal);
Expand Down Expand Up @@ -498,8 +500,6 @@ - (NSMutableDictionary*)getCrashMetrics
crashReport[kCountlyCRKeyResolution] = CountlyDeviceInfo.resolution;
crashReport[kCountlyCRKeyAppVersion] = CountlyDeviceInfo.appVersion;
crashReport[kCountlyCRKeyAppBuild] = CountlyDeviceInfo.appBuild;
crashReport[kCountlyCRKeyBuildUUID] = CountlyCrashReporter.sharedInstance.buildUUID ?: @"";
crashReport[kCountlyCRKeyExecutableName] = CountlyCrashReporter.sharedInstance.executableName ?: @"";

crashReport[kCountlyCRKeyRAMCurrent] = @((CountlyDeviceInfo.totalRAM - CountlyDeviceInfo.freeRAM) / kCLYMebibit);
crashReport[kCountlyCRKeyRAMTotal] = @(CountlyDeviceInfo.totalRAM / kCLYMebibit);
Expand Down
11 changes: 0 additions & 11 deletions CountlyWebViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,6 @@ - (void)createWebViewWithURL:(NSURL *)url
UIViewController *rootViewController = UIApplication.sharedApplication.keyWindow.rootViewController;
CGRect backgroundFrame = rootViewController.view.bounds;

if (@available(iOS 11.0, *)) {
CGFloat top = UIApplication.sharedApplication.keyWindow.safeAreaInsets.top;
backgroundFrame.origin.y += top ? top + 5 : 20.0;
backgroundFrame.size.height -= top ? top + 5 : 20.0;
} else {
backgroundFrame.origin.y += 20.0;
backgroundFrame.size.height -= 20.0;
}

self.backgroundView = [[PassThroughBackgroundView alloc] initWithFrame:backgroundFrame];
self.backgroundView.backgroundColor = [UIColor clearColor];
[rootViewController.view addSubview:self.backgroundView];
Expand Down Expand Up @@ -297,8 +288,6 @@ - (void)resizeWebViewWithJSONString:(NSString *)jsonString {
}];
}



- (void)closeWebView {
dispatch_async(dispatch_get_main_queue(), ^{
if (self.dismissBlock) {
Expand Down
78 changes: 76 additions & 2 deletions PassThroughBackgroundView.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ @implementation PassThroughBackgroundView
- (instancetype)initWithFrame:(CGRect)frame {

self = [super initWithFrame:frame];
if (self) {
}
#if (TARGET_OS_IOS)
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleScreenChange) name:UIDeviceOrientationDidChangeNotification object:nil];
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleScreenChange) name:UIScreenModeDidChangeNotification object:nil];
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleScreenChange) name:UIApplicationDidBecomeActiveNotification object:nil];
#endif
return self;
}

Expand All @@ -31,6 +34,77 @@ - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
return NO;
}

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];

if (self.traitCollection.horizontalSizeClass != previousTraitCollection.horizontalSizeClass) {
[self adjustWebViewForTraitCollection:self.traitCollection];
}
}

- (void)adjustWebViewForTraitCollection:(UITraitCollection *)traitCollection {
if (traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) {
[self handleScreenChange];
}
}

CGSize getWindowSize(void) {
CGSize size = CGSizeZero;

// Attempt to retrieve the size from the connected scenes (for modern apps)
if (@available(iOS 13.0, *)) {
NSSet<UIScene *> *scenes = [[UIApplication sharedApplication] connectedScenes];
for (UIScene *scene in scenes) {
if ([scene isKindOfClass:[UIWindowScene class]]) {
UIWindowScene *windowScene = (UIWindowScene *)scene;
UIWindow *window = windowScene.windows.firstObject;
if (window) {
size = window.bounds.size;
return size; // Return immediately if we find a valid size
}
}
}
}

// Fallback for legacy apps using AppDelegate
id<UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
if ([appDelegate respondsToSelector:@selector(window)]) {
UIWindow *legacyWindow = [appDelegate performSelector:@selector(window)];
if (legacyWindow) {
size = legacyWindow.bounds.size;
}
}

return size;
}

- (void)handleScreenChange {
// Execute after a short delay to ensure properties are updated
dispatch_async(dispatch_get_main_queue(), ^{
[self updateWindowSize];
});
}

- (void)updateWindowSize {
CGSize size = getWindowSize();
CGFloat width = size.width;
CGFloat height = size.height;

NSString *postMessage = [NSString stringWithFormat:
@"javascript:window.postMessage({type: 'resize', width: %f, height: %f}, '*');",
width,
height];
[self.webView evaluateJavaScript:postMessage completionHandler:^(id result, NSError *err) {
if (err != nil) {
CLY_LOG_E(@"[PassThroughBackgroundView] updateWindowSize, %@", err);
}
}];
}

// Always remove observers when the view is deallocated
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end
#endif
Loading