From 89e5e8836ddadffd1560e4f840f73acbded4ba97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=20R=C4=B1za=20Kat?= Date: Tue, 5 Nov 2024 14:45:03 +0300 Subject: [PATCH 1/5] Android Array Support Added --- Countly.d.ts | 4 +++- Validators.js | 14 ++++++----- .../android/sdk/react/CountlyReactNative.java | 24 +++++++++++++++++++ example/CountlyRNExample/Events.tsx | 9 +++++++ 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/Countly.d.ts b/Countly.d.ts index 8de656e9..c5b83d36 100644 --- a/Countly.d.ts +++ b/Countly.d.ts @@ -1,5 +1,7 @@ +type SegmentationValue = number | string | boolean | SegmentationValue[]; + interface Segmentation { - [key: string]: number | string | boolean; + [key: string]: SegmentationValue; } interface CountlyEventOptions { diff --git a/Validators.js b/Validators.js index 9f09e424..c626e517 100644 --- a/Validators.js +++ b/Validators.js @@ -134,28 +134,30 @@ function areEventParametersValid(functionName, eventName, segmentation, eventCou return false; } - // validate segmentation values if (segmentation) { for (const key in segmentation) { const value = segmentation[key]; const valueType = typeof value; - if (value && valueType !== "string" && valueType !== "number" && valueType !== "boolean") { - L.w(`${functionName}, segmentation value: [${value}] for the key: [${key}] must be a number, string or boolean!`); + if (Array.isArray(value)) { + // check array elements + if (!value.every(item => ["string", "number", "boolean"].includes(typeof item))) { + L.w(`${functionName}, segmentation value: [${value}] for the key: [${key}] must contain only strings, numbers, or booleans in the array!`); + return false; + } + } else if (value && valueType !== "string" && valueType !== "number" && valueType !== "boolean") { + L.w(`${functionName}, segmentation value: [${value}] for the key: [${key}] must be a number, string, boolean, or an array of these types!`); return false; } } } - if (eventCount && (typeof eventCount !== "number" || eventCount < 0)) { L.w(`${functionName}, provided eventCount: [${eventCount}]. It must be a positive number!`); return false; } - if (eventSum && typeof eventSum !== "number") { L.w(`${functionName}, provided eventSum: [${eventSum}]. It must be a number!`); return false; } - return true; } diff --git a/android/src/main/java/ly/count/android/sdk/react/CountlyReactNative.java b/android/src/main/java/ly/count/android/sdk/react/CountlyReactNative.java index 5ccfda9a..5e738b44 100644 --- a/android/src/main/java/ly/count/android/sdk/react/CountlyReactNative.java +++ b/android/src/main/java/ly/count/android/sdk/react/CountlyReactNative.java @@ -1680,6 +1680,30 @@ public Map convertToEventMap(ReadableArray segments) { segmentation.put(key, doubleValue); } break; + case Array: + ReadableArray arrayValue = segments.getArray(i + 1); + List arrayList = new ArrayList<>(); + for (int j = 0; j < arrayValue.size(); j++) { + ReadableType elementType = arrayValue.getType(j); + switch (elementType) { + case String: + arrayList.add(arrayValue.getString(j)); + break; + case Boolean: + arrayList.add(arrayValue.getBoolean(j)); + break; + case Number: + double elemDouble = arrayValue.getDouble(j); + int elemInt = (int) elemDouble; + arrayList.add(elemDouble == elemInt ? elemInt : elemDouble); + break; + default: + // Skip non-primitive types + break; + } + } + segmentation.put(key, arrayList); + break; default: // Skip other types break; diff --git a/example/CountlyRNExample/Events.tsx b/example/CountlyRNExample/Events.tsx index e6276732..fd0e339c 100644 --- a/example/CountlyRNExample/Events.tsx +++ b/example/CountlyRNExample/Events.tsx @@ -16,6 +16,15 @@ const eventWithSegment = () => { // example for event with segment Countly.events.recordEvent("Event With Segment", { Country: "Paris", Age: 28 }, 1, undefined); Countly.events.recordEvent("Event With Segment", { Country: "France", Age: 38 }, 1, undefined); + Countly.events.recordEvent("Event With Segment With Mixed Types", { + Country: "UK", + Active: true, + JerseyNo: 11, + Names: ["James", "Bond"], + AgeRange: [25, 30], + Bools: [true, false, false], + Preferences: ["Music", 42, true] + }, 1, undefined); }; const eventWithSumAndSegment = () => { // example for event with segment and sum From 3ff2261e0bc8028fe0b94307787c0e1fbf91a81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=20R=C4=B1za=20Kat?= Date: Tue, 5 Nov 2024 14:52:15 +0300 Subject: [PATCH 2/5] Update Countly.d.ts --- Countly.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Countly.d.ts b/Countly.d.ts index c5b83d36..38db3366 100644 --- a/Countly.d.ts +++ b/Countly.d.ts @@ -1,7 +1,7 @@ type SegmentationValue = number | string | boolean | SegmentationValue[]; interface Segmentation { - [key: string]: SegmentationValue; + [key: string]: SegmentationValue; } interface CountlyEventOptions { From 1f6324c6dce8643ef86fa4166b9fc40c70e63fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=20R=C4=B1za=20Kat?= Date: Tue, 5 Nov 2024 17:16:16 +0300 Subject: [PATCH 3/5] Updated the check --- Validators.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Validators.js b/Validators.js index c626e517..2430ae04 100644 --- a/Validators.js +++ b/Validators.js @@ -144,8 +144,8 @@ function areEventParametersValid(functionName, eventName, segmentation, eventCou L.w(`${functionName}, segmentation value: [${value}] for the key: [${key}] must contain only strings, numbers, or booleans in the array!`); return false; } - } else if (value && valueType !== "string" && valueType !== "number" && valueType !== "boolean") { - L.w(`${functionName}, segmentation value: [${value}] for the key: [${key}] must be a number, string, boolean, or an array of these types!`); + } else if (value && !["string", "number", "boolean"].includes(typeof value)) { + L.w(`${functionName}, segmentation value: [${value}] for the key: [${key}] must be a string, number, or boolean!`); return false; } } From 61f3a88d251f65bb5a65a5b014985f743d2cd665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=20R=C4=B1za=20Kat?= Date: Tue, 12 Nov 2024 19:20:29 +0300 Subject: [PATCH 4/5] Update Validators.js --- Validators.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Validators.js b/Validators.js index 2430ae04..ad73fa10 100644 --- a/Validators.js +++ b/Validators.js @@ -137,15 +137,8 @@ function areEventParametersValid(functionName, eventName, segmentation, eventCou if (segmentation) { for (const key in segmentation) { const value = segmentation[key]; - const valueType = typeof value; - if (Array.isArray(value)) { - // check array elements - if (!value.every(item => ["string", "number", "boolean"].includes(typeof item))) { - L.w(`${functionName}, segmentation value: [${value}] for the key: [${key}] must contain only strings, numbers, or booleans in the array!`); - return false; - } - } else if (value && !["string", "number", "boolean"].includes(typeof value)) { - L.w(`${functionName}, segmentation value: [${value}] for the key: [${key}] must be a string, number, or boolean!`); + if (!value) { + L.w(`${functionName}, provided value for the key: [${key}] is null!`); return false; } } From ca7a2013b17890bd777c354b8b9a0a7e1fdc83c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ali=20R=C4=B1za=20Kat?= Date: Tue, 12 Nov 2024 19:54:41 +0300 Subject: [PATCH 5/5] Updated Example --- Countly.d.ts | 2 +- example/CountlyRNExample/Events.tsx | 34 +++++++++++++++++++---------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/Countly.d.ts b/Countly.d.ts index 38db3366..ad039875 100644 --- a/Countly.d.ts +++ b/Countly.d.ts @@ -1,4 +1,4 @@ -type SegmentationValue = number | string | boolean | SegmentationValue[]; +type SegmentationValue = number | string | boolean | SegmentationValue[] | { [key: string]: SegmentationValue }; interface Segmentation { [key: string]: SegmentationValue; diff --git a/example/CountlyRNExample/Events.tsx b/example/CountlyRNExample/Events.tsx index fd0e339c..fb2e2650 100644 --- a/example/CountlyRNExample/Events.tsx +++ b/example/CountlyRNExample/Events.tsx @@ -13,18 +13,28 @@ const eventWithSum = () => { Countly.events.recordEvent("Event With Sum", undefined, 1, 0.99); }; const eventWithSegment = () => { - // example for event with segment - Countly.events.recordEvent("Event With Segment", { Country: "Paris", Age: 28 }, 1, undefined); - Countly.events.recordEvent("Event With Segment", { Country: "France", Age: 38 }, 1, undefined); - Countly.events.recordEvent("Event With Segment With Mixed Types", { - Country: "UK", - Active: true, - JerseyNo: 11, - Names: ["James", "Bond"], - AgeRange: [25, 30], - Bools: [true, false, false], - Preferences: ["Music", 42, true] - }, 1, undefined); + const segment: Segmentation = { + stringList: ['value1', 'value2', 'value3'], + intList: [1, 2, 3], + doubleList: [1.1, 2.2, 3.3], + boolList: [true, false, true], + mixedList: ['value1', 2, 3.3, true], + mapList: [ // currently this is not supported + { key1: 'value1', key2: 2 }, + { key1: 'value2', key2: 3 }, + { key1: 'value3', key2: 4 } + ], + nestedList: [ // currently this is not supported + ['value1', 'value2'], + ['value3', 'value4'], + ['value5', 'value6'] + ], + normalString: 'normalString', + normalInt: 1, + normalDouble: 1.1, + normalBool: true + }; + Countly.events.recordEvent("Event With Segment With Mixed Types", segment, 1, undefined); }; const eventWithSumAndSegment = () => { // example for event with segment and sum