mirror of
https://github.com/foss42/apidash.git
synced 2025-05-30 21:41:50 +08:00
Merge pull request #236 from opxdelwin/issue-114
[feat] Enable parallel request handling
This commit is contained in:
@ -29,6 +29,7 @@ class RequestModel {
|
|||||||
this.responseStatus,
|
this.responseStatus,
|
||||||
this.message,
|
this.message,
|
||||||
this.responseModel,
|
this.responseModel,
|
||||||
|
this.isWorking = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
@ -47,6 +48,7 @@ class RequestModel {
|
|||||||
final int? responseStatus;
|
final int? responseStatus;
|
||||||
final String? message;
|
final String? message;
|
||||||
final ResponseModel? responseModel;
|
final ResponseModel? responseModel;
|
||||||
|
final bool isWorking;
|
||||||
|
|
||||||
List<NameValueModel>? get enabledRequestHeaders =>
|
List<NameValueModel>? get enabledRequestHeaders =>
|
||||||
getEnabledRows(requestHeaders, isHeaderEnabledList);
|
getEnabledRows(requestHeaders, isHeaderEnabledList);
|
||||||
@ -106,6 +108,7 @@ class RequestModel {
|
|||||||
int? responseStatus,
|
int? responseStatus,
|
||||||
String? message,
|
String? message,
|
||||||
ResponseModel? responseModel,
|
ResponseModel? responseModel,
|
||||||
|
bool? isWorking,
|
||||||
}) {
|
}) {
|
||||||
var headers = requestHeaders ?? this.requestHeaders;
|
var headers = requestHeaders ?? this.requestHeaders;
|
||||||
var params = requestParams ?? this.requestParams;
|
var params = requestParams ?? this.requestParams;
|
||||||
@ -129,6 +132,7 @@ class RequestModel {
|
|||||||
responseStatus: responseStatus ?? this.responseStatus,
|
responseStatus: responseStatus ?? this.responseStatus,
|
||||||
message: message ?? this.message,
|
message: message ?? this.message,
|
||||||
responseModel: responseModel ?? this.responseModel,
|
responseModel: responseModel ?? this.responseModel,
|
||||||
|
isWorking: isWorking ?? this.isWorking,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,11 +156,20 @@ class CollectionStateNotifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> sendRequest(String id) async {
|
Future<void> sendRequest(String id) async {
|
||||||
ref.read(sentRequestIdStateProvider.notifier).state = id;
|
|
||||||
ref.read(codePaneVisibleStateProvider.notifier).state = false;
|
ref.read(codePaneVisibleStateProvider.notifier).state = false;
|
||||||
final defaultUriScheme =
|
final defaultUriScheme = ref.read(
|
||||||
ref.read(settingsProvider.select((value) => value.defaultUriScheme));
|
settingsProvider.select(
|
||||||
|
(value) => value.defaultUriScheme,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
RequestModel requestModel = state![id]!;
|
RequestModel requestModel = state![id]!;
|
||||||
|
|
||||||
|
// set current model's isWorking to true and update state
|
||||||
|
var map = {...state!};
|
||||||
|
map[id] = requestModel.copyWith(isWorking: true);
|
||||||
|
state = map;
|
||||||
|
|
||||||
(http.Response?, Duration?, String?)? responseRec = await request(
|
(http.Response?, Duration?, String?)? responseRec = await request(
|
||||||
requestModel,
|
requestModel,
|
||||||
defaultUriScheme: defaultUriScheme,
|
defaultUriScheme: defaultUriScheme,
|
||||||
@ -172,6 +181,7 @@ class CollectionStateNotifier
|
|||||||
newRequestModel = requestModel.copyWith(
|
newRequestModel = requestModel.copyWith(
|
||||||
responseStatus: -1,
|
responseStatus: -1,
|
||||||
message: responseRec.$3,
|
message: responseRec.$3,
|
||||||
|
isWorking: false,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
final responseModel = baseResponseModel.fromResponse(
|
final responseModel = baseResponseModel.fromResponse(
|
||||||
@ -183,10 +193,12 @@ class CollectionStateNotifier
|
|||||||
responseStatus: statusCode,
|
responseStatus: statusCode,
|
||||||
message: kResponseCodeReasons[statusCode],
|
message: kResponseCodeReasons[statusCode],
|
||||||
responseModel: responseModel,
|
responseModel: responseModel,
|
||||||
|
isWorking: false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ref.read(sentRequestIdStateProvider.notifier).state = null;
|
|
||||||
var map = {...state!};
|
// update state with response data
|
||||||
|
map = {...state!};
|
||||||
map[id] = newRequestModel;
|
map[id] = newRequestModel;
|
||||||
state = map;
|
state = map;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||||||
|
|
||||||
final navRailIndexStateProvider = StateProvider<int>((ref) => 0);
|
final navRailIndexStateProvider = StateProvider<int>((ref) => 0);
|
||||||
final selectedIdEditStateProvider = StateProvider<String?>((ref) => null);
|
final selectedIdEditStateProvider = StateProvider<String?>((ref) => null);
|
||||||
final sentRequestIdStateProvider = StateProvider<String?>((ref) => null);
|
|
||||||
final codePaneVisibleStateProvider = StateProvider<bool>((ref) => false);
|
final codePaneVisibleStateProvider = StateProvider<bool>((ref) => false);
|
||||||
final saveDataStateProvider = StateProvider<bool>((ref) => false);
|
final saveDataStateProvider = StateProvider<bool>((ref) => false);
|
||||||
final clearDataStateProvider = StateProvider<bool>((ref) => false);
|
final clearDataStateProvider = StateProvider<bool>((ref) => false);
|
||||||
|
@ -9,13 +9,14 @@ class ResponsePane extends ConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final selectedId = ref.watch(selectedIdStateProvider);
|
final isWorking = ref.watch(
|
||||||
final sentRequestId = ref.watch(sentRequestIdStateProvider);
|
selectedRequestModelProvider.select((value) => value?.isWorking)) ??
|
||||||
|
false;
|
||||||
final responseStatus = ref.watch(
|
final responseStatus = ref.watch(
|
||||||
selectedRequestModelProvider.select((value) => value?.responseStatus));
|
selectedRequestModelProvider.select((value) => value?.responseStatus));
|
||||||
final message = ref
|
final message = ref
|
||||||
.watch(selectedRequestModelProvider.select((value) => value?.message));
|
.watch(selectedRequestModelProvider.select((value) => value?.message));
|
||||||
if (sentRequestId != null && sentRequestId == selectedId) {
|
if (isWorking) {
|
||||||
return const SendingWidget();
|
return const SendingWidget();
|
||||||
}
|
}
|
||||||
if (responseStatus == null) {
|
if (responseStatus == null) {
|
||||||
|
@ -98,10 +98,11 @@ class SendButton extends ConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final selectedId = ref.watch(selectedIdStateProvider);
|
final selectedId = ref.watch(selectedIdStateProvider);
|
||||||
final sentRequestId = ref.watch(sentRequestIdStateProvider);
|
final isWorking = ref.watch(
|
||||||
|
selectedRequestModelProvider.select((value) => value?.isWorking));
|
||||||
|
|
||||||
return SendRequestButton(
|
return SendRequestButton(
|
||||||
selectedId: selectedId,
|
isWorking: isWorking ?? false,
|
||||||
sentRequestId: sentRequestId,
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ref
|
ref
|
||||||
.read(collectionStateNotifierProvider.notifier)
|
.read(collectionStateNotifierProvider.notifier)
|
||||||
|
@ -47,36 +47,37 @@ class CopyButton extends StatelessWidget {
|
|||||||
class SendRequestButton extends StatelessWidget {
|
class SendRequestButton extends StatelessWidget {
|
||||||
const SendRequestButton({
|
const SendRequestButton({
|
||||||
super.key,
|
super.key,
|
||||||
required this.selectedId,
|
required this.isWorking,
|
||||||
required this.sentRequestId,
|
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String? selectedId;
|
final bool isWorking;
|
||||||
final String? sentRequestId;
|
|
||||||
final void Function() onTap;
|
final void Function() onTap;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool disable = sentRequestId != null;
|
|
||||||
return FilledButton(
|
return FilledButton(
|
||||||
onPressed: disable ? null : onTap,
|
onPressed: isWorking ? null : onTap,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: isWorking
|
||||||
Text(
|
? const [
|
||||||
disable
|
Text(
|
||||||
? (selectedId == sentRequestId ? kLabelSending : kLabelBusy)
|
kLabelSending,
|
||||||
: kLabelSend,
|
style: kTextStyleButton,
|
||||||
style: kTextStyleButton,
|
),
|
||||||
),
|
]
|
||||||
if (!disable) kHSpacer10,
|
: const [
|
||||||
if (!disable)
|
Text(
|
||||||
const Icon(
|
kLabelSend,
|
||||||
size: 16,
|
style: kTextStyleButton,
|
||||||
Icons.send,
|
),
|
||||||
),
|
kHSpacer10,
|
||||||
],
|
Icon(
|
||||||
|
size: 16,
|
||||||
|
Icons.send,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,7 @@ void main() {
|
|||||||
theme: kThemeDataLight,
|
theme: kThemeDataLight,
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
body: SendRequestButton(
|
body: SendRequestButton(
|
||||||
selectedId: '1',
|
isWorking: false,
|
||||||
sentRequestId: null,
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
changedValue = 'Send';
|
changedValue = 'Send';
|
||||||
},
|
},
|
||||||
@ -55,7 +54,8 @@ void main() {
|
|||||||
expect(changedValue, 'Send');
|
expect(changedValue, 'Send');
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Testing for Send Request button when sentRequestId is not null',
|
testWidgets(
|
||||||
|
'Testing for Send Request button when RequestModel is viewed and is waiting for response',
|
||||||
(tester) async {
|
(tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
@ -63,32 +63,7 @@ void main() {
|
|||||||
theme: kThemeDataLight,
|
theme: kThemeDataLight,
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
body: SendRequestButton(
|
body: SendRequestButton(
|
||||||
selectedId: '1',
|
isWorking: true,
|
||||||
sentRequestId: '2',
|
|
||||||
onTap: () {},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(find.byIcon(Icons.send), findsNothing);
|
|
||||||
expect(find.text(kLabelBusy), findsOneWidget);
|
|
||||||
final button1 = find.byType(FilledButton);
|
|
||||||
expect(button1, findsOneWidget);
|
|
||||||
|
|
||||||
expect(tester.widget<FilledButton>(button1).enabled, isFalse);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Testing for Send Request button when sentRequestId = selectedId',
|
|
||||||
(tester) async {
|
|
||||||
await tester.pumpWidget(
|
|
||||||
MaterialApp(
|
|
||||||
title: 'Send Request button',
|
|
||||||
theme: kThemeDataLight,
|
|
||||||
home: Scaffold(
|
|
||||||
body: SendRequestButton(
|
|
||||||
selectedId: '1',
|
|
||||||
sentRequestId: '1',
|
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Reference in New Issue
Block a user