86 lines
2.3 KiB
Dart
86 lines
2.3 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../core/providers.dart';
|
|
|
|
class AutoRefresh extends ConsumerStatefulWidget {
|
|
const AutoRefresh({super.key, required this.location, required this.child});
|
|
final String location;
|
|
final Widget child;
|
|
|
|
static const pollEvery = Duration(seconds: 60);
|
|
static const gap = Duration(seconds: 30);
|
|
static const resumeGap = Duration(seconds: 30);
|
|
|
|
@override
|
|
ConsumerState<AutoRefresh> createState() => _AutoRefreshState();
|
|
}
|
|
|
|
class _AutoRefreshState extends ConsumerState<AutoRefresh>
|
|
with WidgetsBindingObserver {
|
|
Timer? _poll, _cool, _resumeCool;
|
|
|
|
static const _lists = ['/results', '/shops', '/orders', '/users'];
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
WidgetsBinding.instance.addObserver(this);
|
|
_poll = Timer.periodic(AutoRefresh.pollEvery, (_) => _onPoll());
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
WidgetsBinding.instance.removeObserver(this);
|
|
_poll?.cancel();
|
|
_cool?.cancel();
|
|
_resumeCool?.cancel();
|
|
super.dispose();
|
|
}
|
|
|
|
bool get _onList => _lists.contains(widget.location);
|
|
|
|
bool get _visible {
|
|
final s = WidgetsBinding.instance.lifecycleState;
|
|
return s == null || s == AppLifecycleState.resumed;
|
|
}
|
|
|
|
// False while a sheet or dialog sits on top of the screen.
|
|
bool get _uncovered => ModalRoute.of(context)?.isCurrent ?? true;
|
|
|
|
bool get _signedIn => ref.read(sessionProvider) != null;
|
|
|
|
void _reload() => ref.read(dataVersionProvider.notifier).bump();
|
|
|
|
void _onPoll() {
|
|
if (_cool != null ||
|
|
!_visible ||
|
|
!_signedIn ||
|
|
!_uncovered ||
|
|
widget.location != '/orders') {
|
|
return;
|
|
}
|
|
_reload();
|
|
}
|
|
|
|
@override
|
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
|
if (state != AppLifecycleState.resumed) return;
|
|
if (_resumeCool != null || !_signedIn || !_onList || !_uncovered) return;
|
|
_reload();
|
|
_resumeCool = Timer(AutoRefresh.resumeGap, () => _resumeCool = null);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Every reload, whoever started it, restarts the quiet period.
|
|
ref.listen(dataVersionProvider, (_, _) {
|
|
_cool?.cancel();
|
|
_cool = Timer(AutoRefresh.gap, () => _cool = null);
|
|
});
|
|
return widget.child;
|
|
}
|
|
}
|