Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add response previewer for text/html #243

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions lib/widgets/html_previewer.dart
Original file line number Diff line number Diff line change
@@ -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<HtmlPreviewer> {
final WebViewController _controller = WebViewController();
final _textController = TextEditingController();
String title = "";
Future<void> 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<JavascriptChannel> 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));
}
}
1 change: 1 addition & 0 deletions lib/widgets/previewer.dart
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
126 changes: 74 additions & 52 deletions lib/widgets/response_widgets.dart
Original file line number Diff line number Diff line change
@@ -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});
Expand Down Expand Up @@ -343,7 +348,7 @@ class ResponseBody extends StatelessWidget {
}
}

class BodySuccess extends StatefulWidget {
class BodySuccess extends ConsumerStatefulWidget {
const BodySuccess(
{super.key,
required this.mediaType,
Expand All @@ -359,14 +364,20 @@ class BodySuccess extends StatefulWidget {
final String? formattedBody;
final String? highlightLanguage;
@override
State<BodySuccess> createState() => _BodySuccessState();
ConsumerState<BodySuccess> createState() => _BodySuccessState();
}

class _BodySuccessState extends State<BodySuccess> {
class _BodySuccessState extends ConsumerState<BodySuccess> {
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
Expand All @@ -388,55 +399,64 @@ class _BodySuccessState extends State<BodySuccess> {
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<ResponseBodyView>(
style: const ButtonStyle(
padding: MaterialStatePropertyAll(
EdgeInsets.symmetric(
horizontal: 8,
),
!isHtmlResponse
? Column(
children: [
Row(
children: [
(widget.options == kRawBodyViewOptions)
? const SizedBox()
: SegmentedButton<ResponseBodyView>(
style: const ButtonStyle(
padding: MaterialStatePropertyAll(
EdgeInsets.symmetric(
horizontal: 8,
),
),
),
selectedIcon: Icon(currentSeg.icon),
segments: widget.options
.map<ButtonSegment<ResponseBodyView>>(
(e) =>
ButtonSegment<ResponseBodyView>(
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<ButtonSegment<ResponseBodyView>>(
(e) => ButtonSegment<ResponseBodyView>(
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(
Expand All @@ -457,12 +477,14 @@ class _BodySuccessState extends State<BodySuccess> {
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(
Expand Down
44 changes: 42 additions & 2 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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"
2 changes: 2 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down