fix: PR fixes with few enhancements

This commit is contained in:
Vidya Sagar
2023-12-23 22:47:53 +05:30
parent b320090378
commit 1444317d91
10 changed files with 122 additions and 129 deletions

View File

@ -1,10 +1,9 @@
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:convert';
import 'package:davi/davi.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:davi/davi.dart';
const kDiscordUrl = "https://bit.ly/heyfoss"; const kDiscordUrl = "https://bit.ly/heyfoss";
const kGitUrl = "https://github.com/foss42/apidash"; const kGitUrl = "https://github.com/foss42/apidash";
@ -49,6 +48,10 @@ const kHintOpacity = 0.6;
const kForegroundOpacity = 0.05; const kForegroundOpacity = 0.05;
const kTextStyleButton = TextStyle(fontWeight: FontWeight.bold); const kTextStyleButton = TextStyle(fontWeight: FontWeight.bold);
const kFormDataButton = TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
);
const kBorderRadius8 = BorderRadius.all(Radius.circular(8)); const kBorderRadius8 = BorderRadius.all(Radius.circular(8));
final kBorderRadius10 = BorderRadius.circular(10); final kBorderRadius10 = BorderRadius.circular(10);
@ -74,7 +77,7 @@ const kPh60 = EdgeInsets.symmetric(horizontal: 60);
const kP24CollectionPane = EdgeInsets.only(top: 24, left: 8.0, bottom: 8.0); const kP24CollectionPane = EdgeInsets.only(top: 24, left: 8.0, bottom: 8.0);
const kP8CollectionPane = EdgeInsets.only(top: 8.0, left: 8.0, bottom: 8.0); const kP8CollectionPane = EdgeInsets.only(top: 8.0, left: 8.0, bottom: 8.0);
const kPr8CollectionPane = EdgeInsets.only(right: 8.0); const kPr8CollectionPane = EdgeInsets.only(right: 8.0);
const kpsV5 = EdgeInsets.symmetric(vertical: 2);
const kHSpacer4 = SizedBox(width: 4); const kHSpacer4 = SizedBox(width: 4);
const kHSpacer5 = SizedBox(width: 5); const kHSpacer5 = SizedBox(width: 5);
const kHSpacer10 = SizedBox(width: 10); const kHSpacer10 = SizedBox(width: 10);
@ -300,14 +303,6 @@ const kContentTypeMap = {
ContentType.text: "$kTypeText/$kSubTypePlain", ContentType.text: "$kTypeText/$kSubTypePlain",
ContentType.formdata: "multipart/form-data", ContentType.formdata: "multipart/form-data",
}; };
const kFormDataTypeMap = {
FormDataType.file: "file",
FormDataType.text: "text",
};
const kMapFormDataType = {
"file": FormDataType.file,
"text": FormDataType.text,
};
enum ResponseBodyView { preview, code, raw, none } enum ResponseBodyView { preview, code, raw, none }

View File

