Skip to content
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

Integrate advanced Bugsee features #49

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
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
3 changes: 2 additions & 1 deletion src/app/.env.dev
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ DAD_JOKES_BASE_URL='https://www.reddit.com/r/dadjokes'
APP_STORE_URL_IOS=https://apps.apple.com/us/app/uno-calculator/id1464736591
APP_STORE_URL_Android=https://play.google.com/store/apps/details?id=uno.platform.calculator
REMOTE_CONFIG_FETCH_INTERVAL_MINUTES=1
DIAGNOSTIC_ENABLED=true
Copy link
Member

Choose a reason for hiding this comment

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

Should DIAGNOSTIC_ENABLED=true be removed? I also have the same comment for the prod file too.

DIAGNOSTIC_ENABLED=true
koukibadr marked this conversation as resolved.
Show resolved Hide resolved
koukibadr marked this conversation as resolved.
Show resolved Hide resolved
IS_DATA_OBSCURE=true
3 changes: 2 additions & 1 deletion src/app/.env.prod
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ DAD_JOKES_BASE_URL='https://www.reddit.com/r/dadjokes'
APP_STORE_URL_IOS=https://apps.apple.com/us/app/uno-calculator/id1464736591
APP_STORE_URL_Android=https://play.google.com/store/apps/details?id=uno.platform.calculator
REMOTE_CONFIG_FETCH_INTERVAL_MINUTES=720
DIAGNOSTIC_ENABLED=false
DIAGNOSTIC_ENABLED=false
IS_DATA_OBSCURE=true
6 changes: 5 additions & 1 deletion src/app/.env.staging
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ DAD_JOKES_BASE_URL='https://www.reddit.com/r/dadjokes'
APP_STORE_URL_IOS=https://apps.apple.com/us/app/uno-calculator/id1464736591
APP_STORE_URL_Android=https://play.google.com/store/apps/details?id=uno.platform.calculator
REMOTE_CONFIG_FETCH_INTERVAL_MINUTES=1
DIAGNOSTIC_ENABLED=true
DIAGNOSTIC_ENABLED=true
IS_DATA_OBSCURE=true
DISABLE_LOG_COLLECTION=true
FILTER_LOG_COLLECTION=false
ATTACH_LOG_FILE=true
9 changes: 9 additions & 0 deletions src/app/integration_test/bugsee_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'package:flutter_test/flutter_test.dart';

/// Test all Bugsee setup features
Future<void> bugseeSetupTest() async {
testWidgets(
'Test Bugsee configuration',
(tester) async {},
Copy link
Member

Choose a reason for hiding this comment

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

I'm guessing this is incomplete?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes for this I've only prepared an integration test file for Bugsee we can later implement it
or I remove it for now ?

Copy link
Member

Choose a reason for hiding this comment

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

If it's not done, I would remove it. That way we don't have an incomplete test that could lead us to believe that Bugsee is tested even though it isn't.

);
}
7 changes: 7 additions & 0 deletions src/app/integration_test/integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:get_it/get_it.dart';
import 'package:integration_test/integration_test.dart';

import 'bugsee_test.dart';
import 'dad_jokes_page_test.dart';
import 'forced_update_test.dart';
import 'kill_switch_test.dart';
Expand All @@ -12,6 +13,11 @@ import 'kill_switch_test.dart';
Future<void> main() async {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
await initializeComponents(isMocked: true);
await registerBugseeManager(
isMock: true,
//A mock hexadecimal-based Bugsee token
bugseeToken: '01234567-0123-0123-0123-0123456789AB',
);

tearDownAll(
() async => await GetIt.I.get<MockingRepository>().setMocking(false),
Expand All @@ -20,4 +26,5 @@ Future<void> main() async {
await dadJokeTest();
await killSwitchTest();
await forcedUpdateTest();
await bugseeSetupTest();
}
53 changes: 50 additions & 3 deletions src/app/lib/access/bugsee/bugsee_configuration_data.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,59 @@
final class BugseeConfigurationData {
import 'package:equatable/equatable.dart';

final class BugseeConfigurationData extends Equatable {
/// Gets whether the Bugsee SDK is enabled or not. if [Null] it fallbacks to a new installed app so it will be enabled.
final bool? isBugseeEnabled;

/// Indicate whether the video capturing feature in Bugsee is enabled or not.
final bool? isVideoCaptureEnabled;

/// Indicate whether bugsee obscure application data in videos and images or not.
final bool? isDataObscured;
koukibadr marked this conversation as resolved.
Show resolved Hide resolved
koukibadr marked this conversation as resolved.
Show resolved Hide resolved
koukibadr marked this conversation as resolved.
Show resolved Hide resolved

/// Indicate whether logs are collected or not.
final bool? isLogCollectionEnabled;

/// Indicate whether logs are filtred during reports or not.
final bool? isLogsFilterEnabled;

/// Indicate whether attaching file in the Bugsee report is enabled or not
final bool? attachLogFileEnabled;

const BugseeConfigurationData({
required this.isBugseeEnabled,
required this.isVideoCaptureEnabled,
this.isBugseeEnabled,
this.isVideoCaptureEnabled,
this.isDataObscured,
this.isLogCollectionEnabled,
this.isLogsFilterEnabled,
this.attachLogFileEnabled,
});

BugseeConfigurationData copyWith({
bool? isBugseeEnabled,
bool? isVideoCaptureEnabled,
bool? isDataObscured,
bool? isLogCollectionEnabled,
bool? isLogsFilterEnabled,
bool? attachLogFileEnabled,
}) =>
BugseeConfigurationData(
isBugseeEnabled: isBugseeEnabled ?? this.isBugseeEnabled,
isVideoCaptureEnabled:
isVideoCaptureEnabled ?? this.isVideoCaptureEnabled,
isDataObscured: isDataObscured ?? this.isDataObscured,
isLogCollectionEnabled:
isLogCollectionEnabled ?? this.isLogCollectionEnabled,
isLogsFilterEnabled: isLogsFilterEnabled ?? this.isLogsFilterEnabled,
attachLogFileEnabled: attachLogFileEnabled ?? this.attachLogFileEnabled,
);

@override
List<Object?> get props => [
isBugseeEnabled,
isVideoCaptureEnabled,
isDataObscured,
isLogCollectionEnabled,
isLogsFilterEnabled,
attachLogFileEnabled,
];
}
87 changes: 87 additions & 0 deletions src/app/lib/access/bugsee/bugsee_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,39 @@ abstract interface class BugseeRepository {

/// Update the current video captured or not flag in shared prefs.
Future setIsVideoCaptureEnabled(bool isVideoCaptureEnabled);

/// Update whether data is obscure in shared prefs.
koukibadr marked this conversation as resolved.
Show resolved Hide resolved
Future setIsDataObscure(bool isDataObscure);

/// Update the logCollection flag in shared prefs.
Future setIsLogCollectionEnabled(bool isLogCollectionEnabled);

/// Update the logFilter flag in shared prefs.
Future setIsLogFilterEnabled(bool isLogFilterEnabled);

/// Update the attachFile boolean flag in shared prefs.
Future setAttachLogFileEnabled(bool attachLogFile);
}

final class _BugseeRepository implements BugseeRepository {
final String _bugseeEnabledKey = 'bugseeEnabledKey';
final String _videoCaptureKey = 'videoCaptureKey';
final String _dataObscureKey = 'dataObscureKey';
koukibadr marked this conversation as resolved.
Show resolved Hide resolved
final String _disableLogCollectionKey = 'disableLogCollectionKey';
final String _disableLogFilterKey = 'disableLogFilterKey';
final String _attachLogFileKey = 'attachLogFileKey';

@override
Future<BugseeConfigurationData> getBugseeConfiguration() async {
final sharedPrefInstance = await SharedPreferences.getInstance();
return BugseeConfigurationData(
isBugseeEnabled: sharedPrefInstance.getBool(_bugseeEnabledKey),
isVideoCaptureEnabled: sharedPrefInstance.getBool(_videoCaptureKey),
isDataObscured: sharedPrefInstance.getBool(_dataObscureKey),
isLogCollectionEnabled:
sharedPrefInstance.getBool(_disableLogCollectionKey),
isLogsFilterEnabled: sharedPrefInstance.getBool(_disableLogFilterKey),
attachLogFileEnabled: sharedPrefInstance.getBool(_attachLogFileKey),
);
}

Expand Down Expand Up @@ -59,4 +80,70 @@ final class _BugseeRepository implements BugseeRepository {
);
}
}

@override
Future setIsDataObscure(bool isDataObscured) async {
final sharedPrefInstance = await SharedPreferences.getInstance();

bool isSaved = await sharedPrefInstance.setBool(
_dataObscureKey,
isDataObscured,
);

if (!isSaved) {
throw PersistenceException(
message: 'Error while setting $_dataObscureKey $isDataObscured',
);
}
}

@override
Future setIsLogCollectionEnabled(bool isLogCollected) async {
final sharedPrefInstance = await SharedPreferences.getInstance();

bool isSaved = await sharedPrefInstance.setBool(
_disableLogCollectionKey,
isLogCollected,
);

if (!isSaved) {
throw PersistenceException(
message:
'Error while setting $_disableLogCollectionKey $isLogCollected',
);
}
}

@override
Future setIsLogFilterEnabled(bool isLogFilterEnabled) async {
final sharedPrefInstance = await SharedPreferences.getInstance();

bool isSaved = await sharedPrefInstance.setBool(
_disableLogFilterKey,
isLogFilterEnabled,
);

if (!isSaved) {
throw PersistenceException(
message:
'Error while setting $_disableLogFilterKey $isLogFilterEnabled',
);
}
}

@override
Future setAttachLogFileEnabled(bool attachLogFile) async {
final sharedPrefInstance = await SharedPreferences.getInstance();

bool isSaved = await sharedPrefInstance.setBool(
_attachLogFileKey,
attachLogFile,
);

if (!isSaved) {
throw PersistenceException(
message: 'Error while setting $_attachLogFileKey $attachLogFile',
);
}
}
}
107 changes: 107 additions & 0 deletions src/app/lib/business/bugsee/bugsee_config_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import 'package:equatable/equatable.dart';

enum ConfigErrorEnum {
invalidReleaseMode(error: 'Bugsee is disabled in debug mode'),
invalidToken(error: 'Invalid token, cannot start Bugsee reporting'),
invalidPlatform(error: 'Bugsee cannot be configured on this platform');

final String error;
const ConfigErrorEnum({
required this.error,
});
}

final class BugseeConfigState extends Equatable {
/// Indicate if the app require a restart to reactivate the bugsee configurations
Copy link
Member

Choose a reason for hiding this comment

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

  • Indicates
  • requires
  • Add a period at the end.

///
/// `true` only if `isConfigurationValid == true` and bugsee is turned on
final bool isRestartRequired;

/// Indicate if bugsee is enabled or not
/// by default bugsee is enabled if `isConfigurationValid == true`.
final bool isBugseeEnabled;

/// Indicate whether video capturing is enabled or not.
/// enabled by default if `isBugseeEnabled == true`.
///
/// cannot be true if `isBugseeEnabled == false`.
final bool isVideoCaptureEnabled;

/// Indicate if bugsee configuration is valid
Copy link
Member

Choose a reason for hiding this comment

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

Make sure you separate the sentences with a period and start sentences with a capital letter.

/// config is valid if app in release mode and the provided token is valid
/// following the [bugseeTokenFormat] regex.
final bool isConfigurationValid;

/// Indicate whether data is obscured in report videos
///
/// cannot be true if `isBugseeEnabled == false`.
final bool isDataObscured;

/// Indicate whether log will be collected during Bugsee reporting or not
/// by default logs are collected but filterd.
///
/// This value is initialized from [dotenv.env] and shared prefs storage.
final bool isLogCollectionEnabled;

/// Indicate whether log will be filterd or not
/// by default all logs are filted using [bugseeFilterRegex] defined in [BugseeManager]
///
/// This value is initialized from [dotenv.env] map and shared prefs storage.
final bool isLogFilterEnabled;

/// Indicate whether Bugsee will attach the log file when reporting crashes/exceptions
/// or not
///
/// The initial value is taken from [dotenv.env] and shared prefs.
/// By default it's enabled.
final bool attachLogFile;

/// Indicate the configuration error type (debug, invalid token or invalid platform)
final ConfigErrorEnum? configErrorEnum;

const BugseeConfigState({
this.isRestartRequired = false,
this.isBugseeEnabled = false,
this.isVideoCaptureEnabled = false,
this.isConfigurationValid = false,
this.isDataObscured = false,
this.isLogCollectionEnabled = false,
this.isLogFilterEnabled = false,
this.attachLogFile = false,
this.configErrorEnum,
});

BugseeConfigState copyWith({
bool? isRestartRequired,
bool? isBugseeEnabled,
bool? isVideoCaptureEnabled,
bool? isConfigurationValid,
bool? isDataObscured,
bool? isLogCollectionEnabled,
bool? isLogFilterEnabled,
bool? attachLogFile,
ConfigErrorEnum? configErrorEnum,
}) =>
BugseeConfigState(
isRestartRequired: isRestartRequired ?? this.isRestartRequired,
isBugseeEnabled: isBugseeEnabled ?? this.isBugseeEnabled,
isConfigurationValid: isConfigurationValid ?? this.isConfigurationValid,
isDataObscured: isDataObscured ?? this.isDataObscured,
isLogFilterEnabled: isLogFilterEnabled ?? this.isLogFilterEnabled,
attachLogFile: attachLogFile ?? this.attachLogFile,
isLogCollectionEnabled:
isLogCollectionEnabled ?? this.isLogCollectionEnabled,
isVideoCaptureEnabled:
isVideoCaptureEnabled ?? this.isVideoCaptureEnabled,
configErrorEnum: configErrorEnum ?? this.configErrorEnum,
);

@override
List<Object?> get props => [
isRestartRequired,
isBugseeEnabled,
isVideoCaptureEnabled,
isConfigurationValid,
isDataObscured,
];
}
Loading
Loading