From 814130b004e9e9f140eaacbb22c633c549eda44f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 10:54:02 +0000 Subject: [PATCH 1/6] Initial plan From 02b8459ce28a2c7269489a06afeff579c959e656 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 11:05:50 +0000 Subject: [PATCH 2/6] Fix Polish character encoding in share functionality Co-authored-by: PiotrRogulski <18120733+PiotrRogulski@users.noreply.github.com> --- .../logger_log_details_screen.dart | 4 +- .../request_details_screen.dart | 6 +-- .../widgets/logs_inspector_share_button.dart | 6 +-- .../lib/src/ui/share_text_helper.dart | 41 +++++++++++++++++++ packages/leancode_debug_page/pubspec.yaml | 1 + 5 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 packages/leancode_debug_page/lib/src/ui/share_text_helper.dart diff --git a/packages/leancode_debug_page/lib/src/ui/logs_inspector/logger/logger_log_details_screen/logger_log_details_screen.dart b/packages/leancode_debug_page/lib/src/ui/logs_inspector/logger/logger_log_details_screen/logger_log_details_screen.dart index 9f679c2b..981a32c2 100644 --- a/packages/leancode_debug_page/lib/src/ui/logs_inspector/logger/logger_log_details_screen/logger_log_details_screen.dart +++ b/packages/leancode_debug_page/lib/src/ui/logs_inspector/logger/logger_log_details_screen/logger_log_details_screen.dart @@ -5,9 +5,9 @@ import 'package:leancode_debug_page/src/ui/debug_page_route.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/logger/level_color_extension.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/map_view.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/widgets/share_button.dart'; +import 'package:leancode_debug_page/src/ui/share_text_helper.dart'; import 'package:leancode_debug_page/src/ui/typography.dart'; import 'package:logging/logging.dart'; -import 'package:share_plus/share_plus.dart'; class LoggerLogDetailsRoute extends DebugPageRoute { LoggerLogDetailsRoute({required LogRecord logRecord}) @@ -94,7 +94,7 @@ class LoggerLogDetailsScreen extends StatelessWidget { return Scaffold( floatingActionButtonLocation: FloatingActionButtonLocation.startFloat, floatingActionButton: ShareButton( - onPressed: () => Share.share(_shareLogDetails()), + onPressed: () => shareTextWithEncoding(_shareLogDetails()), ), appBar: AppBar( title: const Text('Logger log details'), diff --git a/packages/leancode_debug_page/lib/src/ui/logs_inspector/requests/request_details_screen/request_details_screen.dart b/packages/leancode_debug_page/lib/src/ui/logs_inspector/requests/request_details_screen/request_details_screen.dart index 405be73b..ccf31a6f 100644 --- a/packages/leancode_debug_page/lib/src/ui/logs_inspector/requests/request_details_screen/request_details_screen.dart +++ b/packages/leancode_debug_page/lib/src/ui/logs_inspector/requests/request_details_screen/request_details_screen.dart @@ -6,7 +6,7 @@ import 'package:leancode_debug_page/src/ui/logs_inspector/requests/request_detai import 'package:leancode_debug_page/src/ui/logs_inspector/requests/request_details_screen/request_details_screen_response_tab.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/requests/request_details_screen/show_share_request_log_dialog.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/widgets/share_button.dart'; -import 'package:share_plus/share_plus.dart'; +import 'package:leancode_debug_page/src/ui/share_text_helper.dart'; class RequestDetailsRoute extends DebugPageRoute { RequestDetailsRoute(RequestLogRecord requestLog) @@ -28,9 +28,7 @@ class RequestDetailsScreen extends StatelessWidget { const RequestSharingConfiguration(includeResponse: true), ); - if (summary.isNotEmpty) { - await Share.share(summary); - } + await shareTextWithEncoding(summary); } @override diff --git a/packages/leancode_debug_page/lib/src/ui/logs_inspector/widgets/logs_inspector_share_button.dart b/packages/leancode_debug_page/lib/src/ui/logs_inspector/widgets/logs_inspector_share_button.dart index b8a0aaa1..e780093e 100644 --- a/packages/leancode_debug_page/lib/src/ui/logs_inspector/widgets/logs_inspector_share_button.dart +++ b/packages/leancode_debug_page/lib/src/ui/logs_inspector/widgets/logs_inspector_share_button.dart @@ -5,7 +5,7 @@ import 'package:leancode_debug_page/src/core/logs_summarizers/request_logs_summa import 'package:leancode_debug_page/src/ui/logs_inspector/logs_inspector.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/requests/request_details_screen/show_share_request_log_dialog.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/widgets/share_button.dart'; -import 'package:share_plus/share_plus.dart'; +import 'package:leancode_debug_page/src/ui/share_text_helper.dart'; class LogsInspectorShareButton extends StatelessWidget { const LogsInspectorShareButton({ @@ -40,9 +40,7 @@ class LogsInspectorShareButton extends StatelessWidget { throw StateError('Unknown tab'); } - if (sharedData.isNotEmpty) { - await Share.share(sharedData); - } + await shareTextWithEncoding(sharedData); }, ); } diff --git a/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart b/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart new file mode 100644 index 00000000..f24e5adb --- /dev/null +++ b/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart @@ -0,0 +1,41 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:path_provider/path_provider.dart'; +import 'package:share_plus/share_plus.dart'; + +/// Helper function to share text with proper UTF-8 encoding. +/// +/// This function creates a temporary file with UTF-8 encoding and shares it +/// as text/plain to ensure proper character rendering, especially for +/// non-ASCII characters like Polish letters (Ł, Ń, ą, etc.). +Future shareTextWithEncoding(String text) async { + if (text.isEmpty) { + return; + } + + try { + // Create a temporary file with UTF-8 encoding + final directory = await getTemporaryDirectory(); + final file = File('${directory.path}/shared_log_${DateTime.now().millisecondsSinceEpoch}.txt'); + + // Write the text with UTF-8 encoding + await file.writeAsString(text, encoding: utf8); + + // Share the file with explicit MIME type + await Share.shareXFiles( + [XFile(file.path, mimeType: 'text/plain')], + text: text, + ); + + // Clean up the temporary file after a delay to ensure sharing is complete + Future.delayed(const Duration(seconds: 5), () { + if (file.existsSync()) { + file.deleteSync(); + } + }); + } catch (e) { + // Fallback to regular share if file sharing fails + await Share.share(text); + } +} diff --git a/packages/leancode_debug_page/pubspec.yaml b/packages/leancode_debug_page/pubspec.yaml index 13334183..7711c1ba 100644 --- a/packages/leancode_debug_page/pubspec.yaml +++ b/packages/leancode_debug_page/pubspec.yaml @@ -14,6 +14,7 @@ dependencies: sdk: flutter http: ^1.1.0 logging: ^1.2.0 + path_provider: ^2.1.0 rxdart: ^0.28.0 sensors_plus: ^6.0.0 share_plus: ^10.0.0 From d2bbec5cfba2b7448b59e2769a72274c6e5f9c96 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 11:07:29 +0000 Subject: [PATCH 3/6] Add web platform support and improved error handling Co-authored-by: PiotrRogulski <18120733+PiotrRogulski@users.noreply.github.com> --- .../lib/src/ui/share_text_helper.dart | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart b/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart index f24e5adb..886746c4 100644 --- a/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart +++ b/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:flutter/foundation.dart' show kIsWeb; import 'package:path_provider/path_provider.dart'; import 'package:share_plus/share_plus.dart'; @@ -9,25 +10,36 @@ import 'package:share_plus/share_plus.dart'; /// This function creates a temporary file with UTF-8 encoding and shares it /// as text/plain to ensure proper character rendering, especially for /// non-ASCII characters like Polish letters (Ł, Ń, ą, etc.). +/// +/// On web platform or when file sharing fails, it falls back to regular +/// text sharing. Future shareTextWithEncoding(String text) async { if (text.isEmpty) { return; } + // On web, use regular share as file system access is limited + if (kIsWeb) { + await Share.share(text); + return; + } + try { // Create a temporary file with UTF-8 encoding final directory = await getTemporaryDirectory(); - final file = File('${directory.path}/shared_log_${DateTime.now().millisecondsSinceEpoch}.txt'); - + final file = File( + '${directory.path}/shared_log_${DateTime.now().millisecondsSinceEpoch}.txt', + ); + // Write the text with UTF-8 encoding await file.writeAsString(text, encoding: utf8); - + // Share the file with explicit MIME type await Share.shareXFiles( [XFile(file.path, mimeType: 'text/plain')], text: text, ); - + // Clean up the temporary file after a delay to ensure sharing is complete Future.delayed(const Duration(seconds: 5), () { if (file.existsSync()) { From c5d22e6d93d2413c46a544c0cde2c8681806550b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 11:09:23 +0000 Subject: [PATCH 4/6] Address code review feedback - improve file cleanup handling Co-authored-by: PiotrRogulski <18120733+PiotrRogulski@users.noreply.github.com> --- .../lib/src/ui/share_text_helper.dart | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart b/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart index 886746c4..0368c5ce 100644 --- a/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart +++ b/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:convert'; import 'dart:io'; @@ -5,6 +6,12 @@ import 'package:flutter/foundation.dart' show kIsWeb; import 'package:path_provider/path_provider.dart'; import 'package:share_plus/share_plus.dart'; +/// Delay before cleaning up temporary share files. +/// +/// This allows enough time for the sharing operation to complete and for +/// the receiving application to read the file before it's deleted. +const _cleanupDelay = Duration(seconds: 5); + /// Helper function to share text with proper UTF-8 encoding. /// /// This function creates a temporary file with UTF-8 encoding and shares it @@ -41,11 +48,17 @@ Future shareTextWithEncoding(String text) async { ); // Clean up the temporary file after a delay to ensure sharing is complete - Future.delayed(const Duration(seconds: 5), () { - if (file.existsSync()) { - file.deleteSync(); - } - }); + unawaited( + Future.delayed(_cleanupDelay, () { + try { + if (file.existsSync()) { + file.deleteSync(); + } + } catch (_) { + // Ignore cleanup errors as they're not critical + } + }), + ); } catch (e) { // Fallback to regular share if file sharing fails await Share.share(text); From b6d6c15b3515c2b7fc8a5df8b4640bac8fa66265 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 11:14:31 +0000 Subject: [PATCH 5/6] Fix Polish character display by using UTF-8 decoding for response bodies Co-authored-by: PiotrRogulski <18120733+PiotrRogulski@users.noreply.github.com> --- .../lib/src/core/logging_http_client.dart | 8 ++- .../logger_log_details_screen.dart | 4 +- .../request_details_screen.dart | 6 +- .../widgets/logs_inspector_share_button.dart | 6 +- .../lib/src/ui/share_text_helper.dart | 66 ------------------- packages/leancode_debug_page/pubspec.yaml | 1 - 6 files changed, 15 insertions(+), 76 deletions(-) delete mode 100644 packages/leancode_debug_page/lib/src/ui/share_text_helper.dart diff --git a/packages/leancode_debug_page/lib/src/core/logging_http_client.dart b/packages/leancode_debug_page/lib/src/core/logging_http_client.dart index 28c07570..96e05209 100644 --- a/packages/leancode_debug_page/lib/src/core/logging_http_client.dart +++ b/packages/leancode_debug_page/lib/src/core/logging_http_client.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:leancode_debug_page/src/models/log_gatherer.dart'; @@ -59,9 +60,10 @@ class LoggingHttpClient extends http.BaseClient return http.StreamedResponse( response.stream.doOnData(responseBodyBytes.addAll).doOnDone(() { - responseBodyCompleter.complete( - http.Response.bytes(responseBodyBytes, response.statusCode).body, - ); + // Decode the response body using UTF-8 encoding to properly handle + // special characters like Polish letters (Ł, Ń, ą, etc.) + final responseBody = utf8.decode(responseBodyBytes, allowMalformed: true); + responseBodyCompleter.complete(responseBody); }), response.statusCode, contentLength: response.contentLength, diff --git a/packages/leancode_debug_page/lib/src/ui/logs_inspector/logger/logger_log_details_screen/logger_log_details_screen.dart b/packages/leancode_debug_page/lib/src/ui/logs_inspector/logger/logger_log_details_screen/logger_log_details_screen.dart index 981a32c2..9f679c2b 100644 --- a/packages/leancode_debug_page/lib/src/ui/logs_inspector/logger/logger_log_details_screen/logger_log_details_screen.dart +++ b/packages/leancode_debug_page/lib/src/ui/logs_inspector/logger/logger_log_details_screen/logger_log_details_screen.dart @@ -5,9 +5,9 @@ import 'package:leancode_debug_page/src/ui/debug_page_route.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/logger/level_color_extension.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/map_view.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/widgets/share_button.dart'; -import 'package:leancode_debug_page/src/ui/share_text_helper.dart'; import 'package:leancode_debug_page/src/ui/typography.dart'; import 'package:logging/logging.dart'; +import 'package:share_plus/share_plus.dart'; class LoggerLogDetailsRoute extends DebugPageRoute { LoggerLogDetailsRoute({required LogRecord logRecord}) @@ -94,7 +94,7 @@ class LoggerLogDetailsScreen extends StatelessWidget { return Scaffold( floatingActionButtonLocation: FloatingActionButtonLocation.startFloat, floatingActionButton: ShareButton( - onPressed: () => shareTextWithEncoding(_shareLogDetails()), + onPressed: () => Share.share(_shareLogDetails()), ), appBar: AppBar( title: const Text('Logger log details'), diff --git a/packages/leancode_debug_page/lib/src/ui/logs_inspector/requests/request_details_screen/request_details_screen.dart b/packages/leancode_debug_page/lib/src/ui/logs_inspector/requests/request_details_screen/request_details_screen.dart index ccf31a6f..405be73b 100644 --- a/packages/leancode_debug_page/lib/src/ui/logs_inspector/requests/request_details_screen/request_details_screen.dart +++ b/packages/leancode_debug_page/lib/src/ui/logs_inspector/requests/request_details_screen/request_details_screen.dart @@ -6,7 +6,7 @@ import 'package:leancode_debug_page/src/ui/logs_inspector/requests/request_detai import 'package:leancode_debug_page/src/ui/logs_inspector/requests/request_details_screen/request_details_screen_response_tab.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/requests/request_details_screen/show_share_request_log_dialog.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/widgets/share_button.dart'; -import 'package:leancode_debug_page/src/ui/share_text_helper.dart'; +import 'package:share_plus/share_plus.dart'; class RequestDetailsRoute extends DebugPageRoute { RequestDetailsRoute(RequestLogRecord requestLog) @@ -28,7 +28,9 @@ class RequestDetailsScreen extends StatelessWidget { const RequestSharingConfiguration(includeResponse: true), ); - await shareTextWithEncoding(summary); + if (summary.isNotEmpty) { + await Share.share(summary); + } } @override diff --git a/packages/leancode_debug_page/lib/src/ui/logs_inspector/widgets/logs_inspector_share_button.dart b/packages/leancode_debug_page/lib/src/ui/logs_inspector/widgets/logs_inspector_share_button.dart index e780093e..b8a0aaa1 100644 --- a/packages/leancode_debug_page/lib/src/ui/logs_inspector/widgets/logs_inspector_share_button.dart +++ b/packages/leancode_debug_page/lib/src/ui/logs_inspector/widgets/logs_inspector_share_button.dart @@ -5,7 +5,7 @@ import 'package:leancode_debug_page/src/core/logs_summarizers/request_logs_summa import 'package:leancode_debug_page/src/ui/logs_inspector/logs_inspector.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/requests/request_details_screen/show_share_request_log_dialog.dart'; import 'package:leancode_debug_page/src/ui/logs_inspector/widgets/share_button.dart'; -import 'package:leancode_debug_page/src/ui/share_text_helper.dart'; +import 'package:share_plus/share_plus.dart'; class LogsInspectorShareButton extends StatelessWidget { const LogsInspectorShareButton({ @@ -40,7 +40,9 @@ class LogsInspectorShareButton extends StatelessWidget { throw StateError('Unknown tab'); } - await shareTextWithEncoding(sharedData); + if (sharedData.isNotEmpty) { + await Share.share(sharedData); + } }, ); } diff --git a/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart b/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart deleted file mode 100644 index 0368c5ce..00000000 --- a/packages/leancode_debug_page/lib/src/ui/share_text_helper.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -import 'package:flutter/foundation.dart' show kIsWeb; -import 'package:path_provider/path_provider.dart'; -import 'package:share_plus/share_plus.dart'; - -/// Delay before cleaning up temporary share files. -/// -/// This allows enough time for the sharing operation to complete and for -/// the receiving application to read the file before it's deleted. -const _cleanupDelay = Duration(seconds: 5); - -/// Helper function to share text with proper UTF-8 encoding. -/// -/// This function creates a temporary file with UTF-8 encoding and shares it -/// as text/plain to ensure proper character rendering, especially for -/// non-ASCII characters like Polish letters (Ł, Ń, ą, etc.). -/// -/// On web platform or when file sharing fails, it falls back to regular -/// text sharing. -Future shareTextWithEncoding(String text) async { - if (text.isEmpty) { - return; - } - - // On web, use regular share as file system access is limited - if (kIsWeb) { - await Share.share(text); - return; - } - - try { - // Create a temporary file with UTF-8 encoding - final directory = await getTemporaryDirectory(); - final file = File( - '${directory.path}/shared_log_${DateTime.now().millisecondsSinceEpoch}.txt', - ); - - // Write the text with UTF-8 encoding - await file.writeAsString(text, encoding: utf8); - - // Share the file with explicit MIME type - await Share.shareXFiles( - [XFile(file.path, mimeType: 'text/plain')], - text: text, - ); - - // Clean up the temporary file after a delay to ensure sharing is complete - unawaited( - Future.delayed(_cleanupDelay, () { - try { - if (file.existsSync()) { - file.deleteSync(); - } - } catch (_) { - // Ignore cleanup errors as they're not critical - } - }), - ); - } catch (e) { - // Fallback to regular share if file sharing fails - await Share.share(text); - } -} diff --git a/packages/leancode_debug_page/pubspec.yaml b/packages/leancode_debug_page/pubspec.yaml index 7711c1ba..13334183 100644 --- a/packages/leancode_debug_page/pubspec.yaml +++ b/packages/leancode_debug_page/pubspec.yaml @@ -14,7 +14,6 @@ dependencies: sdk: flutter http: ^1.1.0 logging: ^1.2.0 - path_provider: ^2.1.0 rxdart: ^0.28.0 sensors_plus: ^6.0.0 share_plus: ^10.0.0 From 5bad03df90c84edcff46e11895f030c00c4bfc09 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 11:17:25 +0000 Subject: [PATCH 6/6] Add test for UTF-8 character decoding with Polish letters Co-authored-by: PiotrRogulski <18120733+PiotrRogulski@users.noreply.github.com> --- .../test/logging_http_client_test.dart | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/packages/leancode_debug_page/test/logging_http_client_test.dart b/packages/leancode_debug_page/test/logging_http_client_test.dart index 53801d26..b57ad400 100644 --- a/packages/leancode_debug_page/test/logging_http_client_test.dart +++ b/packages/leancode_debug_page/test/logging_http_client_test.dart @@ -3,6 +3,8 @@ // clearly show all parameters being tested. // ignore_for_file: avoid_redundant_argument_values +import 'dart:convert'; + import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart'; import 'package:leancode_debug_page/src/core/logging_http_client.dart'; @@ -96,6 +98,43 @@ void main() { ); }, ); + + test( + 'properly decodes UTF-8 characters including Polish letters', + () async { + const polishText = 'Autoryzacja nie została wykonana. Łódź, Gdańsk, Kraków.'; + final polishBytes = utf8.encode(polishText); + final streamWithPolishText = Stream.fromIterable([polishBytes]); + + when>(() => mockHttpClient.send(any())) + .thenAnswer( + (invocation) async => StreamedResponse( + streamWithPolishText, + statusCode, + contentLength: polishBytes.length, + request: request, + headers: headers, + isRedirect: isRedirect, + persistentConnection: persistentConnection, + reasonPhrase: reasonPhrase, + ), + ); + + await loggingHttpClient.send(request); + + // Wait for the response body to be completed + await Future.delayed(const Duration(milliseconds: 100)); + + expect(loggingHttpClient.logs, hasLength(1)); + final log = loggingHttpClient.logs.first; + final responseBody = await log.responseBodyCompleter.future; + + expect(responseBody, contains('Autoryzacja')); + expect(responseBody, contains('Łódź')); + expect(responseBody, contains('Gdańsk')); + expect(responseBody, contains('Kraków')); + }, + ); }, ); }