mirror of
https://github.com/foss42/apidash.git
synced 2025-06-07 03:48:11 +08:00
fix: PR fixes with few enhancements
This commit is contained in:
@ -1,10 +1,9 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:davi/davi.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:davi/davi.dart';
|
||||
|
||||
const kDiscordUrl = "https://bit.ly/heyfoss";
|
||||
const kGitUrl = "https://github.com/foss42/apidash";
|
||||
@ -49,6 +48,10 @@ const kHintOpacity = 0.6;
|
||||
const kForegroundOpacity = 0.05;
|
||||
|
||||
const kTextStyleButton = TextStyle(fontWeight: FontWeight.bold);
|
||||
const kFormDataButton = TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
);
|
||||
|
||||
const kBorderRadius8 = BorderRadius.all(Radius.circular(8));
|
||||
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 kP8CollectionPane = EdgeInsets.only(top: 8.0, left: 8.0, bottom: 8.0);
|
||||
const kPr8CollectionPane = EdgeInsets.only(right: 8.0);
|
||||
|
||||
const kpsV5 = EdgeInsets.symmetric(vertical: 2);
|
||||
const kHSpacer4 = SizedBox(width: 4);
|
||||
const kHSpacer5 = SizedBox(width: 5);
|
||||
const kHSpacer10 = SizedBox(width: 10);
|
||||
@ -300,14 +303,6 @@ const kContentTypeMap = {
|
||||
ContentType.text: "$kTypeText/$kSubTypePlain",
|
||||
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 }
|
||||
|
||||
|
@ -8,7 +8,7 @@ part 'form_data_model.g.dart';
|
||||
class FormDataModel with _$FormDataModel {
|
||||
const factory FormDataModel({
|
||||
required String name,
|
||||
required dynamic value,
|
||||
required String value,
|
||||
required FormDataType type,
|
||||
}) = _FormDataModel;
|
||||
|
||||
|
@ -21,7 +21,7 @@ FormDataModel _$FormDataModelFromJson(Map<String, dynamic> json) {
|
||||
/// @nodoc
|
||||
mixin _$FormDataModel {
|
||||
String get name => throw _privateConstructorUsedError;
|
||||
dynamic get value => throw _privateConstructorUsedError;
|
||||
String get value => throw _privateConstructorUsedError;
|
||||
FormDataType get type => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@ -36,7 +36,7 @@ abstract class $FormDataModelCopyWith<$Res> {
|
||||
FormDataModel value, $Res Function(FormDataModel) then) =
|
||||
_$FormDataModelCopyWithImpl<$Res, FormDataModel>;
|
||||
@useResult
|
||||
$Res call({String name, dynamic value, FormDataType type});
|
||||
$Res call({String name, String value, FormDataType type});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -53,7 +53,7 @@ class _$FormDataModelCopyWithImpl<$Res, $Val extends FormDataModel>
|
||||
@override
|
||||
$Res call({
|
||||
Object? name = null,
|
||||
Object? value = freezed,
|
||||
Object? value = null,
|
||||
Object? type = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
@ -61,10 +61,10 @@ class _$FormDataModelCopyWithImpl<$Res, $Val extends FormDataModel>
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
value: freezed == value
|
||||
value: null == value
|
||||
? _value.value
|
||||
: value // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,
|
||||
as String,
|
||||
type: null == type
|
||||
? _value.type
|
||||
: type // ignore: cast_nullable_to_non_nullable
|
||||
@ -81,7 +81,7 @@ abstract class _$$FormDataModelImplCopyWith<$Res>
|
||||
__$$FormDataModelImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({String name, dynamic value, FormDataType type});
|
||||
$Res call({String name, String value, FormDataType type});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -96,7 +96,7 @@ class __$$FormDataModelImplCopyWithImpl<$Res>
|
||||
@override
|
||||
$Res call({
|
||||
Object? name = null,
|
||||
Object? value = freezed,
|
||||
Object? value = null,
|
||||
Object? type = null,
|
||||
}) {
|
||||
return _then(_$FormDataModelImpl(
|
||||
@ -104,10 +104,10 @@ class __$$FormDataModelImplCopyWithImpl<$Res>
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
value: freezed == value
|
||||
value: null == value
|
||||
? _value.value
|
||||
: value // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,
|
||||
as String,
|
||||
type: null == type
|
||||
? _value.type
|
||||
: type // ignore: cast_nullable_to_non_nullable
|
||||
@ -128,7 +128,7 @@ class _$FormDataModelImpl implements _FormDataModel {
|
||||
@override
|
||||
final String name;
|
||||
@override
|
||||
final dynamic value;
|
||||
final String value;
|
||||
@override
|
||||
final FormDataType type;
|
||||
|
||||
@ -143,14 +143,13 @@ class _$FormDataModelImpl implements _FormDataModel {
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$FormDataModelImpl &&
|
||||
(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));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, name, const DeepCollectionEquality().hash(value), type);
|
||||
int get hashCode => Object.hash(runtimeType, name, value, type);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@ -169,7 +168,7 @@ class _$FormDataModelImpl implements _FormDataModel {
|
||||
abstract class _FormDataModel implements FormDataModel {
|
||||
const factory _FormDataModel(
|
||||
{required final String name,
|
||||
required final dynamic value,
|
||||
required final String value,
|
||||
required final FormDataType type}) = _$FormDataModelImpl;
|
||||
|
||||
factory _FormDataModel.fromJson(Map<String, dynamic> json) =
|
||||
@ -178,7 +177,7 @@ abstract class _FormDataModel implements FormDataModel {
|
||||
@override
|
||||
String get name;
|
||||
@override
|
||||
dynamic get value;
|
||||
String get value;
|
||||
@override
|
||||
FormDataType get type;
|
||||
@override
|
||||
|
@ -9,7 +9,7 @@ part of 'form_data_model.dart';
|
||||
_$FormDataModelImpl _$$FormDataModelImplFromJson(Map<String, dynamic> json) =>
|
||||
_$FormDataModelImpl(
|
||||
name: json['name'] as String,
|
||||
value: json['value'],
|
||||
value: json['value'] as String,
|
||||
type: $enumDecode(_$FormDataTypeEnumMap, json['type']),
|
||||
);
|
||||
|
||||
|
@ -2,3 +2,4 @@ export 'name_value_model.dart';
|
||||
export 'request_model.dart';
|
||||
export 'response_model.dart';
|
||||
export 'settings_model.dart';
|
||||
export 'form_data_model.dart';
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'package:apidash/widgets/form_data_widget.dart';
|
||||
@ -15,12 +13,9 @@ class EditRequestBody extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _EditRequestBodyState extends ConsumerState<EditRequestBody> {
|
||||
final random = Random.secure();
|
||||
late int seed;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
seed = random.nextInt(kRandMax);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -54,12 +49,7 @@ class _EditRequestBodyState extends ConsumerState<EditRequestBody> {
|
||||
),
|
||||
Expanded(
|
||||
child: requestBodyStateWatcher == ContentType.formdata
|
||||
? FormDataWidget(
|
||||
seed: seed,
|
||||
onFormDataRemove: () {
|
||||
seed = random.nextInt(kRandMax);
|
||||
},
|
||||
)
|
||||
? const FormDataWidget()
|
||||
: TextFieldEditor(
|
||||
key: Key("$activeId-body"),
|
||||
fieldKey: "$activeId-body-editor",
|
||||
|
@ -1,12 +1,9 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:apidash/models/form_data_model.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:apidash/models/models.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../consts.dart';
|
||||
import '../models/models.dart';
|
||||
|
||||
String humanizeDuration(Duration? duration) {
|
||||
if (duration == null) {
|
||||
return "";
|
||||
@ -113,16 +110,24 @@ List<FormDataModel>? listToFormDataModel(List? kvMap) {
|
||||
if (kvMap == null) {
|
||||
return null;
|
||||
}
|
||||
List<FormDataModel> finalRows = kvMap
|
||||
.map((formData) => FormDataModel(
|
||||
List<FormDataModel> finalRows = kvMap.map(
|
||||
(formData) {
|
||||
return FormDataModel(
|
||||
name: formData["name"],
|
||||
value: formData["value"],
|
||||
type: kMapFormDataType[formData["type"]] ?? FormDataType.text,
|
||||
))
|
||||
.toList();
|
||||
type: getFormDataType(formData["type"]),
|
||||
);
|
||||
},
|
||||
).toList();
|
||||
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) {
|
||||
if (text == null) {
|
||||
return null;
|
||||
|
@ -129,6 +129,7 @@ class _DropdownButtonFormData extends State<DropdownButtonFormData> {
|
||||
Widget build(BuildContext context) {
|
||||
final surfaceColor = Theme.of(context).colorScheme.surface;
|
||||
return DropdownButton<FormDataType>(
|
||||
dropdownColor: surfaceColor,
|
||||
focusColor: surfaceColor,
|
||||
value: widget.formDataType,
|
||||
icon: const Icon(
|
||||
|
@ -27,10 +27,8 @@ class FormDataField extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _FormDataFieldState extends State<FormDataField> {
|
||||
TextEditingController valueController = TextEditingController();
|
||||
@override
|
||||
void initState() {
|
||||
valueController.text = widget.initialValue ?? "";
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@ -42,7 +40,7 @@ class _FormDataFieldState extends State<FormDataField> {
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: TextFormField(
|
||||
controller: valueController,
|
||||
initialValue: widget.initialValue,
|
||||
key: Key(widget.keyId),
|
||||
style: kCodeStyle.copyWith(
|
||||
color: colorScheme.onSurface,
|
||||
@ -66,21 +64,17 @@ class _FormDataFieldState extends State<FormDataField> {
|
||||
color: colorScheme.surfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
onChanged: widget.onChanged,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: DropdownButtonFormData(
|
||||
suffixIcon: DropdownButtonFormData(
|
||||
formDataType: widget.formDataType,
|
||||
onChanged: (p0) {
|
||||
if (widget.onFormDataTypeChanged != null) {
|
||||
widget.onFormDataTypeChanged!(p0);
|
||||
valueController.clear();
|
||||
}
|
||||
},
|
||||
)),
|
||||
onChanged: widget.onChanged,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import 'dart:math';
|
||||
import 'package:apidash/consts.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/widgets/form_data_field.dart';
|
||||
import 'package:apidash/widgets/textfields.dart';
|
||||
@ -9,43 +11,48 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class FormDataWidget extends ConsumerStatefulWidget {
|
||||
const FormDataWidget({
|
||||
super.key,
|
||||
required this.seed,
|
||||
required this.onFormDataRemove,
|
||||
});
|
||||
final int seed;
|
||||
final Function onFormDataRemove;
|
||||
const FormDataWidget({super.key});
|
||||
@override
|
||||
ConsumerState<FormDataWidget> createState() => _FormDataBodyState();
|
||||
}
|
||||
|
||||
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
|
||||
Widget build(BuildContext context) {
|
||||
final activeId = ref.watch(activeIdStateProvider);
|
||||
final requestModel = ref
|
||||
.read(collectionStateNotifierProvider.notifier)
|
||||
.getRequestModel(activeId!);
|
||||
List<FormDataModel> rows = requestModel?.formDataList ?? [];
|
||||
DaviModel<FormDataModel> model = DaviModel<FormDataModel>(
|
||||
var formRows = ref.read(activeRequestModelProvider)?.formDataList;
|
||||
rows =
|
||||
formRows == null || formRows.isEmpty ? [kFormDataEmptyModel] : formRows;
|
||||
|
||||
DaviModel<FormDataModel> daviModelRows = DaviModel<FormDataModel>(
|
||||
rows: rows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
cellPadding: kpsV5,
|
||||
name: 'Key',
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
return SizedBox(
|
||||
return Theme(
|
||||
data: Theme.of(context),
|
||||
child: FormDataField(
|
||||
keyId: "$activeId-$idx-form-v-${widget.seed}",
|
||||
keyId: "$activeId-$idx-form-v-$seed",
|
||||
initialValue: rows[idx].name,
|
||||
hintText: " Key",
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(
|
||||
name: value,
|
||||
);
|
||||
_onFieldChange(activeId);
|
||||
_onFieldChange(activeId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
formDataType: rows[idx].type,
|
||||
@ -54,7 +61,8 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
type: value ?? FormDataType.text,
|
||||
);
|
||||
rows[idx] = rows[idx].copyWith(value: "");
|
||||
_onFieldChange(activeId);
|
||||
setState(() {});
|
||||
_onFieldChange(activeId!);
|
||||
},
|
||||
),
|
||||
);
|
||||
@ -62,7 +70,9 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
width: 10,
|
||||
width: 30,
|
||||
cellPadding: kpsV5,
|
||||
cellAlignment: Alignment.center,
|
||||
cellBuilder: (_, row) {
|
||||
return Text(
|
||||
"=",
|
||||
@ -73,6 +83,7 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
DaviColumn(
|
||||
name: 'Value',
|
||||
grow: 4,
|
||||
cellPadding: kpsV5,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
return rows[idx].type == FormDataType.file
|
||||
@ -83,36 +94,35 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ElevatedButtonTheme(
|
||||
data: const ElevatedButtonThemeData(),
|
||||
child: Theme(
|
||||
data: Theme.of(context),
|
||||
child: ElevatedButton.icon(
|
||||
icon: const Icon(
|
||||
Icons.snippet_folder_rounded,
|
||||
size: 20,
|
||||
),
|
||||
style: const ButtonStyle(),
|
||||
onPressed: () async {
|
||||
FilePickerResult? pickedResult =
|
||||
await FilePicker.platform.pickFiles();
|
||||
if (pickedResult != null &&
|
||||
pickedResult.files.isNotEmpty) {
|
||||
pickedResult.files.isNotEmpty &&
|
||||
pickedResult.files.first.path != null) {
|
||||
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(
|
||||
rows[idx].type == FormDataType.file
|
||||
? (rows[idx].value != null
|
||||
(rows[idx].type == FormDataType.file &&
|
||||
rows[idx].value.isNotEmpty)
|
||||
? rows[idx].value.toString()
|
||||
: "Select File")
|
||||
: "Select File",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: kTextStyleButton.copyWith(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
style: kFormDataButton,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -122,12 +132,12 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
),
|
||||
)
|
||||
: CellField(
|
||||
keyId: "$activeId-$idx-form-v-${widget.seed}",
|
||||
keyId: "$activeId-$idx-form-v-$seed",
|
||||
initialValue: rows[idx].value,
|
||||
hintText: " Value",
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(value: value);
|
||||
_onFieldChange(activeId);
|
||||
_onFieldChange(activeId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
@ -143,17 +153,16 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
onTap: () {
|
||||
widget.onFormDataRemove();
|
||||
seed = random.nextInt(kRandMax);
|
||||
if (rows.length == 1) {
|
||||
setState(() {
|
||||
rows = [
|
||||
kFormDataEmptyModel,
|
||||
];
|
||||
rows = [kFormDataEmptyModel];
|
||||
});
|
||||
} else {
|
||||
rows.removeAt(row.index);
|
||||
}
|
||||
_onFieldChange(activeId);
|
||||
_onFieldChange(activeId!);
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
@ -173,7 +182,7 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
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),
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
rows.add(kFormDataEmptyModel);
|
||||
_onFieldChange(activeId);
|
||||
});
|
||||
_onFieldChange(activeId!);
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text(
|
||||
@ -201,12 +212,9 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
}
|
||||
|
||||
void _onFieldChange(String activeId) {
|
||||
List<FormDataModel> formDataList =
|
||||
ref.read(collectionStateNotifierProvider)?[activeId]?.formDataList ??
|
||||
[];
|
||||
ref.read(collectionStateNotifierProvider.notifier).update(
|
||||
activeId,
|
||||
formDataList: formDataList,
|
||||
formDataList: rows,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user