Files
standardnotes-app-web/app/assets/javascripts/Services/AutolockService.ts
2022-04-13 22:02:34 +05:30

130 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
override onAppLaunch() {
this.beginPolling()
return super.onAppLaunch()
}
override 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().catch(console.error)
}
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).catch(console.error)
} else if (!hasFocus && this.lastFocusState === 'visible') {
this.documentVisibilityChanged(false).catch(console.error)
}
/* 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().catch(console.error)
}
}
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
}
}