Skip to content

Commit

Permalink
Release of version 0.17.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Krzysztof Kurzawa committed Dec 5, 2023
1 parent d443e42 commit 71e359e
Show file tree
Hide file tree
Showing 19 changed files with 492 additions and 12 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@

All notable changes to this project will be documented in this file.

## [0.17.0] - 2023-12-05

### Fixed
- [iOS] Issue with location of some SDK files in the Documents directory. The old location caused the SDK files to be visible in the shared documents directory if the host application file sharing was enabled.
- [iOS] Potential issue with native notification buttons when Simple Push campaign contained Rich Media (Single Media) or had a custom notification category identifier.

### Added
- We added a new `Synerise.Content.generateDocument(slug:onSuccess:onError:)` method. It's analogous to `Synerise.Content.getDocument(slug:onSuccess:onError:)`. The old method is deprecated. The new method generates the document that is defined for the provided slug.
- We added a new `Synerise.Content.getRecommendationsV2(options:onSuccess:onError:)` method. It's analogous to `Synerise.Content.getRecommendations(options:onSuccess:onError:)`. The old method is deprecated. The new method gets recommendations that are defined for the options provided.
- We added a new `Synerise.Content.generateScreenView(feedSlug:onSuccess:onError:)` method. It's analogous to `Synerise.Content.getScreenView(onSuccess:onError:)`. The old method is deprecated. The new method generates a customer's highest-priority screen view campaign that is defined for the provided slug.
- We added models correlating with new methods: `ScreenView`, `Document`.

### Changed
- `Synerise.Content.getDocument(slug:onSuccess:onError:)` is deprecated now.
- `Synerise.Content.getDocuments(apiQuery:onSuccess:onError:)` is deprecated now.
- `Synerise.Content.getRecommendations(options:onSuccess:onError:)` is deprecated now.
- `Synerise.Content.getScreenView(onSuccess:onError:)` is deprecated now.
- Update of native SDK's dependencies.


## [0.16.0] - 2023-10-30

### Added
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Synerise React Native SDK (react-native-synerise-sdk) (0.16.0)
# Synerise React Native SDK (react-native-synerise-sdk) (0.17.0)

[![Platform](https://img.shields.io/badge/platform-ios%20%7C%20android-orange.svg)](https://github.com/synerise/react-native-synerise-sdk)
[![Languages](https://img.shields.io/badge/language-TypeScript%20%7C%20Java%20%7C%20Objective--C-orange.svg)](https://github.com/synerise/react-native-synerise-sdk)
Expand Down
6 changes: 3 additions & 3 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ ext.versions = [
'minSdk' : 21,
'compileSdk' : 33,
'targetSdk' : 33,
'versionCode': 30,
'versionName': "0.16.0"
'versionCode': 31,
'versionName': "0.17.0"
]

buildscript {
Expand Down Expand Up @@ -57,7 +57,7 @@ repositories {
dependencies {
implementation 'com.facebook.react:react-native:+'
implementation "com.squareup.okhttp3:logging-interceptor:4.9.1"
api 'com.synerise.sdk:synerise-mobile-sdk:5.11.0'
api 'com.synerise.sdk:synerise-mobile-sdk:5.12.0'
}

//apply from: 'publish.gradle'
123 changes: 121 additions & 2 deletions android/src/main/java/com/synerise/sdk/react/RNContent.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
import com.synerise.sdk.content.model.DocumentsApiQuery;
import com.synerise.sdk.content.model.DocumentsApiQueryType;
import com.synerise.sdk.content.model.ScreenViewResponse;
import com.synerise.sdk.content.model.document.Document;
import com.synerise.sdk.content.model.recommendation.RecommendationRequestBody;
import com.synerise.sdk.content.model.recommendation.RecommendationResponse;
import com.synerise.sdk.content.model.screenview.ScreenView;
import com.synerise.sdk.content.widgets.dataModel.Recommendation;
import com.synerise.sdk.core.listeners.DataActionListener;
import com.synerise.sdk.core.net.IDataApiCall;
Expand All @@ -34,11 +36,13 @@

public class RNContent extends RNBaseModule {

IDataApiCall<Object> getDocumentApiCall;
IDataApiCall<List<Object>> getDocumentsApiCall;
private IDataApiCall<Object> getDocumentApiCall;
private IDataApiCall<List<Object>> getDocumentsApiCall;
private IDataApiCall<Document> generateDocumentApiCall;
private final String ISO8601_FORMAT = "yyyy-MM-dd'T'kk:mm:ss.SSS'Z'";
private IDataApiCall<RecommendationResponse> getRecommendationsApiCall;
private IDataApiCall<ScreenViewResponse> getScreenViewApiCall;
private IDataApiCall<ScreenView> generateScreenViewApiCall;
private Gson gson = new Gson();

public RNContent(ReactApplicationContext reactApplicationContext) {
Expand Down Expand Up @@ -185,6 +189,111 @@ public void onDataAction(ApiError apiError) {
});
}

@ReactMethod
public void getRecommendationsV2(ReadableMap recommendationsOptions, Callback callback) {
String productId = recommendationsOptions.hasKey("productID") ? recommendationsOptions.getString("productID") : "";
String slugName = recommendationsOptions.hasKey("slug") ? recommendationsOptions.getString("slug") : "";

if (getRecommendationsApiCall != null) getRecommendationsApiCall.cancel();

RecommendationRequestBody recommendationRequestBody = new RecommendationRequestBody();
recommendationRequestBody.setProductId(productId);

getRecommendationsApiCall = Content.getRecommendationsV2(slugName, recommendationRequestBody);
getRecommendationsApiCall.execute(new DataActionListener<RecommendationResponse>() {
@Override
public void onDataAction(RecommendationResponse responseBody) {
WritableMap recommendationMap = Arguments.createMap();

recommendationMap.putString("campaignHash", responseBody.getCampaignHash());
recommendationMap.putString("campaignId", responseBody.getCampaignId());
recommendationMap.putString("schema", responseBody.getSchema());
recommendationMap.putString("slug", responseBody.getSlug());
recommendationMap.putString("uuid", responseBody.getUuid());

recommendationMap.putArray("items", recommendationToWritableArray(responseBody.getRecommendations()));
executeSuccessCallbackResponse(callback, recommendationMap, null);
}
}, new DataActionListener<ApiError>() {
@Override
public void onDataAction(ApiError apiError) {
executeFailureCallbackResponse(callback, null, apiError);
}
});
}

@ReactMethod
public void generateDocument(String slug, Callback callback) {
if (generateDocumentApiCall != null) generateDocumentApiCall.cancel();

generateDocumentApiCall = Content.generateDocument(slug);
generateDocumentApiCall.execute(new DataActionListener<Document>() {

@Override
public void onDataAction(Document document) {
WritableMap documentMap = Arguments.createMap();
documentMap.putString("uuid", document.getUuid());
documentMap.putString("slug", document.getSlug());
documentMap.putString("schema", document.getSchema());
try {
String jsonObject = gson.toJson(document);
WritableMap objectMap = convertJsonToMap(new JSONObject(jsonObject));
documentMap.putMap("content", objectMap);
executeSuccessCallbackResponse(callback, documentMap, null);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new DataActionListener<ApiError>() {
@Override
public void onDataAction(ApiError apiError) {
executeFailureCallbackResponse(callback, null, apiError);
}
});
}

@ReactMethod
public void generateScreenView(String feedSlug, Callback callback) {
if (generateScreenViewApiCall != null) generateScreenViewApiCall.cancel();
generateScreenViewApiCall = Content.generateScreenView(feedSlug);
generateScreenViewApiCall.execute(
new DataActionListener<ScreenView>() {
@Override
public void onDataAction(ScreenView data) {
WritableMap screenViewMap = Arguments.createMap();
screenViewMap.putMap("audience", audienceNewScreenViewsToWritableMap(data.getAudience()));
screenViewMap.putString("identifier", data.getId());
screenViewMap.putString("hash", data.getHash());
screenViewMap.putString("path", data.getPath());
screenViewMap.putString("name", data.getName());
screenViewMap.putInt("priority", data.getPriority());
screenViewMap.putMap("data", screenViewDataToWritableMap(data.getData()));

try {
Date createdAtDate = new SimpleDateFormat(ISO8601_FORMAT, Locale.getDefault()).parse(data.getCreatedAt());
Date updatedAtDate = new SimpleDateFormat(ISO8601_FORMAT, Locale.getDefault()).parse(data.getUpdatedAt());

if (createdAtDate != null) {
screenViewMap.putDouble("createdAt", createdAtDate.getTime());
}
if (updatedAtDate != null) {
screenViewMap.putDouble("updatedAt", updatedAtDate.getTime());
}
} catch (ParseException e) {
e.printStackTrace();
}

executeSuccessCallbackResponse(callback, screenViewMap, null);
}
}, new DataActionListener<ApiError>() {
@Override
public void onDataAction(ApiError apiError) {
executeFailureCallbackResponse(callback, null, apiError);
}
}
);
}

private WritableArray recommendationToWritableArray(List<Recommendation> array) {
WritableArray writableArray = Arguments.createArray();

Expand Down Expand Up @@ -227,6 +336,16 @@ private WritableMap audienceToWritableMap(Audience audience) {
return audienceMap;
}

private WritableMap audienceNewScreenViewsToWritableMap(com.synerise.sdk.content.model.screenview.Audience audience) {
WritableMap audienceMap = Arguments.createMap();
List<String> segments = audience.getSegments();
audienceMap.putArray("segments", segments != null ? listOfStringsIntoWritableArray(segments) : null);
audienceMap.putString("targetType", audience.getTargetType());
audienceMap.putString("query", audience.getQuery());

return audienceMap;
}

private WritableMap screenViewDataToWritableMap(Object data) {
WritableMap screenViewData = Arguments.createMap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class RNSyneriseInitializer {
public Boolean isCrashHandlingEnabled;
public static volatile boolean isInitialized = false;

public static final String SDK_PLUGIN_VERSION = "0.16.0";
public static final String SDK_PLUGIN_VERSION = "0.17.0";

public void initialize(Application app) {
if (isInitialized == false) {
Expand Down
2 changes: 1 addition & 1 deletion ios/ReactNativeSynerise/Main/RNSyneriseInitializer.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#import "RNSyneriseInitializer.h"

NSString * const SNRSyneriseSDKPluginVersion = @"0.16.0";
NSString * const SNRSyneriseSDKPluginVersion = @"0.17.0";

@implementation RNSyneriseInitializer

Expand Down
110 changes: 109 additions & 1 deletion ios/ReactNativeSynerise/Modules/RNContent.m
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,21 @@ - (SNRRecommendationOptions *)modelRecommendationOptionsWithDictionary:(NSDictio

#pragma mark - JS Mapping

- (nullable NSDictionary *)dictionaryWithDocument:(SNRDocument *)model {
if (model != nil) {
NSMutableDictionary *dictionary = [@{} mutableCopy];

[dictionary setString:model.identifier forKey:@"uuid"];
[dictionary setString:model.slug forKey:@"slug"];
[dictionary setString:model.schema forKey:@"schema"];
[dictionary setDictionary:model.content forKey:@"content"];

return dictionary;
}

return nil;
}

- (nullable NSDictionary *)dictionaryWithRecommendationResponse:(SNRRecommendationResponse *)model {
if (model != nil) {
NSMutableDictionary *dictionary = [@{} mutableCopy];
Expand Down Expand Up @@ -128,6 +143,28 @@ - (nullable NSDictionary *)dictionaryWithScreenViewResponse:(SNRScreenViewRespon
return nil;
}

- (nullable NSDictionary *)dictionaryWithScreenView:(SNRScreenView *)model {
if (model != nil) {
NSMutableDictionary *dictionary = [@{} mutableCopy];

[dictionary setString:model.identifier forKey:@"identifier"];
[dictionary setString:model.name forKey:@"name"];
[dictionary setString:model.hashString forKey:@"hashString"];
[dictionary setString:model.path forKey:@"path"];
[dictionary setInteger:model.priority forKey:@"priority"];
[dictionary setDictionary:[self dictionaryWithScreenViewAudienceInfo:model.audience] forKey:@"audience"];

[dictionary setGenericObject:model.data forKey:@"data"];

[dictionary setDate:model.createdAt forKey:@"createdAt"];
[dictionary setDate:model.updatedAt forKey:@"updatedAt"];

return dictionary;
}

return nil;
}

- (nullable NSDictionary *)dictionaryWithScreenViewAudience:(SNRScreenViewAudience *)model {
if (model != nil) {
NSMutableDictionary *dictionary = [@{} mutableCopy];
Expand All @@ -141,6 +178,20 @@ - (nullable NSDictionary *)dictionaryWithScreenViewAudience:(SNRScreenViewAudien
return nil;
}

- (nullable NSDictionary *)dictionaryWithScreenViewAudienceInfo:(SNRScreenViewAudienceInfo *)model {
if (model != nil) {
NSMutableDictionary *dictionary = [@{} mutableCopy];

[dictionary setArray:model.segments forKey:@"segments"];
[dictionary setString:model.query forKey:@"query"];
[dictionary setString:model.targetType forKey:@"targetType"];

return dictionary;
}

return nil;
}

#pragma mark - JS Module

//getDocument(slug: String, onSuccess: (documentResponse: Object) => void, onError: (error: Error) => void)
Expand All @@ -158,6 +209,22 @@ - (nullable NSDictionary *)dictionaryWithScreenViewAudience:(SNRScreenViewAudien
}];
}

//generateDocument(slug: string, onSuccess: (document: Document) => void, onError: (error: Error) => void)

RCT_EXPORT_METHOD(generateDocument:(NSString *)slug response:(RCTResponseSenderBlock)response)
{
[SNRContent generateDocument:slug success:^(SNRDocument *document) {
NSDictionary *documentDictionary = [self dictionaryWithDocument:document];
if (documentDictionary != nil) {
[self executeSuccessCallbackResponse:response data:documentDictionary];
} else {
[self executeDefaultFailureCallbackResponse:response];
}
} failure:^(NSError *error) {
[self executeFailureCallbackResponse:response error:error];
}];
}

//getDocuments(documentsApiQuery: DocumentsApiQuery, onSuccess: (documentResponse: Object) => void, onError: (error: Error) => void)

RCT_EXPORT_METHOD(getDocuments:(NSDictionary *)dictionary response:(RCTResponseSenderBlock)response)
Expand All @@ -176,7 +243,7 @@ - (nullable NSDictionary *)dictionaryWithScreenViewAudience:(SNRScreenViewAudien
}
}

//getRecommendations(recommendationOptions: RecommendationOptions, onSuccess: (recommendationResponse: RecommendationResponse) => void, onError: (error: Error) => void)
//getRecommendations(options: RecommendationOptions, onSuccess: (recommendationResponse: RecommendationResponse) => void, onError: (error: Error) => void)

RCT_EXPORT_METHOD(getRecommendations:(NSDictionary *)dictionary response:(RCTResponseSenderBlock)response)
{
Expand All @@ -199,6 +266,29 @@ - (nullable NSDictionary *)dictionaryWithScreenViewAudience:(SNRScreenViewAudien
}
}

//getRecommendationsV2(options: RecommendationOptions, onSuccess: (recommendationResponse: RecommendationResponse)

RCT_EXPORT_METHOD(getRecommendationsV2:(NSDictionary *)dictionary response:(RCTResponseSenderBlock)response)
{
SNRRecommendationOptions *recommendationOptions = [self modelRecommendationOptionsWithDictionary:dictionary];
if (recommendationOptions != nil) {
[SNRContent getRecommendationsV2:recommendationOptions success:^(SNRRecommendationResponse *recommendationResponse) {
if (recommendationResponse != nil) {
NSDictionary *recommendationResponseDictionary = [self dictionaryWithRecommendationResponse:recommendationResponse];
if (recommendationResponseDictionary != nil) {
[self executeSuccessCallbackResponse:response data:recommendationResponseDictionary];
} else {
[self executeDefaultFailureCallbackResponse:response];
}
} else {
[self executeDefaultFailureCallbackResponse:response];
}
} failure:^(NSError *error) {
[self executeFailureCallbackResponse:response error:error];
}];
}
}

//getScreenView(onSuccess: (screenViewResponse: ScreenViewResponse) => void, onError: (error: Error) => void)

RCT_REMAP_METHOD(getScreenView, getScreenViewWithResponse:(RCTResponseSenderBlock)response)
Expand All @@ -217,6 +307,24 @@ - (nullable NSDictionary *)dictionaryWithScreenViewAudience:(SNRScreenViewAudien
}];
}

//generateScreenView(feedSlug: string, onSuccess: (screenView: ScreenView) => void, onError: (error: Error) => void)

RCT_EXPORT_METHOD(generateScreenView:(NSString *)feedSlug response:(RCTResponseSenderBlock)response)
{
[SNRContent generateScreenView:feedSlug success:^(SNRScreenView *screenView) {
if (screenView != nil) {
NSDictionary *screenViewDictionary = [self dictionaryWithScreenView:screenView];
if (screenViewDictionary != nil) {
[self executeSuccessCallbackResponse:response data:screenViewDictionary];
} else {
[self executeDefaultFailureCallbackResponse:response];
}
}
} failure:^(NSError *error) {
[self executeFailureCallbackResponse:response error:error];
}];
}

@end

NS_ASSUME_NONNULL_END
2 changes: 1 addition & 1 deletion ios/react-native-synerise-sdk.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ require 'json'

package = JSON.parse(File.read('./../package.json'))

SYNERISE_SDK_FRAMEWORK_VERSION = '4.14.7'
SYNERISE_SDK_FRAMEWORK_VERSION = '4.14.9'

Pod::Spec.new do |s|
s.name = package['name']
Expand Down
Loading

0 comments on commit 71e359e

Please sign in to comment.