diff --git a/lib/widgets/html_previewer.dart b/lib/widgets/html_previewer.dart
new file mode 100644
index 000000000..060d6fab9
--- /dev/null
+++ b/lib/widgets/html_previewer.dart
@@ -0,0 +1,61 @@
+import 'package:flutter/material.dart';
+import 'package:webview_cef/webview_cef.dart';
+
+class HtmlPreviewer extends StatefulWidget {
+ const HtmlPreviewer({super.key, required this.url});
+ final String url;
+
+ @override
+ _HtmlPreviewerState createState() => _HtmlPreviewerState();
+}
+
+class _HtmlPreviewerState extends State {
+ final WebViewController _controller = WebViewController();
+ final _textController = TextEditingController();
+ String title = "";
+ Future initPlatformState() async {
+ _textController.text = widget.url;
+ await _controller.initialize();
+ await _controller.loadUrl(widget.url);
+ _controller.setWebviewListener(WebviewEventsListener(
+ onTitleChanged: (t) {
+ setState(() {
+ title = t;
+ });
+ },
+ onUrlChanged: (url) {
+ _textController.text = url;
+ },
+ ));
+
+ // ignore: prefer_collection_literals
+ final Set jsChannels = [
+ JavascriptChannel(
+ name: 'Print',
+ onMessageReceived: (JavascriptMessage message) {
+ _controller.sendJavaScriptChannelCallBack(
+ false,
+ "{'code':'200','message':'print succeed!'}",
+ message.callbackId,
+ message.frameId);
+ }),
+ ].toSet();
+
+ await _controller.setJavaScriptChannels(jsChannels);
+
+ await _controller.executeJavaScript("function abc(e){console.log(e)}");
+
+ if (!mounted) return;
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ initPlatformState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Expanded(child: WebView(_controller));
+ }
+}
diff --git a/lib/widgets/previewer.dart b/lib/widgets/previewer.dart
index dd2f51869..46130ace5 100644
--- a/lib/widgets/previewer.dart
+++ b/lib/widgets/previewer.dart
@@ -1,4 +1,5 @@
import 'dart:convert';
+import 'package:apidash/widgets/html_previewer.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:printing/printing.dart';
diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart
index 539a2a341..bba43bc03 100644
--- a/lib/widgets/response_widgets.dart
+++ b/lib/widgets/response_widgets.dart
@@ -1,11 +1,16 @@
+import 'package:apidash/providers/collection_providers.dart';
+import 'package:apidash/providers/providers.dart';
+import 'package:apidash/widgets/html_previewer.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http_parser/http_parser.dart';
import 'package:lottie/lottie.dart';
import 'package:apidash/utils/utils.dart';
import 'package:apidash/widgets/widgets.dart';
import 'package:apidash/models/models.dart';
import 'package:apidash/consts.dart';
+import 'package:provider/provider.dart';
class NotSentWidget extends StatelessWidget {
const NotSentWidget({super.key});
@@ -343,7 +348,7 @@ class ResponseBody extends StatelessWidget {
}
}
-class BodySuccess extends StatefulWidget {
+class BodySuccess extends ConsumerStatefulWidget {
const BodySuccess(
{super.key,
required this.mediaType,
@@ -359,14 +364,20 @@ class BodySuccess extends StatefulWidget {
final String? formattedBody;
final String? highlightLanguage;
@override
- State createState() => _BodySuccessState();
+ ConsumerState createState() => _BodySuccessState();
}
-class _BodySuccessState extends State {
+class _BodySuccessState extends ConsumerState {
int segmentIdx = 0;
+ @override
+ void initState() {
+ super.initState();
+ ref.read(selectedRequestModelProvider);
+ }
@override
Widget build(BuildContext context) {
+ final String url = ref.watch(selectedRequestModelProvider)!.url;
var currentSeg = widget.options[segmentIdx];
var codeTheme = Theme.of(context).brightness == Brightness.light
? kLightCodeTheme
@@ -388,55 +399,64 @@ class _BodySuccessState extends State {
widget.options.length,
constraints.maxWidth,
);
+ final isHtmlResponse = widget.mediaType.type == kTypeText &&
+ widget.mediaType.subtype == kSubTypeHtml;
return Padding(
padding: kP10,
child: Column(
children: [
- Row(
- children: [
- (widget.options == kRawBodyViewOptions)
- ? const SizedBox()
- : SegmentedButton(
- style: const ButtonStyle(
- padding: MaterialStatePropertyAll(
- EdgeInsets.symmetric(
- horizontal: 8,
- ),
+ !isHtmlResponse
+ ? Column(
+ children: [
+ Row(
+ children: [
+ (widget.options == kRawBodyViewOptions)
+ ? const SizedBox()
+ : SegmentedButton(
+ style: const ButtonStyle(
+ padding: MaterialStatePropertyAll(
+ EdgeInsets.symmetric(
+ horizontal: 8,
+ ),
+ ),
+ ),
+ selectedIcon: Icon(currentSeg.icon),
+ segments: widget.options
+ .map>(
+ (e) =>
+ ButtonSegment(
+ value: e,
+ label: Text(e.label),
+ icon: Icon(e.icon),
+ ),
+ )
+ .toList(),
+ selected: {currentSeg},
+ onSelectionChanged: (newSelection) {
+ setState(() {
+ segmentIdx = widget.options
+ .indexOf(newSelection.first);
+ });
+ },
+ ),
+ const Spacer(),
+ kCodeRawBodyViewOptions.contains(currentSeg)
+ ? CopyButton(
+ toCopy: widget.formattedBody ?? widget.body,
+ showLabel: showLabel,
+ )
+ : const SizedBox(),
+ SaveInDownloadsButton(
+ content: widget.bytes,
+ mimeType: widget.mediaType.mimeType,
+ showLabel: showLabel,
),
- ),
- selectedIcon: Icon(currentSeg.icon),
- segments: widget.options
- .map>(
- (e) => ButtonSegment(
- value: e,
- label: Text(e.label),
- icon: Icon(e.icon),
- ),
- )
- .toList(),
- selected: {currentSeg},
- onSelectionChanged: (newSelection) {
- setState(() {
- segmentIdx =
- widget.options.indexOf(newSelection.first);
- });
- },
+ ],
),
- const Spacer(),
- kCodeRawBodyViewOptions.contains(currentSeg)
- ? CopyButton(
- toCopy: widget.formattedBody ?? widget.body,
- showLabel: showLabel,
- )
- : const SizedBox(),
- SaveInDownloadsButton(
- content: widget.bytes,
- mimeType: widget.mediaType.mimeType,
- showLabel: showLabel,
- ),
- ],
- ),
- kVSpacer10,
+ kVSpacer10
+ ],
+ )
+ : Container(),
switch (currentSeg) {
ResponseBodyView.preview || ResponseBodyView.none => Expanded(
child: Container(
@@ -457,12 +477,14 @@ class _BodySuccessState extends State {
width: double.maxFinite,
padding: kP8,
decoration: textContainerdecoration,
- child: CodePreviewer(
- code: widget.formattedBody ?? widget.body,
- theme: codeTheme,
- language: widget.highlightLanguage,
- textStyle: kCodeStyle,
- ),
+ child: !isHtmlResponse
+ ? CodePreviewer(
+ code: widget.formattedBody ?? widget.body,
+ theme: codeTheme,
+ language: widget.highlightLanguage,
+ textStyle: kCodeStyle,
+ )
+ : HtmlPreviewer(url: url),
),
),
ResponseBodyView.raw => Expanded(
diff --git a/pubspec.lock b/pubspec.lock
index 4125ed984..fd4fcfc4e 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1326,6 +1326,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.1"
+ webview_cef:
+ dependency: "direct main"
+ description:
+ name: webview_cef
+ sha256: a3e7a8e54ea612324be47359601808af9b9cdc57bdb96056b88394c345e3c3c6
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.0"
+ webview_flutter:
+ dependency: "direct main"
+ description:
+ name: webview_flutter
+ sha256: "25e1b6e839e8cbfbd708abc6f85ed09d1727e24e08e08c6b8590d7c65c9a8932"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.7.0"
+ webview_flutter_android:
+ dependency: transitive
+ description:
+ name: webview_flutter_android
+ sha256: "3e5f4e9d818086b0d01a66fb1ff9cc72ab0cc58c71980e3d3661c5685ea0efb0"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.15.0"
+ webview_flutter_platform_interface:
+ dependency: transitive
+ description:
+ name: webview_flutter_platform_interface
+ sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.10.0"
+ webview_flutter_wkwebview:
+ dependency: transitive
+ description:
+ name: webview_flutter_wkwebview
+ sha256: "9bf168bccdf179ce90450b5f37e36fe263f591c9338828d6bf09b6f8d0f57f86"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.12.0"
win32:
dependency: transitive
description:
@@ -1376,5 +1416,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
- dart: ">=3.3.0 <4.0.0"
- flutter: ">=3.19.0"
+ dart: ">=3.2.3 <4.0.0"
+ flutter: ">=3.16.6"
diff --git a/pubspec.yaml b/pubspec.yaml
index ab250f26f..39f436663 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -56,6 +56,8 @@ dependencies:
dart_style: ^2.3.4
json_text_field: ^1.1.0
csv: ^5.1.1
+ webview_cef: ^0.1.0
+ webview_flutter: ^4.7.0
dev_dependencies:
flutter_test: