Skip to content

feat: support variants in feature flags #471

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 32 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
66085bc
feat: support Variants in Features & Experiments APIs
ahmedAlaaInstabug Jun 3, 2024
a1cbbeb
fix: deprecated comment
ahmedAlaaInstabug Jun 3, 2024
16e7d27
fix: removeFeatureFlagsFeatureFlag catch
ahmedAlaaInstabug Jun 3, 2024
2f10fb9
fix: removeFeatureFlagsFeatureFlag catch
ahmedAlaaInstabug Jun 3, 2024
4a8ea19
Merge branch 'dev' into feat/support-Variants-in-Features
ahmedAlaaInstabug Jun 3, 2024
e0bd43f
fix: removeFeatureFlagsFeatureFlag catch
ahmedAlaaInstabug Jun 3, 2024
9bf7ad4
fix: removeFeatureFlagsFeatureFlag catch
ahmedAlaaInstabug Jun 3, 2024
fab167d
fix: removeFeatureFlagsFeatureFlag catch
ahmedAlaaInstabug Jun 3, 2024
4add73d
fix: removeFeatureFlagsFeatureFlag catch
ahmedAlaaInstabug Jun 3, 2024
b99fb1b
Merge branch 'dev' into feat/support-Variants-in-Features
ahmedAlaaInstabug Jun 4, 2024
da1f0ce
fix removeFeaturFlag test case
ahmedAlaaInstabug Jun 4, 2024
c1e4e0f
test: decommission native e2e tests in favor of captain (#484)
a7medev Jul 7, 2024
fea5c3d
chore(android): bump sdk to 13.2.0 (#482)
a7medev Jul 7, 2024
66ff626
chore(ios): bump sdk to v13.2.0 (#483)
a7medev Jul 7, 2024
554c17f
feat: add screen loading manual & automatic approaches (#477)
AndrewAminInstabug Jul 7, 2024
ea27866
release: v13.2.0 (#485)
a7medev Jul 7, 2024
96ce979
Merge branch 'refs/heads/master' into feat/support-Variants-in-Features
ahmedAlaaInstabug Jul 15, 2024
9b5a91b
fix: format files
ahmedAlaaInstabug Jul 15, 2024
c33d438
fix: format files
ahmedAlaaInstabug Jul 15, 2024
2a386b9
fix: format files
ahmedAlaaInstabug Jul 15, 2024
0ed1d47
fix: pr comments
ahmedAlaaInstabug Jul 15, 2024
0c70010
fix: PR comments
ahmedAlaaInstabug Jul 16, 2024
156aa49
fix: PR comments
ahmedAlaaInstabug Jul 17, 2024
b0b5404
fix: PR comments
ahmedAlaaInstabug Jul 17, 2024
c7782e8
fix: PR comments
ahmedAlaaInstabug Jul 17, 2024
efb7977
fix: PR comments
ahmedAlaaInstabug Jul 17, 2024
2d56c5b
chore: correct pr number in changelog
a7medev Aug 4, 2024
11cbbaf
chore: correct pr number in changelog
a7medev Aug 4, 2024
30ae2f7
chore: correct changelog section level
a7medev Aug 4, 2024
0ee6df5
refactor: remove unnecessary `List.of`
a7medev Aug 4, 2024
defae18
Merge branch 'dev' into feat/support-Variants-in-Features
a7medev Aug 4, 2024
899db2d
chore: mention variants support in changelog
a7medev Aug 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## [Unreleased](https://github.com/Instabug/Instabug-Flutter/compare/v13.2.0...dev)

### Added

- Add support for variants in Feature Flags through the APIs `Instabug.addFeatureFlags`, `Instabug.removeFeatureFlags` and `Instabug.clearAllFeatureFlags` ([#471](https://github.com/Instabug/Instabug-Flutter/pull/471)).

### Deprecated

- Deprecate Experiments APIs `Instabug.addExperiments`, `Instabug.removeExperiments` and `Instabug.clearAllExperiments` in favor of the new Feature Flags APIs ([#471](https://github.com/Instabug/Instabug-Flutter/pull/471)).

## [13.2.0](https://github.com/Instabug/Instabug-Flutter/compare/v13.1.1...v13.2.0)

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@
import com.instabug.flutter.util.ArgsRegistry;
import com.instabug.flutter.util.Reflection;
import com.instabug.flutter.util.ThreadManager;
import com.instabug.library.*;
import com.instabug.library.Feature;
import com.instabug.library.Instabug;
import com.instabug.library.InstabugColorTheme;
import com.instabug.library.InstabugCustomTextPlaceHolder;
import com.instabug.library.IssueType;
import com.instabug.library.Platform;
import com.instabug.library.ReproConfigurations;
import com.instabug.library.featuresflags.model.IBGFeatureFlag;
import com.instabug.library.internal.module.InstabugLocale;
import com.instabug.library.invocation.InstabugInvocationEvent;
import com.instabug.library.model.NetworkLog;
Expand All @@ -28,6 +35,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -225,6 +233,37 @@ public void clearAllExperiments() {
Instabug.clearAllExperiments();
}

@Override
public void addFeatureFlags(@NonNull Map<String, String> featureFlags) {
try {
List<IBGFeatureFlag> features = new ArrayList<>();
for (Map.Entry<String, String> entry : featureFlags.entrySet()) {
features.add(new IBGFeatureFlag(entry.getKey(), entry.getValue().isEmpty() ? null : entry.getValue()));
}
Comment on lines +239 to +242
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW we can use Java 8 streams here instead if you think they will be more readable, I'm okay with keeping this one as well.

Instabug.addFeatureFlags(features);
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void removeFeatureFlags(@NonNull List<String> featureFlags) {
try {
Instabug.removeFeatureFlag(featureFlags);
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void removeAllFeatureFlags() {
try {
Instabug.removeAllFeatureFlags();
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void setUserAttribute(@NonNull String value, @NonNull String key) {
Instabug.setUserAttribute(key, value);
Expand Down
28 changes: 28 additions & 0 deletions android/src/test/java/com/instabug/flutter/InstabugApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.instabug.library.Platform;
import com.instabug.library.ReproConfigurations;
import com.instabug.library.ReproMode;
import com.instabug.library.featuresflags.model.IBGFeatureFlag;
import com.instabug.library.invocation.InstabugInvocationEvent;
import com.instabug.library.model.NetworkLog;
import com.instabug.library.ui.onboarding.WelcomeMessage;
Expand All @@ -48,6 +49,7 @@

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
Expand Down Expand Up @@ -345,6 +347,32 @@ public void testClearAllExperiments() {
mInstabug.verify(Instabug::clearAllExperiments);
}

@Test
public void testAddFeatureFlags() {
Map<String,String > featureFlags = new HashMap<>();
featureFlags.put("key1","variant1");
api.addFeatureFlags(featureFlags);
List<IBGFeatureFlag> flags=new ArrayList<IBGFeatureFlag>();
flags.add(new IBGFeatureFlag("key1","variant1"));
mInstabug.verify(() -> Instabug.addFeatureFlags(flags));
}

@Test
public void testRemoveFeatureFlags() {
List<String> featureFlags = Arrays.asList("premium", "star");

api.removeFeatureFlags(featureFlags);

mInstabug.verify(() -> Instabug.removeFeatureFlag(featureFlags));
}

@Test
public void testClearAllFeatureFlags() {
api.removeAllFeatureFlags();

mInstabug.verify(Instabug::removeAllFeatureFlags);
}

@Test
public void testSetUserAttribute() {
String key = "is_premium";
Expand Down
40 changes: 40 additions & 0 deletions example/ios/InstabugTests/InstabugApiTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,46 @@ - (void)testClearAllExperiments {
OCMVerify([self.mInstabug clearAllExperiments]);
}

- (void)testAddFeatureFlags {
NSDictionary *featureFlagsMap = @{ @"key13" : @"value1", @"key2" : @"value2"};
FlutterError *error;

[self.api addFeatureFlagsFeatureFlagsMap:featureFlagsMap error:&error];
OCMVerify([self.mInstabug addFeatureFlags: [OCMArg checkWithBlock:^(id value) {
NSArray<IBGFeatureFlag *> *featureFlags = value;
NSString* firstFeatureFlagName = [featureFlags objectAtIndex:0 ].name;
NSString* firstFeatureFlagKey = [[featureFlagsMap allKeys] objectAtIndex:0] ;
if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){
return YES;
}
return NO;
}]]);
}

- (void)testRemoveFeatureFlags {
NSArray *featureFlags = @[@"exp1"];
FlutterError *error;

[self.api removeFeatureFlagsFeatureFlags:featureFlags error:&error];
OCMVerify([self.mInstabug removeFeatureFlags: [OCMArg checkWithBlock:^(id value) {
NSArray<IBGFeatureFlag *> *featureFlagsObJ = value;
NSString* firstFeatureFlagName = [featureFlagsObJ objectAtIndex:0 ].name;
NSString* firstFeatureFlagKey = [featureFlags firstObject] ;
if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){
return YES;
}
return NO;
}]]);}

- (void)testRemoveAllFeatureFlags {
FlutterError *error;

[self.api removeAllFeatureFlagsWithError:&error];
OCMVerify([self.mInstabug removeAllFeatureFlags]);
}



- (void)testSetUserAttribute {
NSString *key = @"is_premium";
NSString *value = @"true";
Expand Down
2 changes: 1 addition & 1 deletion example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
platform :ios, '13.0'
platform :ios, '13.4'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand Down
38 changes: 38 additions & 0 deletions example/lib/src/screens/my_home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ class _MyHomePageState extends State<MyHomePage> {

final primaryColorController = TextEditingController();
final screenNameController = TextEditingController();
final featureFlagsController = TextEditingController();

@override
void dispose() {
featureFlagsController.dispose();
screenNameController.dispose();
primaryColorController.dispose();
super.dispose();
}

void restartInstabug() {
Instabug.setEnabled(false);
Expand Down Expand Up @@ -325,7 +334,36 @@ class _MyHomePageState extends State<MyHomePage> {
),
],
),
SectionTitle('FeatureFlags'),
InstabugTextField(
controller: featureFlagsController,
label: 'Feature Flag name',
),
InstabugButton(
onPressed: () => setFeatureFlag(),
text: 'SetFeatureFlag',
),
InstabugButton(
onPressed: () => removeFeatureFlag(),
text: 'RemoveFeatureFlag',
),
InstabugButton(
onPressed: () => removeAllFeatureFlags(),
text: 'RemoveAllFeatureFlags',
),
],
);
}

setFeatureFlag() {
Instabug.addFeatureFlags([FeatureFlag(name: featureFlagsController.text)]);
}

removeFeatureFlag() {
Instabug.removeFeatureFlags([featureFlagsController.text]);
}

removeAllFeatureFlags() {
Instabug.clearAllFeatureFlags();
}
}
35 changes: 35 additions & 0 deletions ios/Classes/Modules/InstabugApi.m
Original file line number Diff line number Diff line change
Expand Up @@ -318,5 +318,40 @@ - (void)willRedirectToStoreWithError:(FlutterError * _Nullable __autoreleasing *
[Instabug willRedirectToAppStore];
}

- (void)addFeatureFlagsFeatureFlagsMap:(nonnull NSDictionary<NSString *,NSString *> *)featureFlagsMap error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {
NSMutableArray<IBGFeatureFlag *> *featureFlags = [NSMutableArray array];
for(id key in featureFlagsMap){
NSString* variant =((NSString * )[featureFlagsMap objectForKey:key]);
if ([variant length]==0) {
[featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key]];
}
else{
[featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key variant:variant]];

}
}
[Instabug addFeatureFlags:featureFlags];
}


- (void)removeAllFeatureFlagsWithError:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {
[Instabug removeAllFeatureFlags];

}


- (void)removeFeatureFlagsFeatureFlags:(nonnull NSArray<NSString *> *)featureFlags error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {

NSMutableArray<IBGFeatureFlag *> *features = [NSMutableArray array];
for(id item in featureFlags){
[features addObject:[[IBGFeatureFlag alloc] initWithName:item]];
}
@try {
[Instabug removeFeatureFlags:features];
} @catch (NSException *exception) {
NSLog(@"%@", exception);

}
}

@end
1 change: 1 addition & 0 deletions lib/instabug_flutter.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Models
export 'src/models/crash_data.dart';
export 'src/models/exception_data.dart';
export 'src/models/feature_flag.dart';
export 'src/models/network_data.dart';
export 'src/models/trace.dart';
// Modules
Expand Down
9 changes: 9 additions & 0 deletions lib/src/models/feature_flag.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class FeatureFlag {
/// the name of feature flag
String name;

/// The variant of the feature flag.
String? variant;

FeatureFlag({required this.name, this.variant});
}
32 changes: 32 additions & 0 deletions lib/src/modules/instabug.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// ignore_for_file: avoid_classes_with_only_static_members

import 'dart:async';

// to maintain supported versions prior to Flutter 3.3
// ignore: unnecessary_import
import 'dart:typed_data';

// to maintain supported versions prior to Flutter 3.3
// ignore: unnecessary_import
import 'dart:ui';
Expand Down Expand Up @@ -246,20 +248,50 @@ class Instabug {
}

/// Adds experiments to the next report.
@Deprecated(
'Please migrate to the new feature flags APIs: Instabug.addFeatureFlags.',
)
static Future<void> addExperiments(List<String> experiments) async {
return _host.addExperiments(experiments);
}

/// Removes certain experiments from the next report.
@Deprecated(
'Please migrate to the new feature flags APIs: Instabug.removeFeatureFlags.',
)
static Future<void> removeExperiments(List<String> experiments) async {
return _host.removeExperiments(experiments);
}

/// Clears all experiments from the next report.

@Deprecated(
'Please migrate to the new feature flags APIs: Instabug.clearAllFeatureFlags.',
)
static Future<void> clearAllExperiments() async {
return _host.clearAllExperiments();
}

/// Adds feature flags to the next report.
static Future<void> addFeatureFlags(List<FeatureFlag> featureFlags) async {
final map = <String, String>{};
for (final value in featureFlags) {
map[value.name] = value.variant ?? '';
}

return _host.addFeatureFlags(map);
}

/// Removes certain feature flags from the next report.
static Future<void> removeFeatureFlags(List<String> featureFlags) async {
return _host.removeFeatureFlags(featureFlags);
}

/// Clears all feature flags from the next report.
static Future<void> clearAllFeatureFlags() async {
return _host.removeAllFeatureFlags();
}

/// Add custom user attribute [value] with a [key] that is going to be sent with each feedback, bug or crash.
static Future<void> setUserAttribute(String value, String key) async {
return _host.setUserAttribute(value, key);
Expand Down
3 changes: 3 additions & 0 deletions pigeons/instabug.api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ abstract class InstabugHostApi {
void addExperiments(List<String> experiments);
void removeExperiments(List<String> experiments);
void clearAllExperiments();
void addFeatureFlags(Map<String, String> featureFlagsMap);
void removeFeatureFlags(List<String> featureFlags);
void removeAllFeatureFlags();

void setUserAttribute(String value, String key);
void removeUserAttribute(String key);
Expand Down
Loading