feat: implement refetchOnApplicationResume and refetchOnWindowFocus
This commit is contained in:
@@ -1 +1 @@
|
||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity_plus","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.6/","native_build":true,"dependencies":[]}],"android":[{"name":"connectivity_plus","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.6/","native_build":true,"dependencies":[]}],"macos":[{"name":"connectivity_plus_macos","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_macos-1.2.4/","native_build":true,"dependencies":[]}],"linux":[{"name":"connectivity_plus_linux","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_linux-1.3.1/","native_build":false,"dependencies":[]}],"windows":[{"name":"connectivity_plus_windows","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_windows-1.2.2/","native_build":true,"dependencies":[]}],"web":[{"name":"connectivity_plus_web","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_web-1.2.3/","dependencies":[]}]},"dependencyGraph":[{"name":"connectivity_plus","dependencies":["connectivity_plus_linux","connectivity_plus_macos","connectivity_plus_web","connectivity_plus_windows"]},{"name":"connectivity_plus_linux","dependencies":[]},{"name":"connectivity_plus_macos","dependencies":[]},{"name":"connectivity_plus_web","dependencies":[]},{"name":"connectivity_plus_windows","dependencies":[]}],"date_created":"2022-10-07 11:18:58.310019","version":"3.3.4"}
|
||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity_plus","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.6/","native_build":true,"dependencies":[]}],"android":[{"name":"connectivity_plus","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus-2.3.6/","native_build":true,"dependencies":[]}],"macos":[{"name":"connectivity_plus_macos","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_macos-1.2.4/","native_build":true,"dependencies":[]}],"linux":[{"name":"connectivity_plus_linux","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_linux-1.3.1/","native_build":false,"dependencies":[]}],"windows":[{"name":"connectivity_plus_windows","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_windows-1.2.2/","native_build":true,"dependencies":[]}],"web":[{"name":"connectivity_plus_web","path":"/opt/flutter/.pub-cache/hosted/pub.dartlang.org/connectivity_plus_web-1.2.3/","dependencies":[]}]},"dependencyGraph":[{"name":"connectivity_plus","dependencies":["connectivity_plus_linux","connectivity_plus_macos","connectivity_plus_web","connectivity_plus_windows"]},{"name":"connectivity_plus_linux","dependencies":[]},{"name":"connectivity_plus_macos","dependencies":[]},{"name":"connectivity_plus_web","dependencies":[]},{"name":"connectivity_plus_windows","dependencies":[]}],"date_created":"2022-10-08 11:24:03.169440","version":"3.3.4"}
|
||||
Binary file not shown.
@@ -41,6 +41,9 @@ abstract class BaseQuery<T extends Object, Outside, Error>
|
||||
|
||||
Timer? _refetchIntervalTimer;
|
||||
|
||||
bool? refetchOnApplicationResume;
|
||||
bool? refetchOnWindowFocus;
|
||||
|
||||
Connectivity _connectivity;
|
||||
|
||||
T? _previousData;
|
||||
@@ -56,6 +59,8 @@ abstract class BaseQuery<T extends Object, Outside, Error>
|
||||
this.refetchOnMount,
|
||||
this.refetchOnReconnect,
|
||||
this.refetchInterval,
|
||||
this.refetchOnApplicationResume,
|
||||
this.refetchOnWindowFocus,
|
||||
this.enabled = true,
|
||||
T? previousData,
|
||||
Connectivity? connectivity,
|
||||
@@ -245,6 +250,8 @@ abstract class BaseQuery<T extends Object, Outside, Error>
|
||||
Duration? cacheTime,
|
||||
bool? refetchOnMount,
|
||||
bool? refetchOnReconnect,
|
||||
bool? refetchOnApplicationResume,
|
||||
bool? refetchOnWindowFocus,
|
||||
}) {
|
||||
bool updated = false;
|
||||
if (this.refetchInterval == null &&
|
||||
@@ -272,6 +279,15 @@ abstract class BaseQuery<T extends Object, Outside, Error>
|
||||
this.refetchOnReconnect = refetchOnReconnect;
|
||||
updated = true;
|
||||
}
|
||||
if (this.refetchOnApplicationResume == null &&
|
||||
refetchOnApplicationResume != null) {
|
||||
this.refetchOnApplicationResume = refetchOnApplicationResume;
|
||||
updated = true;
|
||||
}
|
||||
if (this.refetchOnWindowFocus == null && refetchOnWindowFocus != null) {
|
||||
this.refetchOnWindowFocus = refetchOnWindowFocus;
|
||||
updated = true;
|
||||
}
|
||||
if (updated) notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ class InfiniteQuery<T extends Object, Outside, PageParam extends Object>
|
||||
super.enabled,
|
||||
super.previousData,
|
||||
super.connectivity,
|
||||
super.refetchOnApplicationResume,
|
||||
InfiniteQueryListeners<T, PageParam>? super.onData,
|
||||
InfiniteQueryListeners<dynamic, PageParam>? super.onError,
|
||||
required T? initialPage,
|
||||
@@ -93,6 +94,9 @@ class InfiniteQuery<T extends Object, Outside, PageParam extends Object>
|
||||
connectivity: options.connectivity ?? Connectivity(),
|
||||
queryKey: options.queryKey,
|
||||
initialData: {options.initialParam: options.initialPage},
|
||||
refetchOnApplicationResume: options.refetchOnApplicationResume,
|
||||
onData: onData,
|
||||
onError: onError,
|
||||
);
|
||||
|
||||
List<PageParam> get pageParams => data?.keys.toList() ?? [];
|
||||
|
||||
@@ -19,6 +19,8 @@ class InfiniteQueryJob<T extends Object, Outside, PageParam extends Object> {
|
||||
final bool? refetchOnMount;
|
||||
final bool? refetchOnReconnect;
|
||||
final bool? refetchOnExternalDataChange;
|
||||
final bool? refetchOnApplicationResume;
|
||||
final bool? refetchOnWindowFocus;
|
||||
final Duration? staleTime;
|
||||
final Duration? cacheTime;
|
||||
|
||||
@@ -46,6 +48,8 @@ class InfiniteQueryJob<T extends Object, Outside, PageParam extends Object> {
|
||||
this.refetchOnMount,
|
||||
this.refetchOnReconnect,
|
||||
this.refetchOnExternalDataChange,
|
||||
this.refetchOnApplicationResume,
|
||||
this.refetchOnWindowFocus,
|
||||
this.connectivity,
|
||||
}) : _queryKey = queryKey;
|
||||
|
||||
@@ -72,6 +76,8 @@ class InfiniteQueryJob<T extends Object, Outside, PageParam extends Object> {
|
||||
bool? refetchOnMount,
|
||||
bool? refetchOnReconnect,
|
||||
bool? refetchOnExternalDataChange,
|
||||
bool? refetchOnApplicationResume,
|
||||
bool? refetchOnWindowFocus,
|
||||
Connectivity? connectivity,
|
||||
}) {
|
||||
return (String queryKey) {
|
||||
@@ -91,6 +97,8 @@ class InfiniteQueryJob<T extends Object, Outside, PageParam extends Object> {
|
||||
refetchOnMount: refetchOnMount,
|
||||
refetchOnReconnect: refetchOnReconnect,
|
||||
refetchOnExternalDataChange: refetchOnExternalDataChange,
|
||||
refetchOnApplicationResume: refetchOnApplicationResume,
|
||||
refetchOnWindowFocus: refetchOnWindowFocus,
|
||||
connectivity: connectivity,
|
||||
initialParam: initialParam,
|
||||
);
|
||||
|
||||
@@ -18,6 +18,8 @@ class QueryJob<T extends Object, Outside> {
|
||||
final bool? refetchOnMount;
|
||||
final bool? refetchOnReconnect;
|
||||
final bool? refetchOnExternalDataChange;
|
||||
final bool? refetchOnApplicationResume;
|
||||
final bool? refetchOnWindowFocus;
|
||||
final bool? keepPreviousData;
|
||||
final Duration? staleTime;
|
||||
final Duration? cacheTime;
|
||||
@@ -43,6 +45,8 @@ class QueryJob<T extends Object, Outside> {
|
||||
this.refetchOnExternalDataChange,
|
||||
this.connectivity,
|
||||
this.keepPreviousData,
|
||||
this.refetchOnApplicationResume,
|
||||
this.refetchOnWindowFocus,
|
||||
}) : _queryKey = queryKey;
|
||||
|
||||
String get queryKey => _queryKey;
|
||||
@@ -65,6 +69,8 @@ class QueryJob<T extends Object, Outside> {
|
||||
bool? refetchOnMount,
|
||||
bool? refetchOnReconnect,
|
||||
bool? refetchOnExternalDataChange,
|
||||
bool? refetchOnApplicationResume,
|
||||
bool? refetchOnWindowFocus,
|
||||
Connectivity? connectivity,
|
||||
bool? keepPreviousData,
|
||||
}) {
|
||||
@@ -85,6 +91,8 @@ class QueryJob<T extends Object, Outside> {
|
||||
refetchOnExternalDataChange: refetchOnExternalDataChange,
|
||||
connectivity: connectivity,
|
||||
keepPreviousData: keepPreviousData,
|
||||
refetchOnApplicationResume: refetchOnApplicationResume,
|
||||
refetchOnWindowFocus: refetchOnWindowFocus,
|
||||
);
|
||||
query.isDynamic = true;
|
||||
return query;
|
||||
|
||||
@@ -58,6 +58,7 @@ class Query<T extends Object, Outside> extends BaseQuery<T, Outside, dynamic> {
|
||||
super.previousData,
|
||||
super.connectivity,
|
||||
super.initialData,
|
||||
super.refetchOnApplicationResume,
|
||||
QueryListener<T>? super.onData,
|
||||
QueryListener<dynamic>? super.onError,
|
||||
});
|
||||
@@ -84,6 +85,9 @@ class Query<T extends Object, Outside> extends BaseQuery<T, Outside, dynamic> {
|
||||
connectivity: options.connectivity ?? Connectivity(),
|
||||
previousData: previousData,
|
||||
queryKey: options.queryKey,
|
||||
refetchOnApplicationResume: options.refetchOnApplicationResume,
|
||||
onData: onData,
|
||||
onError: onError,
|
||||
);
|
||||
|
||||
@override
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:fl_query/src/query_cache.dart';
|
||||
import 'package:fl_query/src/utils.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
/// The widget that holds every [Query] & [Mutation] to your
|
||||
/// entire Flutter application in anywhere
|
||||
@@ -35,13 +36,31 @@ class QueryBowl {
|
||||
/// refetch query when new query instance mounts
|
||||
final bool refetchOnMount;
|
||||
|
||||
/// for desktop & web only (DUMMY & isn't implemented yet)
|
||||
/// refetch when desktop/web app regains Focus
|
||||
final bool refetchOnWindowFocus;
|
||||
|
||||
/// for mobile only (DUMMY & isn't implemented yet)
|
||||
/// the delay to call each query when desktop/web application gets focused after
|
||||
/// being unfocused. Using a delay after each refetch so refetching all the
|
||||
/// queries at once won't create high CPU spikes & also wouldn't violate
|
||||
/// rate-limit
|
||||
///
|
||||
/// Though its recommended most of the time to use but it can be turned
|
||||
/// off by passing [Duration.zero]
|
||||
final Duration refetchOnWindowFocusDelay;
|
||||
|
||||
/// refetch when application resumes from the background in mobile devices
|
||||
final bool refetchOnApplicationResume;
|
||||
|
||||
/// refetch when user's device reconnects to the internet after no being
|
||||
/// the delay to call each query when app resumes from the background in
|
||||
/// mobile devices. Using a delay after each refetch so refetching all the
|
||||
/// queries at once won't create high CPU spikes & also wouldn't violate
|
||||
/// rate-limit
|
||||
///
|
||||
/// Though its recommended most of the time to use but it can be turned
|
||||
/// off by passing [Duration.zero]
|
||||
final Duration refetchOnApplicationResumeDelay;
|
||||
|
||||
/// refetch when user's device reconnects to the internet after not being
|
||||
/// connected before
|
||||
final bool refetchOnReconnect;
|
||||
|
||||
@@ -82,6 +101,8 @@ class QueryBowl {
|
||||
this.refetchOnMount = false,
|
||||
this.refetchOnReconnect = true,
|
||||
this.refetchOnReconnectDelay = const Duration(milliseconds: 100),
|
||||
this.refetchOnApplicationResumeDelay = const Duration(milliseconds: 100),
|
||||
this.refetchOnWindowFocusDelay = const Duration(milliseconds: 100),
|
||||
this.refetchOnApplicationResume = true,
|
||||
this.refetchOnWindowFocus = true,
|
||||
this.refetchOnExternalDataChange = false,
|
||||
@@ -103,8 +124,33 @@ class QueryBowl {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (kIsMobile) {
|
||||
SystemChannels.lifecycle.setMessageHandler((msg) async {
|
||||
if (msg == 'AppLifecycleState.resumed') {
|
||||
if (_canNotRefetchAfterWeGotTheApp) return null;
|
||||
for (final query in this.cache.queries) {
|
||||
if (query.refetchOnApplicationResume == false || !query.enabled)
|
||||
continue;
|
||||
await query.refetch();
|
||||
await Future.delayed(refetchOnApplicationResumeDelay);
|
||||
}
|
||||
for (final infiniteQuery in this.cache.infiniteQueries) {
|
||||
if (infiniteQuery.refetchOnApplicationResume == false ||
|
||||
!infiniteQuery.enabled) continue;
|
||||
await infiniteQuery.refetchPages();
|
||||
await Future.delayed(refetchOnApplicationResumeDelay);
|
||||
}
|
||||
} else if (msg != null) {
|
||||
updateWeLostTheApp();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DateTime? _weLostTheAppAt;
|
||||
|
||||
/// Returns the number of query is currently fetching or refetching
|
||||
int get isFetching {
|
||||
return cache.queries.fold<int>(
|
||||
@@ -127,6 +173,30 @@ class QueryBowl {
|
||||
);
|
||||
}
|
||||
|
||||
bool get _canNotRefetchAfterWeGotTheApp => (_weLostTheAppAt != null &&
|
||||
_weLostTheAppAt!.difference(DateTime.now()) <= cache.cacheTime);
|
||||
|
||||
@protected
|
||||
updateWeLostTheApp() {
|
||||
_weLostTheAppAt = DateTime.now();
|
||||
}
|
||||
|
||||
@protected
|
||||
notifyWindowFocused() async {
|
||||
if (kIsMobile || _canNotRefetchAfterWeGotTheApp) return;
|
||||
for (final query in this.cache.queries) {
|
||||
if (query.refetchOnWindowFocus == false || !query.enabled) continue;
|
||||
await query.refetch();
|
||||
await Future.delayed(refetchOnWindowFocusDelay);
|
||||
}
|
||||
for (final infiniteQuery in this.cache.infiniteQueries) {
|
||||
if (infiniteQuery.refetchOnWindowFocus == false || !infiniteQuery.enabled)
|
||||
continue;
|
||||
await infiniteQuery.refetchPages();
|
||||
await Future.delayed(refetchOnWindowFocusDelay);
|
||||
}
|
||||
}
|
||||
|
||||
void onQueriesUpdate<T extends Object, Outside>(
|
||||
void Function(Query<T, Outside> query) listener,
|
||||
) {
|
||||
@@ -271,6 +341,8 @@ class QueryBowl {
|
||||
refetchInterval: refetchInterval,
|
||||
refetchOnMount: refetchOnMount,
|
||||
refetchOnReconnect: refetchOnReconnect,
|
||||
refetchOnApplicationResume: refetchOnApplicationResume,
|
||||
refetchOnWindowFocus: refetchOnWindowFocus,
|
||||
);
|
||||
return query;
|
||||
}
|
||||
@@ -290,6 +362,8 @@ class QueryBowl {
|
||||
refetchInterval: refetchInterval,
|
||||
refetchOnMount: refetchOnMount,
|
||||
refetchOnReconnect: refetchOnReconnect,
|
||||
refetchOnApplicationResume: refetchOnApplicationResume,
|
||||
refetchOnWindowFocus: refetchOnWindowFocus,
|
||||
);
|
||||
return infiniteQuery;
|
||||
}
|
||||
@@ -478,7 +552,18 @@ class QueryBowlScope extends InheritedWidget {
|
||||
required this.bowl,
|
||||
required Widget child,
|
||||
Key? key,
|
||||
}) : super(key: key, child: child);
|
||||
}) : super(
|
||||
key: key,
|
||||
child: MouseRegion(
|
||||
onEnter: (event) {
|
||||
bowl.notifyWindowFocused();
|
||||
},
|
||||
onExit: (event) {
|
||||
bowl.updateWeLostTheApp();
|
||||
},
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(covariant oldWidget) => false;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:fl_query/src/query.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'dart:io' show Platform;
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
Future<void> callQueryListeners<T>(Set<QueryListener<T>> listeners, T data) {
|
||||
return Future.wait(listeners.map(
|
||||
@@ -54,3 +56,14 @@ bool isConnectedToInternet(ConnectivityResult result) {
|
||||
String getVariable(String queryKey) {
|
||||
return queryKey.split("#").last;
|
||||
}
|
||||
|
||||
final kIsDesktop = kIsLinux || kIsWindows || kIsMacOS;
|
||||
|
||||
final kIsMobile = kIsAndroid || kIsIOS;
|
||||
|
||||
final kIsMacOS = kIsWeb ? false : Platform.isMacOS;
|
||||
|
||||
final kIsLinux = kIsWeb ? false : Platform.isLinux;
|
||||
final kIsAndroid = kIsWeb ? false : Platform.isAndroid;
|
||||
final kIsIOS = kIsWeb ? false : Platform.isIOS;
|
||||
final kIsWindows = kIsWeb ? false : Platform.isWindows;
|
||||
|
||||
@@ -14,7 +14,7 @@ environment:
|
||||
|
||||
dependencies:
|
||||
collection: ^1.16.0
|
||||
connectivity_plus: ^2.3.5
|
||||
connectivity_plus: ^2.3.9
|
||||
flutter:
|
||||
sdk: flutter
|
||||
queue: ^3.1.0+1
|
||||
|
||||
Reference in New Issue
Block a user