Files
standardnotes-app-web/app/assets/javascripts/services/autolock_service.ts
2022-02-08 10:32:28 -06:00

132 lines
3.3 KiB
TypeScript

import { ApplicationService } from '@standardnotes/snjs';
const MILLISECONDS_PER_SECOND = 1000;
const POLL_INTERVAL = 50;
const LockInterval = {
None: 0,
Immediate: 1,
OneMinute: 60 * MILLISECONDS_PER_SECOND,
FiveMinutes: 300 * MILLISECONDS_PER_SECOND,
OneHour: 3600 * MILLISECONDS_PER_SECOND,
};
const STORAGE_KEY_AUTOLOCK_INTERVAL = 'AutoLockIntervalKey';
export class AutolockService extends ApplicationService {
private pollInterval: any;
private lastFocusState?: 'hidden' | 'visible';
private lockAfterDate?: Date;
onAppLaunch() {
this.beginPolling();
return super.onAppLaunch();
}
deinit() {
this.cancelAutoLockTimer();
if (this.pollInterval) {
clearInterval(this.pollInterval);
}
super.deinit();
}
private lockApplication() {
if (!this.application.hasPasscode()) {
throw Error('Attempting to lock application with no passcode');
}
this.application.lock();
}
async setAutoLockInterval(interval: number) {
return this.application.setValue(STORAGE_KEY_AUTOLOCK_INTERVAL, interval);
}
async getAutoLockInterval() {
const interval = (await this.application.getValue(
STORAGE_KEY_AUTOLOCK_INTERVAL
)) as number;
if (interval) {
return interval;
} else {
return LockInterval.None;
}
}
async deleteAutolockPreference() {
await this.application.removeValue(STORAGE_KEY_AUTOLOCK_INTERVAL);
this.cancelAutoLockTimer();
}
/**
* 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.
*/
beginPolling() {
this.pollInterval = setInterval(async () => {
const locked = await this.application.isLocked();
if (!locked && this.lockAfterDate && new Date() > this.lockAfterDate) {
this.lockApplication();
}
const hasFocus = document.hasFocus();
if (hasFocus && this.lastFocusState === 'hidden') {
this.documentVisibilityChanged(true);
} else if (!hasFocus && this.lastFocusState === 'visible') {
this.documentVisibilityChanged(false);
}
/* Save this to compare against next time around */
this.lastFocusState = hasFocus ? 'visible' : 'hidden';
}, POLL_INTERVAL);
}
getAutoLockIntervalOptions() {
return [
{
value: LockInterval.None,
label: 'Off',
},
{
value: LockInterval.Immediate,
label: 'Immediately',
},
{
value: LockInterval.OneMinute,
label: '1m',
},
{
value: LockInterval.FiveMinutes,
label: '5m',
},
{
value: LockInterval.OneHour,
label: '1h',
},
];
}
async documentVisibilityChanged(visible: boolean) {
if (visible) {
this.cancelAutoLockTimer();
} else {
this.beginAutoLockTimer();
}
}
async beginAutoLockTimer() {
const interval = await this.getAutoLockInterval();
if (interval === LockInterval.None) {
return;
}
const addToNow = (seconds: number) => {
const date = new Date();
date.setSeconds(date.getSeconds() + seconds);
return date;
};
this.lockAfterDate = addToNow(interval / MILLISECONDS_PER_SECOND);
}
cancelAutoLockTimer() {
this.lockAfterDate = undefined;
}
}