I am sure I developed this code from some other question here on SO, but I can't find it.
Anyway, I have a similar function in a webapp of mine: it detects mouse clicks and the likes (not mouse movement!), and logs out the user if the timer runs out. As far as I know, it doesn't have any problem with different tabs.
This is the class that acts as timer:
class SessionTimer {
late Timer timer;
BuildContext context;
Function onLogout;
int minutes;
SessionTimer({required this.context, required this.onLogout, required this.minutes});
void startTimer() {
timer = Timer.periodic(Duration(minutes: minutes), (_) {
timedOut();
});
}
void userActivityDetected([_]) {
//print('detected');
if (timer.isActive) {
timer.cancel();
//print('restarted');
startTimer();
}
return;
}
Future<void> timedOut() async {
timer.cancel();
await showDialog(
context: context,
barrierDismissible: false,
builder: (context) => WillPopScope(
onWillPop: () async {
return false;
},
child: PointerInterceptor(
child: AlertDialog(
title: Text('settingsAutoLogout'.tr()),
content: Text('logoutForced'.tr()),
actions: <Widget>[
TextButton(onPressed: () => onLogout(), child: const Icon(Icons.check)),
],
))),
);
}
}
This is the HomePage
state that has the session timer:
class HomePageState extends State<HomePage> {
SessionTimer? _sessionTimer;
@override
void initState() {
super.initState();
var cfg = Config();
cfg.init(MyApp.database).then((success) {
_sessionTimer = SessionTimer(context: context, onLogout: () => _logout(false), minutes: cfg.autoLogout);
_sessionTimer!.startTimer();
});
}
//rest of the State class...
This is the GestureDetector
at the top of the widget tree (after the user has logged in, of course):
return GestureDetector(
onTap: _sessionTimer?.userActivityDetected,
onPanDown: _sessionTimer?.userActivityDetected,
onScaleStart: _sessionTimer?.userActivityDetected,
child: //rest of the widget tree...
Hope this helps.