From 536cd1c39e476139e9d28fa3d417d3cb719bb948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Pola=C5=84ski?= Date: Fri, 1 Dec 2023 14:18:57 +0100 Subject: [PATCH] wip --- lib/alice.dart | 4 +- lib/src/alice.dart | 3 +- lib/src/core/alice_core.dart | 9 +- lib/src/core/alice_logger.dart | 5 +- lib/src/core/http/alice_http_adapter.dart | 25 +-- lib/src/core/http/alice_http_extensions.dart | 5 +- .../alice_http_client_adapter.dart | 29 ++-- .../alice_http_client_extensions.dart | 5 +- lib/src/helper/alice_alert_helper.dart | 6 +- lib/src/helper/alice_conversion_helper.dart | 20 +-- lib/src/helper/alice_save_helper.dart | 118 +++++++------ lib/src/model/alice_http_call.dart | 44 ++--- lib/src/model/alice_http_error.dart | 2 +- lib/src/model/alice_http_request.dart | 4 +- lib/src/model/alice_log.dart | 4 +- lib/src/model/alice_sort_option.dart | 10 +- .../ui/page/alice_call_details_screen.dart | 25 +-- lib/src/ui/page/alice_calls_list_screen.dart | 157 +++++++++--------- lib/src/ui/page/alice_stats_screen.dart | 52 +++--- .../alice_base_call_details_widget.dart | 2 +- .../ui/widget/alice_call_error_widget.dart | 10 +- .../widget/alice_call_list_item_widget.dart | 41 ++--- .../ui/widget/alice_call_overview_widget.dart | 26 +-- .../ui/widget/alice_call_request_widget.dart | 41 ++--- .../ui/widget/alice_call_response_widget.dart | 114 +++++++------ lib/src/ui/widget/alice_log_list_widget.dart | 15 +- .../ui/widget/alice_raw_log_list_widger.dart | 12 +- lib/src/utils/alice_parser.dart | 19 ++- pubspec.lock | 20 +-- pubspec.yaml | 2 + 30 files changed, 432 insertions(+), 397 deletions(-) diff --git a/lib/alice.dart b/lib/alice.dart index 6b891a93..96eb25a9 100644 --- a/lib/alice.dart +++ b/lib/alice.dart @@ -1,5 +1,5 @@ -export 'package:alice/src/model/alice_log.dart'; export 'package:alice/src/alice.dart'; export 'package:alice/src/core/alice_core.dart'; -export 'package:alice/src/core/http_client/alice_http_client_extensions.dart'; export 'package:alice/src/core/http/alice_http_extensions.dart'; +export 'package:alice/src/core/http_client/alice_http_client_extensions.dart'; +export 'package:alice/src/model/alice_log.dart'; diff --git a/lib/src/alice.dart b/lib/src/alice.dart index 7d046883..e2b1427c 100644 --- a/lib/src/alice.dart +++ b/lib/src/alice.dart @@ -19,7 +19,8 @@ class Alice { ///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. + ///Directionality of app. Directionality of the app will be used if set to + /// null. final TextDirection? directionality; ///Flag used to show/hide share button diff --git a/lib/src/core/alice_core.dart b/lib/src/core/alice_core.dart index 08d38c1c..7aa42f6d 100644 --- a/lib/src/core/alice_core.dart +++ b/lib/src/core/alice_core.dart @@ -1,3 +1,4 @@ +// ignore_for_file: cascade_invocations import 'dart:async'; import 'package:alice/src/core/alice_logger.dart'; @@ -32,7 +33,7 @@ class AliceCore { final Brightness _brightness; bool _isInspectorOpened = false; - StreamSubscription? _callsSubscription; + StreamSubscription? _callsSubscription; /// Creates alice core instance AliceCore({ @@ -88,7 +89,7 @@ class AliceCore { final selectedCall = _selectCall(requestId); if (selectedCall == null) { - debugPrint("Selected call is null"); + debugPrint('Selected call is null'); return; } @@ -100,10 +101,10 @@ class AliceCore { /// Add response to existing alice http call void addResponse(AliceHttpResponse response, Object requestId) { - final AliceHttpCall? selectedCall = _selectCall(requestId); + final selectedCall = _selectCall(requestId); if (selectedCall == null) { - debugPrint("Selected call is null"); + debugPrint('Selected call is null'); return; } selectedCall.loading = false; diff --git a/lib/src/core/alice_logger.dart b/lib/src/core/alice_logger.dart index 71aa25f9..9e146ed5 100644 --- a/lib/src/core/alice_logger.dart +++ b/lib/src/core/alice_logger.dart @@ -16,7 +16,8 @@ class AliceLogger { /// 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 + /// If more logs arrive, the oldest ones (based on their [AliceLog.timestamp]) + /// will /// be removed. int? get maximumSize => _maximumSize; @@ -46,7 +47,7 @@ class AliceLogger { min = mid + 1; } } - assert(min == max); + assert(min == max, 'Invalid'); index = min; } diff --git a/lib/src/core/http/alice_http_adapter.dart b/lib/src/core/http/alice_http_adapter.dart index 009974be..b6002894 100644 --- a/lib/src/core/http/alice_http_adapter.dart +++ b/lib/src/core/http/alice_http_adapter.dart @@ -1,3 +1,4 @@ +// ignore_for_file: cascade_invocations import 'dart:convert'; import 'package:alice/src/core/alice_core.dart'; @@ -15,23 +16,23 @@ class AliceHttpAdapter { AliceHttpAdapter(this.aliceCore); void onRequest(http.BaseRequest request, {dynamic body, Object? id}) { - final AliceHttpCall call = AliceHttpCall(id ?? request.hashCode); + final call = AliceHttpCall(id ?? request.hashCode); call.loading = true; - call.client = "HttpClient (http package)"; + call.client = 'HttpClient (http package)'; call.uri = request.url.toString(); call.method = request.method; var path = request.url.path; if (path.isEmpty) { - path = "/"; + path = '/'; } call.endpoint = path; call.server = request.url.host; - if (request.url.scheme == "https") { + if (request.url.scheme == 'https') { call.secure = true; } - final AliceHttpRequest httpRequest = AliceHttpRequest(); + final httpRequest = AliceHttpRequest(); if (request is http.Request) { // we are guaranteed` the existence of body and headers @@ -39,12 +40,12 @@ class AliceHttpAdapter { httpRequest.body = body; } // ignore: cast_nullable_to_non_nullable - httpRequest.body = body ?? request.body ?? ""; + httpRequest.body = body ?? request.body ?? ''; httpRequest.size = utf8.encode(httpRequest.body.toString()).length; httpRequest.headers = Map.from(request.headers); } else if (body == null) { httpRequest.size = 0; - httpRequest.body = ""; + httpRequest.body = ''; } else { httpRequest.size = utf8.encode(body.toString()).length; httpRequest.body = body; @@ -52,9 +53,9 @@ class AliceHttpAdapter { httpRequest.time = DateTime.now(); - String? contentType = "unknown"; - if (httpRequest.headers.containsKey("Content-Type")) { - contentType = httpRequest.headers["Content-Type"] as String?; + String? contentType = 'unknown'; + if (httpRequest.headers.containsKey('Content-Type')) { + contentType = httpRequest.headers['Content-Type'] as String?; } httpRequest.contentType = contentType; @@ -77,9 +78,9 @@ class AliceHttpAdapter { httpResponse.size = utf8.encode((body ?? '').toString()).length; } httpResponse.time = DateTime.now(); - final Map responseHeaders = {}; + final responseHeaders = {}; response.headers.forEach((header, values) { - responseHeaders[header] = values.toString(); + responseHeaders[header] = values; }); httpResponse.headers = responseHeaders; aliceCore.addResponse(httpResponse, id ?? response.hashCode); diff --git a/lib/src/core/http/alice_http_extensions.dart b/lib/src/core/http/alice_http_extensions.dart index 3562df30..88620586 100644 --- a/lib/src/core/http/alice_http_extensions.dart +++ b/lib/src/core/http/alice_http_extensions.dart @@ -2,10 +2,11 @@ import 'package:alice/src/alice.dart'; import 'package:http/http.dart'; extension AliceHttpExtensions on Future { - /// Intercept http request with alice. This extension method provides additional + /// Intercept http request with alice. This extension method provides addition + /// al /// helpful method to intercept https' response. Future interceptWithAlice(Alice alice, {dynamic body}) async { - final Response response = await this; + final response = await this; alice.onHttpResponse(response, body: body); return response; } diff --git a/lib/src/core/http_client/alice_http_client_adapter.dart b/lib/src/core/http_client/alice_http_client_adapter.dart index 1ca89d44..53ba9bb6 100644 --- a/lib/src/core/http_client/alice_http_client_adapter.dart +++ b/lib/src/core/http_client/alice_http_client_adapter.dart @@ -1,3 +1,4 @@ +// ignore_for_file: cascade_invocations import 'dart:convert'; import 'dart:io'; @@ -15,41 +16,41 @@ class AliceHttpClientAdapter { /// Handles httpClientRequest and creates http alice call from it void onRequest(HttpClientRequest request, {dynamic body}) { - final AliceHttpCall call = AliceHttpCall(request.hashCode); + final call = AliceHttpCall(request.hashCode); call.loading = true; - call.client = "HttpClient (io package)"; + call.client = 'HttpClient (io package)'; call.method = request.method; call.uri = request.uri.toString(); var path = request.uri.path; if (path.isEmpty) { - path = "/"; + path = '/'; } call.endpoint = path; call.server = request.uri.host; - if (request.uri.scheme == "https") { + if (request.uri.scheme == 'https') { call.secure = true; } - final AliceHttpRequest httpRequest = AliceHttpRequest(); + final httpRequest = AliceHttpRequest(); if (body == null) { httpRequest.size = 0; - httpRequest.body = ""; + httpRequest.body = ''; } else { httpRequest.size = utf8.encode(body.toString()).length; httpRequest.body = body; } httpRequest.time = DateTime.now(); - final Map headers = {}; + final headers = {}; httpRequest.headers.forEach((header, dynamic value) { headers[header] = value; }); httpRequest.headers = headers; - String? contentType = "unknown"; - if (headers.containsKey("Content-Type")) { - contentType = headers["Content-Type"] as String?; + String? contentType = 'unknown'; + if (headers.containsKey('Content-Type')) { + contentType = headers['Content-Type'] as String?; } httpRequest.contentType = contentType; @@ -61,23 +62,23 @@ class AliceHttpClientAdapter { } /// Handles httpClientRequest and adds response to http alice call - void onResponse( + Future onResponse( HttpClientResponse response, HttpClientRequest request, { dynamic body, }) async { - final AliceHttpResponse httpResponse = AliceHttpResponse(); + final httpResponse = AliceHttpResponse(); httpResponse.status = response.statusCode; if (body != null) { httpResponse.body = body; httpResponse.size = utf8.encode(body.toString()).length; } else { - httpResponse.body = ""; + httpResponse.body = ''; httpResponse.size = 0; } httpResponse.time = DateTime.now(); - final Map headers = {}; + final headers = {}; response.headers.forEach((header, values) { headers[header] = values.toString(); }); diff --git a/lib/src/core/http_client/alice_http_client_extensions.dart b/lib/src/core/http_client/alice_http_client_extensions.dart index 05365c5d..f724e551 100644 --- a/lib/src/core/http_client/alice_http_client_extensions.dart +++ b/lib/src/core/http_client/alice_http_client_extensions.dart @@ -5,14 +5,15 @@ import 'dart:io'; import 'package:alice/src/alice.dart'; extension AliceHttpClientExtensions on Future { - /// Intercept http client with alice. This extension method provides additional + /// Intercept http client with alice. This extension method provides additiona + /// l /// helpful method to intercept httpClientResponse. Future interceptWithAlice( Alice alice, { dynamic body, Map? headers, }) async { - final HttpClientRequest request = await this; + final request = await this; if (body != null) { request.write(body); } diff --git a/lib/src/helper/alice_alert_helper.dart b/lib/src/helper/alice_alert_helper.dart index a293d824..bc4f301b 100644 --- a/lib/src/helper/alice_alert_helper.dart +++ b/lib/src/helper/alice_alert_helper.dart @@ -1,3 +1,5 @@ +// ignore_for_file: cascade_invocations, avoid_dynamic_calls + import 'package:flutter/material.dart'; class AliceAlertHelper { @@ -6,13 +8,13 @@ class AliceAlertHelper { BuildContext context, String title, String description, { - String firstButtonTitle = "Accept", + String firstButtonTitle = 'Accept', String? secondButtonTitle, Function? firstButtonAction, Function? secondButtonAction, Brightness? brightness, }) { - final List actions = []; + final actions = []; actions.add( TextButton( onPressed: () { diff --git a/lib/src/helper/alice_conversion_helper.dart b/lib/src/helper/alice_conversion_helper.dart index e16e2b01..b67d371a 100644 --- a/lib/src/helper/alice_conversion_helper.dart +++ b/lib/src/helper/alice_conversion_helper.dart @@ -7,16 +7,16 @@ class AliceConversionHelper { /// Format bytes text static String formatBytes(int bytes) { if (bytes < 0) { - return "-1 B"; + return '-1 B'; } if (bytes <= _kilobyteAsByte) { - return "$bytes B"; + return '$bytes B'; } if (bytes <= _megabyteAsByte) { - return "${_formatDouble(bytes / _kilobyteAsByte)} kB"; + return '${_formatDouble(bytes / _kilobyteAsByte)} kB'; } - return "${_formatDouble(bytes / _megabyteAsByte)} MB"; + return '${_formatDouble(bytes / _megabyteAsByte)} MB'; } static String _formatDouble(double value) => value.toStringAsFixed(2); @@ -24,18 +24,18 @@ class AliceConversionHelper { /// Format time in milliseconds static String formatTime(int timeInMillis) { if (timeInMillis < 0) { - return "-1 ms"; + return '-1 ms'; } if (timeInMillis <= _secondAsMillisecond) { - return "$timeInMillis ms"; + return '$timeInMillis ms'; } if (timeInMillis <= _minuteAsMillisecond) { - return "${_formatDouble(timeInMillis / _secondAsMillisecond)} s"; + return '${_formatDouble(timeInMillis / _secondAsMillisecond)} s'; } - final Duration duration = Duration(milliseconds: timeInMillis); + final duration = Duration(milliseconds: timeInMillis); - return "${duration.inMinutes} min ${duration.inSeconds.remainder(60)} s " - "${duration.inMilliseconds.remainder(1000)} ms"; + return '${duration.inMinutes} min ${duration.inSeconds.remainder(60)} s ' + '${duration.inMilliseconds.remainder(1000)} ms'; } } diff --git a/lib/src/helper/alice_save_helper.dart b/lib/src/helper/alice_save_helper.dart index a6c0cea5..c58a3275 100644 --- a/lib/src/helper/alice_save_helper.dart +++ b/lib/src/helper/alice_save_helper.dart @@ -1,3 +1,4 @@ +// ignore_for_file: cascade_invocations import 'dart:async'; import 'dart:convert'; @@ -10,84 +11,97 @@ class AliceSaveHelper { static const JsonEncoder _encoder = JsonEncoder.withIndent(' '); static Future _buildAliceLog() async { - final StringBuffer stringBuffer = StringBuffer(); + final stringBuffer = StringBuffer(); final packageInfo = await PackageInfo.fromPlatform(); - stringBuffer.write("Alice - HTTP Inspector\n"); - stringBuffer.write("App name: ${packageInfo.appName}\n"); - stringBuffer.write("Package: ${packageInfo.packageName}\n"); - stringBuffer.write("Version: ${packageInfo.version}\n"); - stringBuffer.write("Build number: ${packageInfo.buildNumber}\n"); - stringBuffer.write("Generated: ${DateTime.now().toIso8601String()}\n"); - stringBuffer.write("\n"); + stringBuffer.write('Alice - HTTP Inspector\n'); + stringBuffer.write('App name: ${packageInfo.appName}\n'); + stringBuffer.write('Package: ${packageInfo.packageName}\n'); + stringBuffer.write('Version: ${packageInfo.version}\n'); + stringBuffer.write('Build number: ${packageInfo.buildNumber}\n'); + stringBuffer.write('Generated: ${DateTime.now().toIso8601String()}\n'); + stringBuffer.write('\n'); return stringBuffer.toString(); } static String _buildCallLog(AliceHttpCall call) { - final StringBuffer stringBuffer = StringBuffer(); - stringBuffer.write("===========================================\n"); - stringBuffer.write("Id: ${call.id}\n"); - stringBuffer.write("============================================\n"); - stringBuffer.write("--------------------------------------------\n"); - stringBuffer.write("General data\n"); - stringBuffer.write("--------------------------------------------\n"); - stringBuffer.write("Server: ${call.server} \n"); - stringBuffer.write("Method: ${call.method} \n"); - stringBuffer.write("Endpoint: ${call.endpoint} \n"); - stringBuffer.write("Client: ${call.client} \n"); + final stringBuffer = StringBuffer(); + stringBuffer.write('===========================================\n'); + stringBuffer.write('Id: ${call.id}\n'); + stringBuffer.write('============================================\n'); + stringBuffer.write('--------------------------------------------\n'); + stringBuffer.write('General data\n'); + stringBuffer.write('--------------------------------------------\n'); + stringBuffer.write('Server: ${call.server} \n'); + stringBuffer.write('Method: ${call.method} \n'); + stringBuffer.write('Endpoint: ${call.endpoint} \n'); + stringBuffer.write('Client: ${call.client} \n'); stringBuffer - .write("Duration ${AliceConversionHelper.formatTime(call.duration)}\n"); - stringBuffer.write("Secured connection: ${call.secure}\n"); - stringBuffer.write("Completed: ${!call.loading} \n"); - stringBuffer.write("--------------------------------------------\n"); - stringBuffer.write("Request\n"); - stringBuffer.write("--------------------------------------------\n"); - stringBuffer.write("Request time: ${call.request!.time}\n"); - stringBuffer.write("Request content type: ${call.request!.contentType}\n"); + .write('Duration ${AliceConversionHelper.formatTime(call.duration)}\n'); + stringBuffer.write('Secured connection: ${call.secure}\n'); + stringBuffer.write('Completed: ${!call.loading} \n'); + stringBuffer.write('--------------------------------------------\n'); + stringBuffer.write('Request\n'); + stringBuffer.write('--------------------------------------------\n'); + stringBuffer.write('Request time: ${call.request!.time}\n'); + stringBuffer.write('Request content type: ${call.request!.contentType}\n'); stringBuffer - .write("Request cookies: ${_encoder.convert(call.request!.cookies)}\n"); + .write('Request cookies: ${_encoder.convert(call.request!.cookies)}\n'); stringBuffer - .write("Request headers: ${_encoder.convert(call.request!.headers)}\n"); + .write('Request headers: ${_encoder.convert(call.request!.headers)}\n'); if (call.request!.queryParameters.isNotEmpty) { stringBuffer.write( - "Request query params: ${_encoder.convert(call.request!.queryParameters)}\n", + 'Request query params: ${_encoder.convert( + call.request!.queryParameters, + )}\n', ); } stringBuffer.write( - "Request size: ${AliceConversionHelper.formatBytes(call.request!.size)}\n", + 'Request size: ${AliceConversionHelper.formatBytes( + call.request!.size, + )}\n', ); stringBuffer.write( - "Request body: ${AliceParser.formatBody(call.request!.body, AliceParser.getContentType(call.request!.headers))}\n", + 'Request body: ' + '${AliceParser.formatBody( + call.request!.body, + AliceParser.getContentType(call.request!.headers), + )}\n', ); - stringBuffer.write("--------------------------------------------\n"); - stringBuffer.write("Response\n"); - stringBuffer.write("--------------------------------------------\n"); - stringBuffer.write("Response time: ${call.response!.time}\n"); - stringBuffer.write("Response status: ${call.response!.status}\n"); + stringBuffer.write('--------------------------------------------\n'); + stringBuffer.write('Response\n'); + stringBuffer.write('--------------------------------------------\n'); + stringBuffer.write('Response time: ${call.response!.time}\n'); + stringBuffer.write('Response status: ${call.response!.status}\n'); stringBuffer.write( - "Response size: ${AliceConversionHelper.formatBytes(call.response!.size)}\n", + 'Response size: ${AliceConversionHelper.formatBytes( + call.response!.size, + )}\n', ); stringBuffer.write( - "Response headers: ${_encoder.convert(call.response!.headers)}\n", + 'Response headers: ${_encoder.convert(call.response!.headers)}\n', ); stringBuffer.write( - "Response body: ${AliceParser.formatBody(call.response!.body, AliceParser.getContentType(call.response!.headers))}\n", + 'Response body: ${AliceParser.formatBody( + call.response!.body, + AliceParser.getContentType(call.response!.headers), + )}\n', ); if (call.error != null) { - stringBuffer.write("--------------------------------------------\n"); - stringBuffer.write("Error\n"); - stringBuffer.write("--------------------------------------------\n"); - stringBuffer.write("Error: ${call.error!.error}\n"); + stringBuffer.write('--------------------------------------------\n'); + stringBuffer.write('Error\n'); + stringBuffer.write('--------------------------------------------\n'); + stringBuffer.write('Error: ${call.error!.error}\n'); if (call.error!.stackTrace != null) { - stringBuffer.write("Error stacktrace: ${call.error!.stackTrace}\n"); + stringBuffer.write('Error stacktrace: ${call.error!.stackTrace}\n'); } } - stringBuffer.write("--------------------------------------------\n"); - stringBuffer.write("Curl\n"); - stringBuffer.write("--------------------------------------------\n"); + stringBuffer.write('--------------------------------------------\n'); + stringBuffer.write('Curl\n'); + stringBuffer.write('--------------------------------------------\n'); stringBuffer.write(call.getCurlCommand()); - stringBuffer.write("\n"); - stringBuffer.write("==============================================\n"); - stringBuffer.write("\n"); + stringBuffer.write('\n'); + stringBuffer.write('==============================================\n'); + stringBuffer.write('\n'); return stringBuffer.toString(); } @@ -96,7 +110,7 @@ class AliceSaveHelper { try { return await _buildAliceLog() + _buildCallLog(call); } catch (exception) { - return "Failed to generate call log"; + return 'Failed to generate call log'; } } } diff --git a/lib/src/model/alice_http_call.dart b/lib/src/model/alice_http_call.dart index 9ed4773b..fa70069d 100644 --- a/lib/src/model/alice_http_call.dart +++ b/lib/src/model/alice_http_call.dart @@ -1,3 +1,5 @@ +// ignore_for_file: cascade_invocations + import 'package:alice/src/model/alice_http_error.dart'; import 'package:alice/src/model/alice_http_request.dart'; import 'package:alice/src/model/alice_http_response.dart'; @@ -5,13 +7,13 @@ import 'package:alice/src/model/alice_http_response.dart'; class AliceHttpCall { final Object id; late DateTime createdTime; - String client = ""; + String client = ''; bool loading = true; bool secure = false; - String method = ""; - String endpoint = ""; - String server = ""; - String uri = ""; + String method = ''; + String endpoint = ''; + String server = ''; + String uri = ''; int duration = 0; AliceHttpRequest? request; @@ -25,45 +27,47 @@ class AliceHttpCall { String getCurlCommand() { var compressed = false; - var curlCmd = "curl"; - curlCmd += " -X $method"; + var curlCmd = 'curl'; + curlCmd += ' -X $method'; final headers = request!.headers; headers.forEach((key, dynamic value) { - if ("Accept-Encoding" == key && "gzip" == value) { + if ('Accept-Encoding' == key && 'gzip' == value) { compressed = true; } curlCmd += " -H '$key: $value'"; }); - final String requestBody = request!.body.toString(); + final requestBody = request!.body.toString(); if (requestBody != '') { - // try to keep to a single line and use a subshell to preserve any line breaks - curlCmd += " --data \$'${requestBody.replaceAll("\n", "\\n")}'"; + // try to keep to a single line and use a subshell to preserve any line br + // eaks + curlCmd += " --data \$'${requestBody.replaceAll("\n", r"\n")}'"; } final queryParamMap = request!.queryParameters; - int paramCount = queryParamMap.keys.length; - var queryParams = ""; + var paramCount = queryParamMap.keys.length; + var queryParams = ''; if (paramCount > 0) { - queryParams += "?"; + queryParams += '?'; queryParamMap.forEach((key, dynamic value) { queryParams += '$key=$value'; paramCount -= 1; if (paramCount > 0) { - queryParams += "&"; + queryParams += '&'; } }); } // If server already has http(s) don't add it again - if (server.contains("http://") || server.contains("https://")) { + if (server.contains('http://') || server.contains('https://')) { // ignore: join_return_with_assignment - curlCmd += - "${compressed ? " --compressed " : " "}${"'$server$endpoint$queryParams'"}"; + curlCmd += "${compressed ? " --compressed " : " "}" + "${"'$server$endpoint$queryParams'"}"; } else { // ignore: join_return_with_assignment - curlCmd += - "${compressed ? " --compressed " : " "}${"'${secure ? 'https://' : 'http://'}$server$endpoint$queryParams'"}"; + curlCmd += "${compressed ? " --compressed " : " "}" + "${"'${secure ? 'https://' : 'http://'}" + "$server$endpoint$queryParams'"}"; } return curlCmd; diff --git a/lib/src/model/alice_http_error.dart b/lib/src/model/alice_http_error.dart index 03bae00a..b07152d4 100644 --- a/lib/src/model/alice_http_error.dart +++ b/lib/src/model/alice_http_error.dart @@ -6,7 +6,7 @@ class AliceHttpError { final StackTrace? stackTrace; final DateTime time; - AliceHttpError({ + const AliceHttpError({ required this.error, required this.stackTrace, required this.time, diff --git a/lib/src/model/alice_http_request.dart b/lib/src/model/alice_http_request.dart index eee18cfc..afb43df9 100644 --- a/lib/src/model/alice_http_request.dart +++ b/lib/src/model/alice_http_request.dart @@ -7,8 +7,8 @@ class AliceHttpRequest { int size = 0; DateTime time = DateTime.now(); Map headers = {}; - dynamic body = ""; - String? contentType = ""; + dynamic body = ''; + String? contentType = ''; List cookies = []; Map queryParameters = {}; List? formDataFiles; diff --git a/lib/src/model/alice_log.dart b/lib/src/model/alice_log.dart index 87392930..573ac984 100644 --- a/lib/src/model/alice_log.dart +++ b/lib/src/model/alice_log.dart @@ -3,9 +3,9 @@ import 'package:flutter/foundation.dart'; @immutable class AliceLog { AliceLog({ + required this.message, this.level = DiagnosticLevel.info, DateTime? timestamp, - required this.message, this.error, this.stackTrace, }) : assert( @@ -13,7 +13,7 @@ class AliceLog { '`DiagnosticLevel.off` is a "[special] level indicating that no ' 'diagnostics should be shown" and should not be used as a value.', ), - assert(timestamp == null || !timestamp.isUtc), + assert(timestamp == null || !timestamp.isUtc, 'Invalid'), timestamp = timestamp ?? DateTime.now(); final DiagnosticLevel level; diff --git a/lib/src/model/alice_sort_option.dart b/lib/src/model/alice_sort_option.dart index 3c1c009c..c82c26c2 100644 --- a/lib/src/model/alice_sort_option.dart +++ b/lib/src/model/alice_sort_option.dart @@ -11,15 +11,15 @@ extension AliceSortOptionsExtension on AliceSortOption { String get name { switch (this) { case AliceSortOption.time: - return "Create time (default)"; + return 'Create time (default)'; case AliceSortOption.responseTime: - return "Response time"; + return 'Response time'; case AliceSortOption.responseCode: - return "Response code"; + return 'Response code'; case AliceSortOption.responseSize: - return "Response size"; + return 'Response size'; case AliceSortOption.endpoint: - return "Endpoint"; + return 'Endpoint'; } } } diff --git a/lib/src/ui/page/alice_call_details_screen.dart b/lib/src/ui/page/alice_call_details_screen.dart index 7f422b59..e4f6132b 100644 --- a/lib/src/ui/page/alice_call_details_screen.dart +++ b/lib/src/ui/page/alice_call_details_screen.dart @@ -1,11 +1,12 @@ +// ignore_for_file: cascade_invocations import 'package:alice/src/core/alice_core.dart'; import 'package:alice/src/helper/alice_save_helper.dart'; import 'package:alice/src/model/alice_http_call.dart'; -import 'package:alice/src/utils/alice_constants.dart'; import 'package:alice/src/ui/widget/alice_call_error_widget.dart'; import 'package:alice/src/ui/widget/alice_call_overview_widget.dart'; import 'package:alice/src/ui/widget/alice_call_request_widget.dart'; import 'package:alice/src/ui/widget/alice_call_response_widget.dart'; +import 'package:alice/src/utils/alice_constants.dart'; import 'package:collection/collection.dart' show IterableExtension; import 'package:flutter/material.dart'; import 'package:share_plus/share_plus.dart'; @@ -14,10 +15,10 @@ class AliceCallDetailsScreen extends StatefulWidget { final AliceHttpCall call; final AliceCore core; - const AliceCallDetailsScreen(this.call, this.core); + const AliceCallDetailsScreen(this.call, this.core, {super.key}); @override - _AliceCallDetailsScreenState createState() => _AliceCallDetailsScreenState(); + State createState() => _AliceCallDetailsScreenState(); } class _AliceCallDetailsScreenState extends State @@ -40,7 +41,7 @@ class _AliceCallDetailsScreenState extends State initialData: [widget.call], builder: (context, callsSnapshot) { if (callsSnapshot.hasData) { - final AliceHttpCall? call = callsSnapshot.data!.firstWhereOrNull( + final call = callsSnapshot.data!.firstWhereOrNull( (snapshotCall) => snapshotCall.id == widget.call.id, ); if (call != null) { @@ -66,7 +67,7 @@ class _AliceCallDetailsScreenState extends State backgroundColor: AliceConstants.lightRed, key: const Key('share_key'), onPressed: () async { - Share.share( + await Share.share( await _getSharableResponseString(), subject: 'Request Details', ); @@ -92,7 +93,7 @@ class _AliceCallDetailsScreenState extends State } Widget _buildErrorWidget() { - return const Center(child: Text("Failed to load data")); + return const Center(child: Text('Failed to load data')); } Future _getSharableResponseString() async { @@ -100,21 +101,21 @@ class _AliceCallDetailsScreenState extends State } List _getTabBars() { - final List widgets = []; - widgets.add(const Tab(icon: Icon(Icons.info_outline), text: "Overview")); - widgets.add(const Tab(icon: Icon(Icons.arrow_upward), text: "Request")); - widgets.add(const Tab(icon: Icon(Icons.arrow_downward), text: "Response")); + final widgets = []; + widgets.add(const Tab(icon: Icon(Icons.info_outline), text: 'Overview')); + widgets.add(const Tab(icon: Icon(Icons.arrow_upward), text: 'Request')); + widgets.add(const Tab(icon: Icon(Icons.arrow_downward), text: 'Response')); widgets.add( const Tab( icon: Icon(Icons.warning), - text: "Error", + text: 'Error', ), ); return widgets; } List _getTabBarViewList() { - final List widgets = []; + final widgets = []; widgets.add(AliceCallOverviewWidget(widget.call)); widgets.add(AliceCallRequestWidget(widget.call)); widgets.add(AliceCallResponseWidget(widget.call)); diff --git a/lib/src/ui/page/alice_calls_list_screen.dart b/lib/src/ui/page/alice_calls_list_screen.dart index ac4d17eb..9ff83f33 100644 --- a/lib/src/ui/page/alice_calls_list_screen.dart +++ b/lib/src/ui/page/alice_calls_list_screen.dart @@ -1,3 +1,4 @@ +// ignore_for_file: cascade_invocations import 'package:alice/src/core/alice_core.dart'; import 'package:alice/src/core/alice_logger.dart'; import 'package:alice/src/helper/alice_alert_helper.dart'; @@ -6,22 +7,21 @@ import 'package:alice/src/model/alice_menu_item.dart'; import 'package:alice/src/model/alice_sort_option.dart'; import 'package:alice/src/model/alice_tab_item.dart'; import 'package:alice/src/ui/page/alice_call_details_screen.dart'; +import 'package:alice/src/ui/page/alice_stats_screen.dart'; import 'package:alice/src/ui/widget/alice_call_list_item_widget.dart'; import 'package:alice/src/ui/widget/alice_log_list_widget.dart'; import 'package:alice/src/ui/widget/alice_raw_log_list_widger.dart'; import 'package:alice/src/utils/alice_constants.dart'; import 'package:flutter/material.dart'; -import 'alice_stats_screen.dart'; - class AliceCallsListScreen extends StatefulWidget { final AliceCore _aliceCore; final AliceLogger? _aliceLogger; - const AliceCallsListScreen(this._aliceCore, this._aliceLogger); + const AliceCallsListScreen(this._aliceCore, this._aliceLogger, {super.key}); @override - _AliceCallsListScreenState createState() => _AliceCallsListScreenState(); + State createState() => _AliceCallsListScreenState(); } class _AliceCallsListScreenState extends State @@ -43,10 +43,10 @@ class _AliceCallsListScreenState extends State AliceCore get aliceCore => widget._aliceCore; _AliceCallsListScreenState() { - _menuItems.add(AliceMenuItem("Sort", Icons.sort)); - _menuItems.add(AliceMenuItem("Delete", Icons.delete)); - _menuItems.add(AliceMenuItem("Stats", Icons.insert_chart)); - _menuItems.add(AliceMenuItem("Save", Icons.save)); + _menuItems.add(AliceMenuItem('Sort', Icons.sort)); + _menuItems.add(AliceMenuItem('Delete', Icons.delete)); + _menuItems.add(AliceMenuItem('Stats', Icons.insert_chart)); + _menuItems.add(AliceMenuItem('Save', Icons.save)); } @override @@ -89,7 +89,7 @@ class _AliceCallsListScreenState extends State indicatorColor: AliceConstants.orange, tabs: [ for (final item in _tabItems) - Tab(text: item.title.toUpperCase()) + Tab(text: item.title.toUpperCase()), ], ), ), @@ -124,21 +124,22 @@ class _AliceCallsListScreenState extends State mainAxisAlignment: MainAxisAlignment.end, children: [ FloatingActionButton( - heroTag: 'h1', - child: Icon(Icons.arrow_upward, color: AliceConstants.white), - backgroundColor: AliceConstants.orange, - onPressed: () { - _scrollLogsList(true); - }), + heroTag: 'h1', + backgroundColor: AliceConstants.orange, + onPressed: () { + _scrollLogsList(true); + }, + child: Icon(Icons.arrow_upward, color: AliceConstants.white), + ), const SizedBox(height: 8), FloatingActionButton( - heroTag: 'h2', - child: - Icon(Icons.arrow_downward, color: AliceConstants.white), - backgroundColor: AliceConstants.orange, - onPressed: () { - _scrollLogsList(false); - }), + heroTag: 'h2', + backgroundColor: AliceConstants.orange, + onPressed: () { + _scrollLogsList(false); + }, + child: Icon(Icons.arrow_downward, color: AliceConstants.white), + ), ], ) : const SizedBox(); @@ -168,10 +169,10 @@ class _AliceCallsListScreenState extends State void _showClearLogsDialog() { AliceAlertHelper.showAlert( context, - "Delete logs", - "Do you want to clear logs?", - firstButtonTitle: "No", - secondButtonTitle: "Yes", + 'Delete logs', + 'Do you want to clear logs?', + firstButtonTitle: 'No', + secondButtonTitle: 'Yes', secondButtonAction: _onLogsClearClicked, ); } @@ -196,7 +197,7 @@ class _AliceCallsListScreenState extends State setState(() { _searchEnabled = !_searchEnabled; if (!_searchEnabled) { - _queryTextEditingController.text = ""; + _queryTextEditingController.text = ''; } }); } @@ -206,14 +207,14 @@ class _AliceCallsListScreenState extends State _selectedIndex = index; if (_selectedIndex == 1) { _searchEnabled = false; - _queryTextEditingController.text = ""; + _queryTextEditingController.text = ''; } }); } Widget _buildMenuButton() { return PopupMenuButton( - onSelected: (AliceMenuItem item) => _onMenuItemSelected(item), + onSelected: _onMenuItemSelected, itemBuilder: (BuildContext context) { return _menuItems.map((AliceMenuItem item) { return PopupMenuItem( @@ -227,7 +228,7 @@ class _AliceCallsListScreenState extends State const Padding( padding: EdgeInsets.only(left: 10), ), - Text(item.title) + Text(item.title), ], ), ); @@ -237,7 +238,7 @@ class _AliceCallsListScreenState extends State } Widget _buildTitleWidget() { - return const Text("Alice"); + return const Text('Alice'); } Widget _buildSearchField() { @@ -245,23 +246,23 @@ class _AliceCallsListScreenState extends State controller: _queryTextEditingController, autofocus: true, decoration: InputDecoration( - hintText: "Search http request...", - hintStyle: TextStyle(fontSize: 16.0, color: AliceConstants.grey), + hintText: 'Search http request...', + hintStyle: TextStyle(fontSize: 16, color: AliceConstants.grey), border: InputBorder.none, ), - style: const TextStyle(fontSize: 16.0), + style: const TextStyle(fontSize: 16), onChanged: _updateSearchQuery, ); } void _onMenuItemSelected(AliceMenuItem menuItem) { - if (menuItem.title == "Sort") { + if (menuItem.title == 'Sort') { _showSortDialog(); } - if (menuItem.title == "Delete") { + if (menuItem.title == 'Delete') { _showRemoveDialog(); } - if (menuItem.title == "Stats") { + if (menuItem.title == 'Stats') { _showStatsScreen(); } } @@ -270,8 +271,8 @@ class _AliceCallsListScreenState extends State return StreamBuilder>( stream: aliceCore.callsSubject, builder: (context, snapshot) { - List calls = snapshot.data ?? []; - final String query = _queryTextEditingController.text.trim(); + var calls = snapshot.data ?? []; + final query = _queryTextEditingController.text.trim(); if (query.isNotEmpty) { calls = calls .where( @@ -302,30 +303,30 @@ class _AliceCallsListScreenState extends State ), const SizedBox(height: 6), const Text( - "There are no calls to show", + 'There are no calls to show', style: TextStyle(fontSize: 18), ), const SizedBox(height: 12), - Column( + const Column( crossAxisAlignment: CrossAxisAlignment.start, - children: const [ + children: [ Text( - "• Check if you send any http request", + '• Check if you send any http request', style: TextStyle(fontSize: 12), textAlign: TextAlign.center, ), Text( - "• Check your Alice configuration", + '• Check your Alice configuration', style: TextStyle(fontSize: 12), textAlign: TextAlign.center, ), Text( - "• Check search filters", + '• Check search filters', style: TextStyle(fontSize: 12), textAlign: TextAlign.center, - ) + ), ], - ) + ), ], ), ), @@ -333,7 +334,7 @@ class _AliceCallsListScreenState extends State } Widget _buildCallsListWidget(List calls) { - final List callsSorted = List.of(calls); + final callsSorted = List.of(calls); switch (_sortOption) { case AliceSortOption.time: if (_sortAscending) { @@ -345,7 +346,6 @@ class _AliceCallsListScreenState extends State (call1, call2) => call2.createdTime.compareTo(call1.createdTime), ); } - break; case AliceSortOption.responseTime: if (_sortAscending) { callsSorted.sort(); @@ -359,7 +359,6 @@ class _AliceCallsListScreenState extends State call2.response?.time.compareTo(call1.response!.time) ?? -1, ); } - break; case AliceSortOption.responseCode: if (_sortAscending) { callsSorted.sort( @@ -374,7 +373,6 @@ class _AliceCallsListScreenState extends State -1, ); } - break; case AliceSortOption.responseSize: if (_sortAscending) { callsSorted.sort( @@ -387,7 +385,6 @@ class _AliceCallsListScreenState extends State call2.response?.size.compareTo(call1.response!.size) ?? -1, ); } - break; case AliceSortOption.endpoint: if (_sortAscending) { callsSorted @@ -396,9 +393,7 @@ class _AliceCallsListScreenState extends State callsSorted .sort((call1, call2) => call2.endpoint.compareTo(call1.endpoint)); } - break; - default: - break; + case null: } return ListView.builder( @@ -421,12 +416,12 @@ class _AliceCallsListScreenState extends State void _showRemoveDialog() { AliceAlertHelper.showAlert( context, - "Delete calls", - "Do you want to delete http calls?", - firstButtonTitle: "No", + 'Delete calls', + 'Do you want to delete http calls?', + firstButtonTitle: 'No', firstButtonAction: () => {}, - secondButtonTitle: "Yes", - secondButtonAction: () => _removeCalls(), + secondButtonTitle: 'Yes', + secondButtonAction: _removeCalls, ); } @@ -456,30 +451,28 @@ class _AliceCallsListScreenState extends State brightness: Brightness.light, ), child: AlertDialog( - title: const Text("Select filter"), + title: const Text('Select filter'), content: StatefulBuilder( builder: (context, setState) { return Wrap( children: [ - ...AliceSortOption.values - .map( - (AliceSortOption sortOption) => - RadioListTile( - title: Text(sortOption.name), - value: sortOption, - groupValue: _sortOption, - onChanged: (AliceSortOption? value) { - setState(() { - _sortOption = value; - }); - }, - ), - ) - .toList(), + ...AliceSortOption.values.map( + (AliceSortOption sortOption) => + RadioListTile( + title: Text(sortOption.name), + value: sortOption, + groupValue: _sortOption, + onChanged: (AliceSortOption? value) { + setState(() { + _sortOption = value; + }); + }, + ), + ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text("Descending"), + const Text('Descending'), Switch( value: _sortAscending, onChanged: (value) { @@ -490,9 +483,9 @@ class _AliceCallsListScreenState extends State activeTrackColor: Colors.grey, activeColor: Colors.white, ), - const Text("Ascending") + const Text('Ascending'), ], - ) + ), ], ); }, @@ -502,14 +495,14 @@ class _AliceCallsListScreenState extends State onPressed: () { Navigator.of(context).pop(); }, - child: const Text("Cancel"), + child: const Text('Cancel'), ), TextButton( onPressed: () { Navigator.of(context).pop(); sortCalls(); }, - child: const Text("Use filter"), + child: const Text('Use filter'), ), ], ), @@ -556,7 +549,7 @@ class _AliceCallsListScreenState extends State ), const SizedBox(height: 6), const Text( - "There are no logs to show", + 'There are no logs to show', style: TextStyle(fontSize: 18), ), ], diff --git a/lib/src/ui/page/alice_stats_screen.dart b/lib/src/ui/page/alice_stats_screen.dart index 8ff0e191..7a8bd744 100644 --- a/lib/src/ui/page/alice_stats_screen.dart +++ b/lib/src/ui/page/alice_stats_screen.dart @@ -7,7 +7,7 @@ import 'package:flutter/material.dart'; class AliceStatsScreen extends StatelessWidget { final AliceCore aliceCore; - const AliceStatsScreen(this.aliceCore); + const AliceStatsScreen(this.aliceCore, {super.key}); @override Widget build(BuildContext context) { @@ -20,7 +20,7 @@ class AliceStatsScreen extends StatelessWidget { ), child: Scaffold( appBar: AppBar( - title: const Text("Alice - HTTP Inspector - Stats"), + title: const Text('Alice - HTTP Inspector - Stats'), ), body: Container( padding: const EdgeInsets.all(8), @@ -35,38 +35,38 @@ class AliceStatsScreen extends StatelessWidget { List _buildMainListWidgets() { return [ - _getRow("Total requests:", "${_getTotalRequests()}"), - _getRow("Pending requests:", "${_getPendingRequests()}"), - _getRow("Success requests:", "${_getSuccessRequests()}"), - _getRow("Redirection requests:", "${_getRedirectionRequests()}"), - _getRow("Error requests:", "${_getErrorRequests()}"), + _getRow('Total requests:', '${_getTotalRequests()}'), + _getRow('Pending requests:', '${_getPendingRequests()}'), + _getRow('Success requests:', '${_getSuccessRequests()}'), + _getRow('Redirection requests:', '${_getRedirectionRequests()}'), + _getRow('Error requests:', '${_getErrorRequests()}'), _getRow( - "Bytes send:", + 'Bytes send:', AliceConversionHelper.formatBytes(_getBytesSent()), ), _getRow( - "Bytes received:", + 'Bytes received:', AliceConversionHelper.formatBytes(_getBytesReceived()), ), _getRow( - "Average request time:", + 'Average request time:', AliceConversionHelper.formatTime(_getAverageRequestTime()), ), _getRow( - "Max request time:", + 'Max request time:', AliceConversionHelper.formatTime(_getMaxRequestTime()), ), _getRow( - "Min request time:", + 'Min request time:', AliceConversionHelper.formatTime(_getMinRequestTime()), ), - _getRow("Get requests:", "${_getRequests("GET")} "), - _getRow("Post requests:", "${_getRequests("POST")} "), - _getRow("Delete requests:", "${_getRequests("DELETE")} "), - _getRow("Put requests:", "${_getRequests("PUT")} "), - _getRow("Patch requests:", "${_getRequests("PATCH")} "), - _getRow("Secured requests:", "${_getSecuredRequests()}"), - _getRow("Unsecured requests:", "${_getUnsecuredRequests()}"), + _getRow('Get requests:', "${_getRequests("GET")} "), + _getRow('Post requests:', "${_getRequests("POST")} "), + _getRow('Delete requests:', "${_getRequests("DELETE")} "), + _getRow('Put requests:', "${_getRequests("PUT")} "), + _getRow('Patch requests:', "${_getRequests("PATCH")} "), + _getRow('Secured requests:', '${_getSecuredRequests()}'), + _getRow('Unsecured requests:', '${_getUnsecuredRequests()}'), ]; } @@ -83,7 +83,7 @@ class AliceStatsScreen extends StatelessWidget { Text( value, style: _getValueTextStyle(), - ) + ), ], ); } @@ -134,7 +134,7 @@ class AliceStatsScreen extends StatelessWidget { calls.where((call) => call.loading).toList().length; int _getBytesSent() { - int bytes = 0; + var bytes = 0; calls.forEach((AliceHttpCall call) { bytes += call.request!.size; }); @@ -142,7 +142,7 @@ class AliceStatsScreen extends StatelessWidget { } int _getBytesReceived() { - int bytes = 0; + var bytes = 0; calls.forEach((AliceHttpCall call) { if (call.response != null) { bytes += call.response!.size; @@ -152,8 +152,8 @@ class AliceStatsScreen extends StatelessWidget { } int _getAverageRequestTime() { - int requestTimeSum = 0; - int requestsWithDurationCount = 0; + var requestTimeSum = 0; + var requestsWithDurationCount = 0; calls.forEach((AliceHttpCall call) { if (call.duration != 0) { requestTimeSum = call.duration; @@ -167,7 +167,7 @@ class AliceStatsScreen extends StatelessWidget { } int _getMaxRequestTime() { - int maxRequestTime = 0; + var maxRequestTime = 0; calls.forEach((AliceHttpCall call) { if (call.duration > maxRequestTime) { maxRequestTime = call.duration; @@ -177,7 +177,7 @@ class AliceStatsScreen extends StatelessWidget { } int _getMinRequestTime() { - int minRequestTime = 10000000; + var minRequestTime = 10000000; if (calls.isEmpty) { minRequestTime = 0; } else { diff --git a/lib/src/ui/widget/alice_base_call_details_widget.dart b/lib/src/ui/widget/alice_base_call_details_widget.dart index d0136978..d49245c9 100644 --- a/lib/src/ui/widget/alice_base_call_details_widget.dart +++ b/lib/src/ui/widget/alice_base_call_details_widget.dart @@ -26,7 +26,7 @@ abstract class AliceBaseCallDetailsWidgetState ), const Padding( padding: EdgeInsets.only(bottom: 18), - ) + ), ], ); } diff --git a/lib/src/ui/widget/alice_call_error_widget.dart b/lib/src/ui/widget/alice_call_error_widget.dart index 4afd310a..9cfadb37 100644 --- a/lib/src/ui/widget/alice_call_error_widget.dart +++ b/lib/src/ui/widget/alice_call_error_widget.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; class AliceCallErrorWidget extends StatefulWidget { final AliceHttpCall call; - const AliceCallErrorWidget(this.call); + const AliceCallErrorWidget(this.call, {super.key}); @override State createState() { @@ -20,20 +20,20 @@ class _AliceCallErrorWidgetState @override Widget build(BuildContext context) { if (_call.error != null) { - final List rows = []; + final rows = []; final dynamic error = _call.error!.error; - var errorText = "Error is empty"; + var errorText = 'Error is empty'; if (error != null) { errorText = error.toString(); } - rows.add(getListRow("Error:", errorText)); + rows.add(getListRow('Error:', errorText)); return Container( padding: const EdgeInsets.all(6), child: ListView(children: rows), ); } else { - return const Center(child: Text("Nothing to display here")); + return const Center(child: Text('Nothing to display here')); } } } diff --git a/lib/src/ui/widget/alice_call_list_item_widget.dart b/lib/src/ui/widget/alice_call_list_item_widget.dart index ae952611..92198efb 100644 --- a/lib/src/ui/widget/alice_call_list_item_widget.dart +++ b/lib/src/ui/widget/alice_call_list_item_widget.dart @@ -1,3 +1,4 @@ +// ignore_for_file: cascade_invocations, avoid_dynamic_calls import 'package:alice/src/helper/alice_conversion_helper.dart'; import 'package:alice/src/model/alice_http_call.dart'; import 'package:alice/src/model/alice_http_response.dart'; @@ -11,7 +12,7 @@ class AliceCallListItemWidget extends StatelessWidget { final AliceHttpCall call; final Function itemClickAction; - const AliceCallListItemWidget(this.call, this.itemClickAction); + const AliceCallListItemWidget(this.call, this.itemClickAction, {super.key}); @override Widget build(BuildContext context) { @@ -32,22 +33,22 @@ class AliceCallListItemWidget extends StatelessWidget { const SizedBox(height: 4), _buildServerRow(), const SizedBox(height: 4), - _buildStatsRow() + _buildStatsRow(), ], ), ), - _buildResponseColumn(context) + _buildResponseColumn(context), ], ), ), - _buildDivider() + _buildDivider(), ], ), ); } Widget _buildMethodAndEndpointRow(BuildContext context) { - final Color? textColor = _getEndpointTextColor(context); + final textColor = _getEndpointTextColor(context); return Row( children: [ Text( @@ -70,7 +71,7 @@ class AliceCallListItemWidget extends StatelessWidget { ), ), ), - ) + ), ], ); } @@ -111,11 +112,11 @@ class AliceCallListItemWidget extends StatelessWidget { ), Flexible( child: Text( - "${AliceConversionHelper.formatBytes(call.request!.size)} / " - "${AliceConversionHelper.formatBytes(call.response!.size)}", + '${AliceConversionHelper.formatBytes(call.request!.size)} / ' + '${AliceConversionHelper.formatBytes(call.response!.size)}', style: const TextStyle(fontSize: 12), ), - ) + ), ], ); } @@ -125,18 +126,18 @@ class AliceCallListItemWidget extends StatelessWidget { } String _formatTime(DateTime time) { - return "${formatTimeUnit(time.hour)}:" - "${formatTimeUnit(time.minute)}:" - "${formatTimeUnit(time.second)}:" - "${formatTimeUnit(time.millisecond)}"; + return '${formatTimeUnit(time.hour)}:' + '${formatTimeUnit(time.minute)}:' + '${formatTimeUnit(time.second)}:' + '${formatTimeUnit(time.millisecond)}'; } String formatTimeUnit(int timeUnit) { - return (timeUnit < 10) ? "0$timeUnit" : "$timeUnit"; + return (timeUnit < 10) ? '0$timeUnit' : '$timeUnit'; } Widget _buildResponseColumn(BuildContext context) { - final List widgets = []; + final widgets = []; if (call.loading) { widgets.add( SizedBox( @@ -162,7 +163,7 @@ class AliceCallListItemWidget extends StatelessWidget { ), ), ); - return Container( + return SizedBox( width: 50, child: Column( children: widgets, @@ -171,7 +172,7 @@ class AliceCallListItemWidget extends StatelessWidget { } Color? _getStatusTextColor(BuildContext context) { - final int? status = call.response!.status; + final status = call.response!.status; if (status == -1) { return AliceConstants.red; } else if (status! < 200) { @@ -197,11 +198,11 @@ class AliceCallListItemWidget extends StatelessWidget { String _getStatus(AliceHttpResponse response) { if (response.status == -1) { - return "ERR"; + return 'ERR'; } else if (response.status == 0) { - return "???"; + return '???'; } else { - return "${response.status}"; + return '${response.status}'; } } diff --git a/lib/src/ui/widget/alice_call_overview_widget.dart b/lib/src/ui/widget/alice_call_overview_widget.dart index cbdb1e1b..8cd173f9 100644 --- a/lib/src/ui/widget/alice_call_overview_widget.dart +++ b/lib/src/ui/widget/alice_call_overview_widget.dart @@ -1,3 +1,5 @@ +// ignore_for_file: cascade_invocations + import 'package:alice/src/model/alice_http_call.dart'; import 'package:alice/src/ui/widget/alice_base_call_details_widget.dart'; import 'package:flutter/material.dart'; @@ -5,7 +7,7 @@ import 'package:flutter/material.dart'; class AliceCallOverviewWidget extends StatefulWidget { final AliceHttpCall call; - const AliceCallOverviewWidget(this.call); + const AliceCallOverviewWidget(this.call, {super.key}); @override State createState() { @@ -19,17 +21,17 @@ class _AliceCallOverviewWidget @override Widget build(BuildContext context) { - final List rows = []; - rows.add(getListRow("Method: ", _call.method)); - rows.add(getListRow("Server: ", _call.server)); - rows.add(getListRow("Endpoint: ", _call.endpoint)); - rows.add(getListRow("Started:", _call.request!.time.toString())); - rows.add(getListRow("Finished:", _call.response!.time.toString())); - rows.add(getListRow("Duration:", formatDuration(_call.duration))); - rows.add(getListRow("Bytes sent:", formatBytes(_call.request!.size))); - rows.add(getListRow("Bytes received:", formatBytes(_call.response!.size))); - rows.add(getListRow("Client:", _call.client)); - rows.add(getListRow("Secure:", _call.secure.toString())); + final rows = []; + rows.add(getListRow('Method: ', _call.method)); + rows.add(getListRow('Server: ', _call.server)); + rows.add(getListRow('Endpoint: ', _call.endpoint)); + rows.add(getListRow('Started:', _call.request!.time.toString())); + rows.add(getListRow('Finished:', _call.response!.time.toString())); + rows.add(getListRow('Duration:', formatDuration(_call.duration))); + rows.add(getListRow('Bytes sent:', formatBytes(_call.request!.size))); + rows.add(getListRow('Bytes received:', formatBytes(_call.response!.size))); + rows.add(getListRow('Client:', _call.client)); + rows.add(getListRow('Secure:', _call.secure.toString())); return Container( padding: const EdgeInsets.all(6), child: ListView(children: rows), diff --git a/lib/src/ui/widget/alice_call_request_widget.dart b/lib/src/ui/widget/alice_call_request_widget.dart index 3cf0e64a..b10c07ec 100644 --- a/lib/src/ui/widget/alice_call_request_widget.dart +++ b/lib/src/ui/widget/alice_call_request_widget.dart @@ -1,3 +1,4 @@ +// ignore_for_file: cascade_invocations import 'package:alice/src/model/alice_http_call.dart'; import 'package:alice/src/ui/widget/alice_base_call_details_widget.dart'; import 'package:flutter/material.dart'; @@ -5,7 +6,7 @@ import 'package:flutter/material.dart'; class AliceCallRequestWidget extends StatefulWidget { final AliceHttpCall call; - const AliceCallRequestWidget(this.call); + const AliceCallRequestWidget(this.call, {super.key}); @override State createState() { @@ -19,37 +20,37 @@ class _AliceCallRequestWidget @override Widget build(BuildContext context) { - final List rows = []; - rows.add(getListRow("Started:", _call.request!.time.toString())); - rows.add(getListRow("Bytes sent:", formatBytes(_call.request!.size))); + final rows = []; + rows.add(getListRow('Started:', _call.request!.time.toString())); + rows.add(getListRow('Bytes sent:', formatBytes(_call.request!.size))); rows.add( - getListRow("Content type:", getContentType(_call.request!.headers)!), + getListRow('Content type:', getContentType(_call.request!.headers)!), ); final dynamic body = _call.request!.body; - var bodyContent = "Body is empty"; + var bodyContent = 'Body is empty'; if (body != null) { bodyContent = formatBody(body, getContentType(_call.request!.headers)); } - rows.add(getListRow("Body:", bodyContent)); + rows.add(getListRow('Body:', bodyContent)); final formDataFields = _call.request!.formDataFields; if (formDataFields?.isNotEmpty == true) { - rows.add(getListRow("Form data fields: ", "")); + rows.add(getListRow('Form data fields: ', '')); formDataFields!.forEach( (field) { - rows.add(getListRow(" • ${field.name}:", field.value)); + rows.add(getListRow(' • ${field.name}:', field.value)); }, ); } final formDataFiles = _call.request!.formDataFiles; if (formDataFiles?.isNotEmpty == true) { - rows.add(getListRow("Form data files: ", "")); + rows.add(getListRow('Form data files: ', '')); formDataFiles!.forEach( (field) { rows.add( getListRow( - " • ${field.fileName}:", - "${field.contentType} / ${field.length} B", + ' • ${field.fileName}:', + '${field.contentType} / ${field.length} B', ), ); }, @@ -57,22 +58,22 @@ class _AliceCallRequestWidget } final headers = _call.request!.headers; - var headersContent = "Headers are empty"; + var headersContent = 'Headers are empty'; if (headers.isNotEmpty) { - headersContent = ""; + headersContent = ''; } - rows.add(getListRow("Headers: ", headersContent)); + rows.add(getListRow('Headers: ', headersContent)); _call.request!.headers.forEach((header, dynamic value) { - rows.add(getListRow(" • $header:", value.toString())); + rows.add(getListRow(' • $header:', value.toString())); }); final queryParameters = _call.request!.queryParameters; - var queryParametersContent = "Query parameters are empty"; + var queryParametersContent = 'Query parameters are empty'; if (queryParameters.isNotEmpty) { - queryParametersContent = ""; + queryParametersContent = ''; } - rows.add(getListRow("Query Parameters: ", queryParametersContent)); + rows.add(getListRow('Query Parameters: ', queryParametersContent)); _call.request!.queryParameters.forEach((query, dynamic value) { - rows.add(getListRow(" • $query:", value.toString())); + rows.add(getListRow(' • $query:', value.toString())); }); return Container( diff --git a/lib/src/ui/widget/alice_call_response_widget.dart b/lib/src/ui/widget/alice_call_response_widget.dart index 2f9481e8..6da17f44 100644 --- a/lib/src/ui/widget/alice_call_response_widget.dart +++ b/lib/src/ui/widget/alice_call_response_widget.dart @@ -1,3 +1,4 @@ +// ignore_for_file: cascade_invocations import 'package:alice/src/model/alice_http_call.dart'; import 'package:alice/src/ui/widget/alice_base_call_details_widget.dart'; import 'package:alice/src/utils/alice_constants.dart'; @@ -7,7 +8,7 @@ import 'package:url_launcher/url_launcher.dart'; class AliceCallResponseWidget extends StatefulWidget { final AliceHttpCall call; - const AliceCallResponseWidget(this.call); + const AliceCallResponseWidget(this.call, {super.key}); @override State createState() { @@ -17,11 +18,11 @@ class AliceCallResponseWidget extends StatefulWidget { class _AliceCallResponseWidgetState extends AliceBaseCallDetailsWidgetState { - static const _imageContentType = "image"; - static const _videoContentType = "video"; - static const _jsonContentType = "json"; - static const _xmlContentType = "xml"; - static const _textContentType = "text"; + static const _imageContentType = 'image'; + static const _videoContentType = 'video'; + static const _jsonContentType = 'json'; + static const _xmlContentType = 'xml'; + static const _textContentType = 'text'; static const _kLargeOutputSize = 100000; bool _showLargeBody = false; @@ -31,7 +32,7 @@ class _AliceCallResponseWidgetState @override Widget build(BuildContext context) { - final List rows = []; + final rows = []; if (!_call.loading) { rows.addAll(_buildGeneralDataRows()); rows.addAll(_buildHeadersRows()); @@ -42,12 +43,12 @@ class _AliceCallResponseWidgetState child: ListView(children: rows), ); } else { - return Center( + return const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, - children: const [ + children: [ CircularProgressIndicator(), - Text("Awaiting response...") + Text('Awaiting response...'), ], ), ); @@ -55,38 +56,38 @@ class _AliceCallResponseWidgetState } List _buildGeneralDataRows() { - final List rows = []; - rows.add(getListRow("Received:", _call.response!.time.toString())); - rows.add(getListRow("Bytes received:", formatBytes(_call.response!.size))); + final rows = []; + rows.add(getListRow('Received:', _call.response!.time.toString())); + rows.add(getListRow('Bytes received:', formatBytes(_call.response!.size))); final status = _call.response!.status; - var statusText = "$status"; + var statusText = '$status'; if (status == -1) { - statusText = "Error"; + statusText = 'Error'; } - rows.add(getListRow("Status:", statusText)); + rows.add(getListRow('Status:', statusText)); return rows; } List _buildHeadersRows() { - final List rows = []; + final rows = []; final headers = _call.response!.headers; - var headersContent = "Headers are empty"; + var headersContent = 'Headers are empty'; if (headers != null && headers.isNotEmpty) { - headersContent = ""; + headersContent = ''; } - rows.add(getListRow("Headers: ", headersContent)); + rows.add(getListRow('Headers: ', headersContent)); if (_call.response!.headers != null) { _call.response!.headers!.forEach((header, value) { - rows.add(getListRow(" • $header:", value.toString())); + rows.add(getListRow(' • $header:', value)); }); } return rows; } List _buildBodyRows() { - final List rows = []; + final rows = []; if (_isImageResponse()) { rows.addAll(_buildImageBodyRows()); } else if (_isVideoResponse()) { @@ -105,16 +106,16 @@ class _AliceCallResponseWidgetState } List _buildImageBodyRows() { - final List rows = []; + final rows = []; rows.add( Column( children: [ - Row( - children: const [ + const Row( + children: [ Text( - "Body: Image", + 'Body: Image', style: TextStyle(fontWeight: FontWeight.bold), - ) + ), ], ), const SizedBox(height: 8), @@ -146,14 +147,14 @@ class _AliceCallResponseWidgetState } List _buildLargeBodyTextRows() { - final List rows = []; + final rows = []; if (_showLargeBody) { return _buildTextBodyRows(); } else { rows.add( getListRow( - "Body:", - "Too large to show (${_call.response!.body.toString().length} Bytes)", + 'Body:', + 'Too large to show (${_call.response!.body.toString().length} Bytes)', ), ); rows.add(const SizedBox(height: 8)); @@ -168,64 +169,67 @@ class _AliceCallResponseWidgetState _showLargeBody = true; }); }, - child: const Text("Show body"), + child: const Text('Show body'), ), ); rows.add(const SizedBox(height: 8)); - rows.add(const Text("Warning! It will take some time to render output.")); + rows.add(const Text('Warning! It will take some time to render output.')); } return rows; } List _buildTextBodyRows() { - final List rows = []; + final rows = []; final headers = _call.response!.headers; final bodyContent = formatBody(_call.response!.body, getContentType(headers)); - rows.add(getListRow("Body:", bodyContent)); + rows.add(getListRow('Body:', bodyContent)); return rows; } List _buildVideoBodyRows() { - final List rows = []; + final rows = []; rows.add( - Row( - children: const [ + const Row( + children: [ Text( - "Body: Video", + 'Body: Video', style: TextStyle(fontWeight: FontWeight.bold), - ) + ), ], ), ); rows.add(const SizedBox(height: 8)); - rows.add(TextButton( - child: Text("Open video in web browser"), - onPressed: () async { - await launchUrl(Uri.parse(_call.uri)); - }, - )); + rows.add( + TextButton( + child: const Text('Open video in web browser'), + onPressed: () async { + await launchUrl(Uri.parse(_call.uri)); + }, + ), + ); rows.add(const SizedBox(height: 8)); return rows; } List _buildUnknownBodyRows() { - final List rows = []; + final rows = []; final headers = _call.response!.headers; - final contentType = getContentType(headers) ?? ""; + final contentType = getContentType(headers) ?? ''; if (_showUnsupportedBody) { final bodyContent = formatBody(_call.response!.body, getContentType(headers)); - rows.add(getListRow("Body:", bodyContent)); + rows.add(getListRow('Body:', bodyContent)); } else { rows.add( getListRow( - "Body:", - "Unsupported body. Alice can render video/image/text body. " + 'Body:', + 'Unsupported body. Alice can render video/image/text body. ' "Response has Content-Type: $contentType which can't be handled. " - "If you're feeling lucky you can try button below to try render body" - " as text, but it may fail.", + "If you're feeling lucky you can try button " + 'below to try render body' + ' as text, but it may fail.', ), ); rows.add( @@ -239,7 +243,7 @@ class _AliceCallResponseWidgetState _showUnsupportedBody = true; }); }, - child: const Text("Show unsupported body"), + child: const Text('Show unsupported body'), ), ); } @@ -247,7 +251,7 @@ class _AliceCallResponseWidgetState } Map _buildRequestHeaders() { - final Map requestHeaders = {}; + final requestHeaders = {}; if (_call.request?.headers != null) { requestHeaders.addAll( _call.request!.headers.map( @@ -273,7 +277,7 @@ class _AliceCallResponseWidgetState } bool _isTextResponse() { - final String responseContentTypeLowerCase = + final responseContentTypeLowerCase = _getContentTypeOfResponse()!.toLowerCase(); return responseContentTypeLowerCase.contains(_jsonContentType) || diff --git a/lib/src/ui/widget/alice_log_list_widget.dart b/lib/src/ui/widget/alice_log_list_widget.dart index 7026c294..c1104d96 100644 --- a/lib/src/ui/widget/alice_log_list_widget.dart +++ b/lib/src/ui/widget/alice_log_list_widget.dart @@ -1,3 +1,5 @@ +// ignore_for_file: cascade_invocations, avoid_dynamic_calls + import 'dart:convert'; import 'dart:ui'; @@ -11,6 +13,7 @@ class AliceLogListWidget extends StatefulWidget { required this.logsListenable, required this.scrollController, required this.emptyWidget, + super.key, }); final ValueListenable> logsListenable; @@ -22,7 +25,7 @@ class AliceLogListWidget extends StatefulWidget { } class _AliceLogListWidgetState extends State { - var _minLevel = DiagnosticLevel.debug; + final _minLevel = DiagnosticLevel.debug; @override Widget build(BuildContext context) { @@ -67,7 +70,7 @@ class AliceLogEntryWidget extends StatelessWidget { text: formattedTimestamp, style: textTheme.bodySmall?.copyWith( color: color.withOpacity(0.6), - fontFeatures: [FontFeature.tabularFigures()], + fontFeatures: [const FontFeature.tabularFigures()], ), ), TextSpan(text: ' ${log.message}'), @@ -86,7 +89,7 @@ class AliceLogEntryWidget extends StatelessWidget { return InkWell( onLongPress: () => _copyToClipboard(context), child: Padding( - padding: EdgeInsets.symmetric(horizontal: 16, vertical: 4), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -95,7 +98,7 @@ class AliceLogEntryWidget extends StatelessWidget { size: 16, color: color, ), - SizedBox(width: 4), + const SizedBox(width: 4), Expanded(child: content), ], ), @@ -115,7 +118,7 @@ class AliceLogEntryWidget extends StatelessWidget { return [ TextSpan( text: '\n$title:${addLineBreakAfterTitle ? '\n' : ' '}', - style: TextStyle(fontWeight: FontWeight.bold), + style: const TextStyle(fontWeight: FontWeight.bold), ), TextSpan(text: string), ]; @@ -178,7 +181,7 @@ class AliceLogEntryWidget extends StatelessWidget { ].join('\n'); await Clipboard.setData(ClipboardData(text: text)); ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text('Copied!'))); + .showSnackBar(const SnackBar(content: Text('Copied!'))); } String? _stringify(dynamic object) { diff --git a/lib/src/ui/widget/alice_raw_log_list_widger.dart b/lib/src/ui/widget/alice_raw_log_list_widger.dart index c41e66f3..675418e9 100644 --- a/lib/src/ui/widget/alice_raw_log_list_widger.dart +++ b/lib/src/ui/widget/alice_raw_log_list_widger.dart @@ -3,11 +3,11 @@ import 'package:flutter/services.dart'; class AliceRawLogListWidget extends StatelessWidget { const AliceRawLogListWidget({ - Key? key, required this.scrollController, required this.getRawLogs, required this.emptyWidget, - }) : super(key: key); + super.key, + }); final ScrollController scrollController; final Future? getRawLogs; @@ -26,13 +26,13 @@ class AliceRawLogListWidget extends StatelessWidget { child: SingleChildScrollView( controller: scrollController, child: Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: InkWell( onLongPress: () => _copyToClipboard(snapshot.data!, context), child: Text( snapshot.data ?? '', - style: TextStyle(fontSize: 10), + style: const TextStyle(fontSize: 10), ), ), ), @@ -41,7 +41,7 @@ class AliceRawLogListWidget extends StatelessWidget { } return emptyWidget; } - return Center(child: CircularProgressIndicator()); + return const Center(child: CircularProgressIndicator()); }, ); } @@ -49,7 +49,7 @@ class AliceRawLogListWidget extends StatelessWidget { Future _copyToClipboard(String text, BuildContext context) async { await Clipboard.setData(ClipboardData(text: text)); ScaffoldMessenger.of(context).showSnackBar( - SnackBar( + const SnackBar( content: Text('Copied!'), ), ); diff --git a/lib/src/utils/alice_parser.dart b/lib/src/utils/alice_parser.dart index fe518ca2..9c0873ca 100644 --- a/lib/src/utils/alice_parser.dart +++ b/lib/src/utils/alice_parser.dart @@ -1,13 +1,13 @@ import 'dart:convert'; class AliceParser { - static const String _emptyBody = "Body is empty"; - static const String _unknownContentType = "Unknown"; - static const String _jsonContentTypeSmall = "content-type"; - static const String _jsonContentTypeBig = "Content-Type"; - static const String _stream = "Stream"; - static const String _applicationJson = "application/json"; - static const String _parseFailedText = "Failed to parse "; + static const String _emptyBody = 'Body is empty'; + static const String _unknownContentType = 'Unknown'; + static const String _jsonContentTypeSmall = 'content-type'; + static const String _jsonContentTypeBig = 'Content-Type'; + static const String _stream = 'Stream'; + static const String _applicationJson = 'application/json'; + static const String _parseFailedText = 'Failed to parse '; static const JsonEncoder encoder = JsonEncoder.withIndent(' '); static String _parseJson(dynamic json) { @@ -42,12 +42,13 @@ class AliceParser { bodyContent = bodyTemp; } } else { - if (body is String && body.contains("\n")) { + if (body is String && body.contains('\n')) { bodyContent = body; } else { if (body is String) { if (body.isNotEmpty) { - //body is minified json, so decode it to a map and let the encoder pretty print this map + //body is minified json, so decode it to a map and let the encoder + // pretty print this map bodyContent = _parseJson(_decodeJson(body)); } } else if (body is Stream) { diff --git a/pubspec.lock b/pubspec.lock index 1cf095c4..54aae95b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -26,7 +26,7 @@ packages: source: hosted version: "1.2.0" collection: - dependency: transitive + dependency: "direct main" description: name: collection sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a @@ -99,14 +99,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" - lint: - dependency: "direct dev" - description: - name: lint - sha256: f4bd4dbaa39f4ae8836f2d1275f2f32bc68b3a8cce0a0735dd1f7a601f06682a - url: "https://pub.dev" - source: hosted - version: "2.1.2" material_color_utilities: dependency: transitive description: @@ -116,7 +108,7 @@ packages: source: hosted version: "0.5.0" meta: - dependency: transitive + dependency: "direct main" description: name: meta sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e @@ -376,6 +368,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + very_good_analysis: + dependency: "direct dev" + description: + name: very_good_analysis + sha256: "9ae7f3a3bd5764fb021b335ca28a34f040cd0ab6eec00a1b213b445dae58a4b8" + url: "https://pub.dev" + source: hosted + version: "5.1.0" web: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c3b28b85..392cff5b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,6 +17,8 @@ dependencies: package_info_plus: ^4.0.2 share_plus: ^7.2.1 url_launcher: ^6.1.6 + collection: ^1.18.0 + meta: ^1.1.0 dev_dependencies: very_good_analysis: ^5.1.0