Skip to content

Commit

Permalink
use resume detector
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-sidhdhi-p committed May 9, 2024
1 parent 75c2c94 commit 321819b
Show file tree
Hide file tree
Showing 16 changed files with 236 additions and 77 deletions.
40 changes: 40 additions & 0 deletions khelo/lib/components/resume_detector.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:flutter/cupertino.dart';
import 'package:uuid/uuid.dart';
import 'package:visibility_detector/visibility_detector.dart';

class ResumeDetector extends StatefulWidget {
final Function() onResume;
final Widget child;

const ResumeDetector({
super.key,
required this.onResume,
required this.child,
});

@override
State<ResumeDetector> createState() => _ResumeDetectorState();
}

class _ResumeDetectorState extends State<ResumeDetector> {
final String _key = const Uuid().v4();

var _lastNotifiedTime = DateTime.now();

@override
Widget build(BuildContext context) {
return VisibilityDetector(
key: Key(_key),
child: widget.child,
onVisibilityChanged: (info) {
if (info.visibleFraction == 1) {
if (DateTime.now().difference(_lastNotifiedTime).inMilliseconds >
1000) {
widget.onResume();
_lastNotifiedTime = DateTime.now();
}
}
},
);
}
}
21 changes: 17 additions & 4 deletions khelo/lib/ui/flow/home/home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:khelo/components/app_page.dart';
import 'package:khelo/components/error_screen.dart';
import 'package:khelo/components/image_avatar.dart';
import 'package:khelo/components/resume_detector.dart';
import 'package:khelo/domain/extensions/context_extensions.dart';
import 'package:khelo/domain/extensions/enum_extensions.dart';
import 'package:khelo/domain/formatter/date_formatter.dart';
Expand All @@ -25,9 +26,10 @@ class HomeScreen extends ConsumerStatefulWidget {
class _HomeScreenState extends ConsumerState<HomeScreen>
with AutomaticKeepAliveClientMixin, WidgetsBindingObserver {
late HomeViewNotifier notifier;
bool _wantKeepAlive = true;

@override
bool get wantKeepAlive => true;
bool get wantKeepAlive => _wantKeepAlive;

@override
void initState() {
Expand All @@ -37,7 +39,15 @@ class _HomeScreenState extends ConsumerState<HomeScreen>

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.detached) {
if (state == AppLifecycleState.paused) {
setState(() {
_wantKeepAlive = false;
});
} else if (state == AppLifecycleState.resumed) {
setState(() {
_wantKeepAlive = true;
});
} else if (state == AppLifecycleState.detached) {
// deallocate resources
notifier.dispose();
WidgetsBinding.instance.removeObserver(this);
Expand All @@ -52,7 +62,10 @@ class _HomeScreenState extends ConsumerState<HomeScreen>

return AppPage(
title: context.l10n.home_screen_title,
body: _body(context, notifier, state),
body: ResumeDetector(
onResume: notifier.onResume,
child: _body(context, notifier, state),
),
);
}

Expand All @@ -67,7 +80,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen>
if (state.error != null) {
return ErrorScreen(
error: state.error,
onRetryTap: notifier.loadMatches,
onRetryTap: notifier.onResume,
);
}

Expand Down
9 changes: 7 additions & 2 deletions khelo/lib/ui/flow/home/home_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ class HomeViewNotifier extends StateNotifier<HomeViewState> {
late StreamSubscription _streamSubscription;

HomeViewNotifier(this._matchService) : super(const HomeViewState()) {
loadMatches();
_loadMatches();
}

void loadMatches() async {
void _loadMatches() async {
state = state.copyWith(loading: state.matches.isEmpty);

_streamSubscription = _matchService.getRunningMatches().listen(
Expand All @@ -38,6 +38,11 @@ class HomeViewNotifier extends StateNotifier<HomeViewState> {
await _streamSubscription.cancel();
}

onResume() {
_cancelStreamSubscription();
_loadMatches();
}

@override
void dispose() {
_cancelStreamSubscription();
Expand Down
13 changes: 11 additions & 2 deletions khelo/lib/ui/flow/main/main_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ class _MainScreenState extends ConsumerState<MainScreen>

final _materialPageController = PageController();
final _cupertinoTabController = CupertinoTabController();
bool _wantKeepAlive = true;

@override
bool get wantKeepAlive => true;
bool get wantKeepAlive => _wantKeepAlive;

@override
void initState() {
Expand All @@ -41,7 +42,15 @@ class _MainScreenState extends ConsumerState<MainScreen>

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.detached) {
if (state == AppLifecycleState.paused) {
setState(() {
_wantKeepAlive = false;
});
} else if (state == AppLifecycleState.resumed) {
setState(() {
_wantKeepAlive = true;
});
} else if (state == AppLifecycleState.detached) {
// deallocate resources
_materialPageController.dispose();
_cupertinoTabController.dispose();
Expand Down
38 changes: 24 additions & 14 deletions khelo/lib/ui/flow/matches/match_list_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:khelo/components/error_screen.dart';
import 'package:khelo/components/match_status_tag.dart';
import 'package:khelo/components/resume_detector.dart';
import 'package:khelo/components/won_by_message_text.dart';
import 'package:khelo/domain/extensions/context_extensions.dart';
import 'package:khelo/domain/extensions/data_model_extensions/match_model_extension.dart';
Expand All @@ -27,9 +28,10 @@ class MatchListScreen extends ConsumerStatefulWidget {
class _MatchListScreenState extends ConsumerState<MatchListScreen>
with AutomaticKeepAliveClientMixin, WidgetsBindingObserver {
late MatchListViewNotifier notifier;
bool _wantKeepAlive = true;

@override
bool get wantKeepAlive => true;
bool get wantKeepAlive => _wantKeepAlive;

@override
void initState() {
Expand All @@ -39,7 +41,15 @@ class _MatchListScreenState extends ConsumerState<MatchListScreen>

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.detached) {
if (state == AppLifecycleState.paused) {
setState(() {
_wantKeepAlive = false;
});
} else if (state == AppLifecycleState.resumed) {
setState(() {
_wantKeepAlive = true;
});
} else if (state == AppLifecycleState.detached) {
// deallocate resources
notifier.dispose();
WidgetsBinding.instance.removeObserver(this);
Expand All @@ -52,14 +62,17 @@ class _MatchListScreenState extends ConsumerState<MatchListScreen>
final state = ref.watch(matchListStateProvider);
notifier = ref.watch(matchListStateProvider.notifier);

return Column(
children: [
_topStartMatchView(context),
const SizedBox(
height: 24,
),
_matchList(context, notifier, state),
],
return ResumeDetector(
onResume: notifier.onResume,
child: Column(
children: [
_topStartMatchView(context),
const SizedBox(
height: 24,
),
_matchList(context, notifier, state),
],
),
);
}

Expand Down Expand Up @@ -100,10 +113,7 @@ class _MatchListScreenState extends ConsumerState<MatchListScreen>
if (state.error != null) {
return ErrorScreen(
error: state.error,
onRetryTap: () {
notifier.cancelStreamSubscription();
notifier.loadMatches();
},
onRetryTap: notifier.onResume,
);
}

Expand Down
13 changes: 9 additions & 4 deletions khelo/lib/ui/flow/matches/match_list_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ class MatchListViewNotifier extends StateNotifier<MatchListViewState> {
: super(MatchListViewState(
currentUserId: userId,
)) {
loadMatches();
_loadMatches();
}

void setUserId(String? userId) {
state = state.copyWith(currentUserId: userId);
}

Future<void> loadMatches() async {
Future<void> _loadMatches() async {
state = state.copyWith(loading: true);
try {
_matchesStreamSubscription =
Expand All @@ -51,13 +51,18 @@ class MatchListViewNotifier extends StateNotifier<MatchListViewState> {
}
}

cancelStreamSubscription() async {
_cancelStreamSubscription() async {
await _matchesStreamSubscription.cancel();
}

onResume(){
_cancelStreamSubscription();
_loadMatches();
}

@override
void dispose() {
cancelStreamSubscription();
_cancelStreamSubscription();
super.dispose();
}
}
Expand Down
13 changes: 11 additions & 2 deletions khelo/lib/ui/flow/my_game/my_game_tab_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ class _MyGameTabScreenState extends ConsumerState<MyGameTabScreen>
int get _selectedTab => _controller.hasClients
? _controller.page?.round() ?? 0
: _controller.initialPage;
bool _wantKeepAlive = true;

@override
bool get wantKeepAlive => true;
bool get wantKeepAlive => _wantKeepAlive;

@override
void initState() {
Expand All @@ -46,7 +47,15 @@ class _MyGameTabScreenState extends ConsumerState<MyGameTabScreen>

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.detached) {
if (state == AppLifecycleState.paused) {
setState(() {
_wantKeepAlive = false;
});
} else if (state == AppLifecycleState.resumed) {
setState(() {
_wantKeepAlive = true;
});
} else if (state == AppLifecycleState.detached) {
// deallocate resources
_controller.dispose();
WidgetsBinding.instance.removeObserver(this);
Expand Down
13 changes: 11 additions & 2 deletions khelo/lib/ui/flow/stats/my_stats_tab_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ class _MyStatsTabScreenState extends ConsumerState<MyStatsTabScreen>
? _controller.page?.round() ?? 0
: _controller.initialPage;

bool _wantKeepAlive = true;
@override
bool get wantKeepAlive => true;
bool get wantKeepAlive => _wantKeepAlive;

@override
void initState() {
Expand All @@ -44,7 +45,15 @@ class _MyStatsTabScreenState extends ConsumerState<MyStatsTabScreen>

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.detached) {
if (state == AppLifecycleState.paused) {
setState(() {
_wantKeepAlive = false;
});
} else if (state == AppLifecycleState.resumed) {
setState(() {
_wantKeepAlive = true;
});
} else if (state == AppLifecycleState.detached) {
// deallocate resources
_controller.dispose();
WidgetsBinding.instance.removeObserver(this);
Expand Down
35 changes: 25 additions & 10 deletions khelo/lib/ui/flow/stats/user_match/user_match_list_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:khelo/components/error_screen.dart';
import 'package:khelo/components/image_avatar.dart';
import 'package:khelo/components/resume_detector.dart';
import 'package:khelo/components/won_by_message_text.dart';
import 'package:khelo/domain/extensions/context_extensions.dart';
import 'package:khelo/domain/extensions/data_model_extensions/match_model_extension.dart';
Expand All @@ -26,9 +27,10 @@ class UserMatchListScreen extends ConsumerStatefulWidget {
class _UserMatchListScreenState extends ConsumerState<UserMatchListScreen>
with AutomaticKeepAliveClientMixin, WidgetsBindingObserver {
late UserMatchListViewNotifier notifier;
bool _wantKeepAlive = true;

@override
bool get wantKeepAlive => true;
bool get wantKeepAlive => _wantKeepAlive;

@override
void initState() {
Expand All @@ -38,7 +40,15 @@ class _UserMatchListScreenState extends ConsumerState<UserMatchListScreen>

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.detached) {
if (state == AppLifecycleState.paused) {
setState(() {
_wantKeepAlive = false;
});
} else if (state == AppLifecycleState.resumed) {
setState(() {
_wantKeepAlive = true;
});
} else if (state == AppLifecycleState.detached) {
// deallocate resources
notifier.dispose();
WidgetsBinding.instance.removeObserver(this);
Expand All @@ -52,23 +62,28 @@ class _UserMatchListScreenState extends ConsumerState<UserMatchListScreen>
final state = ref.watch(userMatchListStateProvider);
notifier = ref.watch(userMatchListStateProvider.notifier);

return ResumeDetector(
onResume: notifier.onResume,
child: _body(context, notifier, state),
);
}

Widget _body(
BuildContext context,
UserMatchListViewNotifier notifier,
UserMatchListState state,
) {
if (state.loading) {
return const AppProgressIndicator();
}

if (state.error != null) {
return ErrorScreen(
error: state.error,
onRetryTap: () {
notifier.cancelStreamSubscription();
notifier.loadUserMatches();
},
onRetryTap: notifier.onResume,
);
}

return _body(context, state);
}

Widget _body(BuildContext context, UserMatchListState state) {
if (state.matches.isNotEmpty) {
return ListView.separated(
padding: const EdgeInsets.only(bottom: 50, top: 24),
Expand Down
Loading

0 comments on commit 321819b

Please sign in to comment.