diff --git a/lib/consts.dart b/lib/consts.dart index 2aa98fff..b5f65905 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -291,7 +291,7 @@ const Map>> kSubTypeDefaultViewOptions: kNoRawBodyViewOptions, kSubTypeJson: kCodeRawBodyViewOptions, kSubTypeOctetStream: kNoBodyViewOptions, - kSubTypePdf: kPreviewBodyViewOptions, + kSubTypePdf: kNoBodyViewOptions, kSubTypeSql: kCodeRawBodyViewOptions, kSubTypeXml: kCodeRawBodyViewOptions, kSubTypeYaml: kCodeRawBodyViewOptions, @@ -302,10 +302,10 @@ const Map>> 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."; diff --git a/lib/utils/http_utils.dart b/lib/utils/http_utils.dart index 2d5a9d41..6a6eac2d 100644 --- a/lib/utils/http_utils.dart +++ b/lib/utils/http_utils.dart @@ -89,28 +89,27 @@ MediaType? getMediaTypeFromHeaders(Map? headers) { return (uri, null); } -(List, 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, 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){ diff --git a/lib/widgets/error_message.dart b/lib/widgets/error_message.dart index b2777e54..b6e9cf46 100644 --- a/lib/widgets/error_message.dart +++ b/lib/widgets/error_message.dart @@ -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(), ], ), ), diff --git a/lib/widgets/previewer.dart b/lib/widgets/previewer.dart index b330f7a0..28b3c2ea 100644 --- a/lib/widgets/previewer.dart +++ b/lib/widgets/previewer.dart @@ -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 createState() => _PreviewerState(); } @@ -20,9 +24,6 @@ class Previewer extends StatefulWidget { class _PreviewerState extends State { @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 { }, ); } + 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); } } diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index c9600257..6523546a 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -313,30 +313,35 @@ class _ResponseBodyState extends State { 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 { 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)