Skip to content

Commit

Permalink
[EP-354] Add Custom Logo API (#290)
Browse files Browse the repository at this point in the history
  • Loading branch information
a7medev authored and HeshamMegid committed Nov 24, 2022
1 parent 81991a4 commit e14f29d
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.app.Application;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Log;

Expand All @@ -26,14 +27,18 @@
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Callable;

import io.flutter.FlutterInjector;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.embedding.engine.loader.FlutterLoader;

public class InstabugApi implements InstabugPigeon.InstabugHostApi {
private final String TAG = InstabugApi.class.getName();
Expand Down Expand Up @@ -269,6 +274,43 @@ public void reportScreenChange(@NonNull String screenName) {
}
}

private Bitmap getBitmapForAsset(String assetName) {
try {
FlutterLoader loader = FlutterInjector.instance().flutterLoader();
String key = loader.getLookupKeyForAsset(assetName);
InputStream stream = context.getAssets().open(key);
return BitmapFactory.decodeStream(stream);
} catch (IOException exception) {
return null;
}
}

@Override
public void setCustomBrandingImage(@NonNull String light, @NonNull String dark) {
try {
Bitmap lightLogoVariant = getBitmapForAsset(light);
Bitmap darkLogoVariant = getBitmapForAsset(dark);

if (lightLogoVariant == null) {
lightLogoVariant = darkLogoVariant;
}
if (darkLogoVariant == null) {
darkLogoVariant = lightLogoVariant;
}
if (lightLogoVariant == null) {
throw new Exception("Couldn't find the light or dark logo images");
}

Method method = Reflection.getMethod(Class.forName("com.instabug.library.Instabug"), "setCustomBrandingImage", Bitmap.class, Bitmap.class);

if (method != null) {
method.invoke(null, lightLogoVariant, darkLogoVariant);
}
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void addFileAttachmentWithURL(@NonNull String filePath, @NonNull String fileName) {
final File file = new File(filePath);
Expand Down
14 changes: 14 additions & 0 deletions example/ios/InstabugSampleTests/InstabugSampleTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,18 @@ - (void) testLogout {
[[[mInstabug verify] classMethod] logOut];
}

- (void) testSetCustomBrandingImage {
id mInstabug = OCMClassMock([Instabug class]);
InstabugApi *api = [[InstabugApi alloc] init];
id mApi = OCMPartialMock(api);
NSString *lightImage = @"images/light_logo.jpeg";
NSString *darkImage = @"images/dark_logo.jpeg";
FlutterError *error;

OCMStub([mApi getImageForAsset:[OCMArg isKindOfClass:[NSString class]]]).andReturn([UIImage new]);

[api setCustomBrandingImageLight:lightImage dark:darkImage error:&error];
[[[mInstabug verify] classMethod] setCustomBrandingImage:[OCMArg isKindOfClass:[UIImageAsset class]]];
}

@end
3 changes: 3 additions & 0 deletions ios/Classes/Modules/InstabugApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@
extern void InitInstabugApi(id<FlutterBinaryMessenger> messenger);

@interface InstabugApi : NSObject <InstabugHostApi>

- (UIImage *)getImageForAsset:(NSString *)assetName;

@end
35 changes: 35 additions & 0 deletions ios/Classes/Modules/InstabugApi.m
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,41 @@ - (void)setReproStepsModeMode:(NSString *)mode error:(FlutterError *_Nullable *_
[Instabug setReproStepsMode:resolvedMode];
}

- (UIImage *)getImageForAsset:(NSString *)assetName {
NSString *key = [FlutterDartProject lookupKeyForAsset:assetName];
NSString *path = [[NSBundle mainBundle] pathForResource:key ofType:nil];

return [UIImage imageWithContentsOfFile:path];
}

- (void)setCustomBrandingImageLight:(NSString *)light dark:(NSString *)dark error:(FlutterError * _Nullable __autoreleasing *)error {
UIImage *lightImage = [self getImageForAsset:light];
UIImage *darkImage = [self getImageForAsset:dark];

if (!lightImage) {
lightImage = darkImage;
}
if (!darkImage) {
darkImage = lightImage;
}

if (@available(iOS 12.0, *)) {
UIImageAsset *imageAsset = [[UIImageAsset alloc] init];

[imageAsset registerImage:lightImage withTraitCollection:[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight]];
[imageAsset registerImage:darkImage withTraitCollection:[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark]];

Instabug.customBrandingImage = imageAsset;
} else {
UIImage *defaultImage = lightImage;
if (!lightImage) {
defaultImage = darkImage;
}

Instabug.customBrandingImage = defaultImage.imageAsset;
}
}

- (void)reportScreenChangeScreenName:(NSString *)screenName error:(FlutterError *_Nullable *_Nonnull)error {
SEL setPrivateApiSEL = NSSelectorFromString(@"logViewDidAppearEvent:");
if ([[Instabug class] respondsToSelector:setPrivateApiSEL]) {
Expand Down
20 changes: 20 additions & 0 deletions lib/src/modules/instabug.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'dart:typed_data';
// ignore: unnecessary_import
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:instabug_flutter/generated/instabug.api.g.dart';
import 'package:instabug_flutter/instabug_flutter.dart';
Expand Down Expand Up @@ -346,6 +347,25 @@ class Instabug {
return _host.setReproStepsMode(reproStepsMode.toString());
}

/// Sets a custom branding image logo with [light] and [dark] images for different color modes.
///
/// If no [context] is passed, [asset variants](https://docs.flutter.dev/development/ui/assets-and-images#asset-variants) won't work as expected;
/// if you have different variants of the [light] or [dark] image assets make sure to pass the [context] in order for the right variant to be picked up.
static Future<void> setCustomBrandingImage({
required AssetImage light,
required AssetImage dark,
BuildContext? context,
}) async {
var configuration = ImageConfiguration.empty;
if (context != null) {
configuration = createLocalImageConfiguration(context);
}

final lightKey = await light.obtainKey(configuration);
final darkKey = await dark.obtainKey(configuration);
return _host.setCustomBrandingImage(lightKey.name, darkKey.name);
}

/// Android Only
/// Enables all Instabug functionality
@Deprecated(
Expand Down
2 changes: 2 additions & 0 deletions pigeons/instabug.api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ abstract class InstabugHostApi {
void setReproStepsMode(String mode);
void reportScreenChange(String screenName);

void setCustomBrandingImage(String light, String dark);

void addFileAttachmentWithURL(String filePath, String fileName);
void addFileAttachmentWithData(Uint8List data, String fileName);
void clearFileAttachments();
Expand Down
14 changes: 14 additions & 0 deletions test/instabug_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,20 @@ void main() {
).called(1);
});

test('[setCustomBrandingImage] should call host method', () async {
const lightImage = 'images/light_logo.jpeg';
const darkImage = 'images/dark_logo.jpeg';

await Instabug.setCustomBrandingImage(
light: const AssetImage(lightImage),
dark: const AssetImage(darkImage),
);

verify(
mHost.setCustomBrandingImage(lightImage, darkImage),
).called(1);
});

test('[reportScreenChange] should call host method', () async {
const screen = "home";

Expand Down

0 comments on commit e14f29d

Please sign in to comment.