mirror of
https://github.com/foss42/apidash.git
synced 2025-06-03 08:16:25 +08:00
Fully functional prototype with final UI design
This commit is contained in:
@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../models/models.dart';
|
||||
import '../providers/providers.dart';
|
||||
import '../utils/utils.dart';
|
||||
import 'styles.dart';
|
||||
import '../consts.dart';
|
||||
|
||||
class CollectionPane extends ConsumerStatefulWidget {
|
||||
@ -38,7 +39,10 @@ class _CollectionPaneState extends ConsumerState<CollectionPane> {
|
||||
.read(activeItemIdStateProvider.notifier)
|
||||
.update((state) => newId);
|
||||
},
|
||||
child: const Text('+ New'),
|
||||
child: const Text(
|
||||
'+ New',
|
||||
style: textStyleButton,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -120,12 +124,9 @@ class RequestItem extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _RequestItemState extends ConsumerState<RequestItem> {
|
||||
late Color _color;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_color = Colors.grey.shade50;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -133,11 +134,11 @@ class _RequestItemState extends ConsumerState<RequestItem> {
|
||||
final activeRequest = ref.watch(activeItemIdStateProvider);
|
||||
bool isActiveId = activeRequest == widget.id;
|
||||
return Material(
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
borderRadius: borderRadius10,
|
||||
elevation: isActiveId ? 2 : 0,
|
||||
color: isActiveId ? Colors.grey.shade300 : _color,
|
||||
color: isActiveId ? colorGrey300 : colorGrey50,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
borderRadius: borderRadius10,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(activeItemIdStateProvider.notifier)
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../../providers/providers.dart';
|
||||
import '../styles.dart';
|
||||
import '../../consts.dart';
|
||||
|
||||
class EditRequestBody extends StatefulWidget {
|
||||
@ -13,23 +14,92 @@ class EditRequestBody extends StatefulWidget {
|
||||
class _EditRequestBodyState extends State<EditRequestBody> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
child: DropdownButtonBodyContentType(),
|
||||
height: 30,
|
||||
)
|
||||
],
|
||||
return Container(
|
||||
decoration: tableContainerDecoration,
|
||||
margin: p5,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: p10,
|
||||
child: Row(
|
||||
children: const [
|
||||
Text(
|
||||
"Select Content Type:",
|
||||
//style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
child: DropdownButtonBodyContentType(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextFieldEditor(),
|
||||
)
|
||||
],
|
||||
const Divider(),
|
||||
const Expanded(
|
||||
child: Padding(
|
||||
padding: p10,
|
||||
child: TextFieldEditor(),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DropdownButtonBodyContentType extends ConsumerStatefulWidget {
|
||||
const DropdownButtonBodyContentType({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
ConsumerState<DropdownButtonBodyContentType> createState() =>
|
||||
_DropdownButtonBodyContentTypeState();
|
||||
}
|
||||
|
||||
class _DropdownButtonBodyContentTypeState
|
||||
extends ConsumerState<DropdownButtonBodyContentType> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final activeId = ref.watch(activeItemIdStateProvider);
|
||||
final collection = ref.read(collectionStateNotifierProvider);
|
||||
final idIdx = collection.indexWhere((m) => m.id == activeId);
|
||||
final requestBodyContentType = ref.watch(collectionStateNotifierProvider
|
||||
.select((value) => value[idIdx].requestBodyContentType));
|
||||
return DropdownButton<ContentType>(
|
||||
focusColor: colorGrey50,
|
||||
value: requestBodyContentType,
|
||||
icon: const Icon(
|
||||
Icons.unfold_more_rounded,
|
||||
size: 16,
|
||||
),
|
||||
elevation: 4,
|
||||
style: codeStyle.copyWith(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary), //Theme.of(context).textTheme.bodyMedium,
|
||||
underline: Container(
|
||||
height: 0,
|
||||
),
|
||||
onChanged: (ContentType? value) {
|
||||
ref
|
||||
.read(collectionStateNotifierProvider.notifier)
|
||||
.update(activeId!, requestBodyContentType: value);
|
||||
},
|
||||
borderRadius: borderRadius10,
|
||||
items: ContentType.values
|
||||
.map<DropdownMenuItem<ContentType>>((ContentType value) {
|
||||
return DropdownMenuItem<ContentType>(
|
||||
value: value,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 8),
|
||||
child: Text(
|
||||
value.name,
|
||||
style: textStyleButton,
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -61,9 +131,10 @@ class _TextFieldEditorState extends ConsumerState<TextFieldEditor> {
|
||||
.read(collectionStateNotifierProvider.notifier)
|
||||
.update(activeId, requestBody: value);
|
||||
},
|
||||
style: codeStyle,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Enter body",
|
||||
hintStyle: TextStyle(color: Colors.grey.shade500),
|
||||
hintText: "Enter content (body)",
|
||||
hintStyle: codeStyle.copyWith(color: colorGrey500),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
keyboardType: TextInputType.multiline,
|
||||
@ -72,55 +143,3 @@ class _TextFieldEditorState extends ConsumerState<TextFieldEditor> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DropdownButtonBodyContentType extends ConsumerStatefulWidget {
|
||||
const DropdownButtonBodyContentType({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
ConsumerState<DropdownButtonBodyContentType> createState() =>
|
||||
_DropdownButtonBodyContentTypeState();
|
||||
}
|
||||
|
||||
class _DropdownButtonBodyContentTypeState
|
||||
extends ConsumerState<DropdownButtonBodyContentType> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final activeId = ref.watch(activeItemIdStateProvider);
|
||||
final reqestModel = ref
|
||||
.read(collectionStateNotifierProvider.notifier)
|
||||
.getRequestModel(activeId!);
|
||||
return DropdownButton<ContentType>(
|
||||
focusColor: Colors.white,
|
||||
value: reqestModel.requestBodyContentType,
|
||||
icon: const Icon(
|
||||
Icons.unfold_more_rounded,
|
||||
size: 16,
|
||||
),
|
||||
elevation: 4,
|
||||
underline: Container(
|
||||
height: 0,
|
||||
//color: Colors.deepPurpleAccent,
|
||||
),
|
||||
onChanged: (ContentType? value) {
|
||||
ref
|
||||
.read(collectionStateNotifierProvider.notifier)
|
||||
.update(activeId!, requestBodyContentType: value);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
items: ContentType.values
|
||||
.map<DropdownMenuItem<ContentType>>((ContentType value) {
|
||||
return DropdownMenuItem<ContentType>(
|
||||
value: value,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 8),
|
||||
child: Text(
|
||||
value.name,
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:multi_split_view/multi_split_view.dart';
|
||||
import 'request_pane.dart';
|
||||
import 'response_pane.dart';
|
||||
@ -30,8 +29,8 @@ class _EditorPaneRequestDetailsCardState
|
||||
data: MultiSplitViewThemeData(
|
||||
dividerThickness: 3,
|
||||
dividerPainter: DividerPainters.background(
|
||||
color: Colors.grey.shade200,
|
||||
highlightedColor: Colors.grey.shade400,
|
||||
color: colorGrey200,
|
||||
highlightedColor: colorGrey400,
|
||||
animationEnabled: false,
|
||||
),
|
||||
),
|
||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:tab_container/tab_container.dart';
|
||||
import '../../providers/providers.dart';
|
||||
import '../styles.dart';
|
||||
import 'tables.dart';
|
||||
import 'body_editor.dart';
|
||||
|
||||
@ -28,28 +29,41 @@ class _EditRequestPaneState extends ConsumerState<EditRequestPane> {
|
||||
.read(collectionStateNotifierProvider.notifier)
|
||||
.getRequestModel(activeId!)
|
||||
.requestTabIndex);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: TabContainer(
|
||||
key: Key(activeId),
|
||||
controller: _controller,
|
||||
color: Colors.grey.shade100,
|
||||
onEnd: () {
|
||||
ref
|
||||
.read(collectionStateNotifierProvider.notifier)
|
||||
.update(activeId, requestTabIndex: _controller.index);
|
||||
},
|
||||
tabs: const [
|
||||
return TabContainer(
|
||||
key: Key(activeId),
|
||||
controller: _controller,
|
||||
color: colorGrey100,
|
||||
onEnd: () {
|
||||
ref
|
||||
.read(collectionStateNotifierProvider.notifier)
|
||||
.update(activeId, requestTabIndex: _controller.index);
|
||||
},
|
||||
isStringTabs: false,
|
||||
tabs: const [
|
||||
Text(
|
||||
'URL Params',
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.fade,
|
||||
style: textStyleButton,
|
||||
),
|
||||
Text(
|
||||
'Headers',
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.fade,
|
||||
style: textStyleButton,
|
||||
),
|
||||
Text(
|
||||
'Body',
|
||||
],
|
||||
children: const [
|
||||
EditRequestURLParams(),
|
||||
EditRequestHeaders(),
|
||||
EditRequestBody(),
|
||||
],
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.fade,
|
||||
style: textStyleButton,
|
||||
)
|
||||
],
|
||||
children: const [
|
||||
EditRequestURLParams(),
|
||||
EditRequestHeaders(),
|
||||
EditRequestBody(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,13 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_json_view/flutter_json_view.dart';
|
||||
import '../../providers/providers.dart';
|
||||
import '../../models/request_model.dart';
|
||||
import '../styles.dart';
|
||||
import "../../utils/utils.dart";
|
||||
import "../../consts.dart";
|
||||
|
||||
class ResponsePane extends ConsumerStatefulWidget {
|
||||
const ResponsePane({super.key});
|
||||
@ -16,12 +24,28 @@ class _ResponsePaneState extends ConsumerState<ResponsePane> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Column(
|
||||
children: [],
|
||||
),
|
||||
);
|
||||
final activeId = ref.watch(activeItemIdStateProvider);
|
||||
final collection = ref.read(collectionStateNotifierProvider);
|
||||
final idIdx = collection.indexWhere((m) => m.id == activeId);
|
||||
final status = ref.watch(collectionStateNotifierProvider
|
||||
.select((value) => (value[idIdx].responseStatus,
|
||||
value[idIdx].message,
|
||||
value[idIdx].responseModel)));
|
||||
if (status.$0 == null) {
|
||||
return const NotSentWidget();
|
||||
}
|
||||
if (status.$0 == -1) {
|
||||
return ErrorMessage(message: status.$1);
|
||||
}
|
||||
else{
|
||||
//var responseModel = ref
|
||||
// .read(collectionStateNotifierProvider.notifier)
|
||||
// .getRequestModel(activeId!)
|
||||
// .responseModel;
|
||||
return ResponseViewer(statusCode: status.$0!,
|
||||
message: status.$1,
|
||||
responseModel: status.$2!);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -29,3 +53,237 @@ class _ResponsePaneState extends ConsumerState<ResponsePane> {
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class NotSentWidget extends StatelessWidget {
|
||||
const NotSentWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.north_east_rounded,
|
||||
size: 40,
|
||||
color: colorErrorMsg,
|
||||
),
|
||||
Text(
|
||||
'Not Sent',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium
|
||||
?.copyWith(color: colorErrorMsg),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ErrorMessage extends StatelessWidget {
|
||||
const ErrorMessage({super.key, required this.message});
|
||||
|
||||
final String? message;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.warning_rounded,
|
||||
size: 40,
|
||||
color: colorErrorMsg,
|
||||
),
|
||||
Text(
|
||||
message ?? 'And error occurred.',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium
|
||||
?.copyWith(color: colorErrorMsg),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final jsonViewTheme = JsonViewTheme(defaultTextStyle : codeStyle,
|
||||
viewType: JsonViewType.collapsible,
|
||||
backgroundColor: colorBg,
|
||||
stringStyle: const TextStyle(color: Colors.brown),
|
||||
closeIcon: const Icon(
|
||||
Icons.arrow_drop_up,
|
||||
size: 18,
|
||||
),
|
||||
openIcon : const Icon(
|
||||
Icons.arrow_drop_down,
|
||||
size: 18,
|
||||
),
|
||||
);
|
||||
|
||||
class ResponseViewer extends StatelessWidget {
|
||||
final int statusCode;
|
||||
final String? message;
|
||||
final ResponseModel responseModel;
|
||||
|
||||
const ResponseViewer({
|
||||
super.key,
|
||||
required this.statusCode,
|
||||
required this.message,
|
||||
required this.responseModel,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var requestHeaders = responseModel.requestHeaders ?? {};
|
||||
var responseHeaders = responseModel.headers ?? {};
|
||||
var body = responseModel.body ?? '';
|
||||
return Padding(
|
||||
padding: p10,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: const [
|
||||
Text(
|
||||
"Response",
|
||||
style: textStyleButton,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width:50,
|
||||
child: Text(
|
||||
statusCode.toString(),
|
||||
style: codeStyle.copyWith(
|
||||
color: getResponseStatusCodeColor(statusCode),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
message ?? "",
|
||||
style: codeStyle.copyWith(
|
||||
color: getResponseStatusCodeColor(statusCode),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width:100,
|
||||
child: Text(
|
||||
humanizeDuration(responseModel.time),
|
||||
style: codeStyle.copyWith(
|
||||
color: getResponseStatusCodeColor(statusCode),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Request Headers (${requestHeaders.length} items)",
|
||||
style: codeStyle,
|
||||
),
|
||||
),
|
||||
if(requestHeaders.isNotEmpty) TextButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(ClipboardData(text: json.encode(requestHeaders)));
|
||||
},
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.content_copy,
|
||||
size: 20,
|
||||
),
|
||||
Text("Copy")
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if(requestHeaders.isNotEmpty) const SizedBox(height: 5),
|
||||
if(requestHeaders.isNotEmpty) JsonView.map(
|
||||
requestHeaders,
|
||||
theme: jsonViewTheme,
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Response Headers (${responseHeaders.length} items)",
|
||||
style: codeStyle,
|
||||
),
|
||||
),
|
||||
if(responseHeaders.isNotEmpty) TextButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(ClipboardData(text: json.encode(responseHeaders)));
|
||||
},
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.content_copy,
|
||||
size: 20,
|
||||
),
|
||||
Text("Copy")
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if(responseHeaders.isNotEmpty) const SizedBox(height: 5),
|
||||
if(responseHeaders.isNotEmpty) JsonView.map(
|
||||
responseHeaders,
|
||||
theme: jsonViewTheme,
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Body ${body.isEmpty ? '(empty)' : ''}",
|
||||
style: codeStyle,
|
||||
),
|
||||
),
|
||||
if(body.isNotEmpty) TextButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(ClipboardData(text: body));
|
||||
},
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.content_copy,
|
||||
size: 20,
|
||||
),
|
||||
Text("Copy")
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
if(body.isNotEmpty && responseModel.contentType!.startsWith(JSON_MIMETYPE))
|
||||
JsonView.string(
|
||||
body,
|
||||
theme: jsonViewTheme,
|
||||
),
|
||||
if(body.isNotEmpty && responseModel.contentType!.startsWith("text/"))
|
||||
Text(body),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:davi/davi.dart';
|
||||
import '../../models/models.dart';
|
||||
import '../../providers/providers.dart';
|
||||
import '../styles.dart';
|
||||
|
||||
class EditRequestURLParams extends ConsumerStatefulWidget {
|
||||
const EditRequestURLParams({Key? key}) : super(key: key);
|
||||
@ -26,7 +27,11 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
return TextFormField(
|
||||
key: Key("$activeId-$idx-params-k"),
|
||||
initialValue: rows[idx].k,
|
||||
decoration: const InputDecoration(hintText: "Add URL Parameter"),
|
||||
style: codeStyle,
|
||||
decoration: InputDecoration(
|
||||
hintStyle: codeStyle,
|
||||
hintText: "Add URL Parameter",
|
||||
),
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(k: value);
|
||||
_onFieldChange(activeId!);
|
||||
@ -39,7 +44,11 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
return TextFormField(
|
||||
key: Key("$activeId-$idx-params-v"),
|
||||
initialValue: rows[idx].v,
|
||||
decoration: const InputDecoration(hintText: "Add Value"),
|
||||
style: codeStyle,
|
||||
decoration: InputDecoration(
|
||||
hintStyle: codeStyle,
|
||||
hintText: "Add Value",
|
||||
),
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(v: value);
|
||||
_onFieldChange(activeId!);
|
||||
@ -75,44 +84,36 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
),
|
||||
],
|
||||
);
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
rows.add(const KVRow("", ""));
|
||||
model.addRow(const KVRow("", ""));
|
||||
},
|
||||
child: const Text("+ Add Param"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: DaviThemeData(
|
||||
columnDividerThickness: 1,
|
||||
columnDividerColor: Colors.grey.shade100,
|
||||
row: RowThemeData(dividerColor: Colors.grey.shade100),
|
||||
decoration: const BoxDecoration(
|
||||
border: Border(),
|
||||
),
|
||||
header: HeaderThemeData(
|
||||
color: Colors.grey.shade100,
|
||||
columnDividerColor: Colors.grey.shade100,
|
||||
bottomBorderHeight: 1,
|
||||
),
|
||||
headerCell: const HeaderCellThemeData(
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
return Container(
|
||||
decoration: tableContainerDecoration,
|
||||
margin: p5,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: p10,
|
||||
child: Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
rows.add(const KVRow("", ""));
|
||||
model.addRow(const KVRow("", ""));
|
||||
},
|
||||
child: const Text(
|
||||
"+ Add Param",
|
||||
style: textStyleButton,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Davi<KVRow>(model),
|
||||
),
|
||||
),
|
||||
],
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: tableThemeData,
|
||||
child: Davi<KVRow>(model),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -138,7 +139,11 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
return TextFormField(
|
||||
key: Key("$activeId-$idx-headers-k"),
|
||||
initialValue: rows[idx].k,
|
||||
decoration: const InputDecoration(hintText: "Add Header Name"),
|
||||
style: codeStyle,
|
||||
decoration: InputDecoration(
|
||||
hintStyle: codeStyle,
|
||||
hintText: "Add Header Name",
|
||||
),
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(k: value);
|
||||
_onFieldChange(activeId!);
|
||||
@ -151,7 +156,11 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
return TextFormField(
|
||||
key: Key("$activeId-$idx-headers-v"),
|
||||
initialValue: rows[idx].v,
|
||||
decoration: const InputDecoration(hintText: "Add Header Value"),
|
||||
style: codeStyle,
|
||||
decoration: InputDecoration(
|
||||
hintStyle: codeStyle,
|
||||
hintText: "Add Header Value",
|
||||
),
|
||||
onChanged: (value) {
|
||||
rows[idx] = rows[idx].copyWith(v: value);
|
||||
_onFieldChange(activeId!);
|
||||
@ -187,44 +196,36 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
),
|
||||
],
|
||||
);
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
rows.add(const KVRow("", ""));
|
||||
model.addRow(const KVRow("", ""));
|
||||
},
|
||||
child: const Text("+ Add Header"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: DaviThemeData(
|
||||
columnDividerThickness: 1,
|
||||
columnDividerColor: Colors.grey.shade100,
|
||||
row: RowThemeData(dividerColor: Colors.grey.shade100),
|
||||
decoration: const BoxDecoration(
|
||||
border: Border(),
|
||||
),
|
||||
header: HeaderThemeData(
|
||||
color: Colors.grey.shade100,
|
||||
columnDividerColor: Colors.grey.shade100,
|
||||
bottomBorderHeight: 1,
|
||||
),
|
||||
headerCell: const HeaderCellThemeData(
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
return Container(
|
||||
decoration: tableContainerDecoration,
|
||||
margin: p5,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: p10,
|
||||
child: Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
rows.add(const KVRow("", ""));
|
||||
model.addRow(const KVRow("", ""));
|
||||
},
|
||||
child: const Text(
|
||||
"+ Add Header",
|
||||
style: textStyleButton,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Davi<KVRow>(model),
|
||||
),
|
||||
),
|
||||
],
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: tableThemeData,
|
||||
child: Davi<KVRow>(model),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -26,23 +26,23 @@ class _EditorPaneRequestURLCardState
|
||||
return Card(
|
||||
shape: cardShape,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 5,
|
||||
horizontal: 20,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
DropdownButtonHTTPMethod(),
|
||||
const DropdownButtonHTTPMethod(),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Expanded(
|
||||
const Expanded(
|
||||
child: URLTextField(),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Container(
|
||||
SizedBox(
|
||||
height: 36,
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
@ -51,8 +51,11 @@ class _EditorPaneRequestURLCardState
|
||||
.sendRequest(activeId!);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Send"),
|
||||
children: const [
|
||||
Text(
|
||||
"Send",
|
||||
style: textStyleButton,
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
@ -80,14 +83,9 @@ class DropdownButtonHTTPMethod extends ConsumerStatefulWidget {
|
||||
|
||||
class _DropdownButtonHTTPMethodState
|
||||
extends ConsumerState<DropdownButtonHTTPMethod> {
|
||||
//late HTTPVerb dropdownValue;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
//dropdownValue = ref
|
||||
// .read(collectionStateNotifierProvider.notifier)
|
||||
// .idxOfId(String id);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -97,34 +95,31 @@ class _DropdownButtonHTTPMethodState
|
||||
final idIdx = collection.indexWhere((m) => m.id == activeId);
|
||||
final method = ref.watch(
|
||||
collectionStateNotifierProvider.select((value) => value[idIdx].method));
|
||||
//final model = ref
|
||||
// .read(collectionStateNotifierProvider.notifier)
|
||||
// .getRequestModel(activeId!);
|
||||
return DropdownButton<HTTPVerb>(
|
||||
focusColor: Colors.white,
|
||||
//value: collection[idIdx].method,
|
||||
value: method, //model.method,
|
||||
focusColor: colorBg,
|
||||
value: method,
|
||||
icon: const Icon(Icons.unfold_more_rounded),
|
||||
elevation: 4,
|
||||
underline: Container(
|
||||
height: 0,
|
||||
//color: Colors.deepPurpleAccent,
|
||||
),
|
||||
onChanged: (HTTPVerb? value) {
|
||||
ref
|
||||
.read(collectionStateNotifierProvider.notifier)
|
||||
.update(activeId!, method: value);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderRadius: borderRadius10,
|
||||
items: HTTPVerb.values.map<DropdownMenuItem<HTTPVerb>>((HTTPVerb value) {
|
||||
return DropdownMenuItem<HTTPVerb>(
|
||||
//alignment: AlignmentDirectional.center,
|
||||
value: value,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 16),
|
||||
child: Text(
|
||||
value.name.toUpperCase(),
|
||||
style: TextStyle(color: getHTTPMethodColor(value)),
|
||||
style: codeStyle.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: getHTTPMethodColor(value),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -157,9 +152,10 @@ class _URLTextFieldState extends ConsumerState<URLTextField> {
|
||||
.read(collectionStateNotifierProvider.notifier)
|
||||
.getRequestModel(activeId!)
|
||||
.url,
|
||||
style: codeStyle,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Enter API endpoint like api.foss42.com/country/codes",
|
||||
hintStyle: TextStyle(color: Colors.grey.shade500),
|
||||
hintStyle: codeStyle.copyWith(color: colorGrey500),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
onChanged: (value) {
|
||||
|
@ -1,11 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:davi/davi.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
final codeStyle = GoogleFonts.sourceCodePro();
|
||||
|
||||
const textStyleButton = TextStyle(fontWeight: FontWeight.bold);
|
||||
|
||||
const colorBg = Colors.white;
|
||||
final colorGrey50 = Colors.grey.shade50;
|
||||
final colorGrey100 = Colors.grey.shade100;
|
||||
final colorGrey200 = Colors.grey.shade200;
|
||||
final colorGrey300 = Colors.grey.shade300;
|
||||
final colorGrey400 = Colors.grey.shade400;
|
||||
final colorGrey500 = Colors.grey.shade500;
|
||||
final colorErrorMsg = colorGrey500;
|
||||
|
||||
final borderRadius10 = BorderRadius.circular(10);
|
||||
final cardShape = RoundedRectangleBorder(
|
||||
side: const BorderSide(
|
||||
color: Colors.white70,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderRadius: borderRadius10,
|
||||
);
|
||||
|
||||
final colorErrorMsg = Colors.grey.shade500;
|
||||
final tableContainerDecoration = BoxDecoration(
|
||||
color: colorBg,
|
||||
borderRadius: borderRadius10,
|
||||
);
|
||||
final tableThemeData = DaviThemeData(
|
||||
columnDividerThickness: 1,
|
||||
columnDividerColor: colorGrey100,
|
||||
row: RowThemeData(dividerColor: colorGrey100),
|
||||
decoration: const BoxDecoration(
|
||||
border: Border(),
|
||||
),
|
||||
header: HeaderThemeData(
|
||||
color: colorGrey50,
|
||||
columnDividerColor: colorGrey100,
|
||||
bottomBorderHeight: 1,
|
||||
bottomBorderColor: colorGrey100,
|
||||
),
|
||||
headerCell: const HeaderCellThemeData(
|
||||
alignment: Alignment.center,
|
||||
textStyle: null,
|
||||
),
|
||||
);
|
||||
|
||||
const p5 = EdgeInsets.all(5);
|
||||
const p10 = EdgeInsets.all(10);
|
||||
|
Reference in New Issue
Block a user