From 43cfbda0b57cdfe1174acdae77c3bc91cf8aca30 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 14:00:50 +0200 Subject: [PATCH 01/20] feat: introduced AliceConfiguration --- examples/alice/lib/main.dart | 7 +- examples/alice_chopper/lib/main.dart | 8 +- examples/alice_dio/lib/main.dart | 8 +- examples/alice_http/lib/main.dart | 8 +- examples/alice_http_client/lib/main.dart | 8 +- examples/alice_objectbox/lib/main.dart | 12 +-- packages/alice/CHANGELOG.md | 8 ++ packages/alice/lib/alice.dart | 63 ++------------ packages/alice/lib/core/alice_core.dart | 85 ++++++++----------- .../alice/lib/model/alice_configuration.dart | 56 ++++++++++++ .../page/alice_call_details_page.dart | 23 ++--- packages/alice/lib/ui/common/alice_page.dart | 3 +- packages/alice/test/core/alice_core_test.dart | 11 +-- packages/alice_dio/pubspec.yaml | 2 +- 14 files changed, 142 insertions(+), 160 deletions(-) create mode 100644 packages/alice/lib/model/alice_configuration.dart diff --git a/examples/alice/lib/main.dart b/examples/alice/lib/main.dart index 5f483389..6d2ddf3a 100644 --- a/examples/alice/lib/main.dart +++ b/examples/alice/lib/main.dart @@ -1,4 +1,5 @@ import 'package:alice/alice.dart'; +import 'package:alice/model/alice_configuration.dart'; import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); @@ -11,11 +12,7 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State { - late final Alice _alice = Alice( - showNotification: true, - showInspectorOnShake: true, - maxCallsCount: 1000, - ); + late final Alice _alice = Alice(configuration: AliceConfiguration()); @override Widget build(BuildContext context) { diff --git a/examples/alice_chopper/lib/main.dart b/examples/alice_chopper/lib/main.dart index 20ef81c4..e9570c70 100644 --- a/examples/alice_chopper/lib/main.dart +++ b/examples/alice_chopper/lib/main.dart @@ -1,4 +1,5 @@ import 'package:alice/alice.dart'; +import 'package:alice/model/alice_configuration.dart'; import 'package:alice_chopper/alice_chopper_adapter.dart'; import 'package:alice_chopper_example/interceptors/json_content_type_inerceptor.dart'; import 'package:alice_chopper_example/interceptors/json_headers_interceptor.dart'; @@ -35,11 +36,8 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { final AliceChopperAdapter _aliceChopperAdapter = AliceChopperAdapter(); - late final Alice _alice = Alice( - showNotification: true, - showInspectorOnShake: true, - maxCallsCount: 1000, - )..addAdapter(_aliceChopperAdapter); + late final Alice _alice = Alice(configuration: AliceConfiguration()) + ..addAdapter(_aliceChopperAdapter); late final ChopperClient _chopper = ChopperClient( baseUrl: Uri.https('jsonplaceholder.typicode.com'), diff --git a/examples/alice_dio/lib/main.dart b/examples/alice_dio/lib/main.dart index c1913b67..7b0b62a7 100644 --- a/examples/alice_dio/lib/main.dart +++ b/examples/alice_dio/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:alice/alice.dart'; +import 'package:alice/model/alice_configuration.dart'; import 'package:alice_dio/alice_dio_adapter.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; @@ -19,11 +20,8 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { late final AliceDioAdapter _aliceDioAdapter = AliceDioAdapter(); - late final Alice _alice = Alice( - showNotification: true, - showInspectorOnShake: true, - maxCallsCount: 1000, - )..addAdapter(_aliceDioAdapter); + late final Alice _alice = Alice(configuration: AliceConfiguration()) + ..addAdapter(_aliceDioAdapter); late final Dio _dio = Dio(BaseOptions(followRedirects: false)) ..interceptors.add(_aliceDioAdapter); diff --git a/examples/alice_http/lib/main.dart b/examples/alice_http/lib/main.dart index 3059cc06..d69be5a6 100644 --- a/examples/alice_http/lib/main.dart +++ b/examples/alice_http/lib/main.dart @@ -1,4 +1,5 @@ import 'package:alice/alice.dart'; +import 'package:alice/model/alice_configuration.dart'; import 'package:alice_http/alice_http_adapter.dart'; import 'package:alice_http/alice_http_extensions.dart'; import 'package:flutter/material.dart'; @@ -16,11 +17,8 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { late final AliceHttpAdapter _aliceHttpAdapter = AliceHttpAdapter(); - late final Alice _alice = Alice( - showNotification: true, - showInspectorOnShake: true, - maxCallsCount: 1000, - )..addAdapter(_aliceHttpAdapter); + late final Alice _alice = Alice(configuration: AliceConfiguration()) + ..addAdapter(_aliceHttpAdapter); @override Widget build(BuildContext context) { diff --git a/examples/alice_http_client/lib/main.dart b/examples/alice_http_client/lib/main.dart index ee35496c..cc9ffec8 100644 --- a/examples/alice_http_client/lib/main.dart +++ b/examples/alice_http_client/lib/main.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:alice/alice.dart'; +import 'package:alice/model/alice_configuration.dart'; import 'package:alice_http_client/alice_http_client_adapter.dart'; import 'package:alice_http_client/alice_http_client_extensions.dart'; import 'package:flutter/material.dart'; @@ -21,11 +22,8 @@ class _MyAppState extends State { late final AliceHttpClientAdapter _httpClientAdapter = AliceHttpClientAdapter(); - late final Alice _alice = Alice( - showNotification: true, - showInspectorOnShake: true, - maxCallsCount: 1000, - )..addAdapter(_httpClientAdapter); + late final Alice _alice = Alice(configuration: AliceConfiguration()) + ..addAdapter(_httpClientAdapter); @override Widget build(BuildContext context) { diff --git a/examples/alice_objectbox/lib/main.dart b/examples/alice_objectbox/lib/main.dart index b3662888..e7f5e0f7 100644 --- a/examples/alice_objectbox/lib/main.dart +++ b/examples/alice_objectbox/lib/main.dart @@ -1,4 +1,5 @@ import 'package:alice/alice.dart'; +import 'package:alice/model/alice_configuration.dart'; import 'package:alice_http/alice_http_adapter.dart'; import 'package:alice_http/alice_http_extensions.dart'; import 'package:alice_objectbox/alice_objectbox.dart'; @@ -35,12 +36,11 @@ class _MyAppState extends State { late final AliceHttpAdapter _aliceHttpAdapter = AliceHttpAdapter(); late final Alice _alice = Alice( - showNotification: true, - showInspectorOnShake: true, - maxCallsCount: 1000, - aliceStorage: AliceObjectBox( - store: widget.store, - maxCallsCount: 1000, + configuration: AliceConfiguration( + storage: AliceObjectBox( + store: widget.store, + maxCallsCount: 1000, + ), ), )..addAdapter(_aliceHttpAdapter); diff --git a/packages/alice/CHANGELOG.md b/packages/alice/CHANGELOG.md index 73fb580f..a3fc5090 100644 --- a/packages/alice/CHANGELOG.md +++ b/packages/alice/CHANGELOG.md @@ -1,4 +1,10 @@ +# 1.0.0-dev.10 + +* [BREAKING_CHANGE] Removed maxCallsCount. To change call count, use `storage` constructor parameter + with call count. + # 1.0.0-dev.9 + * Fixed saving issue with Android 13 onwards. * Added unit tests. * Updated CI/CD task for tests. @@ -6,11 +12,13 @@ * Updated metadata. # 1.0.0-dev.8 + * Added storage abstractions (by Klemen Tusar https://github.com/techouse). * Added in memory storage implementation (by Klemen Tusar https://github.com/techouse). * Added translations. # 1.0.0-dev.7 + * Refactored UI code. # 1.0.0-dev.6 diff --git a/packages/alice/lib/alice.dart b/packages/alice/lib/alice.dart index c24407d5..b23ed70f 100644 --- a/packages/alice/lib/alice.dart +++ b/packages/alice/lib/alice.dart @@ -1,8 +1,6 @@ import 'package:alice/core/alice_adapter.dart'; import 'package:alice/core/alice_core.dart'; -import 'package:alice/core/alice_logger.dart'; -import 'package:alice/core/alice_memory_storage.dart'; -import 'package:alice/core/alice_storage.dart'; +import 'package:alice/model/alice_configuration.dart'; import 'package:alice/model/alice_http_call.dart'; import 'package:alice/model/alice_log.dart'; import 'package:flutter/material.dart'; @@ -14,72 +12,23 @@ export 'package:alice/core/alice_memory_storage.dart'; export 'package:alice/utils/alice_parser.dart'; class Alice { - /// Should user be notified with notification when there's new request caught - /// by Alice - final bool showNotification; - - /// Should inspector be opened on device shake (works only with physical - /// with sensors) - final bool showInspectorOnShake; - - /// Icon url for notification - final String notificationIcon; - - /// Max number of calls that are stored in memory. When count is reached, FIFO - /// method queue will be used to remove elements. - final int maxCallsCount; - - /// Directionality of app. Directionality of the app will be used if set to - /// null. - final TextDirection? directionality; - - /// Flag used to show/hide share button - final bool? showShareButton; + late AliceConfiguration _configuration; /// Alice core instance late final AliceCore _aliceCore; - /// Alice storage instance - final AliceStorage? _aliceStorage; - - /// Navigator key used for navigating to inspector - GlobalKey? _navigatorKey; - /// Creates alice instance. - Alice({ - GlobalKey? navigatorKey, - this.showNotification = true, - this.showInspectorOnShake = false, - this.notificationIcon = '@mipmap/ic_launcher', - this.maxCallsCount = 1000, - this.directionality, - this.showShareButton = true, - AliceStorage? aliceStorage, - }) : _navigatorKey = navigatorKey ?? GlobalKey(), - _aliceStorage = aliceStorage { - _aliceCore = AliceCore( - _navigatorKey, - showNotification: showNotification, - showInspectorOnShake: showInspectorOnShake, - notificationIcon: notificationIcon, - directionality: directionality, - showShareButton: showShareButton, - aliceStorage: _aliceStorage ?? - AliceMemoryStorage( - maxCallsCount: maxCallsCount, - ), - aliceLogger: AliceLogger(), - ); + Alice({required AliceConfiguration configuration}) { + _aliceCore = AliceCore(configuration: configuration); } /// Set custom navigation key. This will help if there's route library. void setNavigatorKey(GlobalKey navigatorKey) { - _navigatorKey = navigatorKey; - _aliceCore.navigatorKey = navigatorKey; + _aliceCore.setNavigatorKey(navigatorKey); } /// Get currently used navigation key - GlobalKey? getNavigatorKey() => _navigatorKey; + GlobalKey? getNavigatorKey() => _configuration.navigatorKey; /// Opens Http calls inspector. This will navigate user to the new fullscreen /// page where all listened http calls can be viewed. diff --git a/packages/alice/lib/core/alice_core.dart b/packages/alice/lib/core/alice_core.dart index ce5519b3..9a45b3aa 100644 --- a/packages/alice/lib/core/alice_core.dart +++ b/packages/alice/lib/core/alice_core.dart @@ -6,6 +6,7 @@ import 'package:alice/core/alice_utils.dart'; import 'package:alice/helper/alice_export_helper.dart'; import 'package:alice/core/alice_notification.dart'; import 'package:alice/helper/operating_system.dart'; +import 'package:alice/model/alice_configuration.dart'; import 'package:alice/model/alice_export_result.dart'; import 'package:alice/model/alice_http_call.dart'; import 'package:alice/model/alice_http_error.dart'; @@ -18,31 +19,9 @@ import 'package:flutter/material.dart'; typedef AliceOnCallsChanged = Future Function(List? calls); class AliceCore { - /// Should user be notified with notification if there's new request caught - /// by Alice - final bool showNotification; - - /// Should inspector be opened on device shake (works only with physical - /// with sensors) - final bool showInspectorOnShake; - - /// Icon url for notification - final String notificationIcon; - - /// Storage used for Alice to keep calls data. - final AliceStorage _aliceStorage; - - /// Logger used for Alice to keep logs; - final AliceLogger _aliceLogger; - - ///Directionality of app. If null then directionality of context will be used. - final TextDirection? directionality; - - ///Flag used to show/hide share button - final bool? showShareButton; - - /// Navigator key used for inspector navigator. - GlobalKey? navigatorKey; + /// Default max logs count. + static const _defaultMaxLogs = 1000; + late AliceConfiguration _configuration; /// Flag used to determine whether is inspector opened bool _isInspectorOpened = false; @@ -56,27 +35,21 @@ class AliceCore { /// Subscription for call changes StreamSubscription>? _callsSubscription; + late AliceLogger _aliceLogger; + /// Creates alice core instance - AliceCore( - this.navigatorKey, { - required this.showNotification, - required this.showInspectorOnShake, - required this.notificationIcon, - required AliceStorage aliceStorage, - required AliceLogger aliceLogger, - this.directionality, - this.showShareButton, - }) : _aliceStorage = aliceStorage, - _aliceLogger = aliceLogger { + AliceCore({required AliceConfiguration configuration}) { + _configuration = configuration; + _aliceLogger = AliceLogger(maximumSize: _defaultMaxLogs); _subscribeToCallChanges(); - if (showNotification) { + if (_configuration.showNotification) { _notification = AliceNotification(); _notification?.configure( - notificationIcon: notificationIcon, + notificationIcon: _configuration.notificationIcon, openInspectorCallback: navigateToCallListScreen, ); } - if (showInspectorOnShake) { + if (_configuration.showInspectorOnShake) { if (OperatingSystem.isAndroid || OperatingSystem.isMacOS) { _shakeDetector = ShakeDetector.autoStart( onPhoneShake: navigateToCallListScreen, @@ -86,6 +59,13 @@ class AliceCore { } } + AliceConfiguration get configuration => _configuration; + + /// Set custom navigation key. This will help if there's route library. + void setNavigatorKey(GlobalKey navigatorKey) { + _configuration = _configuration.copyWith(newNavigatorKey: navigatorKey); + } + /// Dispose subjects and subscriptions void dispose() { _shakeDetector?.stopListening(); @@ -95,7 +75,7 @@ class AliceCore { /// Called when calls has been updated Future _onCallsChanged(List? calls) async { if (calls != null && calls.isNotEmpty) { - final AliceStats stats = _aliceStorage.getStats(); + final AliceStats stats = _configuration.aliceStorage.getStats(); _notification?.showStatsNotification( context: getContext()!, stats: stats, @@ -122,36 +102,40 @@ class AliceCore { } /// Get context from navigator key. Used to open inspector route. - BuildContext? getContext() => navigatorKey?.currentState?.overlay?.context; + BuildContext? getContext() => + _configuration.navigatorKey?.currentState?.overlay?.context; /// Add alice http call to calls subject - FutureOr addCall(AliceHttpCall call) => _aliceStorage.addCall(call); + FutureOr addCall(AliceHttpCall call) => + _configuration.aliceStorage.addCall(call); /// Add error to existing alice http call FutureOr addError(AliceHttpError error, int requestId) => - _aliceStorage.addError(error, requestId); + _configuration.aliceStorage.addError(error, requestId); /// Add response to existing alice http call FutureOr addResponse(AliceHttpResponse response, int requestId) => - _aliceStorage.addResponse(response, requestId); + _configuration.aliceStorage.addResponse(response, requestId); /// Remove all calls from calls subject - FutureOr removeCalls() => _aliceStorage.removeCalls(); + FutureOr removeCalls() => _configuration.aliceStorage.removeCalls(); /// Selects call with given [requestId]. It may return null. @protected AliceHttpCall? selectCall(int requestId) => - _aliceStorage.selectCall(requestId); + _configuration.aliceStorage.selectCall(requestId); /// Returns stream which returns list of HTTP calls - Stream> get callsStream => _aliceStorage.callsStream; + Stream> get callsStream => + _configuration.aliceStorage.callsStream; /// Returns all stored HTTP calls. - List getCalls() => _aliceStorage.getCalls(); + List getCalls() => _configuration.aliceStorage.getCalls(); /// Save all calls to file. Future saveCallsToFile(BuildContext context) { - return AliceExportHelper.saveCallsToFile(context, _aliceStorage.getCalls()); + return AliceExportHelper.saveCallsToFile( + context, _configuration.aliceStorage.getCalls()); } /// Adds new log to Alice logger. @@ -165,7 +149,8 @@ class AliceCore { /// Subscribes to storage for call changes. void _subscribeToCallChanges() { - _callsSubscription = _aliceStorage.callsStream.listen(_onCallsChanged); + _callsSubscription = + _configuration.aliceStorage.callsStream.listen(_onCallsChanged); } /// Unsubscribes storage for call changes. diff --git a/packages/alice/lib/model/alice_configuration.dart b/packages/alice/lib/model/alice_configuration.dart new file mode 100644 index 00000000..dc2a72eb --- /dev/null +++ b/packages/alice/lib/model/alice_configuration.dart @@ -0,0 +1,56 @@ +import 'package:alice/core/alice_memory_storage.dart'; +import 'package:alice/core/alice_storage.dart'; +import 'package:flutter/widgets.dart'; + +class AliceConfiguration { + /// Default max calls count used in default memory storage. + static const _defaultMaxCalls = 1000; + + /// Should user be notified with notification when there's new request caught + /// by Alice. Default value is true. + final bool showNotification; + + /// Should inspector be opened on device shake (works only with physical + /// with sensors). Default value is true. + final bool showInspectorOnShake; + + /// Icon url for notification. Default value is '@mipmap/ic_launcher'. + final String notificationIcon; + + /// Directionality of app. Directionality of the app will be used if set to + /// null. Default value is null. + final TextDirection? directionality; + + /// Flag used to show/hide share button + final bool showShareButton; + + /// Navigator key used to open inspector. Default value is null. + final GlobalKey? navigatorKey; + + /// Storage where calls will be saved. The default storage is memory storage. + final AliceStorage aliceStorage; + + AliceConfiguration({ + this.showNotification = true, + this.showInspectorOnShake = true, + this.notificationIcon = '@mipmap/ic_launcher', + this.directionality, + this.showShareButton = true, + GlobalKey? navigatorKey, + AliceStorage? storage, + }) : aliceStorage = storage ?? AliceMemoryStorage(maxCallsCount: _defaultMaxCalls), + navigatorKey = navigatorKey ?? GlobalKey(); + + AliceConfiguration copyWith({ + required GlobalKey newNavigatorKey, + }) { + return AliceConfiguration( + showNotification: showNotification, + showInspectorOnShake: showInspectorOnShake, + notificationIcon: notificationIcon, + directionality: directionality, + showShareButton: showShareButton, + navigatorKey: newNavigatorKey, + ); + } +} diff --git a/packages/alice/lib/ui/call_details/page/alice_call_details_page.dart b/packages/alice/lib/ui/call_details/page/alice_call_details_page.dart index 1e46cc9f..5475384a 100644 --- a/packages/alice/lib/ui/call_details/page/alice_call_details_page.dart +++ b/packages/alice/lib/ui/call_details/page/alice_call_details_page.dart @@ -74,17 +74,18 @@ class _AliceCallDetailsPageState extends State AliceCallErrorScreen(call: widget.call), ], ), - floatingActionButton: widget.core.showShareButton ?? false - ? FloatingActionButton( - backgroundColor: AliceTheme.lightRed, - key: const Key('share_key'), - onPressed: _shareCall, - child: const Icon( - Icons.share, - color: AliceTheme.white, - ), - ) - : null, + floatingActionButton: + widget.core.configuration.showShareButton + ? FloatingActionButton( + backgroundColor: AliceTheme.lightRed, + key: const Key('share_key'), + onPressed: _shareCall, + child: const Icon( + Icons.share, + color: AliceTheme.white, + ), + ) + : null, ), ); } diff --git a/packages/alice/lib/ui/common/alice_page.dart b/packages/alice/lib/ui/common/alice_page.dart index 748815f6..251ffb30 100644 --- a/packages/alice/lib/ui/common/alice_page.dart +++ b/packages/alice/lib/ui/common/alice_page.dart @@ -12,7 +12,8 @@ class AlicePage extends StatelessWidget { @override Widget build(BuildContext context) { return Directionality( - textDirection: core.directionality ?? Directionality.of(context), + textDirection: + core.configuration.directionality ?? Directionality.of(context), child: Theme( data: AliceTheme.getTheme(), child: child, diff --git a/packages/alice/test/core/alice_core_test.dart b/packages/alice/test/core/alice_core_test.dart index f1d503ec..579de167 100644 --- a/packages/alice/test/core/alice_core_test.dart +++ b/packages/alice/test/core/alice_core_test.dart @@ -2,9 +2,9 @@ import 'package:alice/alice.dart'; import 'package:alice/core/alice_core.dart'; import 'package:alice/core/alice_logger.dart'; import 'package:alice/core/alice_storage.dart'; +import 'package:alice/model/alice_configuration.dart'; import 'package:alice/model/alice_http_error.dart'; import 'package:alice/model/alice_http_response.dart'; -import 'package:flutter/material.dart'; import 'package:mocktail/mocktail.dart'; import 'package:test/test.dart'; @@ -27,14 +27,7 @@ void main() { when(() => aliceStorage.callsStream) .thenAnswer((_) => const Stream.empty()); - aliceCore = AliceCore( - GlobalKey(), - showNotification: false, - showInspectorOnShake: false, - notificationIcon: "", - aliceStorage: aliceStorage, - aliceLogger: aliceLogger, - ); + aliceCore = AliceCore(configuration: AliceConfiguration()); }); group("AliceCore", () { diff --git a/packages/alice_dio/pubspec.yaml b/packages/alice_dio/pubspec.yaml index 24c5d5be..4f6e0d09 100644 --- a/packages/alice_dio/pubspec.yaml +++ b/packages/alice_dio/pubspec.yaml @@ -1,6 +1,6 @@ name: alice_dio description: "Alice + Dio integration. It contains plugin for Alice which allows to use Dio package." -version: 1.0.3 +version: 1.0.4 repository: https://github.com/jhomlala/alice homepage: https://github.com/jhomlala/alice topics: From def2dcbb2bc5fafa256788357ca2550378bf4713 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 14:07:09 +0200 Subject: [PATCH 02/20] feat: introduced AliceConfiguration --- packages/alice/lib/alice.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/alice/lib/alice.dart b/packages/alice/lib/alice.dart index b23ed70f..d14acd51 100644 --- a/packages/alice/lib/alice.dart +++ b/packages/alice/lib/alice.dart @@ -12,8 +12,6 @@ export 'package:alice/core/alice_memory_storage.dart'; export 'package:alice/utils/alice_parser.dart'; class Alice { - late AliceConfiguration _configuration; - /// Alice core instance late final AliceCore _aliceCore; @@ -28,7 +26,8 @@ class Alice { } /// Get currently used navigation key - GlobalKey? getNavigatorKey() => _configuration.navigatorKey; + GlobalKey? getNavigatorKey() => + _aliceCore.configuration.navigatorKey; /// Opens Http calls inspector. This will navigate user to the new fullscreen /// page where all listened http calls can be viewed. From 3abbd7d02c8903931315af22783c7b921a655e5a Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 14:23:22 +0200 Subject: [PATCH 03/20] fix: fixed invalid count of http calls in notification --- packages/alice/CHANGELOG.md | 2 ++ packages/alice/lib/core/alice_memory_storage.dart | 6 ++++-- packages/alice/lib/core/alice_notification.dart | 8 +++++--- packages/alice/lib/core/alice_translations.dart | 4 ++-- packages/alice/test/core/alice_memory_storage_test.dart | 8 ++++++-- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/packages/alice/CHANGELOG.md b/packages/alice/CHANGELOG.md index a3fc5090..4310c2cc 100644 --- a/packages/alice/CHANGELOG.md +++ b/packages/alice/CHANGELOG.md @@ -2,6 +2,8 @@ * [BREAKING_CHANGE] Removed maxCallsCount. To change call count, use `storage` constructor parameter with call count. +* [BREAKING_CHANGE] Replaced configuration parameter of Alice with `AliceConfiguration`. +* Fixed issue with invalid count of calls in notification. # 1.0.0-dev.9 diff --git a/packages/alice/lib/core/alice_memory_storage.dart b/packages/alice/lib/core/alice_memory_storage.dart index dffbfaaf..c3640025 100644 --- a/packages/alice/lib/core/alice_memory_storage.dart +++ b/packages/alice/lib/core/alice_memory_storage.dart @@ -47,8 +47,10 @@ class AliceMemoryStorage implements AliceStorage { errors: calls .where( (AliceHttpCall call) => - (call.response?.status.gte(400) ?? false) && - (call.response?.status.lt(600) ?? false), + ((call.response?.status.gte(400) ?? false) && + (call.response?.status.lt(600) ?? false)) || + call.response?.status == -1 || + call.response?.status == 0, ) .length, loading: calls.where((AliceHttpCall call) => call.loading).length, diff --git a/packages/alice/lib/core/alice_notification.dart b/packages/alice/lib/core/alice_notification.dart index 41cbcfe4..0063809f 100644 --- a/packages/alice/lib/core/alice_notification.dart +++ b/packages/alice/lib/core/alice_notification.dart @@ -99,8 +99,10 @@ class AliceNotification { } /// Formats [stats] for notification message. - String _getNotificationMessage( - {required BuildContext context, required AliceStats stats}) => + String _getNotificationMessage({ + required BuildContext context, + required AliceStats stats, + }) => [ if (stats.loading > 0) '${context.i18n(AliceTranslationKey.notificationLoading)} ${stats.loading}', @@ -136,7 +138,7 @@ class AliceNotification { 0, context .i18n(AliceTranslationKey.notificationTotalRequests) - .replaceAll("[requestCount]", stats.total.toString()), + .replaceAll("[callCount]", stats.total.toString()), message, _notificationDetails, payload: '', diff --git a/packages/alice/lib/core/alice_translations.dart b/packages/alice/lib/core/alice_translations.dart index 9b585146..0c6f4300 100644 --- a/packages/alice/lib/core/alice_translations.dart +++ b/packages/alice/lib/core/alice_translations.dart @@ -121,7 +121,7 @@ class AliceTranslations { AliceTranslationKey.notificationRedirect: "Redirect:", AliceTranslationKey.notificationError: "Error:", AliceTranslationKey.notificationTotalRequests: - "Alice (total [requestCount] requests)", + "Alice (total [callCount] HTTP calls)", AliceTranslationKey.saveDialogPermissionErrorTitle: "Permission error", AliceTranslationKey.saveDialogPermissionErrorDescription: "Permission not granted. Couldn't save logs.", @@ -285,7 +285,7 @@ class AliceTranslations { AliceTranslationKey.notificationRedirect: "Przekierowanie:", AliceTranslationKey.notificationError: "Błąd:", AliceTranslationKey.notificationTotalRequests: - "Alice (razem [requestCount] żądań)", + "Alice (razem [callCount] połączeń HTTP)", AliceTranslationKey.saveDialogPermissionErrorTitle: "Błąd pozwolenia", AliceTranslationKey.saveDialogPermissionErrorDescription: "Pozwolenie nieprzyznane. Nie można zapisać logów.", diff --git a/packages/alice/test/core/alice_memory_storage_test.dart b/packages/alice/test/core/alice_memory_storage_test.dart index 32ba44df..c2dfeae2 100644 --- a/packages/alice/test/core/alice_memory_storage_test.dart +++ b/packages/alice/test/core/alice_memory_storage_test.dart @@ -39,12 +39,16 @@ void main() { storage .addCall(MockedData.getHttpCallWithResponseStatus(statusCode: 500)); storage.addCall(MockedData.getLoadingHttpCall()); + storage + .addCall(MockedData.getHttpCallWithResponseStatus(statusCode: -1)); + storage + .addCall(MockedData.getHttpCallWithResponseStatus(statusCode: 0)); expect(storage.getStats(), ( - total: 8, + total: 10, successes: 2, redirects: 2, - errors: 3, + errors: 5, loading: 1, )); }); From 64483cdfd2774d7083ce56a04728b9d2f502e93f Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 14:26:11 +0200 Subject: [PATCH 04/20] feat: set configuration optional --- packages/alice/lib/alice.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/alice/lib/alice.dart b/packages/alice/lib/alice.dart index d14acd51..8321a9e4 100644 --- a/packages/alice/lib/alice.dart +++ b/packages/alice/lib/alice.dart @@ -16,8 +16,10 @@ class Alice { late final AliceCore _aliceCore; /// Creates alice instance. - Alice({required AliceConfiguration configuration}) { - _aliceCore = AliceCore(configuration: configuration); + Alice({AliceConfiguration? configuration}) { + _aliceCore = AliceCore( + configuration: configuration ?? AliceConfiguration(), + ); } /// Set custom navigation key. This will help if there's route library. From f7c7f1882c1e141dbd25b52e104dc9b19d495c6a Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 14:28:43 +0200 Subject: [PATCH 05/20] feat: added payload to notification --- packages/alice/CHANGELOG.md | 1 + packages/alice/lib/core/alice_notification.dart | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/alice/CHANGELOG.md b/packages/alice/CHANGELOG.md index 4310c2cc..2d0de10e 100644 --- a/packages/alice/CHANGELOG.md +++ b/packages/alice/CHANGELOG.md @@ -4,6 +4,7 @@ with call count. * [BREAKING_CHANGE] Replaced configuration parameter of Alice with `AliceConfiguration`. * Fixed issue with invalid count of calls in notification. +* Added payload to notification. # 1.0.0-dev.9 diff --git a/packages/alice/lib/core/alice_notification.dart b/packages/alice/lib/core/alice_notification.dart index 0063809f..4e539029 100644 --- a/packages/alice/lib/core/alice_notification.dart +++ b/packages/alice/lib/core/alice_notification.dart @@ -8,6 +8,9 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart'; /// Helper for displaying local notifications. class AliceNotification { + static const _payload = 'Alice'; + static const _channel = 'Alice'; + /// Notification plugin instance FlutterLocalNotificationsPlugin? _flutterLocalNotificationsPlugin; @@ -32,9 +35,9 @@ class AliceNotification { _openInspectorCallback = openInspectorCallback; _notificationDetails = NotificationDetails( android: AndroidNotificationDetails( - 'Alice', - 'Alice', - channelDescription: 'Alice', + _channel, + _channel, + channelDescription: _channel, enableVibration: false, playSound: false, largeIcon: DrawableResourceAndroidBitmap(notificationIcon), @@ -141,7 +144,7 @@ class AliceNotification { .replaceAll("[callCount]", stats.total.toString()), message, _notificationDetails, - payload: '', + payload: _payload, ); _notificationMessageDisplayed = message; From 550c9918625f7abcddd7591358258c39bd9e1c24 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 14:31:42 +0200 Subject: [PATCH 06/20] fix: format --- packages/alice/lib/core/alice_core.dart | 9 ++++++--- packages/alice/lib/model/alice_configuration.dart | 3 ++- packages/alice/test/core/alice_memory_storage_test.dart | 6 ++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/alice/lib/core/alice_core.dart b/packages/alice/lib/core/alice_core.dart index 9a45b3aa..1a0c4c91 100644 --- a/packages/alice/lib/core/alice_core.dart +++ b/packages/alice/lib/core/alice_core.dart @@ -21,10 +21,12 @@ typedef AliceOnCallsChanged = Future Function(List? calls); class AliceCore { /// Default max logs count. static const _defaultMaxLogs = 1000; + + /// Configuration of Alice late AliceConfiguration _configuration; - /// Flag used to determine whether is inspector opened - bool _isInspectorOpened = false; + /// Alice logger instance + late AliceLogger _aliceLogger; /// Detector used to detect device shakes ShakeDetector? _shakeDetector; @@ -35,7 +37,8 @@ class AliceCore { /// Subscription for call changes StreamSubscription>? _callsSubscription; - late AliceLogger _aliceLogger; + /// Flag used to determine whether is inspector opened + bool _isInspectorOpened = false; /// Creates alice core instance AliceCore({required AliceConfiguration configuration}) { diff --git a/packages/alice/lib/model/alice_configuration.dart b/packages/alice/lib/model/alice_configuration.dart index dc2a72eb..0a1587c7 100644 --- a/packages/alice/lib/model/alice_configuration.dart +++ b/packages/alice/lib/model/alice_configuration.dart @@ -38,7 +38,8 @@ class AliceConfiguration { this.showShareButton = true, GlobalKey? navigatorKey, AliceStorage? storage, - }) : aliceStorage = storage ?? AliceMemoryStorage(maxCallsCount: _defaultMaxCalls), + }) : aliceStorage = + storage ?? AliceMemoryStorage(maxCallsCount: _defaultMaxCalls), navigatorKey = navigatorKey ?? GlobalKey(); AliceConfiguration copyWith({ diff --git a/packages/alice/test/core/alice_memory_storage_test.dart b/packages/alice/test/core/alice_memory_storage_test.dart index c2dfeae2..d7404f13 100644 --- a/packages/alice/test/core/alice_memory_storage_test.dart +++ b/packages/alice/test/core/alice_memory_storage_test.dart @@ -39,10 +39,8 @@ void main() { storage .addCall(MockedData.getHttpCallWithResponseStatus(statusCode: 500)); storage.addCall(MockedData.getLoadingHttpCall()); - storage - .addCall(MockedData.getHttpCallWithResponseStatus(statusCode: -1)); - storage - .addCall(MockedData.getHttpCallWithResponseStatus(statusCode: 0)); + storage.addCall(MockedData.getHttpCallWithResponseStatus(statusCode: -1)); + storage.addCall(MockedData.getHttpCallWithResponseStatus(statusCode: 0)); expect(storage.getStats(), ( total: 10, From 14b7eb278b44ea274dac193473fbdd5096f0fca3 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 14:41:22 +0200 Subject: [PATCH 07/20] fix: fixed tests --- packages/alice/lib/core/alice_core.dart | 13 +++---------- packages/alice/lib/model/alice_configuration.dart | 11 ++++++++++- .../ui/calls_list/page/alice_calls_list_page.dart | 9 ++++----- packages/alice/lib/ui/common/alice_navigation.dart | 3 +-- packages/alice/test/core/alice_core_test.dart | 13 +++++++++++-- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/packages/alice/lib/core/alice_core.dart b/packages/alice/lib/core/alice_core.dart index 1a0c4c91..5763d8f0 100644 --- a/packages/alice/lib/core/alice_core.dart +++ b/packages/alice/lib/core/alice_core.dart @@ -19,15 +19,9 @@ import 'package:flutter/material.dart'; typedef AliceOnCallsChanged = Future Function(List? calls); class AliceCore { - /// Default max logs count. - static const _defaultMaxLogs = 1000; - /// Configuration of Alice late AliceConfiguration _configuration; - /// Alice logger instance - late AliceLogger _aliceLogger; - /// Detector used to detect device shakes ShakeDetector? _shakeDetector; @@ -43,7 +37,6 @@ class AliceCore { /// Creates alice core instance AliceCore({required AliceConfiguration configuration}) { _configuration = configuration; - _aliceLogger = AliceLogger(maximumSize: _defaultMaxLogs); _subscribeToCallChanges(); if (_configuration.showNotification) { _notification = AliceNotification(); @@ -99,7 +92,7 @@ class AliceCore { } if (!_isInspectorOpened) { _isInspectorOpened = true; - AliceNavigation.navigateToCallsList(core: this, logger: _aliceLogger) + AliceNavigation.navigateToCallsList(core: this) .then((_) => _isInspectorOpened = false); } } @@ -142,10 +135,10 @@ class AliceCore { } /// Adds new log to Alice logger. - void addLog(AliceLog log) => _aliceLogger.add(log); + void addLog(AliceLog log) => _configuration.aliceLogger.add(log); /// Adds list of logs to Alice logger - void addLogs(List logs) => _aliceLogger.addAll(logs); + void addLogs(List logs) => _configuration.aliceLogger.addAll(logs); /// Returns flag which determines whether inspector is opened bool get isInspectorOpened => _isInspectorOpened; diff --git a/packages/alice/lib/model/alice_configuration.dart b/packages/alice/lib/model/alice_configuration.dart index 0a1587c7..b0f5631c 100644 --- a/packages/alice/lib/model/alice_configuration.dart +++ b/packages/alice/lib/model/alice_configuration.dart @@ -1,3 +1,4 @@ +import 'package:alice/core/alice_logger.dart'; import 'package:alice/core/alice_memory_storage.dart'; import 'package:alice/core/alice_storage.dart'; import 'package:flutter/widgets.dart'; @@ -6,6 +7,9 @@ class AliceConfiguration { /// Default max calls count used in default memory storage. static const _defaultMaxCalls = 1000; + /// Default max logs count. + static const _defaultMaxLogs = 1000; + /// Should user be notified with notification when there's new request caught /// by Alice. Default value is true. final bool showNotification; @@ -30,6 +34,9 @@ class AliceConfiguration { /// Storage where calls will be saved. The default storage is memory storage. final AliceStorage aliceStorage; + /// Logger instance. + final AliceLogger aliceLogger; + AliceConfiguration({ this.showNotification = true, this.showInspectorOnShake = true, @@ -38,9 +45,11 @@ class AliceConfiguration { this.showShareButton = true, GlobalKey? navigatorKey, AliceStorage? storage, + AliceLogger? logger, }) : aliceStorage = storage ?? AliceMemoryStorage(maxCallsCount: _defaultMaxCalls), - navigatorKey = navigatorKey ?? GlobalKey(); + navigatorKey = navigatorKey ?? GlobalKey(), + aliceLogger = logger ?? AliceLogger(maximumSize: _defaultMaxCalls); AliceConfiguration copyWith({ required GlobalKey newNavigatorKey, diff --git a/packages/alice/lib/ui/calls_list/page/alice_calls_list_page.dart b/packages/alice/lib/ui/calls_list/page/alice_calls_list_page.dart index 2b0beb6a..74046750 100644 --- a/packages/alice/lib/ui/calls_list/page/alice_calls_list_page.dart +++ b/packages/alice/lib/ui/calls_list/page/alice_calls_list_page.dart @@ -25,11 +25,10 @@ import 'package:open_filex/open_filex.dart'; /// and search calls. class AliceCallsListPage extends StatefulWidget { final AliceCore core; - final AliceLogger? logger; + const AliceCallsListPage({ required this.core, - this.logger, super.key, }); @@ -142,7 +141,7 @@ class _AliceCallsListPageState extends State ), AliceLogsScreen( scrollController: _scrollController, - aliceLogger: widget.logger, + aliceLogger: widget.core.configuration.aliceLogger, isAndroidRawLogsEnabled: isAndroidRawLogsEnabled, ), ], @@ -192,9 +191,9 @@ class _AliceCallsListPageState extends State /// Called when logs clear button has been pressed. void _onLogsClearPressed() => setState(() { if (isAndroidRawLogsEnabled) { - widget.logger?.clearAndroidRawLogs(); + widget.core.configuration.aliceLogger.clearAndroidRawLogs(); } else { - widget.logger?.clearLogs(); + widget.core.configuration.aliceLogger.clearLogs(); } }); diff --git a/packages/alice/lib/ui/common/alice_navigation.dart b/packages/alice/lib/ui/common/alice_navigation.dart index 6c2f5152..69c6086b 100644 --- a/packages/alice/lib/ui/common/alice_navigation.dart +++ b/packages/alice/lib/ui/common/alice_navigation.dart @@ -11,11 +11,10 @@ class AliceNavigation { /// Navigates to calls list page. static Future navigateToCallsList({ required AliceCore core, - required AliceLogger logger, }) { return _navigateToPage( core: core, - child: AliceCallsListPage(core: core, logger: logger), + child: AliceCallsListPage(core: core), ); } diff --git a/packages/alice/test/core/alice_core_test.dart b/packages/alice/test/core/alice_core_test.dart index 579de167..9aa5af6d 100644 --- a/packages/alice/test/core/alice_core_test.dart +++ b/packages/alice/test/core/alice_core_test.dart @@ -5,8 +5,9 @@ import 'package:alice/core/alice_storage.dart'; import 'package:alice/model/alice_configuration.dart'; import 'package:alice/model/alice_http_error.dart'; import 'package:alice/model/alice_http_response.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; -import 'package:test/test.dart'; import '../mock/alice_logger_mock.dart'; import '../mock/alice_storage_mock.dart'; @@ -18,6 +19,7 @@ void main() { late AliceLogger aliceLogger; setUp(() { + TestWidgetsFlutterBinding.ensureInitialized(); registerFallbackValue(MockedData.getLoadingHttpCall()); registerFallbackValue(AliceHttpError()); registerFallbackValue(AliceHttpResponse()); @@ -27,7 +29,14 @@ void main() { when(() => aliceStorage.callsStream) .thenAnswer((_) => const Stream.empty()); - aliceCore = AliceCore(configuration: AliceConfiguration()); + aliceCore = AliceCore( + configuration: AliceConfiguration( + showNotification: false, + showInspectorOnShake: false, + storage: aliceStorage, + logger: aliceLogger, + ), + ); }); group("AliceCore", () { From 78af4b7946009352469ed5f20549f508cddd8216 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 14:53:44 +0200 Subject: [PATCH 08/20] fix: dart format --- packages/alice/lib/core/alice_core.dart | 1 - packages/alice/lib/model/alice_configuration.dart | 2 +- .../alice/lib/ui/calls_list/page/alice_calls_list_page.dart | 2 -- packages/alice/lib/ui/common/alice_navigation.dart | 1 - packages/alice/test/core/alice_core_test.dart | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/alice/lib/core/alice_core.dart b/packages/alice/lib/core/alice_core.dart index 5763d8f0..8c8f8fe0 100644 --- a/packages/alice/lib/core/alice_core.dart +++ b/packages/alice/lib/core/alice_core.dart @@ -1,6 +1,5 @@ import 'dart:async' show FutureOr, StreamSubscription; -import 'package:alice/core/alice_logger.dart'; import 'package:alice/core/alice_storage.dart'; import 'package:alice/core/alice_utils.dart'; import 'package:alice/helper/alice_export_helper.dart'; diff --git a/packages/alice/lib/model/alice_configuration.dart b/packages/alice/lib/model/alice_configuration.dart index b0f5631c..0ce0e9d4 100644 --- a/packages/alice/lib/model/alice_configuration.dart +++ b/packages/alice/lib/model/alice_configuration.dart @@ -49,7 +49,7 @@ class AliceConfiguration { }) : aliceStorage = storage ?? AliceMemoryStorage(maxCallsCount: _defaultMaxCalls), navigatorKey = navigatorKey ?? GlobalKey(), - aliceLogger = logger ?? AliceLogger(maximumSize: _defaultMaxCalls); + aliceLogger = logger ?? AliceLogger(maximumSize: _defaultMaxLogs); AliceConfiguration copyWith({ required GlobalKey newNavigatorKey, diff --git a/packages/alice/lib/ui/calls_list/page/alice_calls_list_page.dart b/packages/alice/lib/ui/calls_list/page/alice_calls_list_page.dart index 74046750..9f5c53f7 100644 --- a/packages/alice/lib/ui/calls_list/page/alice_calls_list_page.dart +++ b/packages/alice/lib/ui/calls_list/page/alice_calls_list_page.dart @@ -1,7 +1,6 @@ // ignore_for_file: use_build_context_synchronously import 'package:alice/core/alice_core.dart'; -import 'package:alice/core/alice_logger.dart'; import 'package:alice/helper/operating_system.dart'; import 'package:alice/model/alice_export_result.dart'; import 'package:alice/model/alice_http_call.dart'; @@ -26,7 +25,6 @@ import 'package:open_filex/open_filex.dart'; class AliceCallsListPage extends StatefulWidget { final AliceCore core; - const AliceCallsListPage({ required this.core, super.key, diff --git a/packages/alice/lib/ui/common/alice_navigation.dart b/packages/alice/lib/ui/common/alice_navigation.dart index 69c6086b..39c85a51 100644 --- a/packages/alice/lib/ui/common/alice_navigation.dart +++ b/packages/alice/lib/ui/common/alice_navigation.dart @@ -1,5 +1,4 @@ import 'package:alice/core/alice_core.dart'; -import 'package:alice/core/alice_logger.dart'; import 'package:alice/model/alice_http_call.dart'; import 'package:alice/ui/call_details/page/alice_call_details_page.dart'; import 'package:alice/ui/calls_list/page/alice_calls_list_page.dart'; diff --git a/packages/alice/test/core/alice_core_test.dart b/packages/alice/test/core/alice_core_test.dart index 9aa5af6d..bc789f74 100644 --- a/packages/alice/test/core/alice_core_test.dart +++ b/packages/alice/test/core/alice_core_test.dart @@ -5,7 +5,6 @@ import 'package:alice/core/alice_storage.dart'; import 'package:alice/model/alice_configuration.dart'; import 'package:alice/model/alice_http_error.dart'; import 'package:alice/model/alice_http_response.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; From 590ddc290fdf0a18f06b874e5e23f4bf35d0b47e Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 15:00:55 +0200 Subject: [PATCH 09/20] feat: updated docs --- docs/config.md | 58 ++++++++++++++++++++++++++++++++++--------------- docs/install.md | 16 +++++++++++++- docs/other.md | 8 ------- docs/usage.md | 9 -------- 4 files changed, 55 insertions(+), 36 deletions(-) diff --git a/docs/config.md b/docs/config.md index 8216ece3..f8e40b09 100644 --- a/docs/config.md +++ b/docs/config.md @@ -1,59 +1,81 @@ ## Configuration + 1. Create Alice instance: ```dart + Alice alice = Alice(); ``` 2. Add navigator key to your application: ```dart -MaterialApp( navigatorKey: alice.getNavigatorKey(), home: ...) +MaterialApp +( +navigatorKey: alice.getNavigatorKey(), home: ...) ``` You need to add this navigator key in order to show inspector UI. You can use also your navigator key in Alice: ```dart -Alice alice = Alice(showNotification: true, navigatorKey: yourNavigatorKeyHere); + +Alice alice = Alice(configuration: AliceConfiguration(navigatorKey: yourNavigatorKeyHere)); ``` If you need to pass navigatorKey lazily, you can use: + ```dart -alice.setNavigatorKey(yourNavigatorKeyHere); +alice.setNavigatorKey +( +yourNavigatorKeyHere +); ``` -This is minimal configuration required to run Alice. Can set optional settings in Alice constructor, which are presented below. If you don't want to change anything, you can move to Http clients configuration. -### Additional settings +This is minimal configuration required to run Alice. Can set optional settings in Alice constructor, +which are presented below. If you don't want to change anything, you can move to Http clients +configuration. -You can set `showNotification` in Alice constructor to show notification. Clicking on this notification will open inspector. -```dart -Alice alice = Alice(..., showNotification: true); -``` +### Alice configuration -You can set `showInspectorOnShake` in Alice constructor to open inspector by shaking your device (default disabled): +You can pass optional `AliceConfiguration` parameter to `Alice` instance. + +You can set `showNotification` in Alice constructor to show notification. Clicking on this +notification will open inspector. ```dart -Alice alice = Alice(..., showInspectorOnShake: true); + +Alice alice = Alice(configuration: AliceConfiguration(showNotification: true)); ``` -If you want to pass another notification icon, you can use `notificationIcon` parameter. Default value is @mipmap/ic_launcher. +You can set `showInspectorOnShake` in Alice constructor to open inspector by shaking your device ( +default disabled): + ```dart -Alice alice = Alice(..., notificationIcon: "myNotificationIconResourceName"); + +Alice alice = Alice(configuration: AliceConfiguation(showInspectorOnShake: true)); ``` -If you want to limit max numbers of HTTP calls saved in memory, you may use `maxCallsCount` parameter. +If you want to pass another notification icon, you can use `notificationIcon` parameter. Default +value is @mipmap/ic_launcher. ```dart -Alice alice = Alice(..., maxCallsCount: 1000)); + +Alice alice = Alice( + configuration: AliceConfiguration(notificationIcon: "myNotificationIconResourceName")); ``` -If you want to change the Directionality of Alice, you can use the `directionality` parameter. If the parameter is set to null, the Directionality of the app will be used. +If you want to change the Directionality of Alice, you can use the `directionality` parameter. If +the parameter is set to null, the Directionality of the app will be used. + ```dart -Alice alice = Alice(..., directionality: TextDirection.ltr); + +Alice alice = Alice(configuration: AliceConfiguration(directionality: TextDirection.ltr)); ``` If you want to hide share button, you can use `showShareButton` parameter. + ```dart -Alice alice = Alice(..., showShareButton: false); + +Alice alice = Alice(configuration: AliceConfiguration(showShareButton: false)); ``` \ No newline at end of file diff --git a/docs/install.md b/docs/install.md index 005dca88..d711a553 100644 --- a/docs/install.md +++ b/docs/install.md @@ -10,30 +10,44 @@ dependencies: 2. Choose adapter based on your HTTP client. **pubspec.yaml** file: ### Dio + ```yaml dependencies: alice_dio: ^1.0.4 ``` ### Chopper + ```yaml dependencies: alice_chopper: ^1.0.5 ``` ### Http + ```yaml dependencies: alice_http: ^1.0.4 ``` ### Http Client + ```yaml dependencies: alice_http_client: ^1.0.4 ``` -3. Run `get` command: +3. Choose optional database: + +### Objectbox + +```yaml +dependencies: + alice_objectbox: ^1.0.1 +``` + +4. Run `get` command: + ```bash $ flutter packages get ``` \ No newline at end of file diff --git a/docs/other.md b/docs/other.md index 72d565ab..cb480550 100644 --- a/docs/other.md +++ b/docs/other.md @@ -8,14 +8,6 @@ You may need that if you won't use shake or notification: alice.showInspector(); ``` -## Saving calls - -Alice supports saving logs to your mobile device storage. In order to make save feature works, you need to add in your Android application manifest: - -```xml - -``` - ## Flutter logs If you want to log Flutter logs in Alice, you may use these methods: diff --git a/docs/usage.md b/docs/usage.md index e9c10743..9f95ca27 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -105,15 +105,6 @@ httpClient Setting up ObjectBox with Alice is simple, however, there are a few crucial steps which need to be followed. -1. Add it to your dependencies - -```yaml -dependencies: - alice_objectbox: ^1.0.0 -``` - -2. Follow the ObjectBox [example](https://github.com/objectbox/objectbox-dart/blob/main/objectbox/example/flutter/objectbox_demo/lib/main.dart) - ```dart Future main() async { /// This is required so ObjectBox can get the application directory From a9c80aff96f4ad53dfd0142396e8109975999ed1 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 15:01:42 +0200 Subject: [PATCH 10/20] feat: updated metadata --- packages/alice/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/alice/CHANGELOG.md b/packages/alice/CHANGELOG.md index 2d0de10e..73e0d655 100644 --- a/packages/alice/CHANGELOG.md +++ b/packages/alice/CHANGELOG.md @@ -5,6 +5,7 @@ * [BREAKING_CHANGE] Replaced configuration parameter of Alice with `AliceConfiguration`. * Fixed issue with invalid count of calls in notification. * Added payload to notification. +* Updated documentation. # 1.0.0-dev.9 From 111cb8a76d23eacc37c9f67dd5b7912cda8b7127 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 17:37:21 +0200 Subject: [PATCH 11/20] feat: updated tests --- packages/alice/test/alice_test.dart | 84 +++++++++++++++++++ packages/alice/test/core/alice_core_test.dart | 2 +- .../test/core/alice_memory_storage_test.dart | 2 +- .../test/helper/alice_export_helper_test.dart | 2 +- .../alice/test/{ => mock}/mocked_data.dart | 0 5 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 packages/alice/test/alice_test.dart rename packages/alice/test/{ => mock}/mocked_data.dart (100%) diff --git a/packages/alice/test/alice_test.dart b/packages/alice/test/alice_test.dart new file mode 100644 index 00000000..abce8383 --- /dev/null +++ b/packages/alice/test/alice_test.dart @@ -0,0 +1,84 @@ +import 'package:alice/alice.dart'; +import 'package:alice/core/alice_adapter.dart'; +import 'package:alice/core/alice_logger.dart'; +import 'package:alice/core/alice_storage.dart'; +import 'package:alice/model/alice_configuration.dart'; +import 'package:alice/model/alice_http_call.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'mock/mocked_data.dart'; + +void main() { + group("Alice", () { + late Alice alice; + late AliceStorage aliceStorage; + late AliceLogger aliceLogger; + setUp(() { + aliceStorage = AliceMemoryStorage(maxCallsCount: 1000); + aliceLogger = AliceLogger(maximumSize: 1000); + alice = Alice( + configuration: AliceConfiguration( + showInspectorOnShake: false, + showNotification: false, + logger: aliceLogger, + storage: aliceStorage, + ), + ); + }); + + test("should set new navigator key", () { + final navigatorKey = GlobalKey(); + + expect(alice.getNavigatorKey() != navigatorKey, true); + + alice.setNavigatorKey(navigatorKey); + + expect(alice.getNavigatorKey() == navigatorKey, true); + }); + + test("should add log", () { + final log = AliceLog(message: "test"); + + alice.addLog(log); + + expect(aliceLogger.logs, [log]); + }); + + test("should add logs", () { + final logs = [AliceLog(message: "test 1"), AliceLog(message: "test 2")]; + + alice.addLogs(logs); + + expect(aliceLogger.logs, logs); + }); + + test("should add call", () { + final call = MockedData.getFilledHttpCall(); + + alice.addHttpCall(call); + + expect(aliceStorage.getCalls(), [call]); + }); + + test("should add adapter", () { + final call = MockedData.getFilledHttpCall(); + final adapter = FakeAdapter(); + alice.addAdapter(adapter); + + adapter.addCallLog(call); + + expect(aliceStorage.getCalls(), [call]); + }); + + test("should return is inspector opened flag", () { + expect(alice.isInspectorOpened, false); + }); + }); +} + +class FakeAdapter with AliceAdapter { + void addCallLog(AliceHttpCall call) { + aliceCore.addCall(call); + } +} diff --git a/packages/alice/test/core/alice_core_test.dart b/packages/alice/test/core/alice_core_test.dart index bc789f74..2a69251b 100644 --- a/packages/alice/test/core/alice_core_test.dart +++ b/packages/alice/test/core/alice_core_test.dart @@ -10,7 +10,7 @@ import 'package:mocktail/mocktail.dart'; import '../mock/alice_logger_mock.dart'; import '../mock/alice_storage_mock.dart'; -import '../mocked_data.dart'; +import '../mock/mocked_data.dart'; void main() { late AliceCore aliceCore; diff --git a/packages/alice/test/core/alice_memory_storage_test.dart b/packages/alice/test/core/alice_memory_storage_test.dart index d7404f13..e2666106 100644 --- a/packages/alice/test/core/alice_memory_storage_test.dart +++ b/packages/alice/test/core/alice_memory_storage_test.dart @@ -6,7 +6,7 @@ import 'package:alice/model/alice_http_response.dart'; import 'package:test/expect.dart'; import 'package:test/scaffolding.dart'; -import '../mocked_data.dart'; +import '../mock/mocked_data.dart'; void main() { late AliceMemoryStorage storage; diff --git a/packages/alice/test/helper/alice_export_helper_test.dart b/packages/alice/test/helper/alice_export_helper_test.dart index 94452a1e..0dd346e0 100644 --- a/packages/alice/test/helper/alice_export_helper_test.dart +++ b/packages/alice/test/helper/alice_export_helper_test.dart @@ -9,7 +9,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:package_info_plus/package_info_plus.dart'; import '../mock/build_context_mock.dart'; -import '../mocked_data.dart'; +import '../mock/mocked_data.dart'; void main() { late BuildContext context; diff --git a/packages/alice/test/mocked_data.dart b/packages/alice/test/mock/mocked_data.dart similarity index 100% rename from packages/alice/test/mocked_data.dart rename to packages/alice/test/mock/mocked_data.dart From b2a7df2990297562012cae8cc16ed1fced776f01 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 21:54:24 +0200 Subject: [PATCH 12/20] refactor: refactored logger --- packages/alice/CHANGELOG.md | 1 + packages/alice/lib/core/alice_adapter.dart | 1 + packages/alice/lib/core/alice_logger.dart | 73 ++++++------------- packages/alice/lib/model/alice_http_call.dart | 12 +-- .../widget/alice_log_list_widget.dart | 11 +-- .../calls_list/widget/alice_logs_screen.dart | 2 +- .../alice/test/core/alice_logger_test.dart | 15 ---- .../lib/model/cached_alice_http_call.dart | 6 -- 8 files changed, 33 insertions(+), 88 deletions(-) diff --git a/packages/alice/CHANGELOG.md b/packages/alice/CHANGELOG.md index 73e0d655..490cba1f 100644 --- a/packages/alice/CHANGELOG.md +++ b/packages/alice/CHANGELOG.md @@ -5,6 +5,7 @@ * [BREAKING_CHANGE] Replaced configuration parameter of Alice with `AliceConfiguration`. * Fixed issue with invalid count of calls in notification. * Added payload to notification. +* General refactor of code base. * Updated documentation. # 1.0.0-dev.9 diff --git a/packages/alice/lib/core/alice_adapter.dart b/packages/alice/lib/core/alice_adapter.dart index d0f5604c..c1116a51 100644 --- a/packages/alice/lib/core/alice_adapter.dart +++ b/packages/alice/lib/core/alice_adapter.dart @@ -4,5 +4,6 @@ import 'package:alice/core/alice_core.dart'; mixin AliceAdapter { late final AliceCore aliceCore; + /// Injects [AliceCore] into adapter. void injectCore(AliceCore aliceCore) => this.aliceCore = aliceCore; } diff --git a/packages/alice/lib/core/alice_logger.dart b/packages/alice/lib/core/alice_logger.dart index e63f5010..adb231ea 100644 --- a/packages/alice/lib/core/alice_logger.dart +++ b/packages/alice/lib/core/alice_logger.dart @@ -2,77 +2,48 @@ import 'dart:io' show Process, ProcessResult; import 'package:alice/helper/operating_system.dart'; import 'package:alice/model/alice_log.dart'; -import 'package:alice/utils/num_comparison.dart'; -import 'package:flutter/foundation.dart'; +import 'package:rxdart/rxdart.dart'; /// Logger used to handle logs from application. class AliceLogger { - AliceLogger({int? maximumSize = 1000}) : _maximumSize = maximumSize; + /// Maximum logs size. If null, logs will be not rotated. + final int? maximumSize; - final ValueNotifier> _logs = ValueNotifier>([]); + /// Subject which keeps logs. + final BehaviorSubject> _logsSubject = + BehaviorSubject.seeded([]); - ValueListenable> get listenable => _logs; + AliceLogger({required this.maximumSize}); - List get logs => listenable.value; + /// Getter of stream of logs + Stream> get logsStream => _logsSubject.stream; - int? _maximumSize; - - /// The maximum number of logs to store or `null` for unlimited storage. - /// - /// If more logs arrive, the oldest ones (based on their [ - /// AliceLog.timestamp]) will be removed. - int? get maximumSize => _maximumSize; - - set maximumSize(int? value) { - _maximumSize = maximumSize; - - if (value != null && logs.length > value) { - _logs.value = logs.sublist(logs.length - value, logs.length); - } - } + /// Getter of all logs + List get logs => _logsSubject.value; + /// Adds all logs. void addAll(List logs) { for (var log in logs) { add(log); } } + /// Add one log. It sorts logs after adding new element. If [maximumSize] is + /// set and max size is reached, first log will be deleted. void add(AliceLog log) { - late final int index; - if (logs.isEmpty || !log.timestamp.isBefore(logs.last.timestamp)) { - // Quick path as new logs are usually more recent. - index = logs.length; - } else { - // Binary search to find the insertion index. - int min = 0; - int max = logs.length; - while (min < max) { - final int mid = min + ((max - min) >> 1); - final AliceLog item = logs[mid]; - if (log.timestamp.isBefore(item.timestamp)) { - max = mid; - } else { - min = mid + 1; - } - } - assert(min == max, ''); - index = min; + final values = _logsSubject.value; + final count = values.length; + if (maximumSize != null && count >= maximumSize!) { + values.removeAt(0); } - int startIndex = 0; - if (maximumSize != null && logs.length.gte(maximumSize)) { - if (index == 0) return; - startIndex = logs.length - maximumSize! + 1; - } - _logs.value = [ - ...logs.sublist(startIndex, index), - log, - ...logs.sublist(index, logs.length), - ]; + values.add(log); + values.sort((log1, log2) => log1.timestamp.compareTo(log2.timestamp)); + _logsSubject.add(values); } /// Clears all logs. - void clearLogs() => _logs.value.clear(); + void clearLogs() => _logsSubject.add([]); /// Returns raw logs from Android via ADB. Future getAndroidRawLogs() async { diff --git a/packages/alice/lib/model/alice_http_call.dart b/packages/alice/lib/model/alice_http_call.dart index 675cf57f..55ca6cd9 100644 --- a/packages/alice/lib/model/alice_http_call.dart +++ b/packages/alice/lib/model/alice_http_call.dart @@ -5,13 +5,10 @@ import 'package:equatable/equatable.dart'; /// Definition of http calls data holder. class AliceHttpCall with EquatableMixin { - AliceHttpCall(this.id) { - loading = true; - createdTime = DateTime.now(); - } + AliceHttpCall(this.id); final int id; - late DateTime createdTime; + final DateTime createdTime = DateTime.now(); String client = ''; bool loading = true; bool secure = false; @@ -25,11 +22,6 @@ class AliceHttpCall with EquatableMixin { AliceHttpResponse? response; AliceHttpError? error; - void setResponse(AliceHttpResponse response) { - this.response = response; - loading = false; - } - @override List get props => [ id, diff --git a/packages/alice/lib/ui/calls_list/widget/alice_log_list_widget.dart b/packages/alice/lib/ui/calls_list/widget/alice_log_list_widget.dart index 2c83abce..c86edf03 100644 --- a/packages/alice/lib/ui/calls_list/widget/alice_log_list_widget.dart +++ b/packages/alice/lib/ui/calls_list/widget/alice_log_list_widget.dart @@ -12,13 +12,13 @@ import 'package:flutter/services.dart'; /// Widget which renders log list for calls list page. class AliceLogListWidget extends StatefulWidget { const AliceLogListWidget({ - required this.logsListenable, + required this.logsStream, required this.scrollController, required this.emptyWidget, super.key, }); - final ValueListenable> logsListenable; + final Stream>? logsStream; final ScrollController? scrollController; final Widget emptyWidget; @@ -32,9 +32,10 @@ class _AliceLogListWidgetState extends State { @override Widget build(BuildContext context) { - return ValueListenableBuilder>( - valueListenable: widget.logsListenable, - builder: (_, List logs, __) { + return StreamBuilder>( + stream: widget.logsStream, + builder: (context, snapshot) { + final logs = snapshot.data ?? []; if (logs.isEmpty) { return widget.emptyWidget; } diff --git a/packages/alice/lib/ui/calls_list/widget/alice_logs_screen.dart b/packages/alice/lib/ui/calls_list/widget/alice_logs_screen.dart index ed49e728..74a81703 100644 --- a/packages/alice/lib/ui/calls_list/widget/alice_logs_screen.dart +++ b/packages/alice/lib/ui/calls_list/widget/alice_logs_screen.dart @@ -26,7 +26,7 @@ class AliceLogsScreen extends StatelessWidget { emptyWidget: const AliceEmptyLogsWidget(), ) : AliceLogListWidget( - logsListenable: aliceLogger!.listenable, + logsStream: aliceLogger?.logsStream, scrollController: scrollController, emptyWidget: const AliceEmptyLogsWidget(), ) diff --git a/packages/alice/test/core/alice_logger_test.dart b/packages/alice/test/core/alice_logger_test.dart index a46e0ce5..c41be6a7 100644 --- a/packages/alice/test/core/alice_logger_test.dart +++ b/packages/alice/test/core/alice_logger_test.dart @@ -40,20 +40,5 @@ void main() { expect(aliceLogger.logs.isEmpty, true); }); - - test("should set maximum size", () { - final logs = [ - AliceLog(message: "test"), - AliceLog(message: "test2"), - ]; - - aliceLogger.addAll(logs); - - expect(aliceLogger.logs.length, 2); - - aliceLogger.maximumSize = 1; - - expect(aliceLogger.logs.length, 1); - }); }); } diff --git a/packages/alice_objectbox/lib/model/cached_alice_http_call.dart b/packages/alice_objectbox/lib/model/cached_alice_http_call.dart index 7616d7f4..baa8358a 100644 --- a/packages/alice_objectbox/lib/model/cached_alice_http_call.dart +++ b/packages/alice_objectbox/lib/model/cached_alice_http_call.dart @@ -107,12 +107,6 @@ class CachedAliceHttpCall implements AliceHttpCall { @internal final ToOne errorRel = ToOne(); - @override - void setResponse(AliceHttpResponse response) { - this.response = response; - loading = false; - } - @override List get props => [ id, From 3d34311c8846f21bc372782a25fb18246a4843e8 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 22:10:16 +0200 Subject: [PATCH 13/20] refactor: refactored codebase --- packages/alice/lib/core/alice_core.dart | 1 + packages/alice/lib/core/alice_storage.dart | 11 +++++++++++ packages/alice/lib/core/alice_store.dart | 3 --- .../alice_objectbox/lib/alice_objectbox_store.dart | 6 ++---- 4 files changed, 14 insertions(+), 7 deletions(-) delete mode 100644 packages/alice/lib/core/alice_store.dart diff --git a/packages/alice/lib/core/alice_core.dart b/packages/alice/lib/core/alice_core.dart index 8c8f8fe0..c9a1717a 100644 --- a/packages/alice/lib/core/alice_core.dart +++ b/packages/alice/lib/core/alice_core.dart @@ -54,6 +54,7 @@ class AliceCore { } } + /// Returns current configuration AliceConfiguration get configuration => _configuration; /// Set custom navigation key. This will help if there's route library. diff --git a/packages/alice/lib/core/alice_storage.dart b/packages/alice/lib/core/alice_storage.dart index d1808882..17b5f274 100644 --- a/packages/alice/lib/core/alice_storage.dart +++ b/packages/alice/lib/core/alice_storage.dart @@ -4,6 +4,7 @@ import 'dart:async' show FutureOr; import 'package:alice/model/alice_http_error.dart'; import 'package:alice/model/alice_http_response.dart'; +/// Definition of call stats. typedef AliceStats = ({ int total, int successes, @@ -12,22 +13,32 @@ typedef AliceStats = ({ int loading, }); +/// Definition of storage abstract interface class AliceStorage { + /// Stream of HTTP calls. abstract final Stream> callsStream; + /// Max calls number which should be stored. abstract final int maxCallsCount; + /// Returns all HTTP calls. List getCalls(); + /// Returns stats based on calls. AliceStats getStats(); + /// Searches for call with specific [requestId]. It may return null. AliceHttpCall? selectCall(int requestId); + /// Adds new call to calls list. FutureOr addCall(AliceHttpCall call); + /// Adds error to a specific call. FutureOr addError(AliceHttpError error, int requestId); + /// Adds response to a specific call. FutureOr addResponse(AliceHttpResponse response, int requestId); + /// Removes all calls. FutureOr removeCalls(); } diff --git a/packages/alice/lib/core/alice_store.dart b/packages/alice/lib/core/alice_store.dart deleted file mode 100644 index 1d97f0f9..00000000 --- a/packages/alice/lib/core/alice_store.dart +++ /dev/null @@ -1,3 +0,0 @@ -abstract interface class AliceStore { - void clear(); -} diff --git a/packages/alice_objectbox/lib/alice_objectbox_store.dart b/packages/alice_objectbox/lib/alice_objectbox_store.dart index 5f9ff667..623baff3 100644 --- a/packages/alice_objectbox/lib/alice_objectbox_store.dart +++ b/packages/alice_objectbox/lib/alice_objectbox_store.dart @@ -1,13 +1,12 @@ import 'dart:io' show Directory; -import 'package:alice/core/alice_store.dart'; import 'package:alice_objectbox/model/cached_alice_http_call.dart'; import 'package:alice_objectbox/objectbox.g.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; -/// Implementation of [AliceStore] using ObjectBox. -class AliceObjectBoxStore implements AliceStore { +/// Implementation of store for ObjectBox. +class AliceObjectBoxStore { AliceObjectBoxStore._create( this._store, { bool persistent = true, @@ -53,7 +52,6 @@ class AliceObjectBoxStore implements AliceStore { }; /// This will remove all the items from all the boxes - @override void clear() { for (final Box box in _boxes.values) { box.removeAll(); From 7d2fb46ebf19e9b34b0e98f66529a5eebef266a3 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Wed, 3 Jul 2024 22:11:46 +0200 Subject: [PATCH 14/20] refactor: refactored codebase --- packages/alice/lib/alice.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/alice/lib/alice.dart b/packages/alice/lib/alice.dart index 8321a9e4..cea943f8 100644 --- a/packages/alice/lib/alice.dart +++ b/packages/alice/lib/alice.dart @@ -6,7 +6,6 @@ import 'package:alice/model/alice_log.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; -export 'package:alice/core/alice_store.dart'; export 'package:alice/model/alice_log.dart'; export 'package:alice/core/alice_memory_storage.dart'; export 'package:alice/utils/alice_parser.dart'; From f16dff675a5e1150be81563ff594d1322754ebd9 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Thu, 4 Jul 2024 07:40:54 +0200 Subject: [PATCH 15/20] refactor: refactored codebase --- packages/alice/lib/core/alice_logger.dart | 6 ++-- .../alice/lib/core/alice_memory_storage.dart | 36 ++++++++++++------- .../alice/lib/core/alice_notification.dart | 7 ++-- packages/alice/lib/core/alice_storage.dart | 2 +- .../alice/lib/core/alice_translations.dart | 5 +++ packages/alice/lib/core/alice_utils.dart | 1 + .../lib/helper/alice_conversion_helper.dart | 24 ++++++++----- .../alice/lib/helper/alice_export_helper.dart | 3 +- .../alice/lib/helper/operating_system.dart | 6 ++++ .../lib/ui/common/alice_context_ext.dart | 3 ++ packages/alice/lib/utils/alice_parser.dart | 2 ++ .../alice_objectbox/lib/alice_objectbox.dart | 11 +++--- 12 files changed, 71 insertions(+), 35 deletions(-) diff --git a/packages/alice/lib/core/alice_logger.dart b/packages/alice/lib/core/alice_logger.dart index adb231ea..f166bbbb 100644 --- a/packages/alice/lib/core/alice_logger.dart +++ b/packages/alice/lib/core/alice_logger.dart @@ -10,10 +10,10 @@ class AliceLogger { final int? maximumSize; /// Subject which keeps logs. - final BehaviorSubject> _logsSubject = - BehaviorSubject.seeded([]); + final BehaviorSubject> _logsSubject; - AliceLogger({required this.maximumSize}); + AliceLogger({required this.maximumSize}) + : _logsSubject = BehaviorSubject.seeded([]); /// Getter of stream of logs Stream> get logsStream => _logsSubject.stream; diff --git a/packages/alice/lib/core/alice_memory_storage.dart b/packages/alice/lib/core/alice_memory_storage.dart index c3640025..48e74daf 100644 --- a/packages/alice/lib/core/alice_memory_storage.dart +++ b/packages/alice/lib/core/alice_memory_storage.dart @@ -9,23 +9,28 @@ import 'package:alice/utils/num_comparison.dart'; import 'package:collection/collection.dart'; import 'package:rxdart/subjects.dart'; +/// Storage which uses memory to store calls data. It's a default storage +/// method. class AliceMemoryStorage implements AliceStorage { AliceMemoryStorage({ required this.maxCallsCount, - }) : callsSubject = BehaviorSubject.seeded([]), + }) : _callsSubject = BehaviorSubject.seeded([]), assert(maxCallsCount > 0, 'Max calls count should be greater than 0'); - @override final int maxCallsCount; - final BehaviorSubject> callsSubject; + /// Subject which stores all HTTP calls. + final BehaviorSubject> _callsSubject; + /// Stream which returns all HTTP calls on change. @override - Stream> get callsStream => callsSubject.stream; + Stream> get callsStream => _callsSubject.stream; + /// Returns all HTTP calls. @override - List getCalls() => callsSubject.value; + List getCalls() => _callsSubject.value; + /// Returns stats based on calls. @override AliceStats getStats() { final List calls = getCalls(); @@ -57,20 +62,22 @@ class AliceMemoryStorage implements AliceStorage { ); } + /// Adds new call to calls list. @override void addCall(AliceHttpCall call) { - final int callsCount = callsSubject.value.length; + final int callsCount = _callsSubject.value.length; if (callsCount >= maxCallsCount) { - final List originalCalls = callsSubject.value; + final List originalCalls = _callsSubject.value; originalCalls.removeAt(0); originalCalls.add(call); - callsSubject.add(originalCalls); + _callsSubject.add(originalCalls); } else { - callsSubject.add([...callsSubject.value, call]); + _callsSubject.add([..._callsSubject.value, call]); } } + /// Adds error to a specific call. @override void addError(AliceHttpError error, int requestId) { final AliceHttpCall? selectedCall = selectCall(requestId); @@ -80,9 +87,10 @@ class AliceMemoryStorage implements AliceStorage { } selectedCall.error = error; - callsSubject.add([...callsSubject.value]); + _callsSubject.add([..._callsSubject.value]); } + /// Adds response to a specific call. @override void addResponse(AliceHttpResponse response, int requestId) { final AliceHttpCall? selectedCall = selectCall(requestId); @@ -97,13 +105,15 @@ class AliceMemoryStorage implements AliceStorage { ..duration = response.time.millisecondsSinceEpoch - (selectedCall.request?.time.millisecondsSinceEpoch ?? 0); - callsSubject.add([...callsSubject.value]); + _callsSubject.add([..._callsSubject.value]); } + /// Removes all calls. @override - void removeCalls() => callsSubject.add([]); + void removeCalls() => _callsSubject.add([]); + /// Searches for call with specific [requestId]. It may return null. @override - AliceHttpCall? selectCall(int requestId) => callsSubject.value + AliceHttpCall? selectCall(int requestId) => _callsSubject.value .firstWhereOrNull((AliceHttpCall call) => call.id == requestId); } diff --git a/packages/alice/lib/core/alice_notification.dart b/packages/alice/lib/core/alice_notification.dart index 4e539029..555a0d0e 100644 --- a/packages/alice/lib/core/alice_notification.dart +++ b/packages/alice/lib/core/alice_notification.dart @@ -8,8 +8,9 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart'; /// Helper for displaying local notifications. class AliceNotification { - static const _payload = 'Alice'; - static const _channel = 'Alice'; + static const String _payload = 'Alice'; + static const String _channel = 'Alice'; + static const String _callCount = '[callCount]'; /// Notification plugin instance FlutterLocalNotificationsPlugin? _flutterLocalNotificationsPlugin; @@ -141,7 +142,7 @@ class AliceNotification { 0, context .i18n(AliceTranslationKey.notificationTotalRequests) - .replaceAll("[callCount]", stats.total.toString()), + .replaceAll(_callCount, stats.total.toString()), message, _notificationDetails, payload: _payload, diff --git a/packages/alice/lib/core/alice_storage.dart b/packages/alice/lib/core/alice_storage.dart index 17b5f274..0f7f7f31 100644 --- a/packages/alice/lib/core/alice_storage.dart +++ b/packages/alice/lib/core/alice_storage.dart @@ -15,7 +15,7 @@ typedef AliceStats = ({ /// Definition of storage abstract interface class AliceStorage { - /// Stream of HTTP calls. + /// Stream which returns all HTTP calls on change. abstract final Stream> callsStream; /// Max calls number which should be stored. diff --git a/packages/alice/lib/core/alice_translations.dart b/packages/alice/lib/core/alice_translations.dart index 0c6f4300..e80f0887 100644 --- a/packages/alice/lib/core/alice_translations.dart +++ b/packages/alice/lib/core/alice_translations.dart @@ -1,8 +1,11 @@ import 'package:alice/model/alice_translation.dart'; +/// Class used to manage translations in Alice. class AliceTranslations { + /// Contains list of translation data for all languages. static final List _translations = _initialise(); + /// Initialises translation data for all languages. static List _initialise() { List translations = []; translations.add(_buildEnTranslations()); @@ -10,6 +13,7 @@ class AliceTranslations { return translations; } + /// Builds [AliceTranslationData] for english language. static AliceTranslationData _buildEnTranslations() { return AliceTranslationData(languageCode: "en", values: { AliceTranslationKey.alice: "Alice", @@ -173,6 +177,7 @@ class AliceTranslations { }); } + /// Builds [AliceTranslationData] for polish language. static AliceTranslationData _buildPlTranslations() { return AliceTranslationData(languageCode: "pl", values: { AliceTranslationKey.alice: "Alice", diff --git a/packages/alice/lib/core/alice_utils.dart b/packages/alice/lib/core/alice_utils.dart index ee15a3cf..74b1ef61 100644 --- a/packages/alice/lib/core/alice_utils.dart +++ b/packages/alice/lib/core/alice_utils.dart @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart' show kReleaseMode, debugPrint; /// Utils used across multiple classes in app. class AliceUtils { + /// Logs debug text. static void log(String logMessage) { if (!kReleaseMode) { debugPrint(logMessage); diff --git a/packages/alice/lib/helper/alice_conversion_helper.dart b/packages/alice/lib/helper/alice_conversion_helper.dart index 0b80608c..1801993c 100644 --- a/packages/alice/lib/helper/alice_conversion_helper.dart +++ b/packages/alice/lib/helper/alice_conversion_helper.dart @@ -4,14 +4,20 @@ class AliceConversionHelper { static const int _megabyteAsByte = 1000000; static const int _secondAsMillisecond = 1000; static const int _minuteAsMillisecond = 60000; + static const String _bytes = "B"; + static const String _kiloBytes = "kB"; + static const String _megaBytes = "MB"; + static const String _milliseconds = "ms"; + static const String _seconds = "s"; + static const String _minutes = "min"; /// Format bytes text static String formatBytes(int bytes) => switch (bytes) { - int bytes when bytes < 0 => '-1 B', - int bytes when bytes <= _kilobyteAsByte => '$bytes B', + int bytes when bytes < 0 => '-1 $_bytes', + int bytes when bytes <= _kilobyteAsByte => '$bytes $_bytes', int bytes when bytes <= _megabyteAsByte => - '${_formatDouble(bytes / _kilobyteAsByte)} kB', - _ => '${_formatDouble(bytes / _megabyteAsByte)} MB', + '${_formatDouble(bytes / _kilobyteAsByte)} $_kiloBytes', + _ => '${_formatDouble(bytes / _megabyteAsByte)} $_megaBytes', }; /// Formats double with two numbers after dot. @@ -20,18 +26,18 @@ class AliceConversionHelper { /// Format time in milliseconds static String formatTime(int timeInMillis) { if (timeInMillis < 0) { - return '-1 ms'; + return '-1 $_milliseconds'; } if (timeInMillis <= _secondAsMillisecond) { - return '$timeInMillis ms'; + return '$timeInMillis $_milliseconds'; } if (timeInMillis <= _minuteAsMillisecond) { - return '${_formatDouble(timeInMillis / _secondAsMillisecond)} s'; + return '${_formatDouble(timeInMillis / _secondAsMillisecond)} $_seconds'; } final Duration duration = Duration(milliseconds: timeInMillis); - return '${duration.inMinutes} min ${duration.inSeconds.remainder(60)} s ' - '${duration.inMilliseconds.remainder(1000)} ms'; + return '${duration.inMinutes} $_minutes ${duration.inSeconds.remainder(60)} $_seconds ' + '${duration.inMilliseconds.remainder(1000)} $_milliseconds'; } } diff --git a/packages/alice/lib/helper/alice_export_helper.dart b/packages/alice/lib/helper/alice_export_helper.dart index 7e956335..2c8702a3 100644 --- a/packages/alice/lib/helper/alice_export_helper.dart +++ b/packages/alice/lib/helper/alice_export_helper.dart @@ -20,6 +20,7 @@ import 'package:share_plus/share_plus.dart'; class AliceExportHelper { static const JsonEncoder _encoder = JsonEncoder.withIndent(' '); + static const String _fileName = "alice_log"; /// Format log based on [call] and tries to share it. static Future shareCall({ @@ -97,7 +98,7 @@ class AliceExportHelper { final Directory externalDir = await getApplicationCacheDirectory(); final String fileName = - 'alice_log_${DateTime.now().millisecondsSinceEpoch}.txt'; + '${_fileName}_${DateTime.now().millisecondsSinceEpoch}.txt'; final File file = File('${externalDir.path}/$fileName')..createSync(); final IOSink sink = file.openWrite(mode: FileMode.append) ..write(await _buildAliceLog(context: context)); diff --git a/packages/alice/lib/helper/operating_system.dart b/packages/alice/lib/helper/operating_system.dart index 44b5941a..21200b61 100644 --- a/packages/alice/lib/helper/operating_system.dart +++ b/packages/alice/lib/helper/operating_system.dart @@ -9,15 +9,21 @@ abstract class OperatingSystem { static const String macos = 'macos'; static const String windows = 'windows'; + /// Flag which determines whether current platform is Android. static bool get isAndroid => defaultTargetPlatform == TargetPlatform.android; + /// Flag which determines whether current platform is iOS. static bool get isIOS => defaultTargetPlatform == TargetPlatform.iOS; + /// Flag which determines whether current platform is MacOS. static bool get isMacOS => defaultTargetPlatform == TargetPlatform.macOS; + /// Flag which determines whether current platform is Windows. static bool get isWindows => defaultTargetPlatform == TargetPlatform.windows; + /// Flag which determines whether current platform is Linux. static bool get isLinux => defaultTargetPlatform == TargetPlatform.linux; + /// Flag which determines whether current platform is Fuchsia. static bool get isFuchsia => defaultTargetPlatform == TargetPlatform.fuchsia; } diff --git a/packages/alice/lib/ui/common/alice_context_ext.dart b/packages/alice/lib/ui/common/alice_context_ext.dart index 30022cd6..7aa20c30 100644 --- a/packages/alice/lib/ui/common/alice_context_ext.dart +++ b/packages/alice/lib/ui/common/alice_context_ext.dart @@ -2,7 +2,10 @@ import 'package:alice/model/alice_translation.dart'; import 'package:alice/core/alice_translations.dart'; import 'package:flutter/material.dart'; +/// Extension for [BuildContext]. extension AliceContextExt on BuildContext { + /// Tries to translate given key based on current language code collected from + /// locale. If it fails to translate [key], it will return [key] itself. String i18n(AliceTranslationKey key) { try { final locale = Localizations.localeOf(this); diff --git a/packages/alice/lib/utils/alice_parser.dart b/packages/alice/lib/utils/alice_parser.dart index df5874b7..e4ebdcbe 100644 --- a/packages/alice/lib/utils/alice_parser.dart +++ b/packages/alice/lib/utils/alice_parser.dart @@ -94,6 +94,8 @@ class AliceParser { return context.i18n(AliceTranslationKey.unknown); } + /// Parses headers from [dynamic] to [Map], if possible. + /// Otherwise it will throw error. static Map parseHeaders({dynamic headers}) { if (headers is Map) { return headers; diff --git a/packages/alice_objectbox/lib/alice_objectbox.dart b/packages/alice_objectbox/lib/alice_objectbox.dart index 23128bc4..c868d621 100644 --- a/packages/alice_objectbox/lib/alice_objectbox.dart +++ b/packages/alice_objectbox/lib/alice_objectbox.dart @@ -119,11 +119,12 @@ class AliceObjectBox implements AliceStorage { .count(), errors: (_store.httpCalls.query() ..link( - CachedAliceHttpCall_.responseRel, - CachedAliceHttpResponse_.status - .greaterOrEqual(400) - .and(CachedAliceHttpResponse_.status.lessThan(600)), - )) + CachedAliceHttpCall_.responseRel, + CachedAliceHttpResponse_.status + .greaterOrEqual(400) + .and(CachedAliceHttpResponse_.status.lessThan(600)) + .and(CachedAliceHttpResponse_.status.equals(-1)) + .and(CachedAliceHttpResponse_.status.equals(0)))) .build() .count(), loading: _store.httpCalls From 4e6a5957e3f9aafbcbe14e43efc55cbc10f3b389 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Thu, 4 Jul 2024 20:52:29 +0200 Subject: [PATCH 16/20] refactor: refactored codebase --- packages/alice/lib/core/alice_core.dart | 2 - .../alice/lib/helper/alice_export_helper.dart | 2 +- .../page/alice_call_details_page.dart | 2 + .../widget/alice_call_response_screen.dart | 28 +++++- .../widget/alice_calls_list_screen.dart | 1 + .../widget/alice_inspector_screen.dart | 2 + .../widget/alice_raw_log_list_widger.dart | 12 ++- packages/alice/lib/utils/curl.dart | 97 ++++++++++--------- packages/alice/lib/utils/shake_detector.dart | 8 +- 9 files changed, 91 insertions(+), 63 deletions(-) diff --git a/packages/alice/lib/core/alice_core.dart b/packages/alice/lib/core/alice_core.dart index c9a1717a..494b776f 100644 --- a/packages/alice/lib/core/alice_core.dart +++ b/packages/alice/lib/core/alice_core.dart @@ -15,8 +15,6 @@ import 'package:alice/ui/common/alice_navigation.dart'; import 'package:alice/utils/shake_detector.dart'; import 'package:flutter/material.dart'; -typedef AliceOnCallsChanged = Future Function(List? calls); - class AliceCore { /// Configuration of Alice late AliceConfiguration _configuration; diff --git a/packages/alice/lib/helper/alice_export_helper.dart b/packages/alice/lib/helper/alice_export_helper.dart index 2c8702a3..5499937e 100644 --- a/packages/alice/lib/helper/alice_export_helper.dart +++ b/packages/alice/lib/helper/alice_export_helper.dart @@ -200,7 +200,7 @@ class AliceExportHelper { '--------------------------------------------\n', '${context.i18n(AliceTranslationKey.saveLogCurl)}\n', '--------------------------------------------\n', - getCurlCommand(call), + Curl.getCurlCommand(call), '\n', '==============================================\n', '\n', diff --git a/packages/alice/lib/ui/call_details/page/alice_call_details_page.dart b/packages/alice/lib/ui/call_details/page/alice_call_details_page.dart index 5475384a..26c3b8f9 100644 --- a/packages/alice/lib/ui/call_details/page/alice_call_details_page.dart +++ b/packages/alice/lib/ui/call_details/page/alice_call_details_page.dart @@ -103,6 +103,8 @@ class _AliceCallDetailsPageState extends State ); } + /// Called when share button has been pressed. It encodes the [widget.call] + /// and tries to invoke system action to share it. void _shareCall() async { await AliceExportHelper.shareCall(context: context, call: widget.call); } diff --git a/packages/alice/lib/ui/call_details/widget/alice_call_response_screen.dart b/packages/alice/lib/ui/call_details/widget/alice_call_response_screen.dart index 17289eae..366d5965 100644 --- a/packages/alice/lib/ui/call_details/widget/alice_call_response_screen.dart +++ b/packages/alice/lib/ui/call_details/widget/alice_call_response_screen.dart @@ -72,6 +72,7 @@ class _GeneralDataColumn extends StatelessWidget { } } +/// Widget which renders column with headers of [call]. class _HeaderDataColumn extends StatelessWidget { final AliceHttpCall call; @@ -99,6 +100,7 @@ class _HeaderDataColumn extends StatelessWidget { } } +/// Widget which renders column with body of [call]. class _BodyDataColumn extends StatefulWidget { const _BodyDataColumn({required this.call}); @@ -148,18 +150,21 @@ class _BodyDataColumnState extends State<_BodyDataColumn> { } } + /// Checks whether content type of response is image. bool _isImageResponse() { return _getContentTypeOfResponse()! .toLowerCase() .contains(_imageContentType); } + /// Checks whether content type of response is video bool _isVideoResponse() { return _getContentTypeOfResponse()! .toLowerCase() .contains(_videoContentType); } + /// Checks whether content type of response is text. bool _isTextResponse() { final responseContentTypeLowerCase = _getContentTypeOfResponse()!.toLowerCase(); @@ -169,20 +174,24 @@ class _BodyDataColumnState extends State<_BodyDataColumn> { responseContentTypeLowerCase.contains(_textContentType); } + /// Parses headers and returns content type of response. It may return null. String? _getContentTypeOfResponse() { return AliceParser.getContentType( context: context, headers: call.response?.headers); } + /// Checks whether response body is large (more than [_largeOutputSize]. bool _isLargeResponseBody() => call.response?.body.toString().length.gt(_largeOutputSize) ?? false; + /// Called when show large body has been pressed. void onShowLargeBodyPressed() { setState(() { _showLargeBody = true; }); } + /// Called when show unsupported body has been pressed. void onShowUnsupportedBodyPressed() { setState(() { _showUnsupportedBody = true; @@ -190,6 +199,7 @@ class _BodyDataColumnState extends State<_BodyDataColumn> { } } +/// Widget which renders body as image. class _ImageBody extends StatelessWidget { const _ImageBody({ required this.call, @@ -235,6 +245,7 @@ class _ImageBody extends StatelessWidget { ); } + /// Builds request headers to access the image. Map _buildRequestHeaders() { final requestHeaders = {}; if (call.request?.headers != null) { @@ -251,6 +262,7 @@ class _ImageBody extends StatelessWidget { } } +/// Widget which renders large body as a text. class _LargeTextBody extends StatelessWidget { const _LargeTextBody({ required this.showLargeBody, @@ -293,6 +305,7 @@ class _LargeTextBody extends StatelessWidget { } } +/// Widget which renders body as a text. class _TextBody extends StatelessWidget { const _TextBody({required this.call}); @@ -313,6 +326,7 @@ class _TextBody extends StatelessWidget { } } +/// Widget which renders body as video. class _VideoBody extends StatelessWidget { const _VideoBody({required this.call}); @@ -344,11 +358,15 @@ class _VideoBody extends StatelessWidget { } } +/// Widget which renders unknown body message. class _UnknownBody extends StatelessWidget { - const _UnknownBody( - {required this.call, - required this.showUnsupportedBody, - required this.onShowUnsupportedBodyPressed}); + static const _contentType = "[contentType]"; + + const _UnknownBody({ + required this.call, + required this.showUnsupportedBody, + required this.onShowUnsupportedBodyPressed, + }); final AliceHttpCall call; final bool showUnsupportedBody; @@ -379,7 +397,7 @@ class _UnknownBody extends StatelessWidget { value: context .i18n(AliceTranslationKey.callResponseBodyUnknown) .replaceAll( - "[contentType]", + _contentType, contentType, ), ), diff --git a/packages/alice/lib/ui/calls_list/widget/alice_calls_list_screen.dart b/packages/alice/lib/ui/calls_list/widget/alice_calls_list_screen.dart index 9ed7097e..4bd970a6 100644 --- a/packages/alice/lib/ui/calls_list/widget/alice_calls_list_screen.dart +++ b/packages/alice/lib/ui/calls_list/widget/alice_calls_list_screen.dart @@ -19,6 +19,7 @@ class AliceCallsListScreen extends StatelessWidget { final bool sortAscending; final void Function(AliceHttpCall) onListItemClicked; + /// Returns sorted calls based [sortOption] and [sortAscending]. List get _sortedCalls => switch (sortOption) { AliceCallsListSortOption.time => sortAscending ? (calls diff --git a/packages/alice/lib/ui/calls_list/widget/alice_inspector_screen.dart b/packages/alice/lib/ui/calls_list/widget/alice_inspector_screen.dart index a90b8c6a..662a2a4f 100644 --- a/packages/alice/lib/ui/calls_list/widget/alice_inspector_screen.dart +++ b/packages/alice/lib/ui/calls_list/widget/alice_inspector_screen.dart @@ -5,6 +5,8 @@ import 'package:alice/ui/calls_list/widget/alice_calls_list_screen.dart'; import 'package:alice/ui/calls_list/widget/alice_empty_logs_widget.dart'; import 'package:flutter/material.dart'; +/// Screen which is hosted in calls list page. It displays HTTP calls. It allows +/// to search call and sort items based on provided criteria. class AliceInspectorScreen extends StatefulWidget { const AliceInspectorScreen({ super.key, diff --git a/packages/alice/lib/ui/calls_list/widget/alice_raw_log_list_widger.dart b/packages/alice/lib/ui/calls_list/widget/alice_raw_log_list_widger.dart index 58537d7f..2bfcfd37 100644 --- a/packages/alice/lib/ui/calls_list/widget/alice_raw_log_list_widger.dart +++ b/packages/alice/lib/ui/calls_list/widget/alice_raw_log_list_widger.dart @@ -31,8 +31,10 @@ class AliceRawLogListWidget extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(8), child: InkWell( - onLongPress: () => - _copyToClipboard(snapshot.data ?? '', context), + onLongPress: () => _copyToClipboard( + context: context, + text: snapshot.data ?? '', + ), child: Text( snapshot.data ?? '', style: const TextStyle(fontSize: 10), @@ -49,7 +51,11 @@ class AliceRawLogListWidget extends StatelessWidget { ); } - Future _copyToClipboard(String text, BuildContext context) async { + /// Copies provided text to clipboard and displays info about it. + Future _copyToClipboard({ + required BuildContext context, + required String text, + }) async { await Clipboard.setData(ClipboardData(text: text)); if (context.mounted) { diff --git a/packages/alice/lib/utils/curl.dart b/packages/alice/lib/utils/curl.dart index ad4e980d..48ffcaef 100644 --- a/packages/alice/lib/utils/curl.dart +++ b/packages/alice/lib/utils/curl.dart @@ -2,59 +2,62 @@ import 'dart:io' show HttpHeaders; import 'package:alice/model/alice_http_call.dart'; -String getCurlCommand(AliceHttpCall call) { - bool compressed = false; - final StringBuffer curlCmd = StringBuffer('curl'); - - curlCmd.write(' -X ${call.method}'); +class Curl { + /// Builds Curl command based on [call] instance. + static String getCurlCommand(AliceHttpCall call) { + bool compressed = false; + final StringBuffer curlCmd = StringBuffer('curl'); + + curlCmd.write(' -X ${call.method}'); + + for (final MapEntry header + in call.request?.headers.entries ?? []) { + if (header.key.toLowerCase() == HttpHeaders.acceptEncodingHeader && + header.value.toString().toLowerCase() == 'gzip') { + compressed = true; + } - for (final MapEntry header - in call.request?.headers.entries ?? []) { - if (header.key.toLowerCase() == HttpHeaders.acceptEncodingHeader && - header.value.toString().toLowerCase() == 'gzip') { - compressed = true; + curlCmd.write(' -H "${header.key}: ${header.value}"'); } - curlCmd.write(' -H "${header.key}: ${header.value}"'); - } - - final String? requestBody = call.request?.body.toString(); - if (requestBody?.isNotEmpty ?? false) { - // try to keep to a single line and use a subshell to preserve any line - // breaks - curlCmd.write(" --data \$'${requestBody?.replaceAll("\n", r"\n")}'"); - } + final String? requestBody = call.request?.body.toString(); + if (requestBody?.isNotEmpty ?? false) { + // try to keep to a single line and use a subshell to preserve any line + // breaks + curlCmd.write(" --data \$'${requestBody?.replaceAll("\n", r"\n")}'"); + } - final Map? queryParamMap = call.request?.queryParameters; - int paramCount = queryParamMap?.keys.length ?? 0; - final StringBuffer queryParams = StringBuffer(); - - if (paramCount > 0) { - queryParams.write('?'); - for (final MapEntry queryParam - in queryParamMap?.entries ?? []) { - queryParams.write('${queryParam.key}=${queryParam.value}'); - paramCount--; - if (paramCount > 0) { - queryParams.write('&'); + final Map? queryParamMap = call.request?.queryParameters; + int paramCount = queryParamMap?.keys.length ?? 0; + final StringBuffer queryParams = StringBuffer(); + + if (paramCount > 0) { + queryParams.write('?'); + for (final MapEntry queryParam + in queryParamMap?.entries ?? []) { + queryParams.write('${queryParam.key}=${queryParam.value}'); + paramCount--; + if (paramCount > 0) { + queryParams.write('&'); + } } } - } - // If server already has http(s) don't add it again - if (call.server.contains('http://') || call.server.contains('https://')) { - // ignore: join_return_with_assignment - curlCmd.write( - "${compressed ? " --compressed " : " "}" - "${"'${call.server}${call.endpoint}$queryParams'"}", - ); - } else { - // ignore: join_return_with_assignment - curlCmd.write( - "${compressed ? " --compressed " : " "}" - "${"'${call.secure ? 'https://' : 'http://'}${call.server}${call.endpoint}$queryParams'"}", - ); - } + // If server already has http(s) don't add it again + if (call.server.contains('http://') || call.server.contains('https://')) { + // ignore: join_return_with_assignment + curlCmd.write( + "${compressed ? " --compressed " : " "}" + "${"'${call.server}${call.endpoint}$queryParams'"}", + ); + } else { + // ignore: join_return_with_assignment + curlCmd.write( + "${compressed ? " --compressed " : " "}" + "${"'${call.secure ? 'https://' : 'http://'}${call.server}${call.endpoint}$queryParams'"}", + ); + } - return curlCmd.toString(); + return curlCmd.toString(); + } } diff --git a/packages/alice/lib/utils/shake_detector.dart b/packages/alice/lib/utils/shake_detector.dart index 5ab13387..4097d4ab 100644 --- a/packages/alice/lib/utils/shake_detector.dart +++ b/packages/alice/lib/utils/shake_detector.dart @@ -1,7 +1,3 @@ -///Code from https://github.com/deven98/shake -///Seems to be not maintained for almost 2 years... (01.03.2021). -library; - import 'dart:async'; import 'dart:math'; @@ -85,10 +81,12 @@ class ShakeDetector { /// Stops listening to accelerometer events void stopListening() { - streamSubscription?.cancel(); + dispose(); } + /// Disposes all subscriptions. void dispose() { streamSubscription?.cancel(); + streamSubscription = null; } } From ed56220c8973003badc5ea4b77a62a00bba65115 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Sun, 7 Jul 2024 09:30:39 +0200 Subject: [PATCH 17/20] fix: fixed PR comments --- docs/config.md | 12 +--- docs/install.md | 1 + examples/alice_chopper/lib/main.dart | 3 +- examples/alice_dio/lib/main.dart | 3 +- examples/alice_http/lib/main.dart | 3 +- examples/alice_http_client/lib/main.dart | 3 +- examples/alice_objectbox/lib/main.dart | 13 ++-- packages/alice/CHANGELOG.md | 2 +- packages/alice/lib/core/alice_core.dart | 15 +++-- packages/alice/lib/core/alice_logger.dart | 9 +-- .../alice/lib/core/alice_memory_storage.dart | 11 ++-- .../alice/lib/core/alice_translations.dart | 2 + .../alice/lib/model/alice_configuration.dart | 30 +++++---- .../alice/lib/model/alice_translation.dart | 1 + .../widget/alice_error_logs_widget.dart | 34 ++++++++++ .../widget/alice_log_list_widget.dart | 17 ++++- .../calls_list/widget/alice_logs_screen.dart | 2 - .../widget/alice_raw_log_list_widger.dart | 62 +++++++++++-------- 18 files changed, 142 insertions(+), 81 deletions(-) create mode 100644 packages/alice/lib/ui/calls_list/widget/alice_error_logs_widget.dart diff --git a/docs/config.md b/docs/config.md index f8e40b09..91d08d89 100644 --- a/docs/config.md +++ b/docs/config.md @@ -10,9 +10,7 @@ Alice alice = Alice(); 2. Add navigator key to your application: ```dart -MaterialApp -( -navigatorKey: alice.getNavigatorKey(), home: ...) +MaterialApp(navigatorKey: alice.getNavigatorKey(), home: ...); ``` You need to add this navigator key in order to show inspector UI. @@ -26,10 +24,7 @@ Alice alice = Alice(configuration: AliceConfiguration(navigatorKey: yourNavigato If you need to pass navigatorKey lazily, you can use: ```dart -alice.setNavigatorKey -( -yourNavigatorKeyHere -); +alice.setNavigatorKey(yourNavigatorKeyHere); ``` This is minimal configuration required to run Alice. Can set optional settings in Alice constructor, @@ -61,8 +56,7 @@ value is @mipmap/ic_launcher. ```dart -Alice alice = Alice( - configuration: AliceConfiguration(notificationIcon: "myNotificationIconResourceName")); +Alice alice = Alice(configuration: AliceConfiguration(notificationIcon: "myNotificationIconResourceName")); ``` If you want to change the Directionality of Alice, you can use the `directionality` parameter. If diff --git a/docs/install.md b/docs/install.md index d711a553..caf80249 100644 --- a/docs/install.md +++ b/docs/install.md @@ -43,6 +43,7 @@ dependencies: ```yaml dependencies: + objectbox: any alice_objectbox: ^1.0.1 ``` diff --git a/examples/alice_chopper/lib/main.dart b/examples/alice_chopper/lib/main.dart index e9570c70..fce75b50 100644 --- a/examples/alice_chopper/lib/main.dart +++ b/examples/alice_chopper/lib/main.dart @@ -36,7 +36,8 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { final AliceChopperAdapter _aliceChopperAdapter = AliceChopperAdapter(); - late final Alice _alice = Alice(configuration: AliceConfiguration()) + final configuration = AliceConfiguration(); + late final Alice _alice = Alice(configuration: configuration) ..addAdapter(_aliceChopperAdapter); late final ChopperClient _chopper = ChopperClient( diff --git a/examples/alice_dio/lib/main.dart b/examples/alice_dio/lib/main.dart index 7b0b62a7..d85883b2 100644 --- a/examples/alice_dio/lib/main.dart +++ b/examples/alice_dio/lib/main.dart @@ -20,7 +20,8 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { late final AliceDioAdapter _aliceDioAdapter = AliceDioAdapter(); - late final Alice _alice = Alice(configuration: AliceConfiguration()) + final configuration = AliceConfiguration(); + late final Alice _alice = Alice(configuration: configuration) ..addAdapter(_aliceDioAdapter); late final Dio _dio = Dio(BaseOptions(followRedirects: false)) diff --git a/examples/alice_http/lib/main.dart b/examples/alice_http/lib/main.dart index d69be5a6..249f6421 100644 --- a/examples/alice_http/lib/main.dart +++ b/examples/alice_http/lib/main.dart @@ -17,7 +17,8 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { late final AliceHttpAdapter _aliceHttpAdapter = AliceHttpAdapter(); - late final Alice _alice = Alice(configuration: AliceConfiguration()) + final configuration = AliceConfiguration(); + late final Alice _alice = Alice(configuration: configuration) ..addAdapter(_aliceHttpAdapter); @override diff --git a/examples/alice_http_client/lib/main.dart b/examples/alice_http_client/lib/main.dart index cc9ffec8..0302e699 100644 --- a/examples/alice_http_client/lib/main.dart +++ b/examples/alice_http_client/lib/main.dart @@ -22,7 +22,8 @@ class _MyAppState extends State { late final AliceHttpClientAdapter _httpClientAdapter = AliceHttpClientAdapter(); - late final Alice _alice = Alice(configuration: AliceConfiguration()) + final configuration = AliceConfiguration(); + late final Alice _alice = Alice(configuration: configuration) ..addAdapter(_httpClientAdapter); @override diff --git a/examples/alice_objectbox/lib/main.dart b/examples/alice_objectbox/lib/main.dart index e7f5e0f7..efbf2013 100644 --- a/examples/alice_objectbox/lib/main.dart +++ b/examples/alice_objectbox/lib/main.dart @@ -35,13 +35,14 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { late final AliceHttpAdapter _aliceHttpAdapter = AliceHttpAdapter(); - late final Alice _alice = Alice( - configuration: AliceConfiguration( - storage: AliceObjectBox( - store: widget.store, - maxCallsCount: 1000, - ), + late final configuration = AliceConfiguration( + storage: AliceObjectBox( + store: widget.store, + maxCallsCount: 1000, ), + ); + late final Alice _alice = Alice( + configuration: configuration )..addAdapter(_aliceHttpAdapter); @override diff --git a/packages/alice/CHANGELOG.md b/packages/alice/CHANGELOG.md index 490cba1f..5bb93eed 100644 --- a/packages/alice/CHANGELOG.md +++ b/packages/alice/CHANGELOG.md @@ -1,6 +1,6 @@ # 1.0.0-dev.10 -* [BREAKING_CHANGE] Removed maxCallsCount. To change call count, use `storage` constructor parameter +* [BREAKING_CHANGE] Removed `maxCallsCount`. To change call count, use `storage` constructor parameter with call count. * [BREAKING_CHANGE] Replaced configuration parameter of Alice with `AliceConfiguration`. * Fixed issue with invalid count of calls in notification. diff --git a/packages/alice/lib/core/alice_core.dart b/packages/alice/lib/core/alice_core.dart index 494b776f..51b2473d 100644 --- a/packages/alice/lib/core/alice_core.dart +++ b/packages/alice/lib/core/alice_core.dart @@ -57,7 +57,7 @@ class AliceCore { /// Set custom navigation key. This will help if there's route library. void setNavigatorKey(GlobalKey navigatorKey) { - _configuration = _configuration.copyWith(newNavigatorKey: navigatorKey); + _configuration = _configuration.copyWith(navigatorKey: navigatorKey); } /// Dispose subjects and subscriptions @@ -79,7 +79,7 @@ class AliceCore { /// Opens Http calls inspector. This will navigate user to the new fullscreen /// page where all listened http calls can be viewed. - void navigateToCallListScreen() { + Future navigateToCallListScreen() async { final BuildContext? context = getContext(); if (context == null) { AliceUtils.log( @@ -90,8 +90,8 @@ class AliceCore { } if (!_isInspectorOpened) { _isInspectorOpened = true; - AliceNavigation.navigateToCallsList(core: this) - .then((_) => _isInspectorOpened = false); + await AliceNavigation.navigateToCallsList(core: this); + _isInspectorOpened = false; } } @@ -127,10 +127,9 @@ class AliceCore { List getCalls() => _configuration.aliceStorage.getCalls(); /// Save all calls to file. - Future saveCallsToFile(BuildContext context) { - return AliceExportHelper.saveCallsToFile( - context, _configuration.aliceStorage.getCalls()); - } + Future saveCallsToFile(BuildContext context) => + AliceExportHelper.saveCallsToFile( + context, _configuration.aliceStorage.getCalls()); /// Adds new log to Alice logger. void addLog(AliceLog log) => _configuration.aliceLogger.add(log); diff --git a/packages/alice/lib/core/alice_logger.dart b/packages/alice/lib/core/alice_logger.dart index f166bbbb..77d9d3ee 100644 --- a/packages/alice/lib/core/alice_logger.dart +++ b/packages/alice/lib/core/alice_logger.dart @@ -2,12 +2,13 @@ import 'dart:io' show Process, ProcessResult; import 'package:alice/helper/operating_system.dart'; import 'package:alice/model/alice_log.dart'; +import 'package:alice/utils/num_comparison.dart'; import 'package:rxdart/rxdart.dart'; /// Logger used to handle logs from application. class AliceLogger { - /// Maximum logs size. If null, logs will be not rotated. - final int? maximumSize; + /// Maximum logs size. If 0, logs will be not rotated. + final int maximumSize; /// Subject which keeps logs. final BehaviorSubject> _logsSubject; @@ -22,7 +23,7 @@ class AliceLogger { List get logs => _logsSubject.value; /// Adds all logs. - void addAll(List logs) { + void addAll(Iterable logs) { for (var log in logs) { add(log); } @@ -33,7 +34,7 @@ class AliceLogger { void add(AliceLog log) { final values = _logsSubject.value; final count = values.length; - if (maximumSize != null && count >= maximumSize!) { + if (maximumSize > 0 && count.gte(maximumSize)) { values.removeAt(0); } diff --git a/packages/alice/lib/core/alice_memory_storage.dart b/packages/alice/lib/core/alice_memory_storage.dart index 48e74daf..bd7c603f 100644 --- a/packages/alice/lib/core/alice_memory_storage.dart +++ b/packages/alice/lib/core/alice_memory_storage.dart @@ -50,13 +50,10 @@ class AliceMemoryStorage implements AliceStorage { (call.response?.status.lt(400) ?? false)) .length, errors: calls - .where( - (AliceHttpCall call) => - ((call.response?.status.gte(400) ?? false) && - (call.response?.status.lt(600) ?? false)) || - call.response?.status == -1 || - call.response?.status == 0, - ) + .where((AliceHttpCall call) => + ((call.response?.status.gte(400) ?? false) && + (call.response?.status.lt(600) ?? false)) || + const [-1, 0].contains(call.response?.status)) .length, loading: calls.where((AliceHttpCall call) => call.loading).length, ); diff --git a/packages/alice/lib/core/alice_translations.dart b/packages/alice/lib/core/alice_translations.dart index e80f0887..a8391c1f 100644 --- a/packages/alice/lib/core/alice_translations.dart +++ b/packages/alice/lib/core/alice_translations.dart @@ -89,6 +89,7 @@ class AliceTranslations { AliceTranslationKey.callsListStats: "Stats", AliceTranslationKey.callsListSave: "Save", AliceTranslationKey.logsEmpty: "There are no logs to show", + AliceTranslationKey.logsError: "Failed to display error", AliceTranslationKey.logsItemError: "Error:", AliceTranslationKey.logsItemStackTrace: "Stack trace:", AliceTranslationKey.logsCopied: "Copied to clipboard.", @@ -254,6 +255,7 @@ class AliceTranslations { AliceTranslationKey.callsListStats: "Statystyki", AliceTranslationKey.callsListSave: "Zapis", AliceTranslationKey.logsEmpty: "Brak rezultatów", + AliceTranslationKey.logsError: "Problem z wyświetleniem logów.", AliceTranslationKey.logsItemError: "Błąd:", AliceTranslationKey.logsItemStackTrace: "Ślad stosu:", AliceTranslationKey.logsCopied: "Skopiowano do schowka.", diff --git a/packages/alice/lib/model/alice_configuration.dart b/packages/alice/lib/model/alice_configuration.dart index 0ce0e9d4..f86c6f53 100644 --- a/packages/alice/lib/model/alice_configuration.dart +++ b/packages/alice/lib/model/alice_configuration.dart @@ -52,15 +52,23 @@ class AliceConfiguration { aliceLogger = logger ?? AliceLogger(maximumSize: _defaultMaxLogs); AliceConfiguration copyWith({ - required GlobalKey newNavigatorKey, - }) { - return AliceConfiguration( - showNotification: showNotification, - showInspectorOnShake: showInspectorOnShake, - notificationIcon: notificationIcon, - directionality: directionality, - showShareButton: showShareButton, - navigatorKey: newNavigatorKey, - ); - } + GlobalKey? navigatorKey, + bool? showNotification, + bool? showInspectorOnShake, + String? notificationIcon, + TextDirection? directionality, + bool? showShareButton, + AliceStorage? aliceStorage, + AliceLogger? aliceLogger, + }) => + AliceConfiguration( + showNotification: showNotification ?? this.showNotification, + showInspectorOnShake: showInspectorOnShake ?? this.showInspectorOnShake, + notificationIcon: notificationIcon ?? this.notificationIcon, + directionality: directionality ?? this.directionality, + showShareButton: showShareButton ?? this.showShareButton, + navigatorKey: navigatorKey ?? this.navigatorKey, + storage: aliceStorage ?? this.aliceStorage, + logger: aliceLogger ?? this.aliceLogger, + ); } diff --git a/packages/alice/lib/model/alice_translation.dart b/packages/alice/lib/model/alice_translation.dart index 477ecf7f..4b966d19 100644 --- a/packages/alice/lib/model/alice_translation.dart +++ b/packages/alice/lib/model/alice_translation.dart @@ -78,6 +78,7 @@ enum AliceTranslationKey { callsListStats, callsListSave, logsEmpty, + logsError, logsItemError, logsItemStackTrace, logsCopied, diff --git a/packages/alice/lib/ui/calls_list/widget/alice_error_logs_widget.dart b/packages/alice/lib/ui/calls_list/widget/alice_error_logs_widget.dart new file mode 100644 index 00000000..4697be59 --- /dev/null +++ b/packages/alice/lib/ui/calls_list/widget/alice_error_logs_widget.dart @@ -0,0 +1,34 @@ +import 'package:alice/model/alice_translation.dart'; +import 'package:alice/ui/common/alice_context_ext.dart'; +import 'package:alice/ui/common/alice_theme.dart'; +import 'package:flutter/material.dart'; + +/// Widget which renders empty text for calls list. +class AliceErrorLogsWidget extends StatelessWidget { + const AliceErrorLogsWidget({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.symmetric(horizontal: 32), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.error_outline, + color: AliceTheme.red, + ), + const SizedBox(height: 6), + Text( + context.i18n(AliceTranslationKey.logsItemError), + style: const TextStyle(fontSize: 18), + ), + ], + ), + ), + ); + } +} diff --git a/packages/alice/lib/ui/calls_list/widget/alice_log_list_widget.dart b/packages/alice/lib/ui/calls_list/widget/alice_log_list_widget.dart index c86edf03..a6cf9b90 100644 --- a/packages/alice/lib/ui/calls_list/widget/alice_log_list_widget.dart +++ b/packages/alice/lib/ui/calls_list/widget/alice_log_list_widget.dart @@ -2,6 +2,8 @@ import 'dart:convert'; import 'package:alice/model/alice_log.dart'; import 'package:alice/model/alice_translation.dart'; +import 'package:alice/ui/calls_list/widget/alice_empty_logs_widget.dart'; +import 'package:alice/ui/calls_list/widget/alice_error_logs_widget.dart'; import 'package:alice/ui/common/alice_context_ext.dart'; import 'package:alice/ui/common/alice_scroll_behavior.dart'; import 'package:alice/ui/common/alice_theme.dart'; @@ -14,13 +16,11 @@ class AliceLogListWidget extends StatefulWidget { const AliceLogListWidget({ required this.logsStream, required this.scrollController, - required this.emptyWidget, super.key, }); final Stream>? logsStream; final ScrollController? scrollController; - final Widget emptyWidget; @override State createState() => _AliceLogListWidgetState(); @@ -35,9 +35,20 @@ class _AliceLogListWidgetState extends State { return StreamBuilder>( stream: widget.logsStream, builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.none || + snapshot.connectionState == ConnectionState.waiting) { + return const Center( + child: CircularProgressIndicator(), + ); + } + + if (snapshot.hasError) { + return const AliceErrorLogsWidget(); + } + final logs = snapshot.data ?? []; if (logs.isEmpty) { - return widget.emptyWidget; + return const AliceEmptyLogsWidget(); } final List filteredLogs = [ diff --git a/packages/alice/lib/ui/calls_list/widget/alice_logs_screen.dart b/packages/alice/lib/ui/calls_list/widget/alice_logs_screen.dart index 74a81703..e56169a7 100644 --- a/packages/alice/lib/ui/calls_list/widget/alice_logs_screen.dart +++ b/packages/alice/lib/ui/calls_list/widget/alice_logs_screen.dart @@ -23,12 +23,10 @@ class AliceLogsScreen extends StatelessWidget { ? AliceRawLogListWidget( scrollController: scrollController, getRawLogs: aliceLogger?.getAndroidRawLogs(), - emptyWidget: const AliceEmptyLogsWidget(), ) : AliceLogListWidget( logsStream: aliceLogger?.logsStream, scrollController: scrollController, - emptyWidget: const AliceEmptyLogsWidget(), ) : const AliceEmptyLogsWidget(); } diff --git a/packages/alice/lib/ui/calls_list/widget/alice_raw_log_list_widger.dart b/packages/alice/lib/ui/calls_list/widget/alice_raw_log_list_widger.dart index 2bfcfd37..81caeb1d 100644 --- a/packages/alice/lib/ui/calls_list/widget/alice_raw_log_list_widger.dart +++ b/packages/alice/lib/ui/calls_list/widget/alice_raw_log_list_widger.dart @@ -1,4 +1,6 @@ import 'package:alice/model/alice_translation.dart'; +import 'package:alice/ui/calls_list/widget/alice_empty_logs_widget.dart'; +import 'package:alice/ui/calls_list/widget/alice_error_logs_widget.dart'; import 'package:alice/ui/common/alice_context_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -8,45 +10,53 @@ class AliceRawLogListWidget extends StatelessWidget { const AliceRawLogListWidget({ required this.scrollController, required this.getRawLogs, - required this.emptyWidget, super.key, }); final ScrollController scrollController; final Future? getRawLogs; - final Widget emptyWidget; @override Widget build(BuildContext context) { return FutureBuilder( future: getRawLogs, builder: (context, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - if (snapshot.data?.isNotEmpty == true) { - return Scrollbar( - thickness: 8, - controller: scrollController, - child: SingleChildScrollView( - controller: scrollController, - child: Padding( - padding: const EdgeInsets.all(8), - child: InkWell( - onLongPress: () => _copyToClipboard( - context: context, - text: snapshot.data ?? '', - ), - child: Text( - snapshot.data ?? '', - style: const TextStyle(fontSize: 10), - ), - ), + if (snapshot.connectionState == ConnectionState.none || + snapshot.connectionState == ConnectionState.waiting) { + return const Center( + child: CircularProgressIndicator(), + ); + } + + if (snapshot.hasError) { + return const AliceErrorLogsWidget(); + } + + final logs = snapshot.data ?? ''; + if (logs.isEmpty) { + return const AliceEmptyLogsWidget(); + } + + return Scrollbar( + thickness: 8, + controller: scrollController, + child: SingleChildScrollView( + controller: scrollController, + child: Padding( + padding: const EdgeInsets.all(8), + child: InkWell( + onLongPress: () => _copyToClipboard( + context: context, + text: snapshot.data ?? '', + ), + child: Text( + snapshot.data ?? '', + style: const TextStyle(fontSize: 10), ), ), - ); - } - return emptyWidget; - } - return const Center(child: CircularProgressIndicator()); + ), + ), + ); }, ); } From b8fe05e8467d42d70aea3563f95e42c78c17c2b8 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Sun, 7 Jul 2024 12:18:04 +0200 Subject: [PATCH 18/20] fix: fixed PR comments, updated metadata --- docs/install.md | 4 ++-- packages/alice/lib/core/alice_logger.dart | 2 +- packages/alice/lib/model/alice_configuration.dart | 15 ++++++++++++++- packages/alice/pubspec.yaml | 2 +- packages/alice_objectbox/CHANGELOG.md | 3 +++ packages/alice_objectbox/pubspec.yaml | 2 +- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/docs/install.md b/docs/install.md index caf80249..0a76f374 100644 --- a/docs/install.md +++ b/docs/install.md @@ -4,7 +4,7 @@ ```yaml dependencies: - alice: ^1.0.0-dev9 + alice: ^1.0.0-dev10 ``` 2. Choose adapter based on your HTTP client. **pubspec.yaml** file: @@ -44,7 +44,7 @@ dependencies: ```yaml dependencies: objectbox: any - alice_objectbox: ^1.0.1 + alice_objectbox: ^1.0.2 ``` 4. Run `get` command: diff --git a/packages/alice/lib/core/alice_logger.dart b/packages/alice/lib/core/alice_logger.dart index 77d9d3ee..18ed693e 100644 --- a/packages/alice/lib/core/alice_logger.dart +++ b/packages/alice/lib/core/alice_logger.dart @@ -34,7 +34,7 @@ class AliceLogger { void add(AliceLog log) { final values = _logsSubject.value; final count = values.length; - if (maximumSize > 0 && count.gte(maximumSize)) { + if (maximumSize > 0 && count >= maximumSize) { values.removeAt(0); } diff --git a/packages/alice/lib/model/alice_configuration.dart b/packages/alice/lib/model/alice_configuration.dart index f86c6f53..e9e6d6ca 100644 --- a/packages/alice/lib/model/alice_configuration.dart +++ b/packages/alice/lib/model/alice_configuration.dart @@ -1,9 +1,10 @@ import 'package:alice/core/alice_logger.dart'; import 'package:alice/core/alice_memory_storage.dart'; import 'package:alice/core/alice_storage.dart'; +import 'package:equatable/equatable.dart'; import 'package:flutter/widgets.dart'; -class AliceConfiguration { +class AliceConfiguration with EquatableMixin { /// Default max calls count used in default memory storage. static const _defaultMaxCalls = 1000; @@ -71,4 +72,16 @@ class AliceConfiguration { storage: aliceStorage ?? this.aliceStorage, logger: aliceLogger ?? this.aliceLogger, ); + + @override + List get props => [ + showNotification, + showInspectorOnShake, + notificationIcon, + directionality, + showShareButton, + navigatorKey, + aliceStorage, + aliceLogger, + ]; } diff --git a/packages/alice/pubspec.yaml b/packages/alice/pubspec.yaml index 22cf999a..ef0642ee 100644 --- a/packages/alice/pubspec.yaml +++ b/packages/alice/pubspec.yaml @@ -1,6 +1,6 @@ name: alice description: Alice is an HTTP Inspector tool which helps debugging http requests. It catches and stores http requests and responses, which can be viewed via simple UI. -version: 1.0.0-dev.9 +version: 1.0.0-dev.10 homepage: https://github.com/jhomlala/alice repository: https://github.com/jhomlala/alice topics: diff --git a/packages/alice_objectbox/CHANGELOG.md b/packages/alice_objectbox/CHANGELOG.md index f6767c03..fb85da39 100644 --- a/packages/alice_objectbox/CHANGELOG.md +++ b/packages/alice_objectbox/CHANGELOG.md @@ -1,3 +1,6 @@ +# 1.0.2 +* Fixed issue with invalid count of calls in notification. + # 1.0.1 * Updated documentation. diff --git a/packages/alice_objectbox/pubspec.yaml b/packages/alice_objectbox/pubspec.yaml index 3f5e962b..b5ce5c09 100644 --- a/packages/alice_objectbox/pubspec.yaml +++ b/packages/alice_objectbox/pubspec.yaml @@ -1,6 +1,6 @@ name: alice_objectbox description: "Alice + ObjectBox integration. It contains a plugin for Alice which stores http requests and responses in an ObjectBox NoSQL database." -version: 1.0.1 +version: 1.0.2 repository: https://github.com/jhomlala/alice homepage: https://github.com/jhomlala/alice topics: From 01e3bd47e2d9079d139a33785431d4d8d3c9f53d Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Sun, 7 Jul 2024 12:19:49 +0200 Subject: [PATCH 19/20] feat: updated metadata --- packages/alice/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/alice/README.md b/packages/alice/README.md index 1e1fa832..a8d7a123 100644 --- a/packages/alice/README.md +++ b/packages/alice/README.md @@ -77,6 +77,8 @@ Alice is an HTTP Inspector tool for Flutter which helps debugging http requests. ✔️ Shake to open inspector ✔️ HTTP calls search ✔️ Flutter/Android logs +✔️ ObjectBox storage + ## Documentation You can find documentation [here.](https://jhomlala.github.io/alice/) \ No newline at end of file From c4d06ad2d677b681c2b0416ccb70a604a81300c5 Mon Sep 17 00:00:00 2001 From: Jakub Homlala Date: Sun, 7 Jul 2024 12:20:53 +0200 Subject: [PATCH 20/20] feat: dart fix --- packages/alice/lib/core/alice_logger.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/alice/lib/core/alice_logger.dart b/packages/alice/lib/core/alice_logger.dart index 18ed693e..3f01e5da 100644 --- a/packages/alice/lib/core/alice_logger.dart +++ b/packages/alice/lib/core/alice_logger.dart @@ -2,7 +2,6 @@ import 'dart:io' show Process, ProcessResult; import 'package:alice/helper/operating_system.dart'; import 'package:alice/model/alice_log.dart'; -import 'package:alice/utils/num_comparison.dart'; import 'package:rxdart/rxdart.dart'; /// Logger used to handle logs from application.