Skip to content

Commit 4d9287a

Browse files
committed
feat: implement bugsee data obscure from reported videos
1 parent 7bcaeba commit 4d9287a

9 files changed

Lines changed: 185 additions & 72 deletions

File tree

src/app/.env.dev

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ DAD_JOKES_BASE_URL='https://www.reddit.com/r/dadjokes'
55
APP_STORE_URL_IOS=https://apps.apple.com/us/app/uno-calculator/id1464736591
66
APP_STORE_URL_Android=https://play.google.com/store/apps/details?id=uno.platform.calculator
77
REMOTE_CONFIG_FETCH_INTERVAL_MINUTES=1
8-
DIAGNOSTIC_ENABLED=true
8+
DIAGNOSTIC_ENABLED=true
9+
IS_DATA_OBSCURE=true

src/app/.env.prod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ DAD_JOKES_BASE_URL='https://www.reddit.com/r/dadjokes'
55
APP_STORE_URL_IOS=https://apps.apple.com/us/app/uno-calculator/id1464736591
66
APP_STORE_URL_Android=https://play.google.com/store/apps/details?id=uno.platform.calculator
77
REMOTE_CONFIG_FETCH_INTERVAL_MINUTES=720
8-
DIAGNOSTIC_ENABLED=false
8+
DIAGNOSTIC_ENABLED=false
9+
IS_DATA_OBSCURE=true

src/app/.env.staging

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ DAD_JOKES_BASE_URL='https://www.reddit.com/r/dadjokes'
55
APP_STORE_URL_IOS=https://apps.apple.com/us/app/uno-calculator/id1464736591
66
APP_STORE_URL_Android=https://play.google.com/store/apps/details?id=uno.platform.calculator
77
REMOTE_CONFIG_FETCH_INTERVAL_MINUTES=1
8-
DIAGNOSTIC_ENABLED=true
8+
DIAGNOSTIC_ENABLED=true
9+
IS_DATA_OBSCURE=true

src/app/lib/access/bugsee/bugsee_configuration_data.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ final class BugseeConfigurationData {
55
/// Indicate whether the video capturing feature in Bugsee is enabled or not.
66
final bool? isVideoCaptureEnabled;
77

8+
/// Indicate whether bugsee obscure application data in videos and images or not.
9+
final bool? isDataObscrured;
10+
811
const BugseeConfigurationData({
9-
required this.isBugseeEnabled,
10-
required this.isVideoCaptureEnabled,
12+
this.isBugseeEnabled,
13+
this.isVideoCaptureEnabled,
14+
this.isDataObscrured,
1115
});
1216
}

src/app/lib/access/bugsee/bugsee_repository.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,23 @@ abstract interface class BugseeRepository {
1313

1414
/// Update the current video captured or not flag in shared prefs.
1515
Future setIsVideoCaptureEnabled(bool isVideoCaptureEnabled);
16+
17+
/// Update whether data is obscure in shared prefs.
18+
Future setIsDataObscure(bool isDataObscure);
1619
}
1720

1821
final class _BugseeRepository implements BugseeRepository {
1922
final String _bugseeEnabledKey = 'bugseeEnabledKey';
2023
final String _videoCaptureKey = 'videoCaptureKey';
24+
final String _dataObscureKey = 'dataObscureKey';
2125

2226
@override
2327
Future<BugseeConfigurationData> getBugseeConfiguration() async {
2428
final sharedPrefInstance = await SharedPreferences.getInstance();
2529
return BugseeConfigurationData(
2630
isBugseeEnabled: sharedPrefInstance.getBool(_bugseeEnabledKey),
2731
isVideoCaptureEnabled: sharedPrefInstance.getBool(_videoCaptureKey),
32+
isDataObscrured: sharedPrefInstance.getBool(_dataObscureKey),
2833
);
2934
}
3035

@@ -59,4 +64,20 @@ final class _BugseeRepository implements BugseeRepository {
5964
);
6065
}
6166
}
67+
68+
@override
69+
Future setIsDataObscure(bool isDataObscured) async {
70+
final sharedPrefInstance = await SharedPreferences.getInstance();
71+
72+
bool isSaved = await sharedPrefInstance.setBool(
73+
_dataObscureKey,
74+
isDataObscured,
75+
);
76+
77+
if (!isSaved) {
78+
throw PersistenceException(
79+
message: 'Error while setting $_dataObscureKey $isDataObscured',
80+
);
81+
}
82+
}
6283
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import 'package:equatable/equatable.dart';
2+
3+
final class BugseeConfigState extends Equatable {
4+
/// indicate if the app require a restart to reactivate the bugsee configurations
5+
///
6+
/// `true` only if `isConfigurationValid == true` and bugsee is turned on
7+
bool isRestartRequired;
8+
9+
/// indicate if bugsee is enabled or not
10+
/// by default bugsee is enabled if `isConfigurationValid == true`.
11+
bool isBugseeEnabled;
12+
13+
/// indicate whether video capturing is enabled or not.
14+
/// enabled by default if `isBugseeEnabled == true`.
15+
///
16+
/// cannot be true if `isBugseeEnabled == false`.
17+
bool isVideoCaptureEnabled;
18+
19+
/// indicate if bugsee configuration is valid
20+
/// config is valid if app in release mode and the provided token is valid
21+
/// following the [bugseeTokenFormat] regex.
22+
bool isConfigurationValid;
23+
24+
/// indicate whether data is obscured in report videos
25+
///
26+
/// cannot be true if `isBugseeEnabled == false`.
27+
bool isDataObscured;
28+
29+
BugseeConfigState({
30+
this.isRestartRequired = false,
31+
this.isBugseeEnabled = false,
32+
this.isVideoCaptureEnabled = false,
33+
this.isConfigurationValid = false,
34+
this.isDataObscured = false,
35+
});
36+
37+
BugseeConfigState copyWith({
38+
bool? isRestartRequired,
39+
bool? isBugseeEnabled,
40+
bool? isVideoCaptureEnabled,
41+
bool? isConfigurationValid,
42+
bool? isDataObscured,
43+
}) =>
44+
BugseeConfigState(
45+
isRestartRequired: isRestartRequired ?? this.isRestartRequired,
46+
isBugseeEnabled: isBugseeEnabled ?? this.isBugseeEnabled,
47+
isConfigurationValid: isConfigurationValid ?? this.isConfigurationValid,
48+
isDataObscured: isDataObscured ?? this.isDataObscured,
49+
isVideoCaptureEnabled:
50+
isVideoCaptureEnabled ?? this.isVideoCaptureEnabled,
51+
);
52+
53+
@override
54+
List<Object?> get props => [
55+
isRestartRequired,
56+
isBugseeEnabled,
57+
isVideoCaptureEnabled,
58+
isConfigurationValid,
59+
isDataObscured,
60+
];
61+
}

src/app/lib/business/bugsee/bugsee_manager.dart

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import 'dart:async';
22
import 'dart:io';
3-
43
import 'package:app/access/bugsee/bugsee_configuration_data.dart';
54
import 'package:app/access/bugsee/bugsee_repository.dart';
5+
import 'package:app/business/bugsee/bugsee_config_state.dart';
66
import 'package:bugsee_flutter/bugsee_flutter.dart';
77
import 'package:flutter/foundation.dart';
8+
import 'package:flutter_dotenv/flutter_dotenv.dart';
89
import 'package:logger/logger.dart';
910
import 'package:logger/web.dart';
1011

@@ -18,25 +19,8 @@ abstract interface class BugseeManager {
1819
required BugseeRepository bugseeRepository,
1920
}) = _BugseeManager;
2021

21-
/// indicate if the app require a restart to reactivate the bugsee configurations
22-
///
23-
/// `true` only if `isConfigurationValid == true` and bugsee is turned on
24-
bool get isRestartRequired;
25-
26-
/// indicate if bugsee is enabled or not
27-
/// by default bugsee is enabled if `isConfigurationValid == true`.
28-
bool get isBugseeEnabled;
29-
30-
/// indicate whether video capturing is enabled or not.
31-
/// enabled by default if `isBugseeEnabled == true`.
32-
///
33-
/// cannot be true if `isBugseeEnabled == false`.
34-
bool get isVideoCaptureEnabled;
35-
36-
/// indicate if bugsee configuration is valid
37-
/// config is valid if app in release mode and the provided token is valid
38-
/// following the [bugseeTokenFormat] regex.
39-
bool get isConfigurationValid;
22+
/// Current BugseeManager state
23+
BugseeConfigState get bugseeConfigState;
4024

4125
/// initialize bugsee with given token
4226
/// bugsee is not available in debug mode
@@ -61,10 +45,13 @@ abstract interface class BugseeManager {
6145
});
6246

6347
/// Manually update the current BugseeEnabled flag in shared prefs and in current manager singleton.
64-
Future<void> setIsBugseeEnabled(bool isBugseeEnabled);
48+
Future<void> setIsBugseeEnabled(bool value);
49+
50+
/// Manually update isDataObscured flag in shared prefs and in current state [bugseeConfigState].
51+
Future<void> setIsDataObscured(bool value);
6552

6653
/// Manually update the current enableVideoCapture flag in shared prefs and in current manager singleton.
67-
Future<void> setIsVideoCaptureEnabled(bool isBugseeEnabled);
54+
Future<void> setIsVideoCaptureEnabled(bool value);
6855

6956
/// Manually shows the built-in capture log report screen of Bugsee.
7057
Future<void> showCaptureLogReport();
@@ -79,17 +66,11 @@ final class _BugseeManager implements BugseeManager {
7966
required this.bugseeRepository,
8067
});
8168

82-
@override
83-
bool isRestartRequired = false;
84-
85-
@override
86-
bool isBugseeEnabled = false;
87-
88-
@override
89-
late bool isVideoCaptureEnabled = false;
69+
bool _initialDataObscuredState = false;
70+
BugseeConfigState _currentState = BugseeConfigState();
9071

9172
@override
92-
bool isConfigurationValid = true;
73+
BugseeConfigState get bugseeConfigState => _currentState;
9374

9475
late bool _isBugSeeInitialized;
9576
BugseeLaunchOptions? launchOptions;
@@ -105,14 +86,18 @@ final class _BugseeManager implements BugseeManager {
10586
_isBugSeeInitialized = false;
10687

10788
if (kDebugMode) {
108-
isConfigurationValid = false;
89+
_currentState = _currentState.copyWith(
90+
isConfigurationValid: false,
91+
);
10992
logger.i("BUGSEE: deactivated in debug mode");
11093
return;
11194
}
11295

11396
if (bugseeToken == null ||
11497
!RegExp(bugseeTokenFormat).hasMatch(bugseeToken)) {
115-
isConfigurationValid = false;
98+
_currentState = _currentState.copyWith(
99+
isConfigurationValid: false,
100+
);
116101
logger.i(
117102
"BUGSEE: token is null or invalid, bugsee won't be initialized",
118103
);
@@ -123,9 +108,17 @@ final class _BugseeManager implements BugseeManager {
123108
await _launchBugseeLogger(bugseeToken);
124109
}
125110

126-
isBugseeEnabled = _isBugSeeInitialized;
127-
isVideoCaptureEnabled = _isBugSeeInitialized &&
128-
(bugseeConfigurationData.isVideoCaptureEnabled ?? true);
111+
var isDataObscured = bugseeConfigurationData.isDataObscrured ??
112+
bool.parse(dotenv.env['IS_DATA_OBSCURE'] ?? 'false');
113+
114+
_currentState = _currentState.copyWith(
115+
isConfigurationValid: _isBugSeeInitialized,
116+
isBugseeEnabled: _isBugSeeInitialized,
117+
isVideoCaptureEnabled: _isBugSeeInitialized &&
118+
(bugseeConfigurationData.isVideoCaptureEnabled ?? true),
119+
isDataObscured: isDataObscured,
120+
);
121+
_initialDataObscuredState = isDataObscured;
129122
}
130123

131124
Future _launchBugseeLogger(String bugseeToken) async {
@@ -158,7 +151,7 @@ final class _BugseeManager implements BugseeManager {
158151
required Exception exception,
159152
StackTrace? stackTrace,
160153
}) async {
161-
if (isBugseeEnabled) {
154+
if (_currentState.isBugseeEnabled) {
162155
await Bugsee.logException(exception, stackTrace);
163156
}
164157
}
@@ -168,32 +161,38 @@ final class _BugseeManager implements BugseeManager {
168161
required Exception exception,
169162
StackTrace? stackTrace,
170163
}) async {
171-
if (isBugseeEnabled) {
164+
if (_currentState.isBugseeEnabled) {
172165
await Bugsee.logUnhandledException(exception);
173166
}
174167
}
175168

176169
@override
177170
Future<void> setIsBugseeEnabled(bool value) async {
178-
if (isConfigurationValid) {
179-
isBugseeEnabled = value;
180-
await bugseeRepository.setIsBugseeEnabled(isBugseeEnabled);
181-
182-
isRestartRequired = _isBugSeeInitialized && isBugseeEnabled;
183-
isVideoCaptureEnabled = isBugseeEnabled;
171+
if (_currentState.isConfigurationValid) {
172+
await bugseeRepository.setIsBugseeEnabled(value);
173+
_currentState = _currentState.copyWith(
174+
isBugseeEnabled: value,
175+
isRestartRequired: value,
176+
isVideoCaptureEnabled: value,
177+
isDataObscured: value,
178+
);
184179

185-
if (!isRestartRequired) {
180+
if (!_currentState.isRestartRequired) {
186181
await Bugsee.stop();
187182
}
188183
}
189184
}
190185

191186
@override
192187
Future<void> setIsVideoCaptureEnabled(bool value) async {
193-
if (isBugseeEnabled) {
194-
isVideoCaptureEnabled = value;
195-
await bugseeRepository.setIsVideoCaptureEnabled(isVideoCaptureEnabled);
196-
if (!isVideoCaptureEnabled) {
188+
if (_currentState.isBugseeEnabled) {
189+
_currentState = _currentState.copyWith(
190+
isVideoCaptureEnabled: value,
191+
);
192+
await bugseeRepository.setIsVideoCaptureEnabled(
193+
_currentState.isVideoCaptureEnabled,
194+
);
195+
if (!_currentState.isVideoCaptureEnabled) {
197196
await Bugsee.pause();
198197
} else {
199198
await Bugsee.resume();
@@ -203,8 +202,19 @@ final class _BugseeManager implements BugseeManager {
203202

204203
@override
205204
Future<void> showCaptureLogReport() async {
206-
if (isBugseeEnabled) {
205+
if (_currentState.isBugseeEnabled) {
207206
await Bugsee.showReportDialog();
208207
}
209208
}
209+
210+
@override
211+
Future<void> setIsDataObscured(bool value) async {
212+
if (_currentState.isBugseeEnabled) {
213+
await bugseeRepository.setIsDataObscure(value);
214+
_currentState = _currentState.copyWith(
215+
isRestartRequired: value != _initialDataObscuredState,
216+
isDataObscured: value,
217+
);
218+
}
219+
}
210220
}

src/app/lib/presentation/dad_jokes/dad_joke_list_item.dart

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1+
import 'package:app/business/bugsee/bugsee_manager.dart';
12
import 'package:app/business/dad_jokes/dad_joke.dart';
23
import 'package:app/business/dad_jokes/dad_jokes_service.dart';
4+
import 'package:bugsee_flutter/bugsee_flutter.dart';
35
import 'package:flutter/material.dart';
46
import 'package:get_it/get_it.dart';
57

68
/// A dad joke list item.
79
final class DadJokeListItem extends StatelessWidget {
810
/// The dad jokes service used to add or remove favorite.
911
final _dadJokesService = GetIt.I<DadJokesService>();
12+
final _bugseeManager = GetIt.I<BugseeManager>();
1013

1114
/// The dad joke.
1215
final DadJoke dadJoke;
@@ -17,8 +20,14 @@ final class DadJokeListItem extends StatelessWidget {
1720
Widget build(BuildContext context) {
1821
return Card(
1922
child: ListTile(
20-
title: Text(dadJoke.title),
21-
subtitle: Text(dadJoke.text),
23+
title: BugseeSecureView(
24+
enabled: _bugseeManager.bugseeConfigState.isDataObscured,
25+
child: Text(dadJoke.title),
26+
),
27+
subtitle: BugseeSecureView(
28+
enabled: _bugseeManager.bugseeConfigState.isDataObscured,
29+
child: Text(dadJoke.text),
30+
),
2231
trailing: dadJoke.isFavorite
2332
? const Icon(
2433
Icons.favorite,

0 commit comments

Comments
 (0)