From 90e7d356a3ef467ec961178fe9f79448e1f4d67d Mon Sep 17 00:00:00 2001 From: ijunaid Date: Tue, 15 Dec 2020 22:01:53 +0500 Subject: [PATCH] [sdk-187] Added feedback widget: (#78) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 20.11.0 Features Added: - Added Surveys and NPS feedback widgets - Added replaceAllAppKeysInQueueWithCurrentAppKey method to replace all app keys in queue with the current app key - Added removeDifferentAppKeysFromQueue method to remove all different app keys from the queue - Added setStarRatingDialogTexts method to set text's for different fields of star rating dialog - Added recordAttributionID method for iOS. * getDeviceIdAuthor implemented for iOS. * Android sdk version updated * Countly pod updated to 20.11.1 for iOS and some small fixes. * Googleservices enables for plugin * Feedback widget changes implemented: — getFeebackwidgets return list of object. — presentFeedbackWidget accept widget object as a parameter. --- Countly.js | 105 ++++++++++++++++++++++++++++++-- index.html | 31 +++++++++- package.js | 2 +- package.json | 2 +- plugin.xml | 11 ++-- src/android/CountlyCordova.java | 36 +++++++++++ src/android/CountlyNative.java | 97 ++++++++++++++++++++++++++++- src/ios/CountlyCordova.h | 6 ++ src/ios/CountlyCordova.m | 72 ++++++++++++++++++++++ src/ios/CountlyNative.m | 69 ++++++++++++++++++--- 10 files changed, 409 insertions(+), 22 deletions(-) diff --git a/Countly.js b/Countly.js index 475b66f..19590fb 100644 --- a/Countly.js +++ b/Countly.js @@ -2,7 +2,7 @@ Countly = {}; Countly.serverUrl = ""; Countly.appKey = ""; Countly.ready = false; -Countly.version = "20.04"; +Countly.version = "20.11.0"; Countly.isDebug = false; var userAgent = navigator.userAgent || navigator.vendor || window.opera; if (/android/i.test(userAgent)) { @@ -496,6 +496,20 @@ Countly.rating = { // cordova.exec(Countly.onSuccess,Countly.onError,"CountlyCordova","sendRating",[rating.toString()]); // } +/** + * Set's the text's for the different fields in the star rating dialog. Set value null if for some field you want to keep the old value + * + * @param {String} starRatingTextTitle - dialog's title text (Only for Android) + * @param {String} starRatingTextMessage - dialog's message text + * @param {String} starRatingTextDismiss - dialog's dismiss buttons text (Only for Android) + */ +Countly.setStarRatingDialogTexts = function(starRatingTextTitle, starRatingTextMessage, starRatingTextDismiss){ + var args = []; + args.push(starRatingTextTitle); + args.push(starRatingTextMessage); + args.push(starRatingTextDismiss); + cordova.exec(Countly.onSuccess,Countly.onError,"CountlyCordova","setStarRatingDialogTexts",args); +} // ui related methods // opens the modal Countly.askForStarRating = function(callback){ @@ -505,7 +519,65 @@ Countly.askForStarRating = function(callback){ Countly.askForFeedback = function(widgetId, buttonText){ cordova.exec(Countly.onSuccess,Countly.onError,"CountlyCordova","askForFeedback",[widgetId, buttonText || ""]); } -// FEEDBACK-WORK + +/** + * Get a list of available feedback widgets for this device ID + */ +Countly.getFeedbackWidgets = function(){ + return new Promise((resolve,reject) => { + cordova.exec(resolve,reject,"CountlyCordova","getFeedbackWidgets",[]); + }); +} + +/** + * Present a chosen feedback widget + * + * @param {Object} feedbackWidget - feeback Widget with id, type and name + * @param {String} closeButtonText - text for cancel/close button + */ +Countly.presentFeedbackWidget = function(feedbackWidget, buttonText){ + if(!feedbackWidget) { + if(Countly.isDebug) { + console.error("[CountlyCordova] presentFeedbackWidget, feedbackWidget should not be null or undefined"); + } + return "feedbackWidget should not be null or undefined"; + } + if(!feedbackWidget.id) { + if(Countly.isDebug){ + console.error("[CountlyCordova] presentFeedbackWidget, feedbackWidget id should not be null or empty"); + } + return "FeedbackWidget id should not be null or empty"; + } + if(!feedbackWidget.type) { + if(Countly.isDebug){ + console.error("[CountlyCordova] presentFeedbackWidget, feedbackWidget type should not be null or empty"); + } + return "FeedbackWidget type should not be null or empty"; + } + var widgetId = feedbackWidget.id; + var widgetType = feedbackWidget.type; + var widgetName = feedbackWidget.name || ""; + buttonText = buttonText || ""; + cordova.exec(Countly.onSuccess,Countly.onError,"CountlyCordova","presentFeedbackWidget",[widgetId, widgetType, widgetName, buttonText]); +} + +/** + * Replaces all requests with a different app key with the current app key. + * In request queue, if there are any request whose app key is different than the current app key, + * these requests' app key will be replaced with the current app key. + */ +Countly.replaceAllAppKeysInQueueWithCurrentAppKey = function() { + cordova.exec(Countly.onSuccess,Countly.onError,"CountlyCordova","replaceAllAppKeysInQueueWithCurrentAppKey",[]); +} + +/** + * Removes all requests with a different app key in request queue. + * In request queue, if there are any request whose app key is different than the current app key, + * these requests will be removed from request queue. + */ +Countly.removeDifferentAppKeysFromQueue = function() { + cordova.exec(Countly.onSuccess,Countly.onError,"CountlyCordova","removeDifferentAppKeysFromQueue",[]); +} // Push Notification Countly.sendPushToken = function(options){ @@ -527,10 +599,35 @@ Countly.setHttpPostForced = function(boolean){ /** * * Enable campaign attribution reporting to Countly. + * For iOS use "recordAttributionID" instead of "enableAttribution" * Should be call before Countly init */ -Countly.enableAttribution = function() { - cordova.exec(Countly.onSuccess,Countly.onError,"CountlyCordova","enableAttribution",[]); +Countly.enableAttribution = function(attributionID = "") { + if (Countly.isiOS) { + if(attributionID == "") { + if(Countly.isDebug){ + console.error("[CountlyReactNative] enableAttribution, attribution Id for iOS can't be empty string"); + } + return "attribution Id for iOS can't be empty string"; + } + Countly.recordAttributionID(attributionID); + } + else { + cordova.exec(Countly.onSuccess,Countly.onError,"CountlyCordova","enableAttribution",[]); + } +} + +/** + * + * set attribution Id for campaign attribution reporting. + * Currently implemented for iOS only + * For Android just call the enableAttribution to enable campaign attribution. + */ +Countly.recordAttributionID = function(attributionID){ + if (!Countly.isiOS) return "recordAttributionID : To be implemented"; + var args = []; + args.push(attributionID); + cordova.exec(Countly.onSuccess,Countly.onError,"CountlyCordova","recordAttributionID",args); } Countly.startTrace = function(traceKey){ diff --git a/index.html b/index.html index bfaa201..965c126 100644 --- a/index.html +++ b/index.html @@ -133,6 +133,8 @@

Countly Cordova Demo App

+ +
Rating Methods End
Performance Methods Start
@@ -168,7 +170,7 @@

Countly Cordova Demo App

Countly.setLoggingEnabled(true); // Enable countly internal debugging logs Countly.enableCrashReporting(); // Enable crash reporting to report unhandled crashes to Countly Countly.setRequiresConsent(true); // Set that consent should be required for features to work. - Countly.giveConsentInit(["location", "sessions", "attribution", "push", "events", "views", "crashes", "users", "push", "star-rating", "apm"]); // give conset for specific features before init. + Countly.giveConsentInit(["location", "sessions", "attribution", "push", "events", "views", "crashes", "users", "push", "star-rating", "apm", "feedback", "remote-config"]); // give conset for specific features before init. Countly.setLocationInit("TR", "Istanbul", "41.0082,28.9784", "10.2.33.12"); // Set user initial location. @@ -183,13 +185,14 @@

Countly Cordova Demo App

}, function(r){ console.log("[CountlyCordova] onError : " + r); }); // Set Automatic value download happens when the SDK is initiated or when the device ID is changed. + Countly.pushTokenType(Countly.messagingMode.TEST); // Set messaging mode for push notifications Countly.init("https://try.count.ly", "YOUR_API_KEY").then((result) => { + Countly.setStarRatingDialogTexts("Title", "Message", "Dismiss"); /** * Push notifications settings * Should be call after init */ - Countly.pushTokenType(Countly.messagingMode.TEST); // Set messaging mode for push notifications Countly.onNotification(function(theNotification){ console.log("[CountlyCordova] onNotification : " + JSON.stringify(theNotification)); }); // Set callback to receive push notifications @@ -517,6 +520,30 @@

