You can handle this by creating a sessionActivityListener class
class SessionInactivity extends StatefulWidget {
VoidCallback onSessionTimeout;
Duration duration;
Widget child;
SessionInactivity(
{super.key,
required this.onSessionTimeout,
required this.duration,
required this.child});
@override
State<SessionInactivity> createState() => _SessionInactivityState();
}
class _SessionInactivityState extends State<SessionInactivity> {
Timer? _timer;
@override
void initState() {
_startTimer();
super.initState();
}
@override
void dispose() {
_checkTimer();
super.dispose();
}
@override Widget build(BuildContext context) {
return Listener(
onPointerDown: (_) {
_startTimer();
},
behavior: HitTestBehavior.translucent,
child: widget.child,
); }
Your timer will be used to countdown once the onSessionTimeout function is triggered
_startTimer() {
_checkTimer();
_timer = Timer(widget.duration, () {
print("session timedout");
widget.onSessionTimeout();
});
}
_checkTimer() {
if (_timer != null) {
print("starting timer");
_timer?.cancel();
_timer = null;
}
}
After these, just wrap your material app with the sessionactivity listener and pass the required arguments.
void main() {runApp(const UserInactivity());
}
class UserInactivity extends StatefulWidget {
const UserInactivity({super.key});
@override
State<UserInactivity> createState() => _UserInactivity();
}
class _UserInactivity extends State<UserInactivity> {
static final navKey = GlobalKey<NavigatorState>();
@override
void initState() {
loggedInStatus = SessionNotifier.notLoggedIn;
super.initState();
}
@override
Widget build(BuildContext context) {
return SessionInactivity(
duration: Duration(minutes: 3),
onSessionTimeout: () {
loggedInStatus != SessionNotifier.notLoggedIn
? _timeoutFunction()
: null;
},
child: MaterialApp(
navigatorKey: _UserInactivity.navKey,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
debugShowCheckedModeBanner: false,
home: const LoginScreen(),
),
);
}
_timeoutFunction() {
Navigator.push(navKey.currentState!.context,
MaterialPageRoute(builder: (context) => const LoginScreen()));
customAlertWidget(
navKey.currentState!.context,
"Your session expired or timedout, please login to continue ",
);
}
}
Please note
the loggedInStatus is an enum that notifies the event of a successful login, and this is because your session inactivity callback function should ideally only run when the user has an active session i.e is logged in
i created the enum this way
enum SessionNotifier {
loggedIn,
notLoggedIn,
authenticating,
}
SessionNotifier loggedInStatus = SessionNotifier.notLoggedIn;
and the _timeout function handles the callback.
I hope this helps.
addGlobalRoute/addRouteso that you will be able to "catch" any pointer event from the devicePointerRoutercatch all events including key, touch, or trackball?RawKeybordclass