Skip to content

Commit 79a227b

Browse files
ahmedAlaaInstabuga7medevAndrewAminInstabug
authored
feat: support variants in feature flags (#471)
* feat: support Variants in Features & Experiments APIs * fix: deprecated comment * fix: removeFeatureFlagsFeatureFlag catch * fix: removeFeatureFlagsFeatureFlag catch * fix: removeFeatureFlagsFeatureFlag catch * fix: removeFeatureFlagsFeatureFlag catch * fix: removeFeatureFlagsFeatureFlag catch * fix: removeFeatureFlagsFeatureFlag catch * fix removeFeaturFlag test case * test: decommission native e2e tests in favor of captain (#484) * chore(android): bump sdk to 13.2.0 (#482) * chore(ios): bump sdk to v13.2.0 (#483) * feat: add screen loading manual & automatic approaches (#477) * release: v13.2.0 (#485) * fix: format files * fix: format files * fix: format files * fix: pr comments * fix: PR comments * fix: PR comments * fix: PR comments * fix: PR comments * fix: PR comments * chore: correct pr number in changelog * chore: correct pr number in changelog * chore: correct changelog section level * refactor: remove unnecessary `List.of` * chore: mention variants support in changelog --------- Co-authored-by: Ahmed Mahmoud <[email protected]> Co-authored-by: Andrew Amin <[email protected]> Co-authored-by: Ahmed Mahmoud <[email protected]>
1 parent 25694e7 commit 79a227b

File tree

12 files changed

+272
-2
lines changed

12 files changed

+272
-2
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changelog
22

3+
## [Unreleased](https://github.com/Instabug/Instabug-Flutter/compare/v13.2.0...dev)
4+
5+
### Added
6+
7+
- 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)).
8+
9+
### Deprecated
10+
11+
- 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)).
12+
313
## [13.2.0](https://github.com/Instabug/Instabug-Flutter/compare/v13.1.1...v13.2.0)
414

515
### Added

android/src/main/java/com/instabug/flutter/modules/InstabugApi.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@
1313
import com.instabug.flutter.util.ArgsRegistry;
1414
import com.instabug.flutter.util.Reflection;
1515
import com.instabug.flutter.util.ThreadManager;
16-
import com.instabug.library.*;
16+
import com.instabug.library.Feature;
17+
import com.instabug.library.Instabug;
18+
import com.instabug.library.InstabugColorTheme;
19+
import com.instabug.library.InstabugCustomTextPlaceHolder;
20+
import com.instabug.library.IssueType;
21+
import com.instabug.library.Platform;
22+
import com.instabug.library.ReproConfigurations;
23+
import com.instabug.library.featuresflags.model.IBGFeatureFlag;
1724
import com.instabug.library.internal.module.InstabugLocale;
1825
import com.instabug.library.invocation.InstabugInvocationEvent;
1926
import com.instabug.library.model.NetworkLog;
@@ -28,6 +35,7 @@
2835
import java.io.IOException;
2936
import java.io.InputStream;
3037
import java.lang.reflect.Method;
38+
import java.util.ArrayList;
3139
import java.util.HashMap;
3240
import java.util.List;
3341
import java.util.Locale;
@@ -225,6 +233,37 @@ public void clearAllExperiments() {
225233
Instabug.clearAllExperiments();
226234
}
227235

236+
@Override
237+
public void addFeatureFlags(@NonNull Map<String, String> featureFlags) {
238+
try {
239+
List<IBGFeatureFlag> features = new ArrayList<>();
240+
for (Map.Entry<String, String> entry : featureFlags.entrySet()) {
241+
features.add(new IBGFeatureFlag(entry.getKey(), entry.getValue().isEmpty() ? null : entry.getValue()));
242+
}
243+
Instabug.addFeatureFlags(features);
244+
} catch (Exception e) {
245+
e.printStackTrace();
246+
}
247+
}
248+
249+
@Override
250+
public void removeFeatureFlags(@NonNull List<String> featureFlags) {
251+
try {
252+
Instabug.removeFeatureFlag(featureFlags);
253+
} catch (Exception e) {
254+
e.printStackTrace();
255+
}
256+
}
257+
258+
@Override
259+
public void removeAllFeatureFlags() {
260+
try {
261+
Instabug.removeAllFeatureFlags();
262+
} catch (Exception e) {
263+
e.printStackTrace();
264+
}
265+
}
266+
228267
@Override
229268
public void setUserAttribute(@NonNull String value, @NonNull String key) {
230269
Instabug.setUserAttribute(key, value);

android/src/test/java/com/instabug/flutter/InstabugApiTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.instabug.library.Platform;
3636
import com.instabug.library.ReproConfigurations;
3737
import com.instabug.library.ReproMode;
38+
import com.instabug.library.featuresflags.model.IBGFeatureFlag;
3839
import com.instabug.library.invocation.InstabugInvocationEvent;
3940
import com.instabug.library.model.NetworkLog;
4041
import com.instabug.library.ui.onboarding.WelcomeMessage;
@@ -48,6 +49,7 @@
4849

4950
import java.io.File;
5051
import java.io.IOException;
52+
import java.util.ArrayList;
5153
import java.util.Arrays;
5254
import java.util.Collections;
5355
import java.util.HashMap;
@@ -345,6 +347,32 @@ public void testClearAllExperiments() {
345347
mInstabug.verify(Instabug::clearAllExperiments);
346348
}
347349

350+
@Test
351+
public void testAddFeatureFlags() {
352+
Map<String,String > featureFlags = new HashMap<>();
353+
featureFlags.put("key1","variant1");
354+
api.addFeatureFlags(featureFlags);
355+
List<IBGFeatureFlag> flags=new ArrayList<IBGFeatureFlag>();
356+
flags.add(new IBGFeatureFlag("key1","variant1"));
357+
mInstabug.verify(() -> Instabug.addFeatureFlags(flags));
358+
}
359+
360+
@Test
361+
public void testRemoveFeatureFlags() {
362+
List<String> featureFlags = Arrays.asList("premium", "star");
363+
364+
api.removeFeatureFlags(featureFlags);
365+
366+
mInstabug.verify(() -> Instabug.removeFeatureFlag(featureFlags));
367+
}
368+
369+
@Test
370+
public void testClearAllFeatureFlags() {
371+
api.removeAllFeatureFlags();
372+
373+
mInstabug.verify(Instabug::removeAllFeatureFlags);
374+
}
375+
348376
@Test
349377
public void testSetUserAttribute() {
350378
String key = "is_premium";

example/ios/InstabugTests/InstabugApiTests.m

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,46 @@ - (void)testClearAllExperiments {
224224
OCMVerify([self.mInstabug clearAllExperiments]);
225225
}
226226

227+
- (void)testAddFeatureFlags {
228+
NSDictionary *featureFlagsMap = @{ @"key13" : @"value1", @"key2" : @"value2"};
229+
FlutterError *error;
230+
231+
[self.api addFeatureFlagsFeatureFlagsMap:featureFlagsMap error:&error];
232+
OCMVerify([self.mInstabug addFeatureFlags: [OCMArg checkWithBlock:^(id value) {
233+
NSArray<IBGFeatureFlag *> *featureFlags = value;
234+
NSString* firstFeatureFlagName = [featureFlags objectAtIndex:0 ].name;
235+
NSString* firstFeatureFlagKey = [[featureFlagsMap allKeys] objectAtIndex:0] ;
236+
if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){
237+
return YES;
238+
}
239+
return NO;
240+
}]]);
241+
}
242+
243+
- (void)testRemoveFeatureFlags {
244+
NSArray *featureFlags = @[@"exp1"];
245+
FlutterError *error;
246+
247+
[self.api removeFeatureFlagsFeatureFlags:featureFlags error:&error];
248+
OCMVerify([self.mInstabug removeFeatureFlags: [OCMArg checkWithBlock:^(id value) {
249+
NSArray<IBGFeatureFlag *> *featureFlagsObJ = value;
250+
NSString* firstFeatureFlagName = [featureFlagsObJ objectAtIndex:0 ].name;
251+
NSString* firstFeatureFlagKey = [featureFlags firstObject] ;
252+
if([ firstFeatureFlagKey isEqualToString: firstFeatureFlagName]){
253+
return YES;
254+
}
255+
return NO;
256+
}]]);}
257+
258+
- (void)testRemoveAllFeatureFlags {
259+
FlutterError *error;
260+
261+
[self.api removeAllFeatureFlagsWithError:&error];
262+
OCMVerify([self.mInstabug removeAllFeatureFlags]);
263+
}
264+
265+
266+
227267
- (void)testSetUserAttribute {
228268
NSString *key = @"is_premium";
229269
NSString *value = @"true";

example/ios/Podfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Uncomment this line to define a global platform for your project
2-
platform :ios, '13.0'
2+
platform :ios, '13.4'
33

44
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
55
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

example/lib/src/screens/my_home_page.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ class _MyHomePageState extends State<MyHomePage> {
1919

2020
final primaryColorController = TextEditingController();
2121
final screenNameController = TextEditingController();
22+
final featureFlagsController = TextEditingController();
23+
24+
@override
25+
void dispose() {
26+
featureFlagsController.dispose();
27+
screenNameController.dispose();
28+
primaryColorController.dispose();
29+
super.dispose();
30+
}
2231

2332
void restartInstabug() {
2433
Instabug.setEnabled(false);
@@ -325,7 +334,36 @@ class _MyHomePageState extends State<MyHomePage> {
325334
),
326335
],
327336
),
337+
SectionTitle('FeatureFlags'),
338+
InstabugTextField(
339+
controller: featureFlagsController,
340+
label: 'Feature Flag name',
341+
),
342+
InstabugButton(
343+
onPressed: () => setFeatureFlag(),
344+
text: 'SetFeatureFlag',
345+
),
346+
InstabugButton(
347+
onPressed: () => removeFeatureFlag(),
348+
text: 'RemoveFeatureFlag',
349+
),
350+
InstabugButton(
351+
onPressed: () => removeAllFeatureFlags(),
352+
text: 'RemoveAllFeatureFlags',
353+
),
328354
],
329355
);
330356
}
357+
358+
setFeatureFlag() {
359+
Instabug.addFeatureFlags([FeatureFlag(name: featureFlagsController.text)]);
360+
}
361+
362+
removeFeatureFlag() {
363+
Instabug.removeFeatureFlags([featureFlagsController.text]);
364+
}
365+
366+
removeAllFeatureFlags() {
367+
Instabug.clearAllFeatureFlags();
368+
}
331369
}

ios/Classes/Modules/InstabugApi.m

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,5 +318,40 @@ - (void)willRedirectToStoreWithError:(FlutterError * _Nullable __autoreleasing *
318318
[Instabug willRedirectToAppStore];
319319
}
320320

321+
- (void)addFeatureFlagsFeatureFlagsMap:(nonnull NSDictionary<NSString *,NSString *> *)featureFlagsMap error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {
322+
NSMutableArray<IBGFeatureFlag *> *featureFlags = [NSMutableArray array];
323+
for(id key in featureFlagsMap){
324+
NSString* variant =((NSString * )[featureFlagsMap objectForKey:key]);
325+
if ([variant length]==0) {
326+
[featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key]];
327+
}
328+
else{
329+
[featureFlags addObject:[[IBGFeatureFlag alloc] initWithName:key variant:variant]];
330+
331+
}
332+
}
333+
[Instabug addFeatureFlags:featureFlags];
334+
}
335+
336+
337+
- (void)removeAllFeatureFlagsWithError:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {
338+
[Instabug removeAllFeatureFlags];
339+
340+
}
341+
342+
343+
- (void)removeFeatureFlagsFeatureFlags:(nonnull NSArray<NSString *> *)featureFlags error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {
344+
345+
NSMutableArray<IBGFeatureFlag *> *features = [NSMutableArray array];
346+
for(id item in featureFlags){
347+
[features addObject:[[IBGFeatureFlag alloc] initWithName:item]];
348+
}
349+
@try {
350+
[Instabug removeFeatureFlags:features];
351+
} @catch (NSException *exception) {
352+
NSLog(@"%@", exception);
353+
354+
}
355+
}
321356

322357
@end

lib/instabug_flutter.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Models
22
export 'src/models/crash_data.dart';
33
export 'src/models/exception_data.dart';
4+
export 'src/models/feature_flag.dart';
45
export 'src/models/network_data.dart';
56
export 'src/models/trace.dart';
67
// Modules

lib/src/models/feature_flag.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class FeatureFlag {
2+
/// the name of feature flag
3+
String name;
4+
5+
/// The variant of the feature flag.
6+
String? variant;
7+
8+
FeatureFlag({required this.name, this.variant});
9+
}

lib/src/modules/instabug.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
// ignore_for_file: avoid_classes_with_only_static_members
22

33
import 'dart:async';
4+
45
// to maintain supported versions prior to Flutter 3.3
56
// ignore: unnecessary_import
67
import 'dart:typed_data';
8+
79
// to maintain supported versions prior to Flutter 3.3
810
// ignore: unnecessary_import
911
import 'dart:ui';
@@ -246,20 +248,50 @@ class Instabug {
246248
}
247249

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

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

258266
/// Clears all experiments from the next report.
267+
268+
@Deprecated(
269+
'Please migrate to the new feature flags APIs: Instabug.clearAllFeatureFlags.',
270+
)
259271
static Future<void> clearAllExperiments() async {
260272
return _host.clearAllExperiments();
261273
}
262274

275+
/// Adds feature flags to the next report.
276+
static Future<void> addFeatureFlags(List<FeatureFlag> featureFlags) async {
277+
final map = <String, String>{};
278+
for (final value in featureFlags) {
279+
map[value.name] = value.variant ?? '';
280+
}
281+
282+
return _host.addFeatureFlags(map);
283+
}
284+
285+
/// Removes certain feature flags from the next report.
286+
static Future<void> removeFeatureFlags(List<String> featureFlags) async {
287+
return _host.removeFeatureFlags(featureFlags);
288+
}
289+
290+
/// Clears all feature flags from the next report.
291+
static Future<void> clearAllFeatureFlags() async {
292+
return _host.removeAllFeatureFlags();
293+
}
294+
263295
/// Add custom user attribute [value] with a [key] that is going to be sent with each feedback, bug or crash.
264296
static Future<void> setUserAttribute(String value, String key) async {
265297
return _host.setUserAttribute(value, key);

pigeons/instabug.api.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ abstract class InstabugHostApi {
3131
void addExperiments(List<String> experiments);
3232
void removeExperiments(List<String> experiments);
3333
void clearAllExperiments();
34+
void addFeatureFlags(Map<String, String> featureFlagsMap);
35+
void removeFeatureFlags(List<String> featureFlags);
36+
void removeAllFeatureFlags();
3437

3538
void setUserAttribute(String value, String key);
3639
void removeUserAttribute(String key);

0 commit comments

Comments
 (0)