@ -8,7 +8,7 @@ part 'form_data_model.g.dart';
class FormDataModel with _$FormDataModel { class FormDataModel with _$FormDataModel {
const factory FormDataModel({ const factory FormDataModel({
required String name, required String name,
required dynamic value, required String value,
required FormDataType type, required FormDataType type,
}) = _FormDataModel; }) = _FormDataModel;

View File

@ -21,7 +21,7 @@ FormDataModel _$FormDataModelFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$FormDataModel { mixin _$FormDataModel {
String get name => throw _privateConstructorUsedError; String get name => throw _privateConstructorUsedError;
dynamic get value => throw _privateConstructorUsedError; String get value => throw _privateConstructorUsedError;
FormDataType get type => throw _privateConstructorUsedError; FormDataType get type => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@ -36,7 +36,7 @@ abstract class $FormDataModelCopyWith<$Res> {
FormDataModel value, $Res Function(FormDataModel) then) = FormDataModel value, $Res Function(FormDataModel) then) =
_$FormDataModelCopyWithImpl<$Res, FormDataModel>; _$FormDataModelCopyWithImpl<$Res, FormDataModel>;
@useResult @useResult
$Res call({String name, dynamic value, FormDataType type}); $Res call({String name, String value, FormDataType type});
} }
/// @nodoc /// @nodoc
@ -53,7 +53,7 @@ class _$FormDataModelCopyWithImpl<$Res, $Val extends FormDataModel>
@override @override
$Res call({ $Res call({
Object? name = null, Object? name = null,
Object? value = freezed, Object? value = null,
Object? type = null, Object? type = null,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
@ -61,10 +61,10 @@ class _$FormDataModelCopyWithImpl<$Res, $Val extends FormDataModel>
? _value.name ? _value.name
: name // ignore: cast_nullable_to_non_nullable : name // ignore: cast_nullable_to_non_nullable
as String, as String,
value: freezed == value value: null == value
? _value.value ? _value.value
: value // ignore: cast_nullable_to_non_nullable : value // ignore: cast_nullable_to_non_nullable
as dynamic, as String,
type: null == type type: null == type
? _value.type ? _value.type
: type // ignore: cast_nullable_to_non_nullable : type // ignore: cast_nullable_to_non_nullable
@ -81,7 +81,7 @@ abstract class _$$FormDataModelImplCopyWith<$Res>
__$$FormDataModelImplCopyWithImpl<$Res>; __$$FormDataModelImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({String name, dynamic value, FormDataType type}); $Res call({String name, String value, FormDataType type});
} }
/// @nodoc /// @nodoc
@ -96,7 +96,7 @@ class __$$FormDataModelImplCopyWithImpl<$Res>
@override @override
$Res call({ $Res call({
Object? name = null, Object? name = null,
Object? value = freezed, Object? value = null,
Object? type = null, Object? type = null,
}) { }) {
return _then(_$FormDataModelImpl( return _then(_$FormDataModelImpl(
@ -104,10 +104,10 @@ class __$$FormDataModelImplCopyWithImpl<$Res>
? _value.name ? _value.name
: name // ignore: cast_nullable_to_non_nullable : name // ignore: cast_nullable_to_non_nullable
as String, as String,
value: freezed == value value: null == value
? _value.value ? _value.value
: value // ignore: cast_nullable_to_non_nullable : value // ignore: cast_nullable_to_non_nullable
as dynamic, as String,
type: null == type type: null == type
? _value.type ? _value.type
: type // ignore: cast_nullable_to_non_nullable : type // ignore: cast_nullable_to_non_nullable
@ -128,7 +128,7 @@ class _$FormDataModelImpl implements _FormDataModel {
@override @override
final String name; final String name;
@override @override
final dynamic value; final String value;
@override @override
final FormDataType type; final FormDataType type;
@ -143,14 +143,13 @@ class _$FormDataModelImpl implements _FormDataModel {
(other.runtimeType == runtimeType && (other.runtimeType == runtimeType &&
other is _$FormDataModelImpl && other is _$FormDataModelImpl &&
(identical(other.name, name) || other.name == name) && (identical(other.name, name) || other.name == name) &&
const DeepCollectionEquality().equals(other.value, value) && (identical(other.value, value) || other.value == value) &&
(identical(other.type, type) || other.type == type)); (identical(other.type, type) || other.type == type));
} }
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
int get hashCode => Object.hash( int get hashCode => Object.hash(runtimeType, name, value, type);
runtimeType, name, const DeepCollectionEquality().hash(value), type);
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@ -169,7 +168,7 @@ class _$FormDataModelImpl implements _FormDataModel {
abstract class _FormDataModel implements FormDataModel { abstract class _FormDataModel implements FormDataModel {
const factory _FormDataModel( const factory _FormDataModel(
{required final String name, {required final String name,
required final dynamic value, required final String value,
required final FormDataType type}) = _$FormDataModelImpl; required final FormDataType type}) = _$FormDataModelImpl;
factory _FormDataModel.fromJson(Map<String, dynamic> json) = factory _FormDataModel.fromJson(Map<String, dynamic> json) =
@ -178,7 +177,7 @@ abstract class _FormDataModel implements FormDataModel {
@override @override
String get name; String get name;
@override @override
dynamic get value; String get value;
@override @override
FormDataType get type; FormDataType get type;
@override @override

View File

@ -9,7 +9,7 @@ part of 'form_data_model.dart';
_$FormDataModelImpl _$$FormDataModelImplFromJson(Map<String, dynamic> json) => _$FormDataModelImpl _$$FormDataModelImplFromJson(Map<String, dynamic> json) =>
_$FormDataModelImpl( _$FormDataModelImpl(
name: json['name'] as String, name: json['name'] as String,
value: json['value'], value: json['value'] as String,
type: $enumDecode(_$FormDataTypeEnumMap, json['type']), type: $enumDecode(_$FormDataTypeEnumMap, json['type']),
); );

View File

@ -2,3 +2,4 @@ export 'name_value_model.dart';
export 'request_model.dart'; export 'request_model.dart';
export 'response_model.dart'; export 'response_model.dart';
export 'settings_model.dart'; export 'settings_model.dart';
export 'form_data_model.dart';

View File

@ -1,5 +1,3 @@
import 'dart:math';
import 'package:apidash/consts.dart'; import 'package:apidash/consts.dart';
import 'package:apidash/providers/providers.dart'; import 'package:apidash/providers/providers.dart';
import 'package:apidash/widgets/form_data_widget.dart'; import 'package:apidash/widgets/form_data_widget.dart';
@ -15,12 +13,9 @@ class EditRequestBody extends ConsumerStatefulWidget {
} }
class _EditRequestBodyState extends ConsumerState<EditRequestBody> { class _EditRequestBodyState extends ConsumerState<EditRequestBody> {
final random = Random.secure();
late int seed;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
seed = random.nextInt(kRandMax);
} }
@override @override
@ -54,12 +49,7 @@ class _EditRequestBodyState extends ConsumerState<EditRequestBody> {
), ),
Expanded( Expanded(
child: requestBodyStateWatcher == ContentType.formdata child: requestBodyStateWatcher == ContentType.formdata
? FormDataWidget( ? const FormDataWidget()
seed: seed,
onFormDataRemove: () {
seed = random.nextInt(kRandMax);
},
)
: TextFieldEditor( : TextFieldEditor(
key: Key("$activeId-body"), key: Key("$activeId-body"),
fieldKey: "$activeId-body-editor", fieldKey: "$activeId-body-editor",

View File

@ -1,12 +1,9 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:apidash/consts.dart';
import 'package:apidash/models/form_data_model.dart'; import 'package:apidash/models/models.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import '../consts.dart';
import '../models/models.dart';
String humanizeDuration(Duration? duration) { String humanizeDuration(Duration? duration) {
if (duration == null) { if (duration == null) {
return ""; return "";
@ -113,16 +110,24 @@ List<FormDataModel>? listToFormDataModel(List? kvMap) {
if (kvMap == null) { if (kvMap == null) {
return null; return null;
} }
List<FormDataModel> finalRows = kvMap List<FormDataModel> finalRows = kvMap.map(
.map((formData) => FormDataModel( (formData) {
return FormDataModel(
name: formData["name"], name: formData["name"],
value: formData["value"], value: formData["value"],
type: kMapFormDataType[formData["type"]] ?? FormDataType.text, type: getFormDataType(formData["type"]),
)) );
.toList(); },
).toList();
return finalRows; return finalRows;
} }
FormDataType getFormDataType(String? type) {
List<FormDataType> formData = FormDataType.values;
return formData.firstWhere((element) => element.name == type,
orElse: () => FormDataType.text);
}
Uint8List? stringToBytes(String? text) { Uint8List? stringToBytes(String? text) {
if (text == null) { if (text == null) {
return null; return null;

View File

@ -129,6 +129,7 @@ class _DropdownButtonFormData extends State<DropdownButtonFormData> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final surfaceColor = Theme.of(context).colorScheme.surface; final surfaceColor = Theme.of(context).colorScheme.surface;
return DropdownButton<FormDataType>( return DropdownButton<FormDataType>(
dropdownColor: surfaceColor,
focusColor: surfaceColor, focusColor: surfaceColor,
value: widget.formDataType, value: widget.formDataType,
icon: const Icon( icon: const Icon(

View File

@ -27,10 +27,8 @@ class FormDataField extends StatefulWidget {
} }
class _FormDataFieldState extends State<FormDataField> { class _FormDataFieldState extends State<FormDataField> {
TextEditingController valueController = TextEditingController();
@override @override
void initState() { void initState() {
valueController.text = widget.initialValue ?? "";
super.initState(); super.initState();
} }
@ -42,7 +40,7 @@ class _FormDataFieldState extends State<FormDataField> {
Expanded( Expanded(
flex: 1, flex: 1,
child: TextFormField( child: TextFormField(
controller: valueController, initialValue: widget.initialValue,
key: Key(widget.keyId), key: Key(widget.keyId),
style: kCodeStyle.copyWith( style: kCodeStyle.copyWith(
color: colorScheme.onSurface, color: colorScheme.onSurface,
@ -66,21 +64,17 @@ class _FormDataFieldState extends State<FormDataField> {
color: colorScheme.surfaceVariant, color: colorScheme.surfaceVariant,
), ),
), ),
), suffixIcon: DropdownButtonFormData(
onChanged: widget.onChanged,
),
),
Expanded(
child: DropdownButtonFormData(
formDataType: widget.formDataType, formDataType: widget.formDataType,
onChanged: (p0) { onChanged: (p0) {
if (widget.onFormDataTypeChanged != null) { if (widget.onFormDataTypeChanged != null) {
widget.onFormDataTypeChanged!(p0); widget.onFormDataTypeChanged!(p0);
valueController.clear();
} }
}, },
)),
onChanged: widget.onChanged,
),
), ),
)
], ],
); );
} }

View File

@ -1,5 +1,7 @@
import 'dart:math';
import 'package:apidash/consts.dart'; import 'package:apidash/consts.dart';
import 'package:apidash/models/form_data_model.dart'; import 'package:apidash/models/form_data_model.dart';
import 'package:apidash/models/models.dart';
import 'package:apidash/providers/collection_providers.dart'; import 'package:apidash/providers/collection_providers.dart';
import 'package:apidash/widgets/form_data_field.dart'; import 'package:apidash/widgets/form_data_field.dart';
import 'package:apidash/widgets/textfields.dart'; import 'package:apidash/widgets/textfields.dart';
@ -9,43 +11,48 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
class FormDataWidget extends ConsumerStatefulWidget { class FormDataWidget extends ConsumerStatefulWidget {
const FormDataWidget({ const FormDataWidget({super.key});
super.key,
required this.seed,
required this.onFormDataRemove,
});
final int seed;
final Function onFormDataRemove;
@override @override
ConsumerState<FormDataWidget> createState() => _FormDataBodyState(); ConsumerState<FormDataWidget> createState() => _FormDataBodyState();
} }
class _FormDataBodyState extends ConsumerState<FormDataWidget> { class _FormDataBodyState extends ConsumerState<FormDataWidget> {
late int seed;
final random = Random.secure();
late List<FormDataModel> rows;
@override
void initState() {
super.initState();
seed = random.nextInt(kRandMax);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final activeId = ref.watch(activeIdStateProvider); final activeId = ref.watch(activeIdStateProvider);
final requestModel = ref var formRows = ref.read(activeRequestModelProvider)?.formDataList;
.read(collectionStateNotifierProvider.notifier) rows =
.getRequestModel(activeId!); formRows == null || formRows.isEmpty ? [kFormDataEmptyModel] : formRows;
List<FormDataModel> rows = requestModel?.formDataList ?? [];
DaviModel<FormDataModel> model = DaviModel<FormDataModel>( DaviModel<FormDataModel> daviModelRows = DaviModel<FormDataModel>(
rows: rows, rows: rows,
columns: [ columns: [
DaviColumn( DaviColumn(
cellPadding: kpsV5,
name: 'Key', name: 'Key',
grow: 1, grow: 1,
cellBuilder: (_, row) { cellBuilder: (_, row) {
int idx = row.index; int idx = row.index;
return SizedBox( return Theme(
data: Theme.of(context),
child: FormDataField( child: FormDataField(
keyId: "$activeId-$idx-form-v-${widget.seed}", keyId: "$activeId-$idx-form-v-$seed",
initialValue: rows[idx].name, initialValue: rows[idx].name,
hintText: " Key", hintText: " Key",
onChanged: (value) { onChanged: (value) {
rows[idx] = rows[idx].copyWith( rows[idx] = rows[idx].copyWith(
name: value, name: value,
); );
_onFieldChange(activeId); _onFieldChange(activeId!);
}, },
colorScheme: Theme.of(context).colorScheme, colorScheme: Theme.of(context).colorScheme,
formDataType: rows[idx].type, formDataType: rows[idx].type,
@ -54,7 +61,8 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
type: value ?? FormDataType.text, type: value ?? FormDataType.text,
); );
rows[idx] = rows[idx].copyWith(value: ""); rows[idx] = rows[idx].copyWith(value: "");
_onFieldChange(activeId); setState(() {});
_onFieldChange(activeId!);
}, },
), ),
); );
@ -62,7 +70,9 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
sortable: false, sortable: false,
), ),
DaviColumn( DaviColumn(
width: 10, width: 30,
cellPadding: kpsV5,
cellAlignment: Alignment.center,
cellBuilder: (_, row) { cellBuilder: (_, row) {
return Text( return Text(
"=", "=",
@ -73,6 +83,7 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
DaviColumn( DaviColumn(
name: 'Value', name: 'Value',
grow: 4, grow: 4,
cellPadding: kpsV5,
cellBuilder: (_, row) { cellBuilder: (_, row) {
int idx = row.index; int idx = row.index;
return rows[idx].type == FormDataType.file return rows[idx].type == FormDataType.file
@ -83,36 +94,35 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
child: ElevatedButtonTheme( child: Theme(
data: const ElevatedButtonThemeData(), data: Theme.of(context),
child: ElevatedButton.icon( child: ElevatedButton.icon(
icon: const Icon(
Icons.snippet_folder_rounded,
size: 20,
),
style: const ButtonStyle(),
onPressed: () async { onPressed: () async {
FilePickerResult? pickedResult = FilePickerResult? pickedResult =
await FilePicker.platform.pickFiles(); await FilePicker.platform.pickFiles();
if (pickedResult != null && if (pickedResult != null &&
pickedResult.files.isNotEmpty) { pickedResult.files.isNotEmpty &&
pickedResult.files.first.path != null) {
rows[idx] = rows[idx].copyWith( rows[idx] = rows[idx].copyWith(
value: pickedResult.files.first.path, value: pickedResult.files.first.path!,
); );
_onFieldChange(activeId); setState(() {});
_onFieldChange(activeId!);
} }
}, },
icon: const Icon(
Icons.snippet_folder_rounded,
size: 18,
),
label: Text( label: Text(
rows[idx].type == FormDataType.file (rows[idx].type == FormDataType.file &&
? (rows[idx].value != null rows[idx].value.isNotEmpty)
? rows[idx].value.toString() ? rows[idx].value.toString()
: "Select File")
: "Select File", : "Select File",
textAlign: TextAlign.center, textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: kTextStyleButton.copyWith( style: kFormDataButton,
fontSize: 12,
fontWeight: FontWeight.w500,
),
), ),
), ),
), ),
@ -122,12 +132,12 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
), ),
) )
: CellField( : CellField(
keyId: "$activeId-$idx-form-v-${widget.seed}", keyId: "$activeId-$idx-form-v-$seed",
initialValue: rows[idx].value, initialValue: rows[idx].value,
hintText: " Value", hintText: " Value",
onChanged: (value) { onChanged: (value) {
rows[idx] = rows[idx].copyWith(value: value); rows[idx] = rows[idx].copyWith(value: value);
_onFieldChange(activeId); _onFieldChange(activeId!);
}, },
colorScheme: Theme.of(context).colorScheme, colorScheme: Theme.of(context).colorScheme,
); );
@ -143,17 +153,16 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
? kIconRemoveDark ? kIconRemoveDark
: kIconRemoveLight, : kIconRemoveLight,
onTap: () { onTap: () {
widget.onFormDataRemove(); seed = random.nextInt(kRandMax);
if (rows.length == 1) { if (rows.length == 1) {
setState(() { setState(() {
rows = [ rows = [kFormDataEmptyModel];
kFormDataEmptyModel,
];
}); });
} else { } else {
rows.removeAt(row.index); rows.removeAt(row.index);
} }
_onFieldChange(activeId); _onFieldChange(activeId!);
setState(() {});
}, },
); );
}, },
@ -173,7 +182,7 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
Expanded( Expanded(
child: DaviTheme( child: DaviTheme(
data: kTableThemeData, data: kTableThemeData,
child: Davi<FormDataModel>(model), child: Davi<FormDataModel>(daviModelRows),
), ),
), ),
], ],
@ -185,8 +194,10 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
padding: const EdgeInsets.only(bottom: 30), padding: const EdgeInsets.only(bottom: 30),
child: ElevatedButton.icon( child: ElevatedButton.icon(
onPressed: () { onPressed: () {
setState(() {
rows.add(kFormDataEmptyModel); rows.add(kFormDataEmptyModel);
_onFieldChange(activeId); });
_onFieldChange(activeId!);
}, },
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
label: const Text( label: const Text(
@ -201,12 +212,9 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
} }
void _onFieldChange(String activeId) { void _onFieldChange(String activeId) {
List<FormDataModel> formDataList =
ref.read(collectionStateNotifierProvider)?[activeId]?.formDataList ??
[];
ref.read(collectionStateNotifierProvider.notifier).update( ref.read(collectionStateNotifierProvider.notifier).update(
activeId, activeId,
formDataList: formDataList, formDataList: rows,
); );
} }
} }