From 05ce744f8cc419ad85f2f90ea68259d9f604ae2e Mon Sep 17 00:00:00 2001 From: hunteraraujo Date: Thu, 24 Aug 2023 20:52:11 -0700 Subject: [PATCH] Add JsonCodeSnippetView to Display and Copy Pretty-Printed JSON This commit introduces the JsonCodeSnippetView, a widget designed to display JSON data in a pretty-printed format. Users can view the JSON content with proper indentation and formatting, enhancing readability. Features: - The JSON data is displayed using the HighlightView with GitHub-themed syntax highlighting. - A copy button (IconButton) is provided to allow users to easily copy the pretty-printed JSON to the clipboard. - Padding and layout adjustments ensure that the view fits seamlessly within the designated space, with scrollable content if the JSON exceeds the available space. This widget enhances the user experience when interacting with JSON data, providing a clean and efficient way to view and copy content. --- lib/views/chat/chat_input_field.dart | 6 +- lib/views/chat/json_code_snippet_view.dart | 64 ++++++++++++++++++++++ pubspec.lock | 16 ++++++ pubspec.yaml | 1 + test/json_code_snippet_view_test.dart | 14 +++++ 5 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 lib/views/chat/json_code_snippet_view.dart create mode 100644 test/json_code_snippet_view_test.dart diff --git a/lib/views/chat/chat_input_field.dart b/lib/views/chat/chat_input_field.dart index 9f6ee817..97ca7fd2 100644 --- a/lib/views/chat/chat_input_field.dart +++ b/lib/views/chat/chat_input_field.dart @@ -39,7 +39,7 @@ class _ChatInputFieldState extends State { child: Container( width: inputWidth, // Defining the minimum and maximum height for the TextField container - constraints: BoxConstraints( + constraints: const BoxConstraints( minHeight: 50, maxHeight: 400, ), @@ -58,7 +58,7 @@ class _ChatInputFieldState extends State { controller: _controller, // Allowing the TextField to expand vertically and accommodate multiple lines maxLines: null, - decoration: InputDecoration( + decoration: const InputDecoration( hintText: 'Type a message...', border: InputBorder.none, ), @@ -68,7 +68,7 @@ class _ChatInputFieldState extends State { ), // Send button to trigger the provided onSendPressed callback IconButton( - icon: Icon(Icons.send), + icon: const Icon(Icons.send), onPressed: widget.onSendPressed, ), ], diff --git a/lib/views/chat/json_code_snippet_view.dart b/lib/views/chat/json_code_snippet_view.dart new file mode 100644 index 00000000..6a09c627 --- /dev/null +++ b/lib/views/chat/json_code_snippet_view.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_highlight/flutter_highlight.dart'; +import 'package:flutter_highlight/themes/github.dart'; +import 'package:flutter/services.dart'; +import 'dart:convert'; + +class JsonCodeSnippetView extends StatelessWidget { + final String jsonString; + + // Constructor to initialize the jsonString that will be displayed + const JsonCodeSnippetView({ + Key? key, + required this.jsonString, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + // Pretty print the JSON using JsonEncoder to format with indentation + String prettyJson = + const JsonEncoder.withIndent(' ').convert(json.decode(jsonString)); + + return Padding( + // Padding applied to align the code snippet view within its container + padding: const EdgeInsets.fromLTRB(30, 30, 0, 30), + child: Row( + children: [ + // Expanded widget to ensure the code snippet view takes the available space + Expanded( + child: SingleChildScrollView( + // SingleChildScrollView to make the code snippet scrollable if it overflows + child: HighlightView( + // Display the pretty-printed JSON + prettyJson, + // Set the language to JSON for syntax highlighting + language: 'json', + // Apply a GitHub-like theme for the highlighting + theme: githubTheme, + // Padding applied to the code snippet inside the view + padding: const EdgeInsets.all(12), + // TextStyle applied to the code snippet (monospace font) + textStyle: const TextStyle( + fontFamily: 'monospace', + fontSize: 12, + ), + ), + ), + ), + // SizedBox to create a gap between the code snippet view and the copy button + const SizedBox(width: 20), + Material( + // IconButton to allow the user to copy the pretty-printed JSON to the clipboard + child: IconButton( + icon: const Icon(Icons.copy), + onPressed: () { + // Copy the pretty-printed JSON to the clipboard + Clipboard.setData(ClipboardData(text: prettyJson)); + }, + ), + ), + ], + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 52f801e7..c83400ca 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -62,6 +62,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_highlight: + dependency: "direct main" + description: + name: flutter_highlight + sha256: "7b96333867aa07e122e245c033b8ad622e4e3a42a1a2372cbb098a2541d8782c" + url: "https://pub.dev" + source: hosted + version: "0.7.0" flutter_lints: dependency: "direct dev" description: @@ -75,6 +83,14 @@ packages: description: flutter source: sdk version: "0.0.0" + highlight: + dependency: transitive + description: + name: highlight + sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21" + url: "https://pub.dev" + source: hosted + version: "0.7.0" lints: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5defb9d1..877bcbd4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,6 +31,7 @@ dependencies: flutter: sdk: flutter collection: ^1.15.0 + flutter_highlight: ^0.7.0 # The following adds the Cupertino Icons font to your application. diff --git a/test/json_code_snippet_view_test.dart b/test/json_code_snippet_view_test.dart new file mode 100644 index 00000000..4a0dc8b3 --- /dev/null +++ b/test/json_code_snippet_view_test.dart @@ -0,0 +1,14 @@ +import 'package:auto_gpt_flutter_client/views/chat/json_code_snippet_view.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + const jsonString = '{"key": "value"}'; + + testWidgets('Renders JsonCodeSnippetView without crashing', + (WidgetTester tester) async { + await tester.pumpWidget( + const MaterialApp(home: JsonCodeSnippetView(jsonString: jsonString))); + expect(find.byType(JsonCodeSnippetView), findsOneWidget); + }); +}