Countly Cordova Demo App

}); } + app.showSurvey = function(){ + Countly.getFeedbackWidgets().then((retrivedWidgets) => { + var surveyWidget = retrivedWidgets.find(x => x.type === 'survey') + if(surveyWidget) { + Countly.presentFeedbackWidget(surveyWidget, "Close") + } + },(err) => { + console.error("showSurvey getFeedbackWidgets error : " +err); + }); + } + + app.showNPS = function(){ + Countly.getFeedbackWidgets().then((retrivedWidgets) => { + var npsWidget = retrivedWidgets.find(x => x.type === 'nps') + if(npsWidget) { + Countly.presentFeedbackWidget(npsWidget, "Cancel") + } + },(err) => { + console.error("showNPS getFeedbackWidgets error : " +err); + }); + } + + + app.addCrashLog = function() { Countly.enableCrashReporting(); Countly.addCrashLog("User Performed Step A"); diff --git a/package.js b/package.js index 339cca4..088e0f9 100644 --- a/package.js +++ b/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'countly:countly-sdk-js', - version: '20.4.0', // Meteor doesn't go with 18.08.1 + version: '20.11.0', summary: 'Countly is an innovative, real-time, open source mobile analytics and push notifications platform. It collects data from mobile devices, and visualizes this information to analyze mobile application usage and end-user behavior. There are two parts of Countly: the server that collects and analyzes data, and mobile SDK that sends this data. Both parts are open source with different licensing terms.', git: 'https://github.com/Countly/countly-sdk-cordova.git', documentation: 'README.md' diff --git a/package.json b/package.json index 357e190..fe6b4a5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "countly-sdk-cordova", "description": "Countly is an innovative, real-time, open source mobile analytics and push notifications platform. It collects data from mobile devices, and visualizes this information to analyze mobile application usage and end-user behavior. There are two parts of Countly: the server that collects and analyzes data, and mobile SDK that sends this data. Both parts are open source with different licensing terms.", - "version": "20.4.0", + "version": "20.11.0", "homepage": "https://github.com/Countly/countly-sdk-cordova#readme", "repository": { "type": "git", diff --git a/plugin.xml b/plugin.xml index 2528281..b813df5 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + Countly @@ -49,7 +49,7 @@ - + @@ -75,6 +75,8 @@ + + @@ -92,7 +94,7 @@ - + @@ -108,7 +110,8 @@ - + + diff --git a/src/android/CountlyCordova.java b/src/android/CountlyCordova.java index 711bbb9..6db400e 100644 --- a/src/android/CountlyCordova.java +++ b/src/android/CountlyCordova.java @@ -10,6 +10,7 @@ import org.apache.cordova.PluginResult; import org.json.JSONArray; import org.json.JSONException; +import org.json.JSONObject; import android.content.Context; import android.os.Bundle; @@ -215,6 +216,9 @@ else if("remoteConfigClearValues".equals(action)){ else if("getRemoteConfigValueForKey".equals(action)){ callbackContext.success(countlyNative.getRemoteConfigValueForKey(args)); } + else if("setStarRatingDialogTexts".equals(action)){ + callbackContext.success(countlyNative.setStarRatingDialogTexts(args)); + } else if("askForStarRating".equals(action)){ callbackContext.success(countlyNative.askForStarRating(args)); } @@ -226,6 +230,38 @@ public void callback(String result) { } }); } + else if ("getFeedbackWidgets".equals(action)) { + countlyNative.getFeedbackWidgets(args, new CountlyNative.JSONObjectCallback() { + @Override + public void success(JSONArray result) { + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, + result); + pluginResult.setKeepCallback(true); + callbackContext.sendPluginResult(pluginResult); + + } + @Override + public void error(String error) { + callbackContext.error(error); + } + }); + } + else if("presentFeedbackWidget".equals(action)){ + countlyNative.presentFeedbackWidget(args, new CountlyNative.Callback() { + @Override + public void callback(String result) { + callbackContext.success(result); + } + }); + } + else if("replaceAllAppKeysInQueueWithCurrentAppKey".equals(action)){ + countlyNative.replaceAllAppKeysInQueueWithCurrentAppKey(); + callbackContext.success("replaceAllAppKeysInQueueWithCurrentAppKey : Success"); + } + else if("removeDifferentAppKeysFromQueue".equals(action)){ + countlyNative.removeDifferentAppKeysFromQueue(); + callbackContext.success("removeDifferentAppKeysFromQueue : Success"); + } else if("sendPushToken".equals(action)){ callbackContext.success(countlyNative.sendPushToken(args)); } diff --git a/src/android/CountlyNative.java b/src/android/CountlyNative.java index 143f82e..417c039 100644 --- a/src/android/CountlyNative.java +++ b/src/android/CountlyNative.java @@ -30,12 +30,13 @@ import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.OnCompleteListener; import com.google.firebase.FirebaseApp; +import ly.count.android.sdk.ModuleFeedback.*; public class CountlyNative { public static final String TAG = "CountlyCordovaPlugin"; - private String COUNTLY_CORDOVA_SDK_VERSION_STRING = "20.4.0"; + private String COUNTLY_CORDOVA_SDK_VERSION_STRING = "20.11.0"; private String COUNTLY_CORDOVA_SDK_NAME = "js-cordovab-android"; private Countly.CountlyMessagingMode pushTokenTypeVariable = Countly.CountlyMessagingMode.PRODUCTION; @@ -54,7 +55,10 @@ public class CountlyNative { Countly.CountlyFeatureNames.attribution, Countly.CountlyFeatureNames.users, Countly.CountlyFeatureNames.push, - Countly.CountlyFeatureNames.starRating + Countly.CountlyFeatureNames.starRating, + Countly.CountlyFeatureNames.apm, + Countly.CountlyFeatureNames.feedback, + Countly.CountlyFeatureNames.remoteConfig )); public CountlyNative(Activity _activity, Context _context){ this.activity = _activity; @@ -73,6 +77,11 @@ public static void onNotification(Map notification){ public interface Callback { void callback(String result); } + public interface JSONObjectCallback { + void error(String result); + void success(JSONArray result); + } + public String init(JSONArray args){ try { @@ -877,12 +886,96 @@ public void callback(String error) { } } + public String setStarRatingDialogTexts(JSONArray args){ + this.log("setStarRatingDialogTexts", args); + try { + this.config.setStarRatingTextTitle(args.getString(0)); + this.config.setStarRatingTextMessage(args.getString(1)); + this.config.setStarRatingTextDismiss(args.getString(2)); + return "setStarRatingDialogTexts success."; + } catch (JSONException e) { + return e.toString(); + } + } + public String askForStarRating(JSONArray args){ this.log("askForStarRating", args); Countly.sharedInstance().ratings().showStarRating(activity, null); return "askForStarRating success."; } + public String getFeedbackWidgets(JSONArray args, final JSONObjectCallback theCallback){ + Countly.sharedInstance().feedback().getAvailableFeedbackWidgets(new RetrieveFeedbackWidgets() { + @Override + public void onFinished(List retrievedWidgets, String error) { + if(error != null) { + theCallback.error(error); + } + + JSONArray retrievedWidgetsArray = new JSONArray(); + for (CountlyFeedbackWidget presentableFeedback : retrievedWidgets) { + try { + JSONObject feedbackWidget = new JSONObject(); + feedbackWidget.put("id", presentableFeedback.widgetId); + feedbackWidget.put("type", presentableFeedback.type.name()); + feedbackWidget.put("name", presentableFeedback.name); + retrievedWidgetsArray.put(feedbackWidget); + + } catch (JSONException e) { + e.printStackTrace(); + } + } + theCallback.success(retrievedWidgetsArray); + } + }); + return "getAvailableFeedbackWidgets success."; + } + + public String presentFeedbackWidget(JSONArray args, final Callback theCallback){ + if (activity == null) { + if(Countly.sharedInstance().isLoggingEnabled()) { + log("presentFeedbackWidget failed : Activity is null", LogLevel.ERROR); + } + theCallback.callback("presentFeedbackWidget Failed, Activity is null"); + return "presentFeedbackWidget Failed, Activity is null"; + } + try { + this.log("presentFeedbackWidget", args); + String widgetId = args.getString(0); + String widgetType = args.getString(1); + String widgetName = args.getString(2); + String closeButtonText = args.getString(3); + CountlyFeedbackWidget presentableFeedback = new CountlyFeedbackWidget(); + presentableFeedback.widgetId = widgetId; + presentableFeedback.type = FeedbackWidgetType.valueOf(widgetType); + presentableFeedback.name = widgetName; + Countly.sharedInstance().feedback().presentFeedbackWidget(presentableFeedback, activity, closeButtonText, new FeedbackCallback() { + @Override + public void onFinished(String error) { + if(error != null) { + theCallback.callback(error); + } + else { + theCallback.callback("presentFeedbackWidget success"); + } + } + }); + return "presentFeedbackWidget: success"; + }catch (JSONException jsonException){ + theCallback.callback(jsonException.toString()); + return jsonException.toString(); + } + } + + + public void replaceAllAppKeysInQueueWithCurrentAppKey(){ + Countly.sharedInstance().requestQueueOverwriteAppKeys(); + } + + public void removeDifferentAppKeysFromQueue(){ + Countly.sharedInstance().requestQueueEraseAppKeysRequests(); + } + public String sendPushToken(JSONArray args){ try { this.log("sendPushToken", args); diff --git a/src/ios/CountlyCordova.h b/src/ios/CountlyCordova.h index ce02511..3d0bdca 100644 --- a/src/ios/CountlyCordova.h +++ b/src/ios/CountlyCordova.h @@ -67,8 +67,14 @@ - (void)remoteConfigClearValues:(CDVInvokedUrlCommand*)command; - (void)getRemoteConfigValueForKey:(CDVInvokedUrlCommand*)command; - (void)askForFeedback:(CDVInvokedUrlCommand*)command; +- (void)setStarRatingDialogTexts:(CDVInvokedUrlCommand*)command; - (void)askForStarRating:(CDVInvokedUrlCommand*)command; +- (void)getFeedbackWidgets:(CDVInvokedUrlCommand*)command; +- (void)presentFeedbackWidget:(CDVInvokedUrlCommand*)command; +- (void)replaceAllAppKeysInQueueWithCurrentAppKey:(CDVInvokedUrlCommand*)command; +- (void)removeDifferentAppKeysFromQueue:(CDVInvokedUrlCommand*)command; - (void)enableAttribution:(CDVInvokedUrlCommand*)command; +- (void)recordAttributionID:(CDVInvokedUrlCommand*)command; - (void)startTrace:(CDVInvokedUrlCommand*)command; - (void)cancelTrace:(CDVInvokedUrlCommand*)command; diff --git a/src/ios/CountlyCordova.m b/src/ios/CountlyCordova.m index 0af24fe..058f439 100644 --- a/src/ios/CountlyCordova.m +++ b/src/ios/CountlyCordova.m @@ -695,6 +695,18 @@ - (void)askForFeedback:(CDVInvokedUrlCommand*)command }]; } +- (void)setStarRatingDialogTexts:(CDVInvokedUrlCommand*)command +{ + if(countlyNative == nil){ + countlyNative = CountlyNative.new; + } + [countlyNative onCall: @"setStarRatingDialogTexts" commandString: command.arguments callback: ^(NSString * theResult) + { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: theResult]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} + - (void)askForStarRating:(CDVInvokedUrlCommand*)command { if(countlyNative == nil){ @@ -707,6 +719,54 @@ - (void)askForStarRating:(CDVInvokedUrlCommand*)command }]; } +- (void)getFeedbackWidgets:(CDVInvokedUrlCommand*)command +{ + if(countlyNative == nil){ + countlyNative = CountlyNative.new; + } + [countlyNative onCall: @"getFeedbackWidgets" commandString: command.arguments callback: ^(NSString * theResult) + { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: theResult]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} + +- (void)presentFeedbackWidget:(CDVInvokedUrlCommand*)command +{ + if(countlyNative == nil){ + countlyNative = CountlyNative.new; + } + [countlyNative onCall: @"presentFeedbackWidget" commandString: command.arguments callback: ^(NSString * theResult) + { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: theResult]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} + +- (void)replaceAllAppKeysInQueueWithCurrentAppKey:(CDVInvokedUrlCommand*)command +{ + if(countlyNative == nil){ + countlyNative = CountlyNative.new; + } + [countlyNative onCall: @"replaceAllAppKeysInQueueWithCurrentAppKey" commandString: command.arguments callback: ^(NSString * theResult) + { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: theResult]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} + +- (void)removeDifferentAppKeysFromQueue:(CDVInvokedUrlCommand*)command +{ + if(countlyNative == nil){ + countlyNative = CountlyNative.new; + } + [countlyNative onCall: @"removeDifferentAppKeysFromQueue" commandString: command.arguments callback: ^(NSString * theResult) + { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: theResult]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} + - (void)enableAttribution:(CDVInvokedUrlCommand*)command { if(countlyNative == nil){ @@ -719,6 +779,18 @@ - (void)enableAttribution:(CDVInvokedUrlCommand*)command }]; } +- (void)recordAttributionID:(CDVInvokedUrlCommand*)command +{ + if(countlyNative == nil){ + countlyNative = CountlyNative.new; + } + [countlyNative onCall: @"recordAttributionID" commandString: command.arguments callback: ^(NSString * theResult) + { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: theResult]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} + - (void)startTrace:(CDVInvokedUrlCommand*)command { if(countlyNative == nil){ diff --git a/src/ios/CountlyNative.m b/src/ios/CountlyNative.m index d31bad5..c2bf321 100644 --- a/src/ios/CountlyNative.m +++ b/src/ios/CountlyNative.m @@ -18,10 +18,14 @@ NSMutableArray* countlyFeatures = nil; Boolean isInitialized = false; NSString *const pushPluginApplicationDidBecomeActiveNotification = @"pushPluginApplicationDidBecomeActiveNotification"; -NSArray *consents = nil; -NSString* const kCountlyCordovaSDKVersion = @"20.4.0"; +NSString* const kCountlyCordovaSDKVersion = @"20.11.0"; NSString* const kCountlyCordovaSDKName = @"js-cordovab-ios"; + +@interface CountlyFeedbackWidget () ++ (CountlyFeedbackWidget *)createWithDictionary:(NSDictionary *)dictionary; +@end + @interface CountlyCommon - (CountlyCommon *)sharedInstance; - (void)setSDKName:(NSString *)SDKName; @@ -284,9 +288,6 @@ - (void) onCall:(NSString *)method commandString:(NSArray *)command callback:(Re dispatch_async(dispatch_get_main_queue(), ^ { isInitialized = true; [[Countly sharedInstance] startWithConfig:config]; - if(consents != nil) { - [Countly.sharedInstance giveConsentForFeatures:consents]; - } [self recordPushAction]; }); result(@"initialized."); @@ -415,8 +416,14 @@ - (void) onCall:(NSString *)method commandString:(NSArray *)command callback:(Re } else if ([@"getDeviceIdAuthor" isEqualToString:method]) { dispatch_async(dispatch_get_main_queue(), ^ { - NSString *value = @"Not implemented for iOS"; - result(value); + id value = [Countly.sharedInstance deviceIDType]; + if(value){ + result(@[value]); + } + else{ + NSString *value = @"deviceIDAuthorNotFound"; + result(@[value]); + } }); }else if ([@"changeDeviceId" isEqualToString:method]) { dispatch_async(dispatch_get_main_queue(), ^ { @@ -750,7 +757,7 @@ - (void) onCall:(NSString *)method commandString:(NSArray *)command callback:(Re }else if ([@"giveConsentInit" isEqualToString:method]) { dispatch_async(dispatch_get_main_queue(), ^ { - consents = command; + config.consents = command; result(@"giveConsentInit!"); }); @@ -917,17 +924,63 @@ - (void) onCall:(NSString *)method commandString:(NSArray *)command callback:(Re }]; }); + }else if ([@"setStarRatingDialogTexts" isEqualToString:method]) { + dispatch_async(dispatch_get_main_queue(), ^ { + NSString* starRatingTextMessage = [command objectAtIndex:1]; + config.starRatingMessage = starRatingTextMessage; + }); }else if ([@"askForStarRating" isEqualToString:method]) { dispatch_async(dispatch_get_main_queue(), ^ { [Countly.sharedInstance askForStarRating:^(NSInteger rating){ result([NSString stringWithFormat: @"Rating:%d", (int)rating]); }]; }); + }else if ([@"getFeedbackWidgets" isEqualToString:method]) { + dispatch_async(dispatch_get_main_queue(), ^ { + [Countly.sharedInstance getFeedbackWidgets:^(NSArray * _Nonnull feedbackWidgets, NSError * _Nonnull error) { + NSMutableArray* feedbackWidgetsArray = [NSMutableArray arrayWithCapacity:feedbackWidgets.count]; + for (CountlyFeedbackWidget* retrievedWidget in feedbackWidgets) { + NSMutableDictionary* feedbackWidget = [NSMutableDictionary dictionaryWithCapacity:3]; + feedbackWidget[@"id"] = retrievedWidget.ID; + feedbackWidget[@"type"] = retrievedWidget.type; + feedbackWidget[@"name"] = retrievedWidget.name; + [feedbackWidgetsArray addObject:feedbackWidget]; + } + result(feedbackWidgetsArray); + }]; + }); + }else if ([@"presentFeedbackWidget" isEqualToString:method]) { + dispatch_async(dispatch_get_main_queue(), ^ { + NSString* widgetId = [command objectAtIndex:0]; + NSString* widgetType = [command objectAtIndex:1]; + NSMutableDictionary* feedbackWidgetsDict = [NSMutableDictionary dictionaryWithCapacity:3]; + + feedbackWidgetsDict[@"_id"] = widgetId; + feedbackWidgetsDict[@"type"] = widgetType; + feedbackWidgetsDict[@"name"] = widgetType; + CountlyFeedbackWidget *feedback = [CountlyFeedbackWidget createWithDictionary:feedbackWidgetsDict]; + [feedback present]; + }); + }else if ([@"replaceAllAppKeysInQueueWithCurrentAppKey" isEqualToString:method]) { + dispatch_async(dispatch_get_main_queue(), ^ { + [Countly.sharedInstance replaceAllAppKeysInQueueWithCurrentAppKey]; + }); + }else if ([@"removeDifferentAppKeysFromQueue" isEqualToString:method]) { + dispatch_async(dispatch_get_main_queue(), ^ { + [Countly.sharedInstance removeDifferentAppKeysFromQueue]; + }); }else if ([@"getPlatformVersion" isEqualToString:method]) { result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); }else if ([@"enableAttribution" isEqualToString:method]) { config.enableAttribution = YES; result(@"enableAttribution"); + }else if ([@"recordAttributionID" isEqualToString:method]) { + dispatch_async(dispatch_get_main_queue(), ^ { + NSString* attributionID = [command objectAtIndex:0]; + [Countly.sharedInstance recordAttributionID: attributionID]; + }); + result(@"recordAttributionID!"); + }else if ([@"startTrace" isEqualToString:method]) { dispatch_async(dispatch_get_main_queue(), ^ { NSString* traceKey = [command objectAtIndex:0];