feat: add app lifecycle refresh coordinator
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
class CacheRefreshCoordinator with WidgetsBindingObserver {
|
||||||
|
final Duration minInterval;
|
||||||
|
final void Function() onRefresh;
|
||||||
|
final DateTime Function() now;
|
||||||
|
|
||||||
|
DateTime? _lastRefreshedAt;
|
||||||
|
|
||||||
|
CacheRefreshCoordinator({
|
||||||
|
required this.minInterval,
|
||||||
|
required this.onRefresh,
|
||||||
|
DateTime Function()? now,
|
||||||
|
}) : now = now ?? DateTime.now;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||||
|
if (state != AppLifecycleState.resumed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final current = now();
|
||||||
|
final last = _lastRefreshedAt;
|
||||||
|
if (last != null && current.difference(last) < minInterval) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_lastRefreshedAt = current;
|
||||||
|
onRefresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import 'core/constants/app_constants.dart';
|
import 'core/constants/app_constants.dart';
|
||||||
|
import 'core/cache/cache_refresh_coordinator.dart';
|
||||||
import 'core/di/injection.dart';
|
import 'core/di/injection.dart';
|
||||||
import 'core/notifications/local_notification_service.dart';
|
import 'core/notifications/local_notification_service.dart';
|
||||||
import 'core/notifications/reminder_notification_callbacks.dart';
|
import 'core/notifications/reminder_notification_callbacks.dart';
|
||||||
@@ -14,9 +15,13 @@ import 'features/auth/presentation/bloc/auth_bloc.dart';
|
|||||||
import 'features/auth/presentation/bloc/auth_event.dart';
|
import 'features/auth/presentation/bloc/auth_event.dart';
|
||||||
import 'features/auth/presentation/bloc/auth_state.dart';
|
import 'features/auth/presentation/bloc/auth_state.dart';
|
||||||
import 'features/calendar/data/services/calendar_service.dart';
|
import 'features/calendar/data/services/calendar_service.dart';
|
||||||
|
import 'features/calendar/data/services/calendar_repository.dart';
|
||||||
import 'features/calendar/reminders/reminder_action_executor.dart';
|
import 'features/calendar/reminders/reminder_action_executor.dart';
|
||||||
import 'features/calendar/reminders/ui/reminder_foreground_presenter.dart';
|
import 'features/calendar/reminders/ui/reminder_foreground_presenter.dart';
|
||||||
|
import 'features/calendar/ui/calendar_state_manager.dart';
|
||||||
import 'features/chat/presentation/bloc/chat_bloc.dart';
|
import 'features/chat/presentation/bloc/chat_bloc.dart';
|
||||||
|
import 'features/settings/data/services/settings_user_cache.dart';
|
||||||
|
import 'features/todo/data/todo_repository.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@@ -44,6 +49,25 @@ void main() async {
|
|||||||
final authBloc = sl<AuthBloc>();
|
final authBloc = sl<AuthBloc>();
|
||||||
authBloc.add(AuthStarted());
|
authBloc.add(AuthStarted());
|
||||||
|
|
||||||
|
final cacheRefreshCoordinator = CacheRefreshCoordinator(
|
||||||
|
minInterval: const Duration(minutes: 5),
|
||||||
|
onRefresh: () {
|
||||||
|
final selected = sl<CalendarStateManager>().selectedDate;
|
||||||
|
unawaited(
|
||||||
|
sl<CalendarRepository>().getDayEvents(selected, forceRefresh: true),
|
||||||
|
);
|
||||||
|
unawaited(
|
||||||
|
sl<CalendarRepository>().getMonthEvents(
|
||||||
|
DateTime(selected.year, selected.month, 1),
|
||||||
|
forceRefresh: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
unawaited(sl<TodoRepository>().getPendingTodos(forceRefresh: true));
|
||||||
|
unawaited(sl<SettingsUserCache>().getProfile(forceRefresh: true));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
WidgetsBinding.instance.addObserver(cacheRefreshCoordinator);
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
LinksyApp(
|
LinksyApp(
|
||||||
authBloc: authBloc,
|
authBloc: authBloc,
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:social_app/core/cache/cache_refresh_coordinator.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
test('resume should trigger refresh only when min interval elapsed', () {
|
||||||
|
var calls = 0;
|
||||||
|
var now = DateTime(2026, 3, 20, 10, 0);
|
||||||
|
|
||||||
|
final coordinator = CacheRefreshCoordinator(
|
||||||
|
minInterval: const Duration(minutes: 5),
|
||||||
|
onRefresh: () => calls += 1,
|
||||||
|
now: () => now,
|
||||||
|
);
|
||||||
|
|
||||||
|
coordinator.didChangeAppLifecycleState(AppLifecycleState.resumed);
|
||||||
|
expect(calls, 1);
|
||||||
|
|
||||||
|
now = DateTime(2026, 3, 20, 10, 3);
|
||||||
|
coordinator.didChangeAppLifecycleState(AppLifecycleState.resumed);
|
||||||
|
expect(calls, 1);
|
||||||
|
|
||||||
|
now = DateTime(2026, 3, 20, 10, 6);
|
||||||
|
coordinator.didChangeAppLifecycleState(AppLifecycleState.resumed);
|
||||||
|
expect(calls, 2);
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user