From 7af0a2f98b0a8e0d57c91c6b4c7499233e0b8ce8 Mon Sep 17 00:00:00 2001 From: Kamo Spertsyan Date: Thu, 4 Apr 2024 17:17:06 +0300 Subject: [PATCH 1/2] Remote config list request implemented (#65) * Remote config list request implemented * CR Fixes --- plugin/plugin.xml | 5 +++-- plugin/src/android/QonversionPlugin.java | 17 ++++++++++++++++- plugin/src/ios/CDVQonversionPlugin.h | 2 ++ plugin/src/ios/CDVQonversionPlugin.m | 16 ++++++++++++++++ plugin/src/plugin/Mapper.ts | 10 ++++++++++ plugin/src/plugin/Qonversion.ts | 2 ++ plugin/src/plugin/QonversionApi.ts | 17 +++++++++++++++++ plugin/src/plugin/QonversionInternal.ts | 20 +++++++++++++++++++- plugin/src/plugin/RemoteConfigList.ts | 21 +++++++++++++++++++++ sample/package.json | 6 ++++-- sample/www/index.html | 1 + sample/www/js/index.js | 6 ++++++ sample/yarn.lock | 2 +- 13 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 plugin/src/plugin/RemoteConfigList.ts diff --git a/plugin/plugin.xml b/plugin/plugin.xml index 6822ac0..8bc20bd 100644 --- a/plugin/plugin.xml +++ b/plugin/plugin.xml @@ -36,6 +36,7 @@ + @@ -53,7 +54,7 @@ - + @@ -71,7 +72,7 @@ - + diff --git a/plugin/src/android/QonversionPlugin.java b/plugin/src/android/QonversionPlugin.java index de0acfa..be3db37 100644 --- a/plugin/src/android/QonversionPlugin.java +++ b/plugin/src/android/QonversionPlugin.java @@ -165,11 +165,26 @@ public void restore(CallbackContext callbackContext) { qonversionSandwich.restore(Utils.getResultListener(callbackContext)); } - @PluginAction(thread = ExecutionThread.UI, actionName = "remoteConfig", isAutofinish = false) + @PluginAction(thread = ExecutionThread.WORKER, actionName = "remoteConfig", isAutofinish = false) public void remoteConfig(@Nullable String contextKey, CallbackContext callbackContext) { qonversionSandwich.remoteConfig(contextKey, Utils.getResultListener(callbackContext)); } + @PluginAction(thread = ExecutionThread.WORKER, actionName = "remoteConfigList", isAutofinish = false) + public void remoteConfigList(CallbackContext callbackContext) { + qonversionSandwich.remoteConfigList(Utils.getResultListener(callbackContext)); + } + + @PluginAction(thread = ExecutionThread.WORKER, actionName = "remoteConfigListForContextKeys", isAutofinish = false) + public void remoteConfigListForContextKeys(JSONArray contextKeys, boolean includeEmptyContextKey, CallbackContext callbackContext) { + try { + List keysList = EntitiesConverter.convertArrayToStringList(contextKeys); + qonversionSandwich.remoteConfigList(keysList, includeEmptyContextKey, Utils.getResultListener(callbackContext)); + } catch (JSONException e) { + e.printStackTrace(); + } + } + @PluginAction(thread = ExecutionThread.UI, actionName = "attachUserToExperiment", isAutofinish = false) public void attachUserToExperiment(String experimentId, String groupId, CallbackContext callbackContext) { qonversionSandwich.attachUserToExperiment(experimentId, groupId, Utils.getEmptyResultListener(callbackContext)); diff --git a/plugin/src/ios/CDVQonversionPlugin.h b/plugin/src/ios/CDVQonversionPlugin.h index 6092891..e74910d 100644 --- a/plugin/src/ios/CDVQonversionPlugin.h +++ b/plugin/src/ios/CDVQonversionPlugin.h @@ -35,6 +35,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)promoPurchase:(CDVInvokedUrlCommand *)command; - (void)subscribeOnPromoPurchases:(CDVInvokedUrlCommand *)command; - (void)remoteConfig:(CDVInvokedUrlCommand *)command; +- (void)remoteConfigList:(CDVInvokedUrlCommand *)command; +- (void)remoteConfigListForContextKeys:(CDVInvokedUrlCommand *)command; - (void)attachUserToExperiment:(CDVInvokedUrlCommand *)command; - (void)detachUserFromExperiment:(CDVInvokedUrlCommand *)command; - (void)attachUserToRemoteConfiguration:(CDVInvokedUrlCommand *)command; diff --git a/plugin/src/ios/CDVQonversionPlugin.m b/plugin/src/ios/CDVQonversionPlugin.m index 023a64e..710e531 100644 --- a/plugin/src/ios/CDVQonversionPlugin.m +++ b/plugin/src/ios/CDVQonversionPlugin.m @@ -156,6 +156,22 @@ - (void)remoteConfig:(CDVInvokedUrlCommand *)command { }]; } +- (void)remoteConfigList:(CDVInvokedUrlCommand *)command { + __block __weak CDVQonversionPlugin *weakSelf = self; + [_qonversionSandwich remoteConfigList:^(NSDictionary * _Nullable result, SandwichError * _Nullable error) { + [weakSelf returnCordovaResult:result error:error command:command]; + }]; +} + +- (void)remoteConfigListForContextKeys:(CDVInvokedUrlCommand *)command { + __block __weak CDVQonversionPlugin *weakSelf = self; + NSArray *contextKeys = [command argumentAtIndex:0]; + BOOL includeEmptyContextKey = [[command argumentAtIndex:1] boolValue]; + [_qonversionSandwich remoteConfigList:contextKeys includeEmptyContextKey:includeEmptyContextKey :^(NSDictionary * _Nullable result, SandwichError * _Nullable error) { + [weakSelf returnCordovaResult:result error:error command:command]; + }]; +} + - (void)attachUserToExperiment:(CDVInvokedUrlCommand *)command { __block __weak CDVQonversionPlugin *weakSelf = self; NSString *experimentId = [command argumentAtIndex:0]; diff --git a/plugin/src/plugin/Mapper.ts b/plugin/src/plugin/Mapper.ts index 95f2939..c129afd 100644 --- a/plugin/src/plugin/Mapper.ts +++ b/plugin/src/plugin/Mapper.ts @@ -37,6 +37,7 @@ import {Experiment} from "./Experiment"; import {ExperimentGroup} from "./ExperimentGroup"; import {SubscriptionPeriod} from "./SubscriptionPeriod"; import {RemoteConfig} from "./RemoteConfig"; +import {RemoteConfigList} from "./RemoteConfigList"; import {UserProperties} from './UserProperties'; import {UserProperty} from './UserProperty'; import {RemoteConfigurationSource} from "./RemoteConfigurationSource"; @@ -247,6 +248,10 @@ export type QRemoteConfig = { source: QRemoteConfigurationSource; }; +export type QRemoteConfigList = { + remoteConfigs: Array; +} + type QRemoteConfigurationSource = { id: string; name: string; @@ -1007,6 +1012,11 @@ class Mapper { return new RemoteConfig(remoteConfig.payload, experiment, source); } + static convertRemoteConfigList(remoteConfigList: QRemoteConfigList): RemoteConfigList { + const remoteConfigs = remoteConfigList.remoteConfigs.map(config => this.convertRemoteConfig(config)); + return new RemoteConfigList(remoteConfigs); + } + static convertRemoteConfigurationSourceType(type: String): RemoteConfigurationSourceType { switch (type) { case "experiment_control_group": diff --git a/plugin/src/plugin/Qonversion.ts b/plugin/src/plugin/Qonversion.ts index e296feb..9a9c592 100644 --- a/plugin/src/plugin/Qonversion.ts +++ b/plugin/src/plugin/Qonversion.ts @@ -45,6 +45,7 @@ import {QonversionConfigBuilder} from './QonversionConfigBuilder'; import {Experiment} from "./Experiment"; import {Transaction} from './Transaction'; import {RemoteConfig} from './RemoteConfig'; +import {RemoteConfigList} from './RemoteConfigList'; import {RemoteConfigurationSource} from "./RemoteConfigurationSource"; import {ExperimentGroup} from './ExperimentGroup'; import {SubscriptionPeriod} from './SubscriptionPeriod'; @@ -101,6 +102,7 @@ export default class Qonversion { static Entitlement = Entitlement; static Transaction = Transaction; static RemoteConfig = RemoteConfig; + static RemoteConfigList = RemoteConfigList; static Experiment = Experiment; static LaunchMode = LaunchMode; static Environment = Environment; diff --git a/plugin/src/plugin/QonversionApi.ts b/plugin/src/plugin/QonversionApi.ts index 568476e..e02b299 100644 --- a/plugin/src/plugin/QonversionApi.ts +++ b/plugin/src/plugin/QonversionApi.ts @@ -7,6 +7,7 @@ import {User} from './User'; import {EntitlementsUpdateListener} from './EntitlementsUpdateListener'; import {PromoPurchasesListener} from './PromoPurchasesListener'; import {RemoteConfig} from "./RemoteConfig"; +import {RemoteConfigList} from "./RemoteConfigList"; import {UserProperties} from './UserProperties'; import {PurchaseModel} from './PurchaseModel'; import {PurchaseUpdateModel} from './PurchaseUpdateModel'; @@ -137,6 +138,22 @@ export interface QonversionApi { */ remoteConfig(contextKey: string | undefined): Promise + /** + * Returns Qonversion remote config objects for all existing context key (including empty one). + * Use this function to get the remote config with specific payload and experiment info. + * @returns the promise with the remote config list. + */ + remoteConfigList(): Promise + + /** + * Returns Qonversion remote config objects by a list of {@link contextKeys}. + * Use this function to get the remote config with specific payload and experiment info. + * @param contextKeys list of context keys to load remote configs for + * @param includeEmptyContextKey set to true if you want to include remote config with empty context key to the result + * @returns the promise with the remote config list. + */ + remoteConfigListForContextKeys(contextKeys: Array, includeEmptyContextKey: boolean): Promise + /** * This function should be used for the test purposes only. Do not forget to delete the usage of this function before the release. * Use this function to attach the user to the experiment. diff --git a/plugin/src/plugin/QonversionInternal.ts b/plugin/src/plugin/QonversionInternal.ts index 79652a6..a2e35d5 100644 --- a/plugin/src/plugin/QonversionInternal.ts +++ b/plugin/src/plugin/QonversionInternal.ts @@ -5,6 +5,7 @@ import Mapper, { QOfferings, QProduct, QRemoteConfig, + QRemoteConfigList, QTrialIntroEligibility, QUser, QUserProperties @@ -19,6 +20,7 @@ import {QonversionApi} from './QonversionApi'; import {QonversionConfig} from './QonversionConfig'; import {EntitlementsUpdateListener} from './EntitlementsUpdateListener'; import {RemoteConfig} from "./RemoteConfig"; +import {RemoteConfigList} from "./RemoteConfigList"; import {UserProperties} from './UserProperties'; import {PurchaseModel} from './PurchaseModel'; import {PurchaseUpdateModel} from './PurchaseUpdateModel'; @@ -197,7 +199,7 @@ export default class QonversionInternal implements QonversionApi { } async remoteConfig(contextKey: string | undefined): Promise { - let remoteConfig = await callNative('remoteConfig', [contextKey]); + const remoteConfig = await callNative('remoteConfig', [contextKey]); // noinspection UnnecessaryLocalVariableJS const mappedRemoteConfig: RemoteConfig = Mapper.convertRemoteConfig( remoteConfig @@ -206,6 +208,22 @@ export default class QonversionInternal implements QonversionApi { return mappedRemoteConfig; } + async remoteConfigList(): Promise { + const remoteConfigList = await callNative('remoteConfigList'); + // noinspection UnnecessaryLocalVariableJS + const mappedRemoteConfigList: RemoteConfigList = Mapper.convertRemoteConfigList(remoteConfigList); + + return mappedRemoteConfigList; + } + + async remoteConfigListForContextKeys(contextKeys: string[], includeEmptyContextKey: boolean): Promise { + let remoteConfigList = await callNative('remoteConfigListForContextKeys', [contextKeys, includeEmptyContextKey]); + // noinspection UnnecessaryLocalVariableJS + const mappedRemoteConfigList: RemoteConfigList = Mapper.convertRemoteConfigList(remoteConfigList); + + return mappedRemoteConfigList; + } + async attachUserToExperiment(experimentId: string, groupId: string): Promise { await callNative('attachUserToExperiment', [experimentId, groupId]); return; diff --git a/plugin/src/plugin/RemoteConfigList.ts b/plugin/src/plugin/RemoteConfigList.ts new file mode 100644 index 0000000..adbd4e2 --- /dev/null +++ b/plugin/src/plugin/RemoteConfigList.ts @@ -0,0 +1,21 @@ +import {RemoteConfig} from './RemoteConfig'; + +export class RemoteConfigList { + remoteConfigs: Array; + + constructor(remoteConfigs: Array) { + this.remoteConfigs = remoteConfigs; + } + + remoteConfigForContextKey(contextKey: string): RemoteConfig | undefined { + return this.findRemoteConfigForContextKey(contextKey); + } + + remoteConfigForEmptyContextKey(): RemoteConfig | undefined { + return this.findRemoteConfigForContextKey(null); + } + + private findRemoteConfigForContextKey(contextKey: string | null): RemoteConfig | undefined { + return this.remoteConfigs.find(config => config.source.contextKey == contextKey); + } +} diff --git a/sample/package.json b/sample/package.json index ff75fac..0597414 100644 --- a/sample/package.json +++ b/sample/package.json @@ -28,6 +28,8 @@ "android", "ios" ], - "plugins": {} + "plugins": { + "cordova-plugin-qonversion": {} + } } -} +} \ No newline at end of file diff --git a/sample/www/index.html b/sample/www/index.html index 7fc9897..42287b0 100644 --- a/sample/www/index.html +++ b/sample/www/index.html @@ -57,6 +57,7 @@

Qonversion Cordova Plugin

+
diff --git a/sample/www/js/index.js b/sample/www/js/index.js index b1c6b22..395939f 100644 --- a/sample/www/js/index.js +++ b/sample/www/js/index.js @@ -29,6 +29,7 @@ const app = { document.getElementById("update-purchase").addEventListener("click", this.updatePurchase); document.getElementById("get-products").addEventListener("click", this.getProducts); document.getElementById("get-remote-config").addEventListener("click", this.getRemoteConfig); + document.getElementById("get-remote-config-list").addEventListener("click", this.getRemoteConfigList); document.getElementById("get-offerings").addEventListener("click", this.getOfferings); document.getElementById("check-trial-into").addEventListener("click", this.checkTrialIntroEligibility); document.getElementById("check-entitlements").addEventListener("click", this.checkEntitlements); @@ -113,6 +114,11 @@ const app = { console.log('Qonversion remote config:', remoteConfig); }, + async getRemoteConfigList() { + const remoteConfigList = await Qonversion.getSharedInstance().remoteConfigList(); + console.log('Qonversion remote config list:', remoteConfigList); + }, + async getOfferings() { const offerings = await Qonversion.getSharedInstance().offerings(); console.log('Qonversion offerings:', offerings); diff --git a/sample/yarn.lock b/sample/yarn.lock index 2021512..e5ad1d7 100644 --- a/sample/yarn.lock +++ b/sample/yarn.lock @@ -184,7 +184,7 @@ cordova-plugin-device@^2.1.0: integrity sha512-FU0Lw1jZpuKOgG4v80LrfMAOIMCGfAVPumn7AwaX9S1iU/X3OPZUyoKUgP09q4bxL35IeNPkqNWVKYduAXZ1sg== "cordova-plugin-qonversion@file:../plugin": - version "5.0.0" + version "5.2.0" resolved "file:../plugin" cross-spawn@^7.0.1, cross-spawn@^7.0.3: From 857489817ea149d4ebb68779f1089e770fd418a1 Mon Sep 17 00:00:00 2001 From: SpertsyanKM Date: Thu, 4 Apr 2024 14:18:33 +0000 Subject: [PATCH 2/2] [create-pull-request] automated change --- plugin/package.json | 2 +- plugin/src/plugin/QonversionInternal.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/package.json b/plugin/package.json index b379c3c..4750636 100644 --- a/plugin/package.json +++ b/plugin/package.json @@ -1,6 +1,6 @@ { "name": "cordova-plugin-qonversion", - "version": "5.2.0", + "version": "5.3.0", "description": "Qonversion Cordova Plugin", "cordova": { "id": "cordova-plugin-qonversion", diff --git a/plugin/src/plugin/QonversionInternal.ts b/plugin/src/plugin/QonversionInternal.ts index a2e35d5..c03a48b 100644 --- a/plugin/src/plugin/QonversionInternal.ts +++ b/plugin/src/plugin/QonversionInternal.ts @@ -25,7 +25,7 @@ import {UserProperties} from './UserProperties'; import {PurchaseModel} from './PurchaseModel'; import {PurchaseUpdateModel} from './PurchaseUpdateModel'; -const sdkVersion = "5.2.0"; +const sdkVersion = "5.3.0"; export default class QonversionInternal implements QonversionApi {