Skip to content

Commit af75189

Browse files
Merge branch 'feat/support-advanced-UI-customization' into chore/-Remove-deprecated-APIS
2 parents d82c1d4 + acdcda7 commit af75189

File tree

11 files changed

+323
-22
lines changed

11 files changed

+323
-22
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Changed
66

77
- **BREAKING** Remove deprecated APIs ([#614](https://github.com/Instabug/Instabug-Flutter/pull/614)). See migration guide for more details.
8+
89
### Added
910

1011
- Add support for Advanced UI customization with comprehensive theming capabilities ([#599](https://github.com/Instabug/Instabug-Flutter/pull/599))
@@ -14,6 +15,8 @@
1415

1516
### Added
1617

18+
- Add support for App variant. ([#585](https://github.com/Instabug/Instabug-Flutter/pull/585))
19+
1720
- Add support for xCode 16. ([#574](https://github.com/Instabug/Instabug-Flutter/pull/574))
1821

1922
- Add support for BugReporting user consents. ([#573](https://github.com/Instabug/Instabug-Flutter/pull/573))

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

Lines changed: 169 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
import android.net.Uri;
88
import android.graphics.Typeface;
99
import android.util.Log;
10+
1011
import androidx.annotation.NonNull;
1112
import androidx.annotation.Nullable;
1213
import androidx.annotation.VisibleForTesting;
14+
1315
import com.instabug.flutter.generated.InstabugPigeon;
1416
import com.instabug.flutter.util.ArgsRegistry;
1517
import com.instabug.flutter.util.Reflection;
@@ -31,9 +33,11 @@
3133
import com.instabug.library.invocation.InstabugInvocationEvent;
3234
import com.instabug.library.model.NetworkLog;
3335
import com.instabug.library.ui.onboarding.WelcomeMessage;
36+
3437
import io.flutter.FlutterInjector;
3538
import io.flutter.embedding.engine.loader.FlutterLoader;
3639
import io.flutter.plugin.common.BinaryMessenger;
40+
3741
import org.jetbrains.annotations.NotNull;
3842
import org.json.JSONObject;
3943

@@ -103,10 +107,12 @@ public Boolean isEnabled() {
103107

104108
@NotNull
105109
@Override
106-
public Boolean isBuilt() { return Instabug.isBuilt(); }
110+
public Boolean isBuilt() {
111+
return Instabug.isBuilt();
112+
}
107113

108114
@Override
109-
public void init(@NonNull String token, @NonNull List<String> invocationEvents, @NonNull String debugLogsLevel) {
115+
public void init(@NonNull String token, @NonNull List<String> invocationEvents, @NonNull String debugLogsLevel, @Nullable String appVariant) {
110116
setCurrentPlatform();
111117

112118
InstabugInvocationEvent[] invocationEventsArray = new InstabugInvocationEvent[invocationEvents.size()];
@@ -117,11 +123,14 @@ public void init(@NonNull String token, @NonNull List<String> invocationEvents,
117123

118124
final Application application = (Application) context;
119125
final int parsedLogLevel = ArgsRegistry.sdkLogLevels.get(debugLogsLevel);
120-
121-
new Instabug.Builder(application, token)
126+
Instabug.Builder builder = new Instabug.Builder(application, token)
122127
.setInvocationEvents(invocationEventsArray)
123-
.setSdkDebugLogsLevel(parsedLogLevel)
124-
.build();
128+
.setSdkDebugLogsLevel(parsedLogLevel);
129+
if (appVariant != null) {
130+
builder.setAppVariant(appVariant);
131+
}
132+
133+
builder.build();
125134

126135
Instabug.setScreenshotProvider(screenshotProvider);
127136
}
@@ -147,6 +156,17 @@ public void setUserData(@NonNull String data) {
147156
Instabug.setUserData(data);
148157
}
149158

159+
@Override
160+
public void setAppVariant(@NonNull String appVariant) {
161+
try {
162+
Instabug.setAppVariant(appVariant);
163+
164+
} catch (Exception e) {
165+
e.printStackTrace();
166+
}
167+
168+
}
169+
150170
@Override
151171
public void logUserEvent(@NonNull String name) {
152172
Instabug.logUserEvent(name);
@@ -487,14 +507,140 @@ public void willRedirectToStore() {
487507
Instabug.willRedirectToStore();
488508
}
489509

490-
510+
491511
@Override
492512
public void setNetworkLogBodyEnabled(@NonNull Boolean isEnabled) {
493-
try {
494-
Instabug.setNetworkLogBodyEnabled(isEnabled);
495-
} catch (Exception e) {
496-
e.printStackTrace();
513+
try {
514+
Instabug.setNetworkLogBodyEnabled(isEnabled);
515+
} catch (Exception e) {
516+
e.printStackTrace();
517+
}
518+
}
519+
520+
@Override
521+
public void setTheme(@NonNull Map<String, Object> themeConfig) {
522+
try {
523+
Log.d(TAG, "setTheme called with config: " + themeConfig.toString());
524+
525+
com.instabug.library.model.IBGTheme.Builder builder = new com.instabug.library.model.IBGTheme.Builder();
526+
527+
if (themeConfig.containsKey("primaryColor")) {
528+
builder.setPrimaryColor(getColor(themeConfig, "primaryColor"));
529+
}
530+
if (themeConfig.containsKey("secondaryTextColor")) {
531+
builder.setSecondaryTextColor(getColor(themeConfig, "secondaryTextColor"));
532+
}
533+
if (themeConfig.containsKey("primaryTextColor")) {
534+
builder.setPrimaryTextColor(getColor(themeConfig, "primaryTextColor"));
535+
}
536+
if (themeConfig.containsKey("titleTextColor")) {
537+
builder.setTitleTextColor(getColor(themeConfig, "titleTextColor"));
538+
}
539+
if (themeConfig.containsKey("backgroundColor")) {
540+
builder.setBackgroundColor(getColor(themeConfig, "backgroundColor"));
541+
}
542+
543+
if (themeConfig.containsKey("primaryTextStyle")) {
544+
builder.setPrimaryTextStyle(getTextStyle(themeConfig, "primaryTextStyle"));
545+
}
546+
if (themeConfig.containsKey("secondaryTextStyle")) {
547+
builder.setSecondaryTextStyle(getTextStyle(themeConfig, "secondaryTextStyle"));
548+
}
549+
if (themeConfig.containsKey("ctaTextStyle")) {
550+
builder.setCtaTextStyle(getTextStyle(themeConfig, "ctaTextStyle"));
551+
}
552+
553+
setFontIfPresent(themeConfig, builder, "primaryFontPath", "primaryFontAsset", "primary");
554+
setFontIfPresent(themeConfig, builder, "secondaryFontPath", "secondaryFontAsset", "secondary");
555+
setFontIfPresent(themeConfig, builder, "ctaFontPath", "ctaFontAsset", "CTA");
556+
557+
com.instabug.library.model.IBGTheme theme = builder.build();
558+
Instabug.setTheme(theme);
559+
Log.d(TAG, "Theme applied successfully");
560+
561+
} catch (Exception e) {
562+
Log.e(TAG, "Error in setTheme: " + e.getMessage());
563+
e.printStackTrace();
564+
}
565+
}
566+
567+
568+
569+
/**
570+
* Retrieves a color value from the Map.
571+
*
572+
* @param map The Map object.
573+
* @param key The key to look for.
574+
* @return The parsed color as an integer, or black if missing or invalid.
575+
*/
576+
private int getColor(Map<String, Object> map, String key) {
577+
try {
578+
if (map != null && map.containsKey(key) && map.get(key) != null) {
579+
String colorString = (String) map.get(key);
580+
return android.graphics.Color.parseColor(colorString);
581+
}
582+
} catch (Exception e) {
583+
e.printStackTrace();
584+
}
585+
return android.graphics.Color.BLACK;
586+
}
587+
588+
/**
589+
* Retrieves a text style from the Map.
590+
*
591+
* @param map The Map object.
592+
* @param key The key to look for.
593+
* @return The corresponding Typeface style, or Typeface.NORMAL if missing or invalid.
594+
*/
595+
private int getTextStyle(Map<String, Object> map, String key) {
596+
try {
597+
if (map != null && map.containsKey(key) && map.get(key) != null) {
598+
String style = (String) map.get(key);
599+
switch (style.toLowerCase()) {
600+
case "bold":
601+
return Typeface.BOLD;
602+
case "italic":
603+
return Typeface.ITALIC;
604+
case "bold_italic":
605+
return Typeface.BOLD_ITALIC;
606+
case "normal":
607+
default:
608+
return Typeface.NORMAL;
497609
}
610+
}
611+
} catch (Exception e) {
612+
e.printStackTrace();
613+
}
614+
return Typeface.NORMAL;
615+
}
616+
617+
/**
618+
* Sets a font on the theme builder if the font configuration is present in the theme config.
619+
*
620+
* @param themeConfig The theme configuration map
621+
* @param builder The theme builder
622+
* @param fileKey The key for font file path
623+
* @param assetKey The key for font asset path
624+
* @param fontType The type of font (for logging purposes)
625+
*/
626+
private void setFontIfPresent(Map<String, Object> themeConfig, com.instabug.library.model.IBGTheme.Builder builder,
627+
String fileKey, String assetKey, String fontType) {
628+
if (themeConfig.containsKey(fileKey) || themeConfig.containsKey(assetKey)) {
629+
Typeface typeface = getTypeface(themeConfig, fileKey, assetKey);
630+
if (typeface != null) {
631+
switch (fontType) {
632+
case "primary":
633+
builder.setPrimaryTextFont(typeface);
634+
break;
635+
case "secondary":
636+
builder.setSecondaryTextFont(typeface);
637+
break;
638+
case "CTA":
639+
builder.setCtaTextFont(typeface);
640+
break;
641+
}
642+
}
643+
}
498644
}
499645

500646
@Override
@@ -648,5 +794,17 @@ private Typeface getTypeface(Map<String, Object> map, String fileKey, String ass
648794
}
649795
}
650796

797+
/**
798+
* Enables or disables displaying in full-screen mode, hiding the status and navigation bars.
799+
* @param isEnabled A boolean to enable/disable setFullscreen.
800+
*/
801+
@Override
802+
public void setFullscreen(@NonNull final Boolean isEnabled) {
803+
try {
804+
Instabug.setFullscreen(isEnabled);
805+
} catch (Exception e) {
806+
e.printStackTrace();
807+
}
808+
}
651809

652810
}

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

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ public void testSetCurrentPlatform() {
134134
@Test
135135
public void testSdkInit() {
136136
String token = "app-token";
137+
String appVariant = "app-variant";
138+
137139
List<String> invocationEvents = Collections.singletonList("InvocationEvent.floatingButton");
138140
String logLevel = "LogLevel.error";
139141

@@ -145,7 +147,7 @@ public void testSdkInit() {
145147
when(mock.setSdkDebugLogsLevel(anyInt())).thenReturn(mock);
146148
});
147149

148-
api.init(token, invocationEvents, logLevel);
150+
api.init(token, invocationEvents, logLevel,appVariant);
149151

150152
Instabug.Builder builder = mInstabugBuilder.constructed().get(0);
151153

@@ -157,6 +159,8 @@ public void testSdkInit() {
157159
);
158160
verify(builder).setInvocationEvents(InstabugInvocationEvent.FLOATING_BUTTON);
159161
verify(builder).setSdkDebugLogsLevel(LogLevel.ERROR);
162+
verify(builder).setAppVariant(appVariant);
163+
160164
verify(builder).build();
161165

162166
// Sets screenshot provider
@@ -625,6 +629,14 @@ public void testSetNetworkLogBodyEnabled() {
625629
mInstabug.verify(() -> Instabug.setNetworkLogBodyEnabled(true));
626630
}
627631

632+
@Test
633+
public void testSetAppVariant() {
634+
String appVariant = "app-variant";
635+
api.setAppVariant(appVariant);
636+
637+
mInstabug.verify(() -> Instabug.setAppVariant(appVariant));
638+
}
639+
628640
@Test
629641
public void testSetNetworkLogBodyDisabled() {
630642
api.setNetworkLogBodyEnabled(false);
@@ -679,5 +691,23 @@ public void testSetThemeWithAllProperties() {
679691
mInstabug.verify(() -> Instabug.setTheme(any(com.instabug.library.model.IBGTheme.class)));
680692
}
681693

694+
@Test
695+
public void testSetFullscreen() {
696+
boolean isEnabled = true;
697+
698+
api.setFullscreen(isEnabled);
699+
700+
mInstabug.verify(() -> Instabug.setFullscreen(isEnabled));
701+
}
702+
703+
@Test
704+
public void testSetFullscreenDisabled() {
705+
boolean isEnabled = false;
706+
707+
api.setFullscreen(isEnabled);
708+
709+
mInstabug.verify(() -> Instabug.setFullscreen(isEnabled));
710+
}
711+
682712

683713
}

example/ios/InstabugTests/InstabugApiTests.m

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,22 @@ - (void)testSetEnabled {
3838

3939
- (void)testInit {
4040
NSString *token = @"app-token";
41+
NSString *appVariant = @"app-variant";
42+
4143
NSArray<NSString *> *invocationEvents = @[@"InvocationEvent.floatingButton", @"InvocationEvent.screenshot"];
4244
NSString *logLevel = @"LogLevel.error";
4345
FlutterError *error;
4446

45-
[self.api initToken:token invocationEvents:invocationEvents debugLogsLevel:logLevel error:&error];
47+
[self.api initToken:token invocationEvents:invocationEvents debugLogsLevel:logLevel appVariant:appVariant error:&error];
4648

4749
OCMVerify([self.mInstabug setCurrentPlatform:IBGPlatformFlutter]);
50+
4851
OCMVerify([self.mInstabug setSdkDebugLogsLevel:IBGSDKDebugLogsLevelError]);
52+
4953
OCMVerify([self.mInstabug startWithToken:token invocationEvents:(IBGInvocationEventFloatingButton | IBGInvocationEventScreenshot)]);
54+
55+
XCTAssertEqual(Instabug.appVariant, appVariant);
56+
5057
}
5158

5259
- (void)testShow {
@@ -614,4 +621,14 @@ - (void)testSetThemeWithAllProperties {
614621
OCMVerify([self.mInstabug setTheme:[OCMArg isNotNil]]);
615622
}
616623

624+
- (void)testSetFullscreen {
625+
NSNumber *isEnabled = @1;
626+
FlutterError *error;
627+
628+
[self.api setFullscreenIsEnabled:isEnabled error:&error];
629+
630+
// Since this is an empty implementation, we just verify the method can be called without error
631+
XCTAssertNil(error);
632+
}
633+
617634
@end

example/ios/Podfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ target 'Runner' do
3030

3131
use_frameworks!
3232
use_modular_headers!
33-
3433
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
3534
end
3635

example/lib/main.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ void main() {
4646
WidgetsFlutterBinding.ensureInitialized();
4747

4848
Instabug.init(
49-
token: 'ed6f659591566da19b67857e1b9d40ab',
50-
invocationEvents: [InvocationEvent.floatingButton],
51-
debugLogsLevel: LogLevel.verbose,
52-
);
49+
token: 'ed6f659591566da19b67857e1b9d40ab',
50+
invocationEvents: [InvocationEvent.floatingButton],
51+
debugLogsLevel: LogLevel.verbose,
52+
appVariant: 'variant 1');
5353

5454
FlutterError.onError = (FlutterErrorDetails details) {
5555
Zone.current.handleUncaughtError(details.exception, details.stack!);

0 commit comments

Comments
 (0)