mirror of
https://github.com/foss42/apidash.git
synced 2025-06-06 19:38:58 +08:00
Add the functionality to import a curl file into the app.
The user can click on the button saying "+ Import" after which, they will be allow to drop a curl file and import the curl command in the app.
This commit is contained in:
@ -664,6 +664,7 @@ const kRaiseIssue =
|
||||
|
||||
const kHintTextUrlCard = "Enter API endpoint like https://$kDefaultUri/";
|
||||
const kLabelPlusNew = "+ New";
|
||||
const kLabelImport = "+ Import";
|
||||
const kLabelSend = "Send";
|
||||
const kLabelSending = "Sending..";
|
||||
const kLabelBusy = "Busy";
|
||||
|
@ -6,12 +6,17 @@ import 'package:apidash/consts.dart';
|
||||
import 'sidebar_save_button.dart';
|
||||
|
||||
class SidebarHeader extends ConsumerWidget {
|
||||
const SidebarHeader({super.key, this.onAddNew});
|
||||
const SidebarHeader({super.key, this.onAddNew, this.onImport});
|
||||
final Function()? onAddNew;
|
||||
final Function()? onImport;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final mobileScaffoldKey = ref.read(mobileScaffoldKeyStateProvider);
|
||||
final elevatedButtonStyle = ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: kPe8,
|
||||
child: Row(
|
||||
@ -20,9 +25,19 @@ class SidebarHeader extends ConsumerWidget {
|
||||
const Spacer(),
|
||||
ElevatedButton(
|
||||
onPressed: onAddNew,
|
||||
style: elevatedButtonStyle,
|
||||
child: const Text(
|
||||
kLabelPlusNew,
|
||||
style: kTextStyleButton,
|
||||
style: kTextStyleButtonSmall,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
ElevatedButton(
|
||||
onPressed: onImport,
|
||||
style: elevatedButtonStyle,
|
||||
child: const Text(
|
||||
kLabelImport,
|
||||
style: kTextStyleButtonSmall,
|
||||
),
|
||||
),
|
||||
context.width <= kMinWindowSize.width
|
||||
|
@ -1,3 +1,8 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:apidash/utils/convert_utils.dart';
|
||||
import 'package:apidash/widgets/drag_and_drop_area.dart';
|
||||
import 'package:curl_converter/curl_converter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
@ -32,6 +37,65 @@ class CollectionPane extends ConsumerWidget {
|
||||
onAddNew: () {
|
||||
ref.read(collectionStateNotifierProvider.notifier).add();
|
||||
},
|
||||
onImport: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
contentPadding: const EdgeInsets.all(12),
|
||||
content: DragAndDropArea(
|
||||
onFileDropped: (file) {
|
||||
final i = file.path.lastIndexOf('.') + 1;
|
||||
final String ext = file.path.substring(i);
|
||||
switch (ext) {
|
||||
case 'curl':
|
||||
file.readAsString().then((value) {
|
||||
if (value.endsWith('\n')) {
|
||||
value = value.substring(0, value.length - 1);
|
||||
}
|
||||
try {
|
||||
final curl = Curl.parse(value);
|
||||
ref
|
||||
.read(
|
||||
collectionStateNotifierProvider.notifier)
|
||||
.add();
|
||||
final selectedId =
|
||||
ref.read(selectedIdStateProvider)!;
|
||||
ref
|
||||
.read(
|
||||
collectionStateNotifierProvider.notifier)
|
||||
.update(
|
||||
selectedId,
|
||||
method: httpVerbFromString(curl.method),
|
||||
url: curl.uri.toString().substring(0,
|
||||
curl.uri.toString().lastIndexOf('?')),
|
||||
headers: curl.headers?.entries
|
||||
.map((entry) => NameValueModel(
|
||||
name: entry.key,
|
||||
value: entry.value,
|
||||
))
|
||||
.toList(),
|
||||
params: curl.uri.queryParameters.entries
|
||||
.map((entry) => NameValueModel(
|
||||
name: entry.key,
|
||||
value: entry.value,
|
||||
))
|
||||
.toList(),
|
||||
body: curl.data,
|
||||
);
|
||||
} catch (e) {
|
||||
throw Error();
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw Error();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
kVSpacer10,
|
||||
SidebarFilter(
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'dart:typed_data';
|
||||
import 'dart:convert';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../models/models.dart';
|
||||
import '../consts.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
@ -179,3 +180,22 @@ List<NameValueModel>? getEnabledRows(
|
||||
rows.where((element) => isRowEnabledList[rows.indexOf(element)]).toList();
|
||||
return finalRows == [] ? null : finalRows;
|
||||
}
|
||||
|
||||
HTTPVerb? httpVerbFromString(String value) {
|
||||
switch (value) {
|
||||
case "GET":
|
||||
return HTTPVerb.get;
|
||||
case "POST":
|
||||
return HTTPVerb.post;
|
||||
case "PUT":
|
||||
return HTTPVerb.put;
|
||||
case "DELETE":
|
||||
return HTTPVerb.delete;
|
||||
case "HEAD":
|
||||
return HTTPVerb.head;
|
||||
case "PATCH":
|
||||
return HTTPVerb.patch;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
51
lib/widgets/drag_and_drop_area.dart
Normal file
51
lib/widgets/drag_and_drop_area.dart
Normal file
@ -0,0 +1,51 @@
|
||||
import 'package:desktop_drop/desktop_drop.dart';
|
||||
import 'package:file_selector/file_selector.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DragAndDropArea extends StatefulWidget {
|
||||
final Function(XFile) onFileDropped;
|
||||
|
||||
const DragAndDropArea({super.key, required this.onFileDropped});
|
||||
|
||||
@override
|
||||
State<DragAndDropArea> createState() => _DragAndDropAreaState();
|
||||
}
|
||||
|
||||
class _DragAndDropAreaState extends State<DragAndDropArea> {
|
||||
final List<XFile> _list = [];
|
||||
bool _dragging = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DropTarget(
|
||||
onDragDone: (detail) {
|
||||
setState(() {
|
||||
_list.addAll(detail.files);
|
||||
});
|
||||
widget.onFileDropped(detail.files[0]);
|
||||
},
|
||||
onDragEntered: (detail) {
|
||||
setState(() {
|
||||
_dragging = true;
|
||||
});
|
||||
},
|
||||
onDragExited: (detail) {
|
||||
setState(() {
|
||||
_dragging = false;
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(22),
|
||||
color: _dragging ? Colors.blue.withOpacity(0.4) : Colors.black26,
|
||||
border: Border.all(color: Colors.white24),
|
||||
),
|
||||
width: 600,
|
||||
height: 400,
|
||||
child: _list.isEmpty
|
||||
? const Center(child: Text("Drop here"))
|
||||
: Text(_list.map((e) => e.path).join("\n")),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ class DashboardSplitView extends StatefulWidget {
|
||||
class DashboardSplitViewState extends State<DashboardSplitView> {
|
||||
final MultiSplitViewController _controller = MultiSplitViewController(
|
||||
areas: [
|
||||
Area(id: "sidebar", size: 250, min: 200),
|
||||
Area(id: "sidebar", size: 270, min: 250),
|
||||
Area(id: "main", min: 0.7),
|
||||
],
|
||||
);
|
||||
|
24
pubspec.lock
24
pubspec.lock
@ -233,6 +233,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
curl_converter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: curl_converter
|
||||
sha256: "32c541b875c6ddea275dfb35ff58c95f0d997f51e92232ff8fa4431b96c62dab"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
dart_style:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -249,6 +257,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.15"
|
||||
desktop_drop:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: desktop_drop
|
||||
sha256: d55a010fe46c8e8fcff4ea4b451a9ff84a162217bdb3b2a0aa1479776205e15d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.4"
|
||||
equatable:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: equatable
|
||||
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
eventify:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -64,6 +64,8 @@ dependencies:
|
||||
flutter_hooks: ^0.20.5
|
||||
flutter_portal: ^1.1.4
|
||||
mention_tag_text_field: ^0.0.5
|
||||
desktop_drop: ^0.4.4
|
||||
curl_converter: ^1.0.4
|
||||
|
||||
dependency_overrides:
|
||||
web: ^0.5.0
|
||||
|
Reference in New Issue
Block a user