fix: don't wait until regaining focus to lock app
This commit is contained in:
@@ -1,10 +1,8 @@
|
|||||||
import { ApplicationService } from '@standardnotes/snjs';
|
import { ApplicationService } from '@standardnotes/snjs';
|
||||||
import { WebApplication } from '@/ui_models/application';
|
|
||||||
import { isDesktopApplication } from '@/utils';
|
import { isDesktopApplication } from '@/utils';
|
||||||
import { AppStateEvent } from '@/ui_models/app_state';
|
|
||||||
|
|
||||||
const MILLISECONDS_PER_SECOND = 1000;
|
const MILLISECONDS_PER_SECOND = 1000;
|
||||||
const FOCUS_POLL_INTERVAL = 1 * MILLISECONDS_PER_SECOND;
|
const POLL_INTERVAL = 10;
|
||||||
const LOCK_INTERVAL_NONE = 0;
|
const LOCK_INTERVAL_NONE = 0;
|
||||||
const LOCK_INTERVAL_IMMEDIATE = 1;
|
const LOCK_INTERVAL_IMMEDIATE = 1;
|
||||||
const LOCK_INTERVAL_ONE_MINUTE = 60 * MILLISECONDS_PER_SECOND;
|
const LOCK_INTERVAL_ONE_MINUTE = 60 * MILLISECONDS_PER_SECOND;
|
||||||
@@ -15,37 +13,21 @@ const STORAGE_KEY_AUTOLOCK_INTERVAL = "AutoLockIntervalKey";
|
|||||||
|
|
||||||
export class AutolockService extends ApplicationService {
|
export class AutolockService extends ApplicationService {
|
||||||
|
|
||||||
private unsubState?: () => void;
|
private pollInterval: any
|
||||||
private pollFocusInterval: any
|
|
||||||
private lastFocusState?: 'hidden' | 'visible'
|
private lastFocusState?: 'hidden' | 'visible'
|
||||||
private lockAfterDate?: Date
|
private lockAfterDate?: Date
|
||||||
private lockTimeout?: any
|
|
||||||
|
|
||||||
onAppLaunch() {
|
onAppLaunch() {
|
||||||
this.observeVisibility();
|
if (!isDesktopApplication()) {
|
||||||
|
this.beginPolling();
|
||||||
|
}
|
||||||
return super.onAppLaunch();
|
return super.onAppLaunch();
|
||||||
}
|
}
|
||||||
|
|
||||||
observeVisibility() {
|
|
||||||
this.unsubState = (this.application as WebApplication).getAppState().addObserver(
|
|
||||||
async (eventName) => {
|
|
||||||
if (eventName === AppStateEvent.WindowDidBlur) {
|
|
||||||
this.documentVisibilityChanged(false);
|
|
||||||
} else if (eventName === AppStateEvent.WindowDidFocus) {
|
|
||||||
this.documentVisibilityChanged(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!isDesktopApplication()) {
|
|
||||||
this.beginWebFocusPolling();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit() {
|
deinit() {
|
||||||
this.unsubState?.();
|
|
||||||
this.cancelAutoLockTimer();
|
this.cancelAutoLockTimer();
|
||||||
if (this.pollFocusInterval) {
|
if (this.pollInterval) {
|
||||||
clearInterval(this.pollFocusInterval);
|
clearInterval(this.pollInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,11 +67,15 @@ export class AutolockService extends ApplicationService {
|
|||||||
* Verify document is in focus every so often as visibilitychange event is
|
* Verify document is in focus every so often as visibilitychange event is
|
||||||
* not triggered on a typical window blur event but rather on tab changes.
|
* not triggered on a typical window blur event but rather on tab changes.
|
||||||
*/
|
*/
|
||||||
beginWebFocusPolling() {
|
beginPolling() {
|
||||||
this.pollFocusInterval = setInterval(() => {
|
this.pollInterval = setInterval(async () => {
|
||||||
if (document.hidden) {
|
const locked = await this.application.isLocked();
|
||||||
/** Native event listeners will have fired */
|
if (
|
||||||
return;
|
!locked &&
|
||||||
|
this.lockAfterDate &&
|
||||||
|
new Date() > this.lockAfterDate
|
||||||
|
) {
|
||||||
|
this.lockApplication();
|
||||||
}
|
}
|
||||||
const hasFocus = document.hasFocus();
|
const hasFocus = document.hasFocus();
|
||||||
if (hasFocus && this.lastFocusState === 'hidden') {
|
if (hasFocus && this.lastFocusState === 'hidden') {
|
||||||
@@ -99,7 +85,7 @@ export class AutolockService extends ApplicationService {
|
|||||||
}
|
}
|
||||||
/* Save this to compare against next time around */
|
/* Save this to compare against next time around */
|
||||||
this.lastFocusState = hasFocus ? 'visible' : 'hidden';
|
this.lastFocusState = hasFocus ? 'visible' : 'hidden';
|
||||||
}, FOCUS_POLL_INTERVAL);
|
}, POLL_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAutoLockIntervalOptions() {
|
getAutoLockIntervalOptions() {
|
||||||
@@ -129,14 +115,6 @@ export class AutolockService extends ApplicationService {
|
|||||||
|
|
||||||
async documentVisibilityChanged(visible: boolean) {
|
async documentVisibilityChanged(visible: boolean) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
const locked = await this.application.isLocked();
|
|
||||||
if (
|
|
||||||
!locked &&
|
|
||||||
this.lockAfterDate &&
|
|
||||||
new Date() > this.lockAfterDate
|
|
||||||
) {
|
|
||||||
this.lockApplication();
|
|
||||||
}
|
|
||||||
this.cancelAutoLockTimer();
|
this.cancelAutoLockTimer();
|
||||||
} else {
|
} else {
|
||||||
this.beginAutoLockTimer();
|
this.beginAutoLockTimer();
|
||||||
@@ -148,29 +126,15 @@ export class AutolockService extends ApplicationService {
|
|||||||
if (interval === LOCK_INTERVAL_NONE) {
|
if (interval === LOCK_INTERVAL_NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Use a timeout if possible, but if the computer is put to sleep, timeouts won't
|
|
||||||
* work. Need to set a date as backup. this.lockAfterDate does not need to be
|
|
||||||
* persisted, as living in memory is sufficient. If memory is cleared, then the
|
|
||||||
* application will lock anyway.
|
|
||||||
*/
|
|
||||||
const addToNow = (seconds: number) => {
|
const addToNow = (seconds: number) => {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
date.setSeconds(date.getSeconds() + seconds);
|
date.setSeconds(date.getSeconds() + seconds);
|
||||||
return date;
|
return date;
|
||||||
};
|
};
|
||||||
this.lockAfterDate = addToNow(interval / MILLISECONDS_PER_SECOND);
|
this.lockAfterDate = addToNow(interval / MILLISECONDS_PER_SECOND);
|
||||||
clearTimeout(this.lockTimeout);
|
|
||||||
this.lockTimeout = setTimeout(() => {
|
|
||||||
this.cancelAutoLockTimer();
|
|
||||||
this.lockApplication();
|
|
||||||
this.lockAfterDate = undefined;
|
|
||||||
}, interval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelAutoLockTimer() {
|
cancelAutoLockTimer() {
|
||||||
clearTimeout(this.lockTimeout);
|
|
||||||
this.lockAfterDate = undefined;
|
this.lockAfterDate = undefined;
|
||||||
this.lockTimeout = undefined;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export class AppState {
|
|||||||
this.noAccountWarning.reset();
|
this.noAccountWarning.reset();
|
||||||
}
|
}
|
||||||
this.actionsMenu.reset();
|
this.actionsMenu.reset();
|
||||||
this.unsubApp();
|
this.unsubApp?.();
|
||||||
this.unsubApp = undefined;
|
this.unsubApp = undefined;
|
||||||
this.observers.length = 0;
|
this.observers.length = 0;
|
||||||
this.appEventObserverRemovers.forEach((remover) => remover());
|
this.appEventObserverRemovers.forEach((remover) => remover());
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ export class PureViewCtrl<P = CtrlProps, S = CtrlState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deinit(): void {
|
deinit(): void {
|
||||||
this.unsubApp();
|
this.unsubApp?.();
|
||||||
this.unsubState();
|
this.unsubState?.();
|
||||||
for (const disposer of this.reactionDisposers) {
|
for (const disposer of this.reactionDisposers) {
|
||||||
disposer();
|
disposer();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user