mirror of
https://github.com/foss42/apidash.git
synced 2025-05-21 16:26:37 +08:00
Updated previewer with downloader
This commit is contained in:
@ -291,7 +291,7 @@ const Map<String, Map<String, List<ResponseBodyView>>>
|
||||
kSubTypeDefaultViewOptions: kNoRawBodyViewOptions,
|
||||
kSubTypeJson: kCodeRawBodyViewOptions,
|
||||
kSubTypeOctetStream: kNoBodyViewOptions,
|
||||
kSubTypePdf: kPreviewBodyViewOptions,
|
||||
kSubTypePdf: kNoBodyViewOptions,
|
||||
kSubTypeSql: kCodeRawBodyViewOptions,
|
||||
kSubTypeXml: kCodeRawBodyViewOptions,
|
||||
kSubTypeYaml: kCodeRawBodyViewOptions,
|
||||
@ -302,10 +302,10 @@ const Map<String, Map<String, List<ResponseBodyView>>>
|
||||
kSubTypeSvg: kCodeRawBodyViewOptions,
|
||||
},
|
||||
kTypeAudio: {
|
||||
kSubTypeDefaultViewOptions: kPreviewBodyViewOptions,
|
||||
kSubTypeDefaultViewOptions: kNoBodyViewOptions,
|
||||
},
|
||||
kTypeVideo: {
|
||||
kSubTypeDefaultViewOptions: kPreviewBodyViewOptions,
|
||||
kSubTypeDefaultViewOptions: kNoBodyViewOptions,
|
||||
},
|
||||
kTypeText: {
|
||||
kSubTypeDefaultViewOptions: kRawBodyViewOptions,
|
||||
@ -404,14 +404,13 @@ const kResponseCodeReasons = {
|
||||
const kIntro =
|
||||
"""API Dash is a beautiful open-source cross-platform API Client built using Flutter which can help you easily create & customize your API requests, visually inspect responses and generate Dart code on the go.""";
|
||||
|
||||
const kMimeTypeRaiseIssueStart =
|
||||
"Please click on 'Raw' to view the unformatted raw results as a visual preview for the response Content-Type - ";
|
||||
const kMimeTypeRawRaiseIssueStart =
|
||||
"Please click on 'Raw' to view the unformatted raw results as the response preview for Content-Type ";
|
||||
|
||||
const kMimeTypeRaiseIssueEnd =
|
||||
" is currently not available.\nKindly raise an issue in API Dash GitHub repo so that we can add a Visual Preview logic for this content-type.";
|
||||
const kMimeTypeRaiseIssueStart = "Response preview for Content-Type ";
|
||||
|
||||
const kMimeTypeRaiseIssue =
|
||||
" is currently not supported.\nPlease raise an issue in API Dash GitHub repo so that we can prioritize adding it to the tool.";
|
||||
" is currently not supported.\nPlease raise an issue in API Dash GitHub repo so that we can add a Previewer for this content-type.";
|
||||
|
||||
const kUnexpectedRaiseIssue =
|
||||
"\nIf the behaviour is unexpected, please raise an issue in API Dash GitHub repo so that we can resolve it.";
|
||||
|
@ -89,28 +89,27 @@ MediaType? getMediaTypeFromHeaders(Map? headers) {
|
||||
return (uri, null);
|
||||
}
|
||||
|
||||
(List<ResponseBodyView>, String?) getResponseBodyViewOptions(MediaType mediaType){
|
||||
var type = mediaType.type;
|
||||
var subtype = mediaType.subtype;
|
||||
//print(mediaType);
|
||||
if(kResponseBodyViewOptions.containsKey(type)){
|
||||
if (kResponseBodyViewOptions[type]!.containsKey(subtype)){
|
||||
return (kResponseBodyViewOptions[type]![subtype]!, kCodeHighlighterMap[subtype] ?? subtype);
|
||||
(List<ResponseBodyView>, String?) getResponseBodyViewOptions(MediaType? mediaType){
|
||||
if(mediaType != null){
|
||||
var type = mediaType.type;
|
||||
var subtype = mediaType.subtype;
|
||||
if(kResponseBodyViewOptions.containsKey(type)){
|
||||
if (kResponseBodyViewOptions[type]!.containsKey(subtype)){
|
||||
return (kResponseBodyViewOptions[type]![subtype]!, kCodeHighlighterMap[subtype] ?? subtype);
|
||||
}
|
||||
if(subtype.contains(kSubTypeJson)){
|
||||
subtype = kSubTypeJson;
|
||||
}
|
||||
if(subtype.contains(kSubTypeXml)){
|
||||
subtype = kSubTypeXml;
|
||||
}
|
||||
if (kResponseBodyViewOptions[type]!.containsKey(subtype)){
|
||||
return (kResponseBodyViewOptions[type]![subtype]!, kCodeHighlighterMap[subtype] ?? subtype);
|
||||
}
|
||||
return (kResponseBodyViewOptions[type]![kSubTypeDefaultViewOptions]!, subtype);
|
||||
}
|
||||
if(subtype.contains(kSubTypeJson)){
|
||||
subtype = kSubTypeJson;
|
||||
}
|
||||
if(subtype.contains(kSubTypeXml)){
|
||||
subtype = kSubTypeXml;
|
||||
}
|
||||
if (kResponseBodyViewOptions[type]!.containsKey(subtype)){
|
||||
return (kResponseBodyViewOptions[type]![subtype]!, kCodeHighlighterMap[subtype] ?? subtype);
|
||||
}
|
||||
return (kResponseBodyViewOptions[type]![kSubTypeDefaultViewOptions]!, subtype);
|
||||
}
|
||||
else {
|
||||
return (kNoBodyViewOptions, null);
|
||||
}
|
||||
return (kNoBodyViewOptions, null);
|
||||
}
|
||||
|
||||
String? formatBody(String? body, MediaType? mediaType){
|
||||
|
@ -3,9 +3,16 @@ import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class ErrorMessage extends StatelessWidget {
|
||||
const ErrorMessage({super.key, required this.message});
|
||||
const ErrorMessage({
|
||||
super.key,
|
||||
required this.message,
|
||||
this.showIcon = true,
|
||||
this.showIssueButton = true,
|
||||
});
|
||||
|
||||
final String? message;
|
||||
final bool showIcon;
|
||||
final bool showIssueButton;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -16,11 +23,13 @@ class ErrorMessage extends StatelessWidget {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.warning_rounded,
|
||||
size: 40,
|
||||
color: color,
|
||||
),
|
||||
showIcon
|
||||
? Icon(
|
||||
Icons.warning_rounded,
|
||||
size: 40,
|
||||
color: color,
|
||||
)
|
||||
: const SizedBox(),
|
||||
SelectableText(
|
||||
message ?? 'An error occurred. $kUnexpectedRaiseIssue',
|
||||
textAlign: TextAlign.center,
|
||||
@ -30,16 +39,18 @@ class ErrorMessage extends StatelessWidget {
|
||||
?.copyWith(color: color),
|
||||
),
|
||||
kVSpacer20,
|
||||
FilledButton.tonalIcon(
|
||||
onPressed: () {
|
||||
launchUrl(Uri.parse(kGitUrl));
|
||||
},
|
||||
icon: const Icon(Icons.arrow_outward_rounded),
|
||||
label: Text(
|
||||
'Raise Issue',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
showIssueButton
|
||||
? FilledButton.tonalIcon(
|
||||
onPressed: () {
|
||||
launchUrl(Uri.parse(kGitUrl));
|
||||
},
|
||||
icon: const Icon(Icons.arrow_outward_rounded),
|
||||
label: Text(
|
||||
'Raise Issue',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
)
|
||||
: const SizedBox(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -4,15 +4,19 @@ import 'error_message.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
|
||||
class Previewer extends StatefulWidget {
|
||||
const Previewer(
|
||||
{super.key,
|
||||
required this.bytes,
|
||||
required this.type,
|
||||
required this.subtype});
|
||||
const Previewer({
|
||||
super.key,
|
||||
required this.bytes,
|
||||
this.type,
|
||||
this.subtype,
|
||||
this.hasRaw = false,
|
||||
});
|
||||
|
||||
final Uint8List bytes;
|
||||
final String type;
|
||||
final String subtype;
|
||||
final String? type;
|
||||
final String? subtype;
|
||||
final bool hasRaw;
|
||||
|
||||
@override
|
||||
State<Previewer> createState() => _PreviewerState();
|
||||
}
|
||||
@ -20,9 +24,6 @@ class Previewer extends StatefulWidget {
|
||||
class _PreviewerState extends State<Previewer> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.type == kTypeApplication && widget.subtype == kSubTypePdf) {
|
||||
return const ErrorMessage(message: "PDF viewing $kMimeTypeRaiseIssue");
|
||||
}
|
||||
if (widget.type == kTypeImage) {
|
||||
return Image.memory(
|
||||
widget.bytes,
|
||||
@ -31,14 +32,18 @@ class _PreviewerState extends State<Previewer> {
|
||||
},
|
||||
);
|
||||
}
|
||||
if (widget.type == kTypeApplication && widget.subtype == kSubTypePdf) {
|
||||
// TODO: PDF Viewer
|
||||
}
|
||||
if (widget.type == kTypeAudio) {
|
||||
return const ErrorMessage(message: "Audio playing $kMimeTypeRaiseIssue");
|
||||
// TODO: Audio Player
|
||||
}
|
||||
if (widget.type == kTypeVideo) {
|
||||
return const ErrorMessage(message: "Video playing $kMimeTypeRaiseIssue");
|
||||
// TODO: Video Player
|
||||
}
|
||||
return ErrorMessage(
|
||||
message:
|
||||
"${widget.type}/${widget.subtype} mimetype preview $kMimeTypeRaiseIssue");
|
||||
String message = widget.hasRaw
|
||||
? "$kMimeTypeRawRaiseIssueStart${widget.type}/${widget.subtype}$kMimeTypeRaiseIssue"
|
||||
: "$kMimeTypeRaiseIssueStart${widget.type}/${widget.subtype}$kMimeTypeRaiseIssue";
|
||||
return ErrorMessage(message: message);
|
||||
}
|
||||
}
|
||||
|
@ -313,30 +313,35 @@ class _ResponseBodyState extends State<ResponseBody> {
|
||||
final responseModel = widget.activeRequestModel?.responseModel;
|
||||
if (responseModel == null) {
|
||||
return const ErrorMessage(
|
||||
message: 'Error: No Response Data Found. $kUnexpectedRaiseIssue');
|
||||
}
|
||||
var mediaType = responseModel.mediaType;
|
||||
if (mediaType == null) {
|
||||
return ErrorMessage(
|
||||
message:
|
||||
'Unknown Response content type - ${responseModel.contentType}. $kUnexpectedRaiseIssue');
|
||||
'Error: Response data does not exist. $kUnexpectedRaiseIssue');
|
||||
}
|
||||
|
||||
var body = responseModel.body;
|
||||
var formattedBody = responseModel.formattedBody;
|
||||
if (body == null) {
|
||||
return const ErrorMessage(
|
||||
message: 'Response body is empty. $kUnexpectedRaiseIssue');
|
||||
message: 'Response body is missing (null). $kUnexpectedRaiseIssue');
|
||||
}
|
||||
var responseBodyView = getResponseBodyViewOptions(mediaType);
|
||||
//print(responseBodyView);
|
||||
var options = responseBodyView.$0;
|
||||
var highlightLanguage = responseBodyView.$1;
|
||||
if (options == kNoBodyViewOptions) {
|
||||
if (body.isEmpty) {
|
||||
return const ErrorMessage(
|
||||
message: 'No content',
|
||||
showIcon: false,
|
||||
showIssueButton: false,
|
||||
);
|
||||
}
|
||||
|
||||
var mediaType = responseModel.mediaType;
|
||||
if (mediaType == null) {
|
||||
return ErrorMessage(
|
||||
message:
|
||||
"Viewing response data of Content-Type\n'${mediaType.mimeType}' $kMimeTypeRaiseIssue");
|
||||
'Unknown Response Content-Type - ${responseModel.contentType}. $kUnexpectedRaiseIssue');
|
||||
}
|
||||
|
||||
var responseBodyView = getResponseBodyViewOptions(mediaType);
|
||||
var options = responseBodyView.$0;
|
||||
var highlightLanguage = responseBodyView.$1;
|
||||
|
||||
if (formattedBody == null) {
|
||||
options = [...options];
|
||||
options.remove(ResponseBodyView.code);
|
||||
@ -456,15 +461,12 @@ class _BodySuccessState extends State<BodySuccess> {
|
||||
visible: currentSeg == ResponseBodyView.preview ||
|
||||
currentSeg == ResponseBodyView.none,
|
||||
child: Expanded(
|
||||
child: currentSeg == ResponseBodyView.preview
|
||||
? Previewer(
|
||||
bytes: widget.bytes,
|
||||
type: widget.mediaType.type,
|
||||
subtype: widget.mediaType.subtype,
|
||||
)
|
||||
: ErrorMessage(
|
||||
message:
|
||||
"$kMimeTypeRaiseIssueStart'${widget.mediaType.mimeType}' $kMimeTypeRaiseIssueEnd"),
|
||||
child: Previewer(
|
||||
bytes: widget.bytes,
|
||||
type: widget.mediaType.type,
|
||||
subtype: widget.mediaType.subtype,
|
||||
hasRaw: widget.options.contains(ResponseBodyView.raw),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.formattedBody != null)
|
||||
|
Reference in New Issue
Block a user