Skip to content

Commit

Permalink
Added remote configuration source
Browse files Browse the repository at this point in the history
  • Loading branch information
suriksarkisyan committed Sep 8, 2023
1 parent 298ede9 commit ccaee05
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 5 deletions.
1 change: 1 addition & 0 deletions Framework/QonversionFramework.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#import <Qonversion/QONIntroEligibility.h>
#import <Qonversion/QONExperiment.h>
#import <Qonversion/QONExperimentGroup.h>
#import <Qonversion/QONRemoteConfigurationSource.h>
#import <Qonversion/QONRemoteConfig.h>
#import <Qonversion/QONUserProperty.h>
#import <Qonversion/QONUserProperties.h>
Expand Down
2 changes: 1 addition & 1 deletion Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: cd1911d751c59f56b7f0243af0b5eba4ce54bf26

COCOAPODS: 1.12.0
COCOAPODS: 1.11.3
12 changes: 12 additions & 0 deletions Qonversion.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
70283DF729F66FAC00D138BC /* PurchasesMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70283DF629F66FAC00D138BC /* PurchasesMapper.swift */; };
702BF8B629531A68000B6C3E /* QONScreenCustomizationDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 702BF8B529531A68000B6C3E /* QONScreenCustomizationDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
702DBDEC2A3216C900D590D0 /* QONExperiment+Protected.h in Headers */ = {isa = PBXBuildFile; fileRef = 702DBDEB2A3216C900D590D0 /* QONExperiment+Protected.h */; };
707734F42A9F607700CFF742 /* QONRemoteConfigurationSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 707734F22A9F607700CFF742 /* QONRemoteConfigurationSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
707734F52A9F607700CFF742 /* QONRemoteConfigurationSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 707734F32A9F607700CFF742 /* QONRemoteConfigurationSource.m */; };
707734F72A9F6B8700CFF742 /* QONRemoteConfigInfo+Protected.h in Headers */ = {isa = PBXBuildFile; fileRef = 707734F62A9F6B8700CFF742 /* QONRemoteConfigInfo+Protected.h */; };
7094501A29CD994200F55E68 /* QONRemoteConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 7094501829CD994200F55E68 /* QONRemoteConfig.h */; settings = {ATTRIBUTES = (Public, ); }; };
7094501B29CD994200F55E68 /* QONRemoteConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 7094501929CD994200F55E68 /* QONRemoteConfig.m */; };
7097C6BE2A38BFC800565DE4 /* QONRemoteConfig+Protected.h in Headers */ = {isa = PBXBuildFile; fileRef = 7097C6BD2A38BFC800565DE4 /* QONRemoteConfig+Protected.h */; };
Expand Down Expand Up @@ -342,6 +345,9 @@
702BF8B529531A68000B6C3E /* QONScreenCustomizationDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QONScreenCustomizationDelegate.h; sourceTree = "<group>"; };
702DBDEB2A3216C900D590D0 /* QONExperiment+Protected.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "QONExperiment+Protected.h"; sourceTree = "<group>"; };
7052136F29F1807A00164AAF /* PurchasesMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PurchasesMapper.swift; sourceTree = "<group>"; };
707734F22A9F607700CFF742 /* QONRemoteConfigurationSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QONRemoteConfigurationSource.h; sourceTree = "<group>"; };
707734F32A9F607700CFF742 /* QONRemoteConfigurationSource.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QONRemoteConfigurationSource.m; sourceTree = "<group>"; };
707734F62A9F6B8700CFF742 /* QONRemoteConfigInfo+Protected.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "QONRemoteConfigInfo+Protected.h"; sourceTree = "<group>"; };
7094501829CD994200F55E68 /* QONRemoteConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QONRemoteConfig.h; sourceTree = "<group>"; };
7094501929CD994200F55E68 /* QONRemoteConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QONRemoteConfig.m; sourceTree = "<group>"; };
7097C6BD2A38BFC800565DE4 /* QONRemoteConfig+Protected.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "QONRemoteConfig+Protected.h"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -938,6 +944,8 @@
70D0E2B7291A9BE3004E8DE8 /* QONConfiguration.m */,
7094501829CD994200F55E68 /* QONRemoteConfig.h */,
7094501929CD994200F55E68 /* QONRemoteConfig.m */,
707734F22A9F607700CFF742 /* QONRemoteConfigurationSource.h */,
707734F32A9F607700CFF742 /* QONRemoteConfigurationSource.m */,
70A26ADC2A31BC44008CE4A7 /* QONExperiment.h */,
70A26ADD2A31BC44008CE4A7 /* QONExperiment.m */,
A1839E84DBCF12F2CDC1930D /* QONUserProperty.m */,
Expand Down Expand Up @@ -1279,6 +1287,7 @@
children = (
700EC171291277130032E205 /* QONExperimentGroup+Protected.h */,
7097C6BD2A38BFC800565DE4 /* QONRemoteConfig+Protected.h */,
707734F62A9F6B8700CFF742 /* QONRemoteConfigInfo+Protected.h */,
702DBDEB2A3216C900D590D0 /* QONExperiment+Protected.h */,
8957324226DD03A3009507A6 /* QONUser+Protected.h */,
8957324326DD03A3009507A6 /* QONOfferings+Protected.h */,
Expand Down Expand Up @@ -1572,6 +1581,7 @@
895732C226DD03A3009507A6 /* QNInMemoryStorage.h in Headers */,
895732A326DD03A3009507A6 /* QONAutomationsEvent+Protected.h in Headers */,
895732C126DD03A3009507A6 /* QNLocalStorage.h in Headers */,
707734F72A9F6B8700CFF742 /* QONRemoteConfigInfo+Protected.h in Headers */,
700EC173291277130032E205 /* QONExperimentGroup+Protected.h in Headers */,
895732BE26DD03A3009507A6 /* QNRequestSerializer.h in Headers */,
895732D626DD03A3009507A6 /* QNMapperObject.h in Headers */,
Expand All @@ -1580,6 +1590,7 @@
895732CF26DD03A3009507A6 /* QNProperties.h in Headers */,
895732F326DD03A3009507A6 /* QNUserPropertiesManager.h in Headers */,
70F07B1B28AD085600A45D41 /* QONEntitlementsCacheLifetime.h in Headers */,
707734F42A9F607700CFF742 /* QONRemoteConfigurationSource.h in Headers */,
702394912923EBF3003126D5 /* QONNotificationsService.h in Headers */,
895732F126DD03A3009507A6 /* QNMapper.h in Headers */,
7097C6BE2A38BFC800565DE4 /* QONRemoteConfig+Protected.h in Headers */,
Expand Down Expand Up @@ -1921,6 +1932,7 @@
70B9A9F2297AB8A700BD30FD /* QONAutomationsNavigationController.m in Sources */,
895732CB26DD03A3009507A6 /* QNUtils.m in Sources */,
70ADE7102951CC7200CB4D2E /* QONScreenPresentationConfiguration.m in Sources */,
707734F52A9F607700CFF742 /* QONRemoteConfigurationSource.m in Sources */,
895732A626DD03A3009507A6 /* QONAutomationsScreen.m in Sources */,
70ED951129FAAF31005F5D00 /* QONStoreKit2PurchaseModel.m in Sources */,
70EC019D29EEE94300E686E2 /* StoreKit2Service.swift in Sources */,
Expand Down
6 changes: 6 additions & 0 deletions Sources/Qonversion/Public/QONRemoteConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import <Foundation/Foundation.h>
#import "QONExperiment.h"
#import "QONRemoteConfigurationSource.h"

NS_ASSUME_NONNULL_BEGIN

Expand All @@ -24,6 +25,11 @@ NS_SWIFT_NAME(Qonversion.RemoteConfig)
*/
@property (nonatomic, strong, nullable, readonly) QONExperiment *experiment;

/**
Remote configuration source
*/
@property (nonatomic, strong, nullable, readonly) QONRemoteConfigurationSource *source;

@end

NS_ASSUME_NONNULL_END
4 changes: 3 additions & 1 deletion Sources/Qonversion/Public/QONRemoteConfig.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@

@implementation QONRemoteConfig

- (instancetype)initWithPayload:(NSDictionary *)payload experiment:(QONExperiment *)experiment {
- (instancetype)initWithPayload:(NSDictionary *)payload experiment:(QONExperiment *)experiment source:(QONRemoteConfigurationSource *)source {
self = [super init];

if (self) {
_payload = payload;
_experiment = experiment;
_source = source;
}

return self;
Expand All @@ -25,6 +26,7 @@ - (NSString *)description {
NSMutableString *description = [NSMutableString stringWithFormat:@"<%@: ", NSStringFromClass([self class])];
[description appendFormat:@"payload=%@\n", self.payload];
[description appendFormat:@"experiment=%@\n", self.experiment];
[description appendFormat:@"source=%@\n", self.source];
[description appendString:@">"];

return [description copy];
Expand Down
51 changes: 51 additions & 0 deletions Sources/Qonversion/Public/QONRemoteConfigurationSource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// QONRemoteConfigurationSource.h
// Qonversion
//
// Created by Suren Sarkisyan on 30.08.2023.
// Copyright © 2023 Qonversion Inc. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(NSInteger, QONRemoteConfigurationAssignmentType) {
QONRemoteConfigurationAssignmentTypeUnknown = -1,
QONRemoteConfigurationAssignmentTypeAuto = 0,
QONRemoteConfigurationAssignmentTypeManual = 1
} NS_SWIFT_NAME(Qonversion.QONRemoteConfigurationAssignmentType);

typedef NS_ENUM(NSInteger, QONRemoteConfigurationSourceType) {
QONRemoteConfigurationSourceTypeUnknown = -1,
QONRemoteConfigurationSourceTypeExperimentControlGroup = 0,
QONRemoteConfigurationSourceTypeExperimentTreatmentGroup = 1,
QONRemoteConfigurationSourceTypeRemoteConfiguration = 2
} NS_SWIFT_NAME(Qonversion.RemoteConfigurationSourceType);

NS_SWIFT_NAME(Qonversion.RemoteConfigurationSource)
@interface QONRemoteConfigurationSource : NSObject

/**
Remote configuration source name. In this field, the experiment identifier or default remote configuration identifier depends on the source of the payload.
*/
@property (nonatomic, copy, readonly) NSString *identifier;

/**
Remote configuration source name. In this field, the experiment name or default remote configuration name depends on the source of the payload..
*/
@property (nonatomic, copy, readonly) NSString *name;

/**
Remote configuration source type
*/
@property (nonatomic, assign, readonly) QONRemoteConfigurationSourceType type;

/**
Remote config assignment type that indicates how the current payload was assigned to the user.
*/
@property (nonatomic, assign, readonly) QONRemoteConfigurationAssignmentType assignmentType;

@end

NS_ASSUME_NONNULL_END
77 changes: 77 additions & 0 deletions Sources/Qonversion/Public/QONRemoteConfigurationSource.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// QONRemoteConfigurationSource.m
// Qonversion
//
// Created by Suren Sarkisyan on 30.08.2023.
// Copyright © 2023 Qonversion Inc. All rights reserved.
//

#import "QONRemoteConfigurationSource.h"

@implementation QONRemoteConfigurationSource

- (instancetype)initWithIdentifier:(NSString *)identifier
name:(NSString *)name
type:(QONRemoteConfigurationSourceType)type
assignmentType:(QONRemoteConfigurationAssignmentType)assignmentType {
self = [super init];

if (self) {
_identifier = identifier;
_name = name;
_type = type;
_assignmentType = assignmentType;
}

return self;
}

- (NSString *)description {
NSMutableString *description = [NSMutableString stringWithFormat:@"<%@: ", NSStringFromClass([self class])];
[description appendFormat:@"identifier=%@\n", self.identifier];
[description appendFormat:@"name=%@\n", self.name];
[description appendFormat:@"type=%@ (enum value = %li),\n", [self prettyType], (long) self.type];
[description appendFormat:@"assignmentType=%@ (enum value = %li),\n", [self prettyAssignmentType], (long) self.assignmentType];
[description appendString:@">"];

return [description copy];
}

- (NSString *)prettyAssignmentType {
NSString *result;

switch (self.assignmentType) {
case QONRemoteConfigurationAssignmentTypeAuto:
result = @"auto"; break;

case QONRemoteConfigurationAssignmentTypeManual:
result = @"manual"; break;

default:
result = @"unknown"; break;
}

return result;
}

- (NSString *)prettyType {
NSString *result;

switch (self.type) {
case QONRemoteConfigurationSourceTypeRemoteConfiguration:
result = @"remote configuration"; break;

case QONRemoteConfigurationSourceTypeExperimentControlGroup:
result = @"experiment control group"; break;

case QONRemoteConfigurationSourceTypeExperimentTreatmentGroup:
result = @"experiment source group"; break;

default:
result = @"unknown"; break;
}

return result;
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,24 @@
#import "QONExperiment+Protected.h"
#import "QONExperimentGroup+Protected.h"
#import "QONRemoteConfig+Protected.h"
#import "QONRemoteConfigurationSource+Protected.h"

NSString *const kControlGroupType = @"control";
NSString *const kTreatmentGroupType = @"treatment";

NSString *const kRemoteConfigurationAssignmentTypeAuto = @"auto";
NSString *const kRemoteConfigurationAssignmentTypeManual = @"manual";

NSString *const kRemoteConfigurationSourceTypeControlGroup = @"experiment_control_group";
NSString *const kRemoteConfigurationSourceTypeTreatmentGroup = @"experiment_treatment_group";
NSString *const kRemoteConfigurationSourceTypeRemoteConfiguration = @"remote_configuration";


@interface QONRemoteConfigMapper ()

@property (nonatomic, copy) NSDictionary<NSString *, NSNumber *> *groupTypes;
@property (nonatomic, copy) NSDictionary<NSString *, NSNumber *> *remoteConfigurationAssignmentTypes;
@property (nonatomic, copy) NSDictionary<NSString *, NSNumber *> *remoteConfigurationSourceTypes;

@end

Expand All @@ -31,6 +42,17 @@ - (instancetype)init {
kControlGroupType: @(QONExperimentGroupTypeControl),
kTreatmentGroupType: @(QONExperimentGroupTypeTreatment)
};

_remoteConfigurationAssignmentTypes = @{
kRemoteConfigurationAssignmentTypeAuto: @(QONRemoteConfigurationAssignmentTypeAuto),
kRemoteConfigurationAssignmentTypeManual: @(QONRemoteConfigurationAssignmentTypeManual)
};

_remoteConfigurationSourceTypes = @{
kRemoteConfigurationSourceTypeControlGroup: @(QONRemoteConfigurationSourceTypeExperimentControlGroup),
kRemoteConfigurationSourceTypeTreatmentGroup: @(QONRemoteConfigurationSourceTypeExperimentTreatmentGroup),
kRemoteConfigurationSourceTypeRemoteConfiguration: @(QONRemoteConfigurationSourceTypeRemoteConfiguration)
};
}

return self;
Expand All @@ -42,16 +64,19 @@ - (QONRemoteConfig * _Nullable)mapRemoteConfig:(NSDictionary *)remoteConfigData
}
NSDictionary *payload = remoteConfigData[@"payload"];
NSDictionary *experimentData = remoteConfigData[@"experiment"];
NSDictionary *remoteConfigurationSourceData = remoteConfigData[@"source"];

QONRemoteConfigurationSource *remoteConfigurationSource = [self mapRemoteConfigurationSource:remoteConfigurationSourceData];
QONExperiment *experiment = [self mapExperiment:experimentData];

return [[QONRemoteConfig alloc] initWithPayload:payload experiment:experiment];
return [[QONRemoteConfig alloc] initWithPayload:payload experiment:experiment source:remoteConfigurationSource];
}

- (QONExperiment *)mapExperiment:(NSDictionary *)experimentData {
if (![experimentData isKindOfClass:[NSDictionary class]]) {
return nil;
}

NSDictionary *experimentGroupData = experimentData[@"group"];
QONExperimentGroup *group = [self mapExperimentGroup:experimentGroupData];
if (!group) {
Expand All @@ -63,6 +88,22 @@ - (QONExperiment *)mapExperiment:(NSDictionary *)experimentData {
return [[QONExperiment alloc] initWithIdentifier:experimentId name:experimentName group:group];
}

- (QONRemoteConfigurationSource *)mapRemoteConfigurationSource:(NSDictionary *)remoteConfigurationSourceData {
if (![remoteConfigurationSourceData isKindOfClass:[NSDictionary class]] || remoteConfigurationSourceData.count == 0) {
return nil;
}

NSString *uid = remoteConfigurationSourceData[@"uid"];
NSString *name = remoteConfigurationSourceData[@"name"];
NSString *typeRawValue = remoteConfigurationSourceData[@"type"];
QONRemoteConfigurationSourceType type = [self mapRemoteConfigurationSourceTypeFromString:typeRawValue];

NSString *assignmentTypeRawValue = remoteConfigurationSourceData[@"assignment_type"];
QONRemoteConfigurationAssignmentType assignmentType = [self mapRemoteConfigurationAssignmentTypeFromString:assignmentTypeRawValue];

return [[QONRemoteConfigurationSource alloc] initWithIdentifier:uid name:name type:type assignmentType:assignmentType];
}

- (QONExperimentGroup *)mapExperimentGroup:(NSDictionary *)experimentGroupData {
if (![experimentGroupData isKindOfClass:[NSDictionary class]]) {
return nil;
Expand All @@ -76,6 +117,28 @@ - (QONExperimentGroup *)mapExperimentGroup:(NSDictionary *)experimentGroupData {
return [[QONExperimentGroup alloc] initWithIdentifier:groupId type:groupType name:groupName];
}

- (QONRemoteConfigurationSourceType)mapRemoteConfigurationAssignmentTypeFromString:(NSString *)typeString {
QONRemoteConfigurationSourceType type = QONRemoteConfigurationSourceTypeUnknown;

NSNumber *typeNumber = self.remoteConfigurationAssignmentTypes[typeString];
if (typeNumber) {
type = typeNumber.integerValue;
}

return type;
}

- (QONRemoteConfigurationAssignmentType)mapRemoteConfigurationSourceTypeFromString:(NSString *)typeString {
QONRemoteConfigurationAssignmentType type = QONRemoteConfigurationAssignmentTypeUnknown;

NSNumber *typeNumber = self.remoteConfigurationSourceTypes[typeString];
if (typeNumber) {
type = typeNumber.integerValue;
}

return type;
}

- (QONExperimentGroupType)mapGroupTypeFromString:(NSString *)groupTypeString {
QONExperimentGroupType groupType = QONExperimentGroupTypeUnknown;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN

@interface QONRemoteConfig ()

- (instancetype)initWithPayload:(NSDictionary *)payload experiment:(QONExperiment *)experiment;
- (instancetype)initWithPayload:(NSDictionary *)payload experiment:(QONExperiment *)experiment source:(QONRemoteConfigurationSource *)source;

@end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// QONRemoteConfigInfo+Protected.h
// Qonversion
//
// Created by Suren Sarkisyan on 30.08.2023.
// Copyright © 2023 Qonversion Inc. All rights reserved.
//

#import <Qonversion/Qonversion.h>

NS_ASSUME_NONNULL_BEGIN

@interface QONRemoteConfigurationSource ()

- (instancetype)initWithIdentifier:(NSString *)identifier
name:(NSString *)name
type:(QONRemoteConfigurationSourceType)type
assignmentType:(QONRemoteConfigurationAssignmentType)assignmentType;

@end

NS_ASSUME_NONNULL_END

0 comments on commit ccaee05

Please sign in to comment.