Issue
I have an AngularDart app created in 2016 that uses the dependencies listed below. My client would like to add a session idle timeout to the application and I have not the first idea how to start. It doesn’t help that the application was created 4 years ago and is not on the current version. Any suggestions on what dart or angulardart libraries might include components that would support this need?
environment:
sdk: '>=1.24.0 <2.0.0'
dependencies:
angular: ^4.0.0+2
angular_router: ^1.0.2
angular_components: ^0.6.0
json_object: any
http: "^0.11.3+14"
angular_dart_ui_bootstrap: '>=0.0.1'
ng_bootstrap: ^0.9.2
dartson: "^0.2.7"
browser_detect: "^1.0.4"
archive: "^1.0.33"
build: "^0.11.0"
intl: "^0.15.6"
dev_dependencies:
browser: ^0.10.0
dart_to_js_script_rewriter: ^1.0.1
test: ^0.12.0
angular_test: ^1.0.0
transformers:
- dartson
- angular:
entry_points:
- web/main.dart
- test/**_test.dart
- test/pub_serve:
$include: test/**_test.dart
- dart_to_js_script_rewriter
# Uncomment the following in sdk 1.24+ to make pub serve
# use dartdevc (webdev.dartlang.org/tools/dartdevc).
#web:
# compiler:
# debug: dartdevc
Edit:
I attempted to create a solution by adding a timer and trapping user interaction on the page.
In my app_component.dart I added event listeners in the init function. I create a timer and set its timeout to one minute just to test.
There is a start event listener that creates the timer when called. This is called the first time after the user successfully logs in.
There is a cancel event timer that cancels the timer, nulls it, and if the user is still logged in, re-creates the timer. This is called by user activity (keypress or mousemove), or by logout. If the user is still logged in when this is called then the timer is canceled, set null, and created again. If the user is logged out, it is not re-created.
The point of this code is to begin the timer when the user logs in, restart it whenever the user interacts with the app (keypress or mousemove), and turn it off when the user is logged out.
It is intended that if there is no user activity for 1 minute, then the handleTimerEvent will be called. This is close to working by I have unexpected behavior.
Future<Null> ngOnInit() async {
_eventService.onStartIdleTimer.stream.listen((timerEvent) {
if(idleTimer == null) {
print(
"Starting idleTimer: " + new DateTime.now().toLocal().toString());
idleTimerStarted = new DateTime.now();
idleTimer = new Timer(new Duration(minutes: 1), handleTimerEvent());
}
});
_eventService.onCancelIdleTimer.stream.listen((timerEvent){
if(idleTimer != null) {
if (idleTimer.isActive) {
print(
"Canceling idleTimer: " +
new DateTime.now().toLocal().toString());
var diff = new DateTime.now().difference(idleTimerStarted);
print(diff.inSeconds.toString() +" seconds elapsed.");
idleTimer.cancel();
idleTimer = null;
if (isLoggedIn)
_eventService.onStartIdleTimer.add(new IdleTimerEvent("Start"));
}
}
});
}
handleTimerEvent(){
print("In handleTimerEvent!");
if(this.isLoggedIn){
if(new DateTime.now().difference(idleTimerStarted).inMinutes > 1){
print("Idle Timer passed configured limit. Logging user out.");
logoutForIdle();
} else {
_eventService.onStartIdleTimer.add(new IdleTimerEvent("Start"));
}
}
}
logoutForIdle() {
_eventService.onError.add(new GenomicsErrorEvent()
..message = globals.idleTimeoutMessage
..dismissable = true
..alertType = alertType);
logout();
_eventService.onCancelIdleTimer.add(new IdleTimerEvent("Cancel"));
}
First of all, when I call Timer.cancel(), the callback seems to be firing, which is unexpected. And when I wait for the timeout, i get this exception:
EXCEPTION: NullError: method not found: 'call$0' on null
STACKTRACE:
TypeError: Cannot read property 'call$0' of null
at StaticClosure.dart._rootRun (http://localhost:63114/main.dart.js:7427:18)
at _ZoneDelegate.run$2 (http://localhost:63114/main.dart.js:10632:41)
at NgZone.dart.NgZone._run$4 (http://localhost:63114/main.dart.js:112512:24)
at Object.eval (eval at Closure_forwardCallTo (http://localhost:63114/main.dart.js:4663:14), <anonymous>:3:45)
at _CustomZone.run$1 (http://localhost:63114/main.dart.js:10765:41)
at _CustomZone.runGuarded$1 (http://localhost:63114/main.dart.js:10681:21)
at _CustomZone_bindCallback_closure.dart._CustomZone_bindCallback_closure.call$0 (http://localhost:63114/main.dart.js:10836:27)
at NgZone__createTimer_closure.dart.NgZone__createTimer_closure.call$0 (http://localhost:63114/main.dart.js:112664:19)
at StaticClosure.dart._rootRun (http://localhost:63114/main.dart.js:7432:16)
at _ZoneDelegate.run$2 (http://localhost:63114/main.dart.js:10632:41)
ORIGINAL EXCEPTION: NullError: method not found: 'call$0' on null
I am very confused.
Solved by
Solution
idleTimer = new Timer(new Duration(minutes: 1), handleTimerEvent());
Should be
idleTimer = new Timer(new Duration(minutes: 1), handleTimerEvent);
The code you wrote is calling handleTimerEvent
when it creates the timer, and passing null
(the implicit return value from handleTimerEvent()
) as the callback to the timer. You are calling it instead of passing it as a callback, that is why it is running. When the timer fires it tries to call null
as a function which is the exception you see. It’s not clear why the cancel isn’t working – perhaps things are running in the wrong order and you are attempting to cancel before starting the timer.
Answered By – Nate Bosch
Answer Checked By – Clifford M. (FlutterFixes Volunteer)