Merge branch 'foss42:main' into main

This commit is contained in:
Aashutosh soni
2024-03-04 22:29:33 +05:30
committed by GitHub
15 changed files with 223 additions and 51 deletions

View File

@ -379,6 +379,7 @@ const Map<String, Map<String, List<ResponseBodyView>>>
kSubTypeDefaultViewOptions: kRawBodyViewOptions,
kSubTypeCss: kCodeRawBodyViewOptions,
kSubTypeHtml: kCodeRawBodyViewOptions,
kSubTypeCsv: kPreviewRawBodyViewOptions,
kSubTypeJavascript: kCodeRawBodyViewOptions,
kSubTypeMarkdown: kCodeRawBodyViewOptions,
kSubTypeTextXml: kCodeRawBodyViewOptions,
@ -496,6 +497,9 @@ const kAudioError =
const kRaiseIssue =
"\nPlease raise an issue in API Dash GitHub repo so that we can resolve it.";
const kCsvError =
"There seems to be an issue rendering this CSV. Please raise an issue in API Dash GitHub repo so that we can resolve it.";
const kHintTextUrlCard = "Enter API endpoint like api.foss42.com/country/codes";
const kLabelPlusNew = "+ New";
const kLabelSend = "Send";

View File

@ -2,6 +2,7 @@ Map<String, String> headers = {
"Accept": "Specifies the media types that are acceptable for the response.",
"Accept-Encoding":
"Indicates the encoding methods the client can understand.",
"Accept-Charset": "Specifies the character sets that are acceptable.",
"Access-Control-Allow-Headers":
"Specifies a list of HTTP headers that can be used in an actual request after a preflight request including the Access-Control-Request-Headers header is made.",
"Access-Control-Allow-Methods":
@ -41,11 +42,16 @@ Map<String, String> headers = {
"Cross-Origin-Resource-Policy":
"Controls how cross-origin requests for resources are handled.",
"Date": "Indicates the date and time at which the message was sent.",
"Device-Memory":
"Indicates the approximate amount of device memory in gigabytes.",
"DNT":
"Informs websites whether the user's preference is to opt out of online tracking.",
"Expect": "Indicates certain expectations that need to be met by the server.",
"Expires":
"Contains the date/time after which the response is considered expired",
"Forwarded":
"Contains information from the client-facing side of proxy servers that is altered or lost when a proxy is involved in the path of the request.",
"From": "Contains an Internet email address for a human user who controls the requesting user agent.",
"Host": "Specifies the domain name of the server and the port number.",
"If-Match":
"Used for conditional requests, allows the server to respond based on certain conditions.",
@ -57,9 +63,15 @@ Map<String, String> headers = {
"Used in conjunction with the Range header to conditionally request a partial resource.",
"If-Unmodified-Since":
"Used for conditional requests, allows the server to respond based on certain conditions.",
"Keep-Alive":
"Used to allow the connection to be reused for further requests.",
"Location":
"Indicates the URL a client should redirect to for further interaction.",
"Max-Forwards":
"Indicates the remaining number of times a request can be forwarded by proxies.",
"Origin": "Specifies the origin of a cross-origin request.",
"Proxy-Authorization":
"Contains credentials for authenticating a client with a proxy server.",
"Range":
"Used to request only part of a resource, typically in the context of downloading large files.",
"Referer":
@ -68,10 +80,14 @@ Map<String, String> headers = {
"Specifies how much information the browser should include in the Referer header when navigating to other pages.",
"Retry-After":
"Informs the client how long it should wait before making another request after a server has responded with a rate-limiting status code.",
"Save-Data":
"Indicates the client's preference for reduced data usage.",
"Server": "Indicates the software used by the origin server.",
"Strict-Transport-Security":
"Instructs the browser to always use HTTPS for the given domain.",
"TE": "Specifies the transfer encodings that are acceptable to the client.",
"Upgrade-Insecure-Requests":
"Instructs the browser to prefer secure connections when available.",
"User-Agent":
"Identifies the client software and version making the request.",
"Via":

View File

@ -0,0 +1,53 @@
import 'package:flutter/material.dart';
import 'package:csv/csv.dart';
import 'error_message.dart';
import '../consts.dart';
class CsvPreviewer extends StatelessWidget {
const CsvPreviewer({super.key, required this.body});
final String body;
@override
Widget build(BuildContext context) {
try {
final List<List<dynamic>> csvData =
const CsvToListConverter().convert(body, eol: '\n');
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: csvData[0]
.map(
(item) => DataColumn(
label: Text(
item.toString(),
),
),
)
.toList(),
rows: csvData
.skip(1)
.map(
(csvrow) => DataRow(
cells: csvrow
.map(
(csvItem) => DataCell(
Text(
csvItem.toString(),
),
),
)
.toList(),
),
)
.toList(),
),
),
);
} catch (e) {
return const ErrorMessage(message: kCsvError);
}
}
}

View File

@ -1,6 +1,6 @@
import 'package:apidash/consts.dart';
import 'package:apidash/utils/header_utils.dart';
import 'package:flutter/material.dart';
import 'package:apidash/consts.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
class HeaderField extends StatefulWidget {
@ -41,6 +41,7 @@ class _HeaderFieldState extends State<HeaderField> {
@override
void didUpdateWidget(HeaderField oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.initialValue != widget.initialValue) {
controller.text = widget.initialValue ?? "";
controller.selection =
@ -54,8 +55,8 @@ class _HeaderFieldState extends State<HeaderField> {
return TypeAheadField(
key: Key(widget.keyId),
hideOnEmpty: true,
minCharsForSuggestions: 1,
onSuggestionSelected: (value) {
controller: controller,
onSelected: (value) {
setState(() {
controller.text = value;
});
@ -68,19 +69,17 @@ class _HeaderFieldState extends State<HeaderField> {
);
},
suggestionsCallback: headerSuggestionCallback,
suggestionsBoxDecoration: suggestionBoxDecorations(context),
textFieldConfiguration: TextFieldConfiguration(
decorationBuilder: (context, child) =>
suggestionBoxDecorations(context, child, colorScheme),
constraints: const BoxConstraints(maxHeight: 400),
builder: (context, controller, focusNode) => TextField(
onChanged: widget.onChanged,
controller: controller,
style: kCodeStyle.copyWith(
color: colorScheme.onSurface,
),
focusNode: focusNode,
style: kCodeStyle.copyWith(color: colorScheme.onSurface),
decoration: InputDecoration(
hintStyle: kCodeStyle.copyWith(
color: colorScheme.outline.withOpacity(
kHintOpacity,
),
),
color: colorScheme.outline.withOpacity(kHintOpacity)),
hintText: widget.hintText,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
@ -99,22 +98,26 @@ class _HeaderFieldState extends State<HeaderField> {
);
}
SuggestionsBoxDecoration suggestionBoxDecorations(BuildContext context) {
return SuggestionsBoxDecoration(
elevation: 4,
constraints: const BoxConstraints(maxHeight: 400),
shape: RoundedRectangleBorder(
side: BorderSide(
color: Theme.of(context).dividerColor,
width: 1.2,
Theme suggestionBoxDecorations(
BuildContext context, Widget child, ColorScheme colorScheme) {
return Theme(
data: ThemeData(colorScheme: colorScheme),
child: Material(
elevation: 4,
shape: RoundedRectangleBorder(
side: BorderSide(color: Theme.of(context).dividerColor, width: 1.2),
borderRadius: const BorderRadius.vertical(bottom: Radius.circular(8)),
),
borderRadius: const BorderRadius.vertical(bottom: Radius.circular(8)),
clipBehavior: Clip.hardEdge,
child: child,
),
clipBehavior: Clip.hardEdge,
);
}
Future<List<String>> headerSuggestionCallback(String pattern) async {
Future<List<String>?> headerSuggestionCallback(String pattern) async {
if (pattern.isEmpty) {
return null;
}
return getHeaderSuggestions(pattern);
}
}

View File

@ -154,6 +154,7 @@ class _JsonPreviewerState extends State<JsonPreviewer> {
@override
void didUpdateWidget(JsonPreviewer oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.code != widget.code) {
store.buildNodes(widget.code, areAllCollapsed: true);
store.expandAll();

View File

@ -7,6 +7,7 @@ import 'package:vector_graphics_compiler/vector_graphics_compiler.dart';
import 'error_message.dart';
import 'uint8_audio_player.dart';
import 'json_previewer.dart';
import 'csv_previewer.dart';
import '../consts.dart';
class Previewer extends StatefulWidget {
@ -81,6 +82,9 @@ class _PreviewerState extends State<Previewer> {
},
);
}
if (widget.type == kTypeText && widget.subtype == kSubTypeCsv) {
return CsvPreviewer(body: widget.body);
}
if (widget.type == kTypeVideo) {
// TODO: Video Player
}