From 091491966f4153e251ea9526d4ed91817cebad51 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Thu, 16 Feb 2023 12:37:35 +0600 Subject: [PATCH] feat: working query builder, remove timeout from retryConfig --- packages/fl_query/example/lib/main.dart | 23 ++++++---- .../lib/src/collections/default_configs.dart | 3 +- .../lib/src/collections/retry_config.dart | 7 +-- .../fl_query/lib/src/core/infinite_query.dart | 4 +- packages/fl_query/lib/src/core/provider.dart | 7 +++ packages/fl_query/lib/src/core/query.dart | 27 ++++++++---- packages/fl_query/lib/src/core/retryer.dart | 10 ----- .../lib/src/widgets/query_builder.dart | 43 ++++++++++++++++++- 8 files changed, 86 insertions(+), 38 deletions(-) diff --git a/packages/fl_query/example/lib/main.dart b/packages/fl_query/example/lib/main.dart index bd6c3ce..5316166 100644 --- a/packages/fl_query/example/lib/main.dart +++ b/packages/fl_query/example/lib/main.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:fl_query/fl_query.dart'; import 'package:flutter/material.dart'; @@ -16,21 +18,26 @@ class MainApp extends StatelessWidget { @override Widget build(BuildContext context) { + final value = Random().nextInt(200000); return MaterialApp( home: Scaffold( - body: QueryBuilder( + body: QueryBuilder( const ValueKey('hello'), () { return Future.delayed( - const Duration(seconds: 5), - () => 'Hello World!', - ); + const Duration(seconds: 6), () => 'Hello World! $value'); }, initial: 'Hello', - // jsonConfig: JsonConfig( - // fromJson: (json) => json['data'], - // toJson: (data) => {'data': data}, - // ), + jsonConfig: JsonConfig( + fromJson: (json) => json['data'], + toJson: (data) => {'data': data}, + ), + onData: (value) { + print('onData: $value'); + }, + onError: (error) { + print('onError: $error'); + }, builder: (context, query) { if (query.isLoading) { return const Center( diff --git a/packages/fl_query/lib/src/collections/default_configs.dart b/packages/fl_query/lib/src/collections/default_configs.dart index afcb61e..1de53bd 100644 --- a/packages/fl_query/lib/src/collections/default_configs.dart +++ b/packages/fl_query/lib/src/collections/default_configs.dart @@ -5,12 +5,11 @@ abstract class DefaultConstants { static const RetryConfig retryConfig = RetryConfig( maxRetries: 3, retryDelay: Duration(seconds: 1), - timeout: Duration(seconds: 5), ); static const RefreshConfig refreshConfig = RefreshConfig( staleDuration: Duration(seconds: 10), - refreshInterval: Duration(seconds: 5), + refreshInterval: Duration.zero, refreshOnMount: true, refreshOnQueryFnChange: false, ); diff --git a/packages/fl_query/lib/src/collections/retry_config.dart b/packages/fl_query/lib/src/collections/retry_config.dart index e88cb87..f3e80f7 100644 --- a/packages/fl_query/lib/src/collections/retry_config.dart +++ b/packages/fl_query/lib/src/collections/retry_config.dart @@ -1,11 +1,6 @@ class RetryConfig { final int maxRetries; final Duration retryDelay; - final Duration timeout; - const RetryConfig({ - required this.maxRetries, - required this.retryDelay, - required this.timeout, - }); + const RetryConfig({required this.maxRetries, required this.retryDelay}); } diff --git a/packages/fl_query/lib/src/core/infinite_query.dart b/packages/fl_query/lib/src/core/infinite_query.dart index 30a3c0c..24b3405 100644 --- a/packages/fl_query/lib/src/core/infinite_query.dart +++ b/packages/fl_query/lib/src/core/infinite_query.dart @@ -131,7 +131,8 @@ class InfiniteQuery ); } }); - + } + if (refreshConfig.refreshInterval > Duration.zero) Timer.periodic(refreshConfig.refreshInterval, (_) async { await Future.wait( state.pages.map((page) async { @@ -141,7 +142,6 @@ class InfiniteQuery }), ); }); - } } final _mutex = Mutex(); diff --git a/packages/fl_query/lib/src/core/provider.dart b/packages/fl_query/lib/src/core/provider.dart index 3761a2b..da1734b 100644 --- a/packages/fl_query/lib/src/core/provider.dart +++ b/packages/fl_query/lib/src/core/provider.dart @@ -1,5 +1,6 @@ import 'package:fl_query/src/core/client.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/src/foundation/diagnostics.dart'; class QueryClientProvider extends InheritedWidget { final QueryClient client; @@ -9,4 +10,10 @@ class QueryClientProvider extends InheritedWidget { bool updateShouldNotify(covariant QueryClientProvider oldWidget) { return client != oldWidget.client; } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('client', client)); + } } diff --git a/packages/fl_query/lib/src/core/query.dart b/packages/fl_query/lib/src/core/query.dart index 20cf99a..0ad8f26 100644 --- a/packages/fl_query/lib/src/core/query.dart +++ b/packages/fl_query/lib/src/core/query.dart @@ -51,21 +51,22 @@ class Query extends StateNotifier> with Retryer { final ValueKey key; - final DataType? initial; final RefreshConfig refreshConfig; final RetryConfig retryConfig; final JsonConfig? jsonConfig; + Query( this.key, QueryFn queryFn, { - this.initial, + DataType? initial, this.retryConfig = DefaultConstants.retryConfig, this.refreshConfig = DefaultConstants.refreshConfig, this.jsonConfig, }) : _box = Hive.lazyBox("cache"), _dataController = StreamController.broadcast(), _errorController = StreamController.broadcast(), + _initial = initial, super(QueryState( updatedAt: DateTime.now(), staleDuration: refreshConfig.staleDuration, @@ -76,28 +77,35 @@ class Query _mutex.protect(() async { final json = await _box.get(key.toString()); if (json != null) { - state = state.copyWith( - data: jsonConfig!.fromJson( - Map.castFrom(json), - ), + _initial = jsonConfig!.fromJson( + Map.castFrom(json), ); + state = state.copyWith(data: _initial); + } + }).then((_) { + if (hasListeners) { + return fetch(); } }); + } else { + _initial = initial; + } + if (refreshConfig.refreshInterval > Duration.zero) Timer.periodic(refreshConfig.refreshInterval, (_) async { if (state.isStale) { await refresh(); } }); - } } + DataType? _initial; final LazyBox _box; final _mutex = Mutex(); final StreamController _dataController; final StreamController _errorController; - bool get isInitial => state.data == initial; + bool get isInitial => hasData && state.data == _initial; bool get isLoading => isInitial ? _mutex.isLocked : !hasData && !hasError; bool get isRefreshing => ((!isInitial && hasData) || hasError) && _mutex.isLocked; @@ -134,7 +142,8 @@ class Query } Future fetch() async { - if (_mutex.isLocked || hasData || hasError) return state.data; + if (_mutex.isLocked || (hasData && !isInitial) || hasError) + return state.data; return _operate().then((_) => state.data); } diff --git a/packages/fl_query/lib/src/core/retryer.dart b/packages/fl_query/lib/src/core/retryer.dart index e486bec..be722df 100644 --- a/packages/fl_query/lib/src/core/retryer.dart +++ b/packages/fl_query/lib/src/core/retryer.dart @@ -15,16 +15,6 @@ mixin Retryer { attempts == 0 ? Duration.zero : config.retryDelay, operation, ).then(completer.complete).catchError(completer.completeError); - await Future.delayed(config.timeout, () { - if (!completer.isCompleted) { - completer.completeError( - TimeoutException( - 'Operation timed out after ${config.timeout.inSeconds} seconds', - ), - StackTrace.current, - ); - } - }); try { final result = await completer.future; onSuccessful(result); diff --git a/packages/fl_query/lib/src/widgets/query_builder.dart b/packages/fl_query/lib/src/widgets/query_builder.dart index aeb2944..09cbeeb 100644 --- a/packages/fl_query/lib/src/widgets/query_builder.dart +++ b/packages/fl_query/lib/src/widgets/query_builder.dart @@ -7,6 +7,7 @@ import 'package:fl_query/src/collections/retry_config.dart'; import 'package:fl_query/src/core/client.dart'; import 'package:fl_query/src/core/query.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/src/foundation/diagnostics.dart'; typedef QueryBuilderFn = Widget Function( BuildContext context, @@ -42,7 +43,10 @@ class QueryBuilder extends StatefulWidget { this.onError, this.enabled = true, super.key, - }); + }) : assert( + enabled && jsonConfig != null, + 'jsonConfig is only supported when enabled is true', + ); @override State> createState() => @@ -132,4 +136,41 @@ class _QueryBuilderState } return widget.builder(context, query!); } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add( + DiagnosticsProperty>('query', query), + ); + properties.add( + DiagnosticsProperty>('queryKey', widget.queryKey), + ); + properties.add( + DiagnosticsProperty('builder', widget.builder), + ); + properties.add(DiagnosticsProperty('initial', widget.initial)); + properties.add( + DiagnosticsProperty('retryConfig', widget.retryConfig), + ); + properties.add( + DiagnosticsProperty( + 'refreshConfig', + widget.refreshConfig, + ), + ); + properties.add( + DiagnosticsProperty>( + 'jsonConfig', + widget.jsonConfig, + ), + ); + properties.add( + DiagnosticsProperty>('onData', widget.onData), + ); + properties.add( + DiagnosticsProperty>('onError', widget.onError), + ); + properties.add(DiagnosticsProperty('enabled', widget.enabled)); + } }