Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
58 changes: 53 additions & 5 deletions contact/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ packages:
dependency: transitive
description:
name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
url: "https://pub.dev"
source: hosted
version: "2.4.2"
version: "2.7.0"
async:
dependency: transitive
description:
Expand Down Expand Up @@ -268,10 +268,10 @@ packages:
dependency: "direct main"
description:
name: dio
sha256: "9fdbf71baeb250fc9da847f6cb2052196f62c19906a3657adfc18631a667d316"
sha256: e44ce32c01f02c54a101551def8586f15d6189b4f999d4420aad38995ac62e6d
url: "https://pub.dev"
source: hosted
version: "5.0.0"
version: "5.2.0"
equatable:
dependency: "direct main"
description:
Expand Down Expand Up @@ -381,6 +381,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.2"
flutter_dotenv:
dependency: transitive
description:
name: flutter_dotenv
sha256: d9283d92059a22e9834bc0a31336658ffba77089fb6f3cc36751f1fc7c6661a3
url: "https://pub.dev"
source: hosted
version: "5.0.2"
flutter_image_compress:
dependency: transitive
description:
Expand Down Expand Up @@ -676,10 +684,18 @@ packages:
description:
path: "."
ref: main
resolved-ref: "446efbbccdde981371b4d2a636762184adf6e926"
resolved-ref: "8e2bd9cb1bbd8236be895aa04bf0d0da8e2ff3b2"
url: "https://github.com/linagora/jmap-dart-client.git"
source: git
version: "0.3.6"
jni:
dependency: transitive
description:
name: jni
sha256: d2c361082d554d4593c3012e26f6b188f902acd291330f13d6427641a92b3da1
url: "https://pub.dev"
source: hosted
version: "0.14.2"
js:
dependency: transitive
description:
Expand Down Expand Up @@ -799,6 +815,14 @@ packages:
relative: true
source: path
version: "1.0.0+1"
objective_c:
dependency: transitive
description:
name: objective_c
sha256: "64e35e1e2e79da4e83f2ace3bf4e5437cef523f46c7db2eba9a1419c49573790"
url: "https://pub.dev"
source: hosted
version: "8.0.0"
package_config:
dependency: transitive
description:
Expand Down Expand Up @@ -1024,6 +1048,22 @@ packages:
url: "https://github.com/linagora/dart-neats.git"
source: git
version: "2.1.0"
sentry:
dependency: transitive
description:
name: sentry
sha256: "10a0bc25f5f21468e3beeae44e561825aaa02cdc6829438e73b9b64658ff88d9"
url: "https://pub.dev"
source: hosted
version: "9.8.0"
sentry_flutter:
dependency: transitive
description:
name: sentry_flutter
sha256: aafbf41c63c98a30b17bdbf3313424d5102db62b08735c44bff810f277e786a5
url: "https://pub.dev"
source: hosted
version: "9.8.0"
shelf:
dependency: transitive
description:
Expand Down Expand Up @@ -1229,6 +1269,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.0"
uuid:
dependency: transitive
description:
name: uuid
sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8
url: "https://pub.dev"
source: hosted
version: "4.5.2"
vector_graphics:
dependency: transitive
description:
Expand Down
2 changes: 1 addition & 1 deletion contact/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ dependencies:

json_annotation: 4.8.0

dio: 5.0.0
dio: 5.2.0

http_mock_adapter: 0.4.2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ void main() {
},
headers: {
"accept": "application/json;jmapVersion=rfc-8621",
"content-length": 330
});

final httpClient = HttpClient(dio);
Expand Down
7 changes: 6 additions & 1 deletion core/lib/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export 'utils/preview_eml_file_utils.dart';
export 'utils/logger/log_tracking.dart';
export 'utils/html/html_utils.dart';
export 'utils/web_link_generator.dart';
export 'utils/sentry/sentry_manager.dart';
export 'utils/config/env_loader.dart';

// Views
export 'presentation/views/text/slogan_builder.dart';
Expand Down Expand Up @@ -138,4 +140,7 @@ export 'data/model/source_type/data_source_type.dart';
export 'data/model/query/query_parameter.dart';

// Action
export 'presentation/action/action_callback_define.dart';
export 'presentation/action/action_callback_define.dart';

// Library
export 'package:package_info_plus/package_info_plus.dart';
34 changes: 16 additions & 18 deletions core/lib/utils/app_logger.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import 'dart:async';
import 'package:universal_html/html.dart' as html;
import 'package:core/utils/build_utils.dart';
import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart';
import 'package:core/utils/sentry/sentry_manager.dart';
import 'package:universal_html/html.dart' as html;

/// ANSI escape colors (Web only)
const ansiReset = '\x1B[0m';
Expand Down Expand Up @@ -64,6 +63,15 @@ void _internalLog(
} else {
_debugPrint(formattedMessage);
}

if (_shouldReportToSentry(level)) {
SentryManager.instance.captureException(
exception ?? rawMessage,
stackTrace: stackTrace,
message: rawMessage,
extras: extras,
);
}
}

String _buildRawMessage(
Expand Down Expand Up @@ -113,6 +121,10 @@ void _printWebConsole(Level level, String value) {
}
}

bool _shouldReportToSentry(Level level) {
return level == Level.error || level == Level.wtf;
}

