From 98c2c46dd7bdf7f57ed71de30b701df313cc9beb Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Wed, 20 Mar 2024 10:13:56 +0200 Subject: [PATCH 01/11] add sendingTime var for Request Model class --- lib/models/request_model.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index 0ea6d735..3a04c0eb 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -31,6 +31,7 @@ class RequestModel { this.message, this.responseModel, this.isWorking = false, + this.sendingTime, }); final String id; @@ -50,6 +51,7 @@ class RequestModel { final String? message; final ResponseModel? responseModel; final bool isWorking; + final DateTime? sendingTime; List? get enabledRequestHeaders => getEnabledRows(requestHeaders, isHeaderEnabledList); @@ -133,6 +135,7 @@ class RequestModel { String? message, ResponseModel? responseModel, bool? isWorking, + DateTime? sendingTime, }) { var headers = requestHeaders ?? this.requestHeaders; var params = requestParams ?? this.requestParams; @@ -158,6 +161,7 @@ class RequestModel { message: message ?? this.message, responseModel: responseModel ?? this.responseModel, isWorking: isWorking ?? this.isWorking, + sendingTime: sendingTime ?? this.sendingTime, ); } From 99c8a002788e110e17e03fa3121c61567bc6329d Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Wed, 20 Mar 2024 10:14:30 +0200 Subject: [PATCH 02/11] Add timer for sending widget --- lib/providers/collection_providers.dart | 5 +- .../details_card/response_pane.dart | 7 +- lib/widgets/response_widgets.dart | 75 ++++++++++++++++--- 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index db6b7cf3..9946112f 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -180,7 +180,8 @@ class CollectionStateNotifier // set current model's isWorking to true and update state var map = {...state!}; - map[id] = requestModel.copyWith(isWorking: true); + map[id] = + requestModel.copyWith(isWorking: true, sendingTime: DateTime.now()); state = map; (http.Response?, Duration?, String?)? responseRec = await request( @@ -193,6 +194,7 @@ class CollectionStateNotifier responseStatus: -1, message: responseRec.$3, isWorking: false, + sendingTime: null, ); } else { final responseModel = baseResponseModel.fromResponse( @@ -205,6 +207,7 @@ class CollectionStateNotifier message: kResponseCodeReasons[statusCode], responseModel: responseModel, isWorking: false, + sendingTime: null, ); } diff --git a/lib/screens/home_page/editor_pane/details_card/response_pane.dart b/lib/screens/home_page/editor_pane/details_card/response_pane.dart index 703b873d..2cd0cbc9 100644 --- a/lib/screens/home_page/editor_pane/details_card/response_pane.dart +++ b/lib/screens/home_page/editor_pane/details_card/response_pane.dart @@ -12,12 +12,17 @@ class ResponsePane extends ConsumerWidget { final isWorking = ref.watch( selectedRequestModelProvider.select((value) => value?.isWorking)) ?? false; + final startSendingDate = ref.watch( + selectedRequestModelProvider.select((value) => value?.sendingTime)); final responseStatus = ref.watch( selectedRequestModelProvider.select((value) => value?.responseStatus)); final message = ref .watch(selectedRequestModelProvider.select((value) => value?.message)); + if (isWorking) { - return const SendingWidget(); + return SendingWidget( + startSendingTime: startSendingDate, + ); } if (responseStatus == null) { return const NotSentWidget(); diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index adf74985..66fbc083 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -1,3 +1,6 @@ +import 'dart:async'; + +import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:http_parser/http_parser.dart'; @@ -24,8 +27,10 @@ class NotSentWidget extends StatelessWidget { ), Text( 'Not Sent', - style: - Theme.of(context).textTheme.titleMedium?.copyWith(color: color), + style: Theme.of(context) + .textTheme + .titleMedium + ?.copyWith(color: color), ), ], ), @@ -33,17 +38,69 @@ class NotSentWidget extends StatelessWidget { } } -class SendingWidget extends StatelessWidget { - const SendingWidget({super.key}); +class SendingWidget extends StatefulWidget { + final DateTime? startSendingTime; + const SendingWidget({super.key, required this.startSendingTime}); + + @override + State createState() => _SendingWidgetState(); +} + +class _SendingWidgetState extends State { + int _millisecondsElapsed = 0; + Timer? _timer; + + @override + void initState() { + super.initState(); + if (widget.startSendingTime != null) { + _millisecondsElapsed = + DateTime.now().difference(widget.startSendingTime!).inMilliseconds; + _timer = Timer.periodic(const Duration(milliseconds: 10), _updateTimer); + } + } + + void _updateTimer(Timer timer) { + setState(() { + _millisecondsElapsed += 10; + }); + } + + @override + void dispose() { + if (_timer != null && _timer!.isActive) _timer?.cancel(); + super.dispose(); + } @override Widget build(BuildContext context) { return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Lottie.asset("assets/sending.json"), - ], + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Visibility( + visible: _millisecondsElapsed > 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.alarm), + const SizedBox( + width: 10, + ), + Text( + 'Time elapsed: ${humanizeDuration(Duration(milliseconds: _millisecondsElapsed))}', + textAlign: TextAlign.center, + overflow: TextOverflow.fade, + softWrap: false, + style: kTextStyleButton, + ), + ], + ), + ), + Lottie.asset("assets/sending.json"), + ], + ), ), ); } From fec18be44b826c17cec73edc22fc041d80f87721 Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Wed, 20 Mar 2024 10:15:06 +0200 Subject: [PATCH 03/11] unit testing for SendingWidget --- test/widgets/response_widgets_test.dart | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/widgets/response_widgets_test.dart b/test/widgets/response_widgets_test.dart index 7877a285..3bdd42a8 100644 --- a/test/widgets/response_widgets_test.dart +++ b/test/widgets/response_widgets_test.dart @@ -10,13 +10,31 @@ import 'package:apidash/models/models.dart'; import '../test_consts.dart'; void main() { - testWidgets('Testing Sending Widget', (tester) async { + testWidgets('Testing Sending Widget Without Timer', (tester) async { await tester.pumpWidget( MaterialApp( title: 'Send', theme: kThemeDataDark, home: const Scaffold( - body: SendingWidget(), + body: SendingWidget( + startSendingTime: null, + ), + ), + ), + ); + + expect(find.byType(Lottie), findsOneWidget); + }); + + testWidgets('Testing Sending Widget With Timer', (tester) async { + await tester.pumpWidget( + MaterialApp( + title: 'Send', + theme: kThemeDataDark, + home: Scaffold( + body: SendingWidget( + startSendingTime: DateTime.now(), + ), ), ), ); From f26ba583cc301d9ca60cce4e9a69af80672f048e Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Thu, 21 Mar 2024 00:32:20 +0200 Subject: [PATCH 04/11] update timer testing function --- lib/widgets/response_widgets.dart | 12 ++++++------ test/widgets/response_widgets_test.dart | 7 ++++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index 66fbc083..22e84a1e 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:http_parser/http_parser.dart'; @@ -40,7 +39,8 @@ class NotSentWidget extends StatelessWidget { class SendingWidget extends StatefulWidget { final DateTime? startSendingTime; - const SendingWidget({super.key, required this.startSendingTime}); + final bool isTest; + const SendingWidget({super.key, required this.startSendingTime, this.isTest=false}); @override State createState() => _SendingWidgetState(); @@ -54,15 +54,15 @@ class _SendingWidgetState extends State { void initState() { super.initState(); if (widget.startSendingTime != null) { - _millisecondsElapsed = + _millisecondsElapsed = widget.isTest ? 0 : DateTime.now().difference(widget.startSendingTime!).inMilliseconds; - _timer = Timer.periodic(const Duration(milliseconds: 10), _updateTimer); + _timer = Timer.periodic(const Duration(milliseconds: 100), _updateTimer); } } void _updateTimer(Timer timer) { setState(() { - _millisecondsElapsed += 10; + _millisecondsElapsed += 100; }); } @@ -80,7 +80,7 @@ class _SendingWidgetState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Visibility( - visible: _millisecondsElapsed > 0, + visible: _millisecondsElapsed >= 0, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ diff --git a/test/widgets/response_widgets_test.dart b/test/widgets/response_widgets_test.dart index 3bdd42a8..a8def9cc 100644 --- a/test/widgets/response_widgets_test.dart +++ b/test/widgets/response_widgets_test.dart @@ -34,12 +34,17 @@ void main() { home: Scaffold( body: SendingWidget( startSendingTime: DateTime.now(), + isTest: true, ), ), ), ); - + expect(find.text('Time elapsed: 0 ms'), findsOneWidget); expect(find.byType(Lottie), findsOneWidget); + + await tester.pump(const Duration(seconds: 1)); + + expect(find.text('Time elapsed: 1.00 s'), findsOneWidget); }); testWidgets('Testing Not Sent Widget', (tester) async { From 12ab5e0b99d7db784646cad7f5ee447c75bc4187 Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Thu, 21 Mar 2024 00:42:41 +0200 Subject: [PATCH 05/11] Renamed variable --- .../home_page/editor_pane/details_card/response_pane.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/home_page/editor_pane/details_card/response_pane.dart b/lib/screens/home_page/editor_pane/details_card/response_pane.dart index 2cd0cbc9..4a240932 100644 --- a/lib/screens/home_page/editor_pane/details_card/response_pane.dart +++ b/lib/screens/home_page/editor_pane/details_card/response_pane.dart @@ -12,7 +12,7 @@ class ResponsePane extends ConsumerWidget { final isWorking = ref.watch( selectedRequestModelProvider.select((value) => value?.isWorking)) ?? false; - final startSendingDate = ref.watch( + final startSendingTime = ref.watch( selectedRequestModelProvider.select((value) => value?.sendingTime)); final responseStatus = ref.watch( selectedRequestModelProvider.select((value) => value?.responseStatus)); @@ -21,7 +21,7 @@ class ResponsePane extends ConsumerWidget { if (isWorking) { return SendingWidget( - startSendingTime: startSendingDate, + startSendingTime: startSendingTime, ); } if (responseStatus == null) { From 83b3031a9a7370267e4a7f1426c162c77e67dfc5 Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Thu, 21 Mar 2024 00:45:25 +0200 Subject: [PATCH 06/11] Update collection_providers.dart --- lib/providers/collection_providers.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 9946112f..07e26822 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -194,7 +194,6 @@ class CollectionStateNotifier responseStatus: -1, message: responseRec.$3, isWorking: false, - sendingTime: null, ); } else { final responseModel = baseResponseModel.fromResponse( @@ -207,7 +206,6 @@ class CollectionStateNotifier message: kResponseCodeReasons[statusCode], responseModel: responseModel, isWorking: false, - sendingTime: null, ); } From 1db26fa86fd1947895026929f8c9ba138dcbc426 Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Fri, 22 Mar 2024 00:41:44 +0200 Subject: [PATCH 07/11] use kAssetSendingLottie --- lib/widgets/response_widgets.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index 22e84a1e..a2f2183a 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -98,7 +98,7 @@ class _SendingWidgetState extends State { ], ), ), - Lottie.asset("assets/sending.json"), + Lottie.asset(kAssetSendingLottie), ], ), ), From ef48f2947fddd06a029c34f8107344271d84b8ca Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Sun, 24 Mar 2024 03:49:21 +0200 Subject: [PATCH 08/11] Replace SingleChildScrollView and Column with Stack --- lib/widgets/response_widgets.dart | 56 ++++++++++++++++--------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index a2f2183a..8228f781 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:http_parser/http_parser.dart'; @@ -74,36 +75,37 @@ class _SendingWidgetState extends State { @override Widget build(BuildContext context) { - return Center( - child: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Visibility( - visible: _millisecondsElapsed >= 0, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.alarm), - const SizedBox( - width: 10, - ), - Text( - 'Time elapsed: ${humanizeDuration(Duration(milliseconds: _millisecondsElapsed))}', - textAlign: TextAlign.center, - overflow: TextOverflow.fade, - softWrap: false, - style: kTextStyleButton, - ), - ], - ), - ), - Lottie.asset(kAssetSendingLottie), - ], + return Stack( + children: [ + Center( + child: Lottie.asset(kAssetSendingLottie), ), - ), + Padding( + padding: kPh20t40, + child: Visibility( + visible: _millisecondsElapsed >= 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.alarm), + const SizedBox( + width: 10, + ), + Text( + 'Time elapsed: ${humanizeDuration(Duration(milliseconds: _millisecondsElapsed))}', + textAlign: TextAlign.center, + overflow: TextOverflow.fade, + softWrap: false, + style: kTextStyleButton, + ), + ], + ), + ), + ), + ], ); } + } class ResponsePaneHeader extends StatelessWidget { From 4932be5ba75e122237da444a2075a28729669e1d Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Thu, 28 Mar 2024 21:46:54 +0530 Subject: [PATCH 09/11] Update collection_providers.dart --- lib/providers/collection_providers.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 5068f4ce..8f00b039 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -181,8 +181,10 @@ class CollectionStateNotifier // set current model's isWorking to true and update state var map = {...state!}; - map[id] = - requestModel.copyWith(isWorking: true, sendingTime: DateTime.now()); + map[id] = requestModel.copyWith( + isWorking: true, + sendingTime: DateTime.now(), + ); state = map; (http.Response?, Duration?, String?)? responseRec = await request( From 6c8686de0affb7f8b3fad5e11e6ef6d3c003135b Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Thu, 28 Mar 2024 22:02:25 +0530 Subject: [PATCH 10/11] Fix time elapsed sending widget --- lib/widgets/response_widgets.dart | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index 2d913f17..a3d9f20b 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -1,6 +1,4 @@ import 'dart:async'; - -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:http_parser/http_parser.dart'; @@ -38,8 +36,10 @@ class NotSentWidget extends StatelessWidget { class SendingWidget extends StatefulWidget { final DateTime? startSendingTime; - final bool isTest; - const SendingWidget({super.key, required this.startSendingTime, this.isTest=false}); + const SendingWidget({ + super.key, + required this.startSendingTime, + }); @override State createState() => _SendingWidgetState(); @@ -53,8 +53,10 @@ class _SendingWidgetState extends State { void initState() { super.initState(); if (widget.startSendingTime != null) { - _millisecondsElapsed = widget.isTest ? 0 : - DateTime.now().difference(widget.startSendingTime!).inMilliseconds; + _millisecondsElapsed = + (DateTime.now().difference(widget.startSendingTime!).inMilliseconds ~/ + 100) * + 100; _timer = Timer.periodic(const Duration(milliseconds: 100), _updateTimer); } } @@ -85,7 +87,10 @@ class _SendingWidgetState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon(Icons.alarm), + Icon( + Icons.alarm, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), const SizedBox( width: 10, ), @@ -94,7 +99,9 @@ class _SendingWidgetState extends State { textAlign: TextAlign.center, overflow: TextOverflow.fade, softWrap: false, - style: kTextStyleButton, + style: kTextStyleButton.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), ], ), @@ -103,7 +110,6 @@ class _SendingWidgetState extends State { ], ); } - } class ResponsePaneHeader extends StatelessWidget { From 5c74a92296d38ad0f4559caf7507eeffbaa25364 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Thu, 28 Mar 2024 22:06:14 +0530 Subject: [PATCH 11/11] Update response_widgets_test.dart --- test/widgets/response_widgets_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/test/widgets/response_widgets_test.dart b/test/widgets/response_widgets_test.dart index 3bd5d2d6..c5617035 100644 --- a/test/widgets/response_widgets_test.dart +++ b/test/widgets/response_widgets_test.dart @@ -34,7 +34,6 @@ void main() { home: Scaffold( body: SendingWidget( startSendingTime: DateTime.now(), - isTest: true, ), ), ),