Skip to content

Commit 997a266

Browse files
ahmedAlaaInstabuga7medevAndrewAminInstabug
committed
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 494a4ca commit 997a266

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
@@ -39,6 +39,7 @@
3939
import com.instabug.library.Platform;
4040
import com.instabug.library.ReproConfigurations;
4141
import com.instabug.library.ReproMode;
42+
import com.instabug.library.featuresflags.model.IBGFeatureFlag;
4243
import com.instabug.library.invocation.InstabugInvocationEvent;
4344
import com.instabug.library.model.NetworkLog;
4445
import com.instabug.library.ui.onboarding.WelcomeMessage;
@@ -54,6 +55,7 @@
5455

5556
import java.io.File;
5657
import java.io.IOException;
58+
import java.util.ArrayList;
5759
import java.util.Arrays;
5860
import java.util.Collections;
5961
import java.util.HashMap;
@@ -356,6 +358,32 @@ public void testClearAllExperiments() {
356358
mInstabug.verify(Instabug::clearAllExperiments);
357359
}
358360

361+
@Test
362+
public void testAddFeatureFlags() {
363+
Map<String,String > featureFlags = new HashMap<>();
364+
featureFlags.put("key1","variant1");
365+
api.addFeatureFlags(featureFlags);
366+
List<IBGFeatureFlag> flags=new ArrayList<IBGFeatureFlag>();
367+
flags.add(new IBGFeatureFlag("key1","variant1"));
368+
mInstabug.verify(() -> Instabug.addFeatureFlags(flags));
369+
}
370+
371+
@Test
372+
public void testRemoveFeatureFlags() {
373+
List<String> featureFlags = Arrays.asList("premium", "star");
374+
375+
api.removeFeatureFlags(featureFlags);
376+
377+
mInstabug.verify(() -> Instabug.removeFeatureFlag(featureFlags));
378+
}
379+
380+
@Test
381+
public void testClearAllFeatureFlags() {
382+
api.removeAllFeatureFlags();
383+
384+
mInstabug.verify(Instabug::removeAllFeatureFlags);
385+
}
386+
359387
@Test
360388
public void testSetUserAttribute() {
361389
String key = "is_premium";

example/ios/InstabugTests/InstabugApiTests.m

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

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

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';
@@ -247,20 +249,50 @@ class Instabug {
247249
}
248250

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

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

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

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

pigeons/instabug.api.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ abstract class InstabugHostApi {
4040
void addExperiments(List<String> experiments);
4141
void removeExperiments(List<String> experiments);
4242
void clearAllExperiments();
43+
void addFeatureFlags(Map<String, String> featureFlagsMap);
44+
void removeFeatureFlags(List<String> featureFlags);
45+
void removeAllFeatureFlags();
4346

4447
void setUserAttribute(String value, String key);
4548
void removeUserAttribute(String key);

0 commit comments

Comments
 (0)