void logError(
String? message, {
Object? exception,
Expand Down Expand Up @@ -204,18 +216,4 @@ enum Level {
info,
debug,
verbose,
}

// Take from: https://flutter.dev/docs/testing/errors
void initLogger(VoidCallback runApp) {
runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
FlutterError.onError = (details) {
FlutterError.dumpErrorToConsole(details);
logWarning('AppLogger::initLogger::runZonedGuarded:FlutterError.onError: ${details.stack.toString()}');
};
runApp.call();
}, (error, stack) {
logWarning('AppLogger::initLogger::runZonedGuarded:onError: $error | stack: $stack');
});
}
}
24 changes: 18 additions & 6 deletions core/lib/utils/application_manager.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@

import 'package:core/utils/app_logger.dart';
import 'package:core/utils/platform_info.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:fk_user_agent/fk_user_agent.dart';
import 'package:flutter/cupertino.dart';
import 'package:package_info_plus/package_info_plus.dart';

class ApplicationManager {
static final ApplicationManager _instance = ApplicationManager._internal();

factory ApplicationManager() => _instance;

ApplicationManager._internal();

final DeviceInfoPlugin _deviceInfoPlugin;
// Allow overriding in unit tests
@visibleForTesting
static DeviceInfoPlugin? debugDeviceInfoOverride;

ApplicationManager(this._deviceInfoPlugin);
DeviceInfoPlugin get _deviceInfoPlugin =>
debugDeviceInfoOverride ?? DeviceInfoPlugin();

Future<PackageInfo> getPackageInfo() async {
final packageInfo = await PackageInfo.fromPlatform();
Expand All @@ -18,9 +26,13 @@ class ApplicationManager {
}

Future<String> getVersion() async {
final version = (await getPackageInfo()).version;
log('ApplicationManager::getVersion: $version');
return version;
try {
final version = (await getPackageInfo()).version;
log('ApplicationManager::getVersion: $version');
return version;
} catch (e) {
return '';
}
}

Future<String> getUserAgent() async {
Expand Down
43 changes: 43 additions & 0 deletions core/lib/utils/config/env_loader.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:core/utils/app_logger.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

class EnvLoader {
const EnvLoader._();

static const String envFileName = 'env.file';
static const String appFCMConfigurationPath = "configurations/env.fcm";

static Future<void> loadEnvFile() async {
await loadConfigFromEnv();
final mapEnvData = Map<String, String>.from(dotenv.env);
await loadFcmConfigFileToEnv(
currentMapEnvData: mapEnvData,
onCallBack: () async {
await loadConfigFromEnv();
},
);
}

static Future<void> loadFcmConfigFileToEnv({
Map<String, String>? currentMapEnvData,
Future<void> Function()? onCallBack,
}) async {
try {
await dotenv.load(
fileName: appFCMConfigurationPath,
mergeWith: currentMapEnvData ?? {},
);
} catch (e) {
logWarning('EnvLoader::loadFcmConfigFileToEnv: Exception = $e');
await onCallBack?.call();
}
}

static Future<void> loadConfigFromEnv() async {
try {
await dotenv.load(fileName: envFileName);
} catch (e) {
logWarning('EnvLoader::loadConfigFromEnv:Exception = $e');
}
}
}
74 changes: 74 additions & 0 deletions core/lib/utils/sentry/sentry_config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import 'package:core/utils/application_manager.dart';
import 'package:core/utils/build_utils.dart';
import 'package:core/utils/config/env_loader.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

/// Holds configuration values for initializing Sentry.
class SentryConfig {
// DSN (Data Source Name) endpoint for the Sentry project
final String dsn;

// Running environment (production/staging/dev)
final String environment;

// Current app release version
final String release;

// // Performance monitoring: Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing
final double tracesSampleRate;

// Optional profiling
final double profilesSampleRate;

// Enable logs to be sent to Sentry. To use Sentry.logger.fmt
final bool enableLogs;

// Debug logs during development
final bool isDebug;

// Automatically attaches a screenshot when capturing an error or exception.
final bool attachScreenshot;

// Check if Sentry is available
final bool isAvailable;

SentryConfig({
required this.dsn,
required this.environment,
required this.release,
this.tracesSampleRate = 1.0,
this.profilesSampleRate = 1.0,
this.enableLogs = true,
this.isDebug = BuildUtils.isDebugMode,
this.attachScreenshot = false,
this.isAvailable = false,
});

/// Load configuration from an env file.
static Future<SentryConfig> load() async {
await EnvLoader.loadConfigFromEnv();

final sentryAvailable = dotenv.get('SENTRY_ENABLED', fallback: 'false');

final isAvailable = sentryAvailable == 'true';
final sentryDSN = dotenv.get('SENTRY_DSN', fallback: '');
final sentryEnvironment = dotenv.get('SENTRY_ENVIRONMENT', fallback: '');

if (!isAvailable) {
throw Exception('Sentry is not available');
}

if (sentryDSN.trim().isEmpty || sentryEnvironment.trim().isEmpty) {
throw Exception('Sentry configuration is missing');
}

final appVersion = await ApplicationManager().getVersion();

return SentryConfig(
dsn: sentryDSN,
environment: sentryEnvironment,
release: appVersion,
isAvailable: isAvailable,
);
}
}
Loading
Loading