Skip to content

Commit d8273ec

Browse files
authored
Merge pull request #443 from Countly/25.01-release-branch
25.01 release branch
2 parents 766f87d + 0f65908 commit d8273ec

38 files changed

+1530
-174
lines changed

CHANGELOG.md

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,52 @@
1-
## XX.X.X
2-
* ! Minor breaking change ! User properties will now be automatically saved under the following conditions:
3-
* When an event is recorded
4-
* During an internal timer tick
5-
* Upon flushing the event queue
1+
## 25.1.0
2+
* ! Minor breaking change ! `Countly.userDataBulk.save()` method is now optional. SDK will save the cached data with internal triggers regularly.
3+
64
* Added Content feature methods:
75
* `enterContentZone`, to start Content checks (Experimental!)
86
* `exitContentZone`, to stop Content checks (Experimental!)
7+
* Added feedback widget convenience methods to display the first available widget or the one meets the criteria:
8+
* `Countly.feedback.showNPS(nameIDorTag?: string, widgetClosedCallback?: WidgetCallback): void`
9+
* `Countly.feedback.showSurvey(nameIDorTag?: string, widgetClosedCallback?: WidgetCallback): void`
10+
* `Countly.feedback.showRating(nameIDorTag?: string, widgetClosedCallback?: WidgetCallback): void`
11+
* Added config interface `experimental` that provides experimental config options:
12+
* `.experimental.enablePreviousNameRecording()` for reporting previous event/view names
13+
* `.experimental.enableVisibilityTracking()` for reporting app visibility with events
914
* Added `Countly.deviceId.setID` method for changing device ID based on the device ID type
10-
* Mitigated an issue where a session could have started while the app was in the background when the device ID was changed (non-merge).
15+
* Added support for Arrays of primitive types in event segmentation
16+
1117
* Deprecated following SDK calls:
1218
* `Countly.getCurrentDeviceId` (replaced with: `Countly.deviceId.getID`)
1319
* `Countly.getDeviceIDType` (replaced with: `Countly.deviceId.getType`)
1420
* `Countly.changeDeviceId` (replaced with: `Countly.deviceId.setID`)
21+
22+
* Mitigated an issue where a session could have started while the app was in the background when the device ID was changed (non-merge).
23+
* Mitigated an issue where intent redirection checks were disabled by default
24+
* Mitigated an issue crash tracking was not enabled with init config
25+
* Mitigated an issue where app start time tracking was on by default
26+
1527
* Android Specific Changes:
1628
* ! Minor breaking change ! Unsupported types for user properties will now be omitted, they won't be converted to strings.
1729
* Disabled caching for webviews.
1830
* Mitigated an issue in the upload plugin that prevented the upload of a symbol file
1931
* Resolved a problem where revoked consents were sent after changes without merging.
20-
* Fixed a bug that caused the device ID to be incorrectly set after changes with merging.
32+
* Mitigated an issue that caused the device ID to be incorrectly set after changes with merging.
2133
* Mitigated an issue where on consent revoke, remote config values were cleared, not anymore.
2234

2335
* iOS Specific Changes:
36+
* Orientation info is now also sent during initialization
2437
* Added visionOS build support
38+
* Updated the SDK to ensure compatibility with the latest server response models
39+
* Improved view tracking capabilities
2540
* Mitigated an issue with the feedback widget URL encoding on iOS 16 and earlier, which prevented the widget from displaying
2641
* Mitigated an issue with content fetch URL encoding on iOS 16 and earlier, which caused the request to fail
2742
* Mitigated an issue where the terms and conditions URL (`tc` key) was sent without double quotes
28-
* Orientation info is now also sent during initialization
2943
* Mitigated an issue where consent information was not sent when no consent was given during initialization
3044
* Mitigated an issue where a session did not end when session consent was removed
31-
* Updated the SDK to ensure compatibility with the latest server response models
45+
* Mitigated an issue where pausing a view resulted in a '0' view duration.
46+
* Mitigated an issue where the user provided URLSessionConfiguration was not applied to direct requests
3247

33-
* Updated the underlying Android SDK version to 24.7.4
34-
* Updated the underlying iOS SDK version to 24.7.4
48+
* Updated the underlying Android SDK version to 24.7.8
49+
* Updated the underlying iOS SDK version to 24.7.9
3550

3651
## 24.4.1
3752
* Added support for Feedback Widget terms and conditions

Countly.d.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
interface Segmentation {
2-
[key: string]: number | string | boolean;
2+
[key: string]: number | string | boolean | (number | string | boolean)[];
33
}
44

55
interface CountlyEventOptions {
@@ -89,6 +89,29 @@ declare module "countly-sdk-react-native-bridge" {
8989
* Countly Feedback Module
9090
*/
9191
namespace feedback {
92+
93+
/**
94+
* Shows the first available NPS widget that meets the criteria.
95+
* @param {String} [nameIDorTag] - name, id, or tag of the widget to show (optional)
96+
* @param {callback} [widgetClosedCallback] - called when the widget is closed (optional)
97+
*/
98+
export function showNPS(nameIDorTag?: string, widgetClosedCallback?: WidgetCallback): void;
99+
100+
/**
101+
* Shows the first available survey widget that meets the criteria.
102+
* @param {String} [nameIDorTag] - name, id, or tag of the widget to show (optional)
103+
* @param {callback} [widgetClosedCallback] - called when the widget is closed (optional)
104+
*/
105+
export function showSurvey(nameIDorTag?: string, widgetClosedCallback?: WidgetCallback): void;
106+
107+
/**
108+
* Shows the first available rating widget that meets the criteria.
109+
* @param {String} [nameIDorTag] - name, id, or tag of the widget to show (optional)
110+
* @param {callback} [widgetClosedCallback] - called when the widget is closed (optional)
111+
*/
112+
export function showRating(nameIDorTag?: string, widgetClosedCallback?: WidgetCallback): void;
113+
114+
92115
/**
93116
* Get a list of available feedback widgets as an array of objects.
94117
* @param {FeedbackWidgetCallback} [onFinished] - returns (retrievedWidgets, error). This parameter is optional.
@@ -106,7 +129,7 @@ declare module "countly-sdk-react-native-bridge" {
106129
*
107130
* @return {ErrorObject} object {error: string or null}
108131
*/
109-
export function presentFeedbackWidget(feedbackWidget: FeedbackWidget, closeButtonText: string, widgetShownCallback: callback, widgetClosedCallback: callback): ErrorObject;
132+
export function presentFeedbackWidget(feedbackWidget: FeedbackWidget, closeButtonText: string, widgetShownCallback: WidgetCallback, widgetClosedCallback: WidgetCallback): ErrorObject;
110133

111134
/**
112135
* Get a feedback widget's data as an object.
@@ -1145,6 +1168,18 @@ declare module "countly-sdk-react-native-bridge" {
11451168
}
11461169

11471170
declare module "countly-sdk-react-native-bridge/CountlyConfig" {
1171+
interface experimental {
1172+
/**
1173+
* Enables previous name recording for views and events
1174+
*/
1175+
enablePreviousNameRecording(): this;
1176+
1177+
/**
1178+
* Enables app visibility tracking with events.
1179+
*/
1180+
enableVisibilityTracking(): this;
1181+
}
1182+
11481183
/**
11491184
*
11501185
* This class holds APM specific configurations to be used with
@@ -1237,6 +1272,11 @@ declare module "countly-sdk-react-native-bridge/CountlyConfig" {
12371272
*/
12381273
sdkInternalLimits: CountlyConfigSDKInternalLimits;
12391274

1275+
/**
1276+
* getter for experimental features
1277+
*/
1278+
experimental: experimental;
1279+
12401280
/**
12411281
* Method to set the server url
12421282
*

CountlyConfig.js

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { initialize } from "./Logger.js";
22
import CountlyConfigApm from "./lib/configuration_interfaces/countly_config_apm.js";
33
import CountlyConfigSDKInternalLimits from "./lib/configuration_interfaces/countly_config_limits.js";
4+
import CountlyConfigExp from "./lib/configuration_interfaces/countly_config_experimental.js";
45
/**
56
* Countly SDK React Native Bridge
67
* https://github.com/Countly/countly-sdk-react-native-bridge
@@ -15,11 +16,15 @@ import CountlyConfigSDKInternalLimits from "./lib/configuration_interfaces/count
1516
* @param {String} appKey application key
1617
*/
1718
class CountlyConfig {
19+
#crashReporting = false;
20+
#apmLegacy = false;
21+
#disableIntentRedirectionCheck = false;
1822
constructor(serverURL, appKey) {
1923
this.serverURL = serverURL;
2024
this.appKey = appKey;
2125
this._countlyConfigApmInstance = new CountlyConfigApm();
2226
this._countlyConfigSDKLimitsInstance = new CountlyConfigSDKInternalLimits();
27+
this._countlyConfigExpInstance = new CountlyConfigExp();
2328
}
2429

2530
/**
@@ -29,10 +34,32 @@ class CountlyConfig {
2934
return this._countlyConfigApmInstance;
3035
}
3136

37+
/**
38+
* Getter to get the SDK internal limits
39+
*/
3240
get sdkInternalLimits() {
3341
return this._countlyConfigSDKLimitsInstance;
3442
}
3543

44+
/**
45+
* Getter to get the experimental configurations
46+
*/
47+
get experimental() {
48+
return this._countlyConfigExpInstance;
49+
}
50+
51+
get _crashReporting() {
52+
return this.#crashReporting;
53+
}
54+
55+
get _apmLegacy() {
56+
return this.#apmLegacy;
57+
}
58+
59+
get _disableIntentRedirectionCheck() {
60+
return this.#disableIntentRedirectionCheck;
61+
}
62+
3663
/**
3764
* Method to set the server url
3865
*
@@ -79,7 +106,7 @@ class CountlyConfig {
79106
* Method to enable crash reporting to report unhandled crashes to Countly
80107
*/
81108
enableCrashReporting() {
82-
this.crashReporting = true;
109+
this.#crashReporting = true;
83110
return this;
84111
}
85112

@@ -142,7 +169,7 @@ class CountlyConfig {
142169
* Method to enable application performance monitoring which includes the recording of app start time.
143170
*/
144171
enableApm() {
145-
this.enableApm = true;
172+
this.#apmLegacy = true;
146173
return this;
147174
}
148175

@@ -151,7 +178,7 @@ class CountlyConfig {
151178
* This method should be used to disable them.
152179
*/
153180
disableAdditionalIntentRedirectionChecks() {
154-
this.disableAdditionalIntentRedirectionChecks = true;
181+
this.#disableIntentRedirectionCheck = true;
155182
return this;
156183
}
157184

CountlyReactNative.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'CountlyReactNative'
3-
s.version = '24.4.1'
3+
s.version = '25.1.0'
44
s.license = {
55
:type => 'COMMUNITY',
66
:text => <<-LICENSE

Feedback.js

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,76 @@ class Feedback {
77
this.#state = state;
88
}
99

10+
/**
11+
* Shows the first available NPS widget that meets the criteria.
12+
* @param {String} [nameIDorTag] - name, id, or tag of the widget to show (optional)
13+
* @param {callback} [callback] - called when the widget is closed (optional)
14+
*/
15+
showNPS(nameIDorTag, callback) {
16+
L.i(`showNPS, Will show NPS widget with name, id, or tag: [${nameIDorTag}], callback provided: [${typeof callback === "function"}]`);
17+
this.#showInternalFeedback("nps", nameIDorTag, callback);
18+
}
19+
/**
20+
* Shows the first available Survey widget that meets the criteria.
21+
* @param {String} [nameIDorTag] - name, id, or tag of the widget to show (optional)
22+
* @param {callback} [callback] - called when the widget is closed (optional)
23+
*/
24+
showSurvey(nameIDorTag, callback) {
25+
L.i(`showSurvey, Will show Survey widget with name, id, or tag: [${nameIDorTag}], callback provided: [${typeof callback === "function"}]`);
26+
this.#showInternalFeedback("survey", nameIDorTag, callback);
27+
}
28+
29+
/**
30+
* Shows the first available Rating widget that meets the criteria.
31+
* @param {String} [nameIDorTag] - name, id, or tag of the widget to show (optional)
32+
* @param {callback} [callback] - called when the widget is closed (optional)
33+
*/
34+
showRating(nameIDorTag, callback) {
35+
L.i(`showRating, Will show Rating widget with name, id, or tag: [${nameIDorTag}], callback provided: [${typeof callback === "function"}]`);
36+
this.#showInternalFeedback("rating", nameIDorTag, callback);
37+
}
38+
39+
#showInternalFeedback(widgetType, nameIDorTag, callback) {
40+
if (!this.#state.isInitialized) {
41+
L.e(`showInternalFeedback, 'init' must be called before 'showInternalFeedback'`);
42+
return;
43+
}
44+
if (typeof nameIDorTag !== "string") {
45+
L.d(`showInternalFeedback, unsupported data type of nameIDorTag or its not given : [${typeof nameIDorTag}]`);
46+
}
47+
this.getAvailableFeedbackWidgets((retrievedWidgets, error) => {
48+
if (error) {
49+
L.e(`showInternalFeedback, ${error}`);
50+
return;
51+
}
52+
if (!retrievedWidgets || retrievedWidgets.length === 0) {
53+
L.d(`showInternalFeedback, no feedback widgets found`);
54+
return;
55+
}
56+
L.d(`showInternalFeedback, Found [${retrievedWidgets.length}] feedback widgets`);
57+
let widget = retrievedWidgets.find(w => w.type === widgetType);
58+
try {
59+
if (nameIDorTag && typeof nameIDorTag === 'string') {
60+
const matchedWidget = retrievedWidgets.find(w =>
61+
w.type === widgetType && (w.name === nameIDorTag || w.id === nameIDorTag || w.tags.includes(nameIDorTag))
62+
);
63+
if (matchedWidget) {
64+
widget = matchedWidget;
65+
L.v(`showInternalFeedback, Found ${widgetType} widget by name, id, or tag: [${JSON.stringify(matchedWidget)}]`);
66+
}
67+
}
68+
} catch (error) {
69+
L.e(`showInternalFeedback, Error while finding widget: ${error}`);
70+
}
71+
72+
if (!widget) {
73+
L.d(`showInternalFeedback, No ${widgetType} widget found.`);
74+
return;
75+
}
76+
this.presentFeedbackWidget(widget, null, null, callback);
77+
});
78+
}
79+
1080
/**
1181
* Get a list of available feedback widgets as an array of objects.
1282
* @param {callback} [onFinished] - returns (retrievedWidgets, error). This parameter is optional.
@@ -19,7 +89,7 @@ class Feedback {
1989
return { error: message, data: null };
2090
}
2191

22-
L.d("getAvailableFeedbackWidgets, getAvailableFeedbackWidgets");
92+
L.d("getAvailableFeedbackWidgets, fetching available feedback widgets");
2393
let result = null;
2494
let error = null;
2595
try {

0 commit comments

Comments
 (0)