refactor: improve device interface types (#996)
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* This file will be imported by desktop, so we make sure imports are carrying
|
||||
* as little extra code as possible with them.
|
||||
*/
|
||||
import { Environment } from '@standardnotes/snjs'
|
||||
|
||||
export interface ElectronDesktopCallbacks {
|
||||
desktop_updateAvailable(): void
|
||||
desktop_windowGainedFocus(): void
|
||||
desktop_windowLostFocus(): void
|
||||
desktop_onComponentInstallationComplete(componentData: any, error: any): Promise<void>
|
||||
desktop_requestBackupFile(): Promise<string | undefined>
|
||||
desktop_didBeginBackup(): void
|
||||
desktop_didFinishBackup(success: boolean): void
|
||||
}
|
||||
|
||||
/** Platform-specific (i-e Electron/browser) behavior is handled by a Bridge object. */
|
||||
export interface Bridge {
|
||||
readonly appVersion: string
|
||||
environment: Environment
|
||||
|
||||
getKeychainValue(): Promise<unknown>
|
||||
setKeychainValue(value: unknown): Promise<void>
|
||||
clearKeychainValue(): Promise<void>
|
||||
|
||||
localBackupsCount(): Promise<number>
|
||||
viewlocalBackups(): void
|
||||
deleteLocalBackups(): Promise<void>
|
||||
|
||||
extensionsServerHost?: string
|
||||
syncComponents(payloads: unknown[]): void
|
||||
onMajorDataChange(): void
|
||||
onInitialDataLoad(): void
|
||||
onSignOut(): void
|
||||
onSearch(text?: string): void
|
||||
downloadBackup(): void | Promise<void>
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { Bridge } from './Bridge'
|
||||
import { Environment } from '@standardnotes/snjs'
|
||||
|
||||
const KEYCHAIN_STORAGE_KEY = 'keychain'
|
||||
|
||||
export class BrowserBridge implements Bridge {
|
||||
constructor(public appVersion: string) {}
|
||||
environment = Environment.Web
|
||||
|
||||
async getKeychainValue(): Promise<unknown> {
|
||||
const value = localStorage.getItem(KEYCHAIN_STORAGE_KEY)
|
||||
if (value) {
|
||||
return JSON.parse(value)
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
async setKeychainValue(value: unknown): Promise<void> {
|
||||
localStorage.setItem(KEYCHAIN_STORAGE_KEY, JSON.stringify(value))
|
||||
}
|
||||
|
||||
async clearKeychainValue(): Promise<void> {
|
||||
localStorage.removeItem(KEYCHAIN_STORAGE_KEY)
|
||||
}
|
||||
|
||||
async localBackupsCount(): Promise<number> {
|
||||
/** Browsers cannot save backups, only let you download one */
|
||||
return 0
|
||||
}
|
||||
|
||||
/** No-ops */
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
async deleteLocalBackups(): Promise<void> {}
|
||||
viewlocalBackups(): void {}
|
||||
syncComponents(): void {}
|
||||
onMajorDataChange(): void {}
|
||||
onInitialDataLoad(): void {}
|
||||
onSearch(): void {}
|
||||
downloadBackup(): void {}
|
||||
onSignOut(): void {}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable camelcase */
|
||||
import {
|
||||
SNComponent,
|
||||
ComponentMutator,
|
||||
@@ -8,27 +7,26 @@ import {
|
||||
removeFromArray,
|
||||
DesktopManagerInterface,
|
||||
InternalEventBus,
|
||||
DecryptedTransferPayload,
|
||||
ComponentContent,
|
||||
assert,
|
||||
} from '@standardnotes/snjs'
|
||||
import { WebAppEvent, WebApplication } from '@/UIModels/Application'
|
||||
import { isDesktopApplication } from '@/Utils'
|
||||
import { Bridge, ElectronDesktopCallbacks } from './Bridge'
|
||||
import { DesktopDeviceInterface } from '../Device/DesktopDeviceInterface'
|
||||
import { DesktopCommunicationReceiver } from '@/Device/DesktopWebCommunication'
|
||||
|
||||
/**
|
||||
* An interface used by the Desktop application to interact with SN
|
||||
*/
|
||||
export class DesktopManager
|
||||
extends ApplicationService
|
||||
implements DesktopManagerInterface, ElectronDesktopCallbacks
|
||||
implements DesktopManagerInterface, DesktopCommunicationReceiver
|
||||
{
|
||||
updateObservers: {
|
||||
callback: (component: SNComponent) => void
|
||||
}[] = []
|
||||
|
||||
isDesktop = isDesktopApplication()
|
||||
dataLoaded = false
|
||||
lastSearchedText?: string
|
||||
|
||||
constructor(application: WebApplication, private bridge: Bridge) {
|
||||
constructor(application: WebApplication, private device: DesktopDeviceInterface) {
|
||||
super(application, new InternalEventBus())
|
||||
}
|
||||
|
||||
@@ -45,19 +43,20 @@ export class DesktopManager
|
||||
super.onAppEvent(eventName).catch(console.error)
|
||||
if (eventName === ApplicationEvent.LocalDataLoaded) {
|
||||
this.dataLoaded = true
|
||||
this.bridge.onInitialDataLoad()
|
||||
this.device.onInitialDataLoad()
|
||||
} else if (eventName === ApplicationEvent.MajorDataChange) {
|
||||
this.bridge.onMajorDataChange()
|
||||
this.device.onMajorDataChange()
|
||||
}
|
||||
}
|
||||
|
||||
saveBackup() {
|
||||
this.bridge.onMajorDataChange()
|
||||
this.device.onMajorDataChange()
|
||||
}
|
||||
|
||||
getExtServerHost(): string {
|
||||
console.assert(!!this.bridge.extensionsServerHost, 'extServerHost is null')
|
||||
return this.bridge.extensionsServerHost as string
|
||||
assert(this.device.extensionsServerHost)
|
||||
|
||||
return this.device.extensionsServerHost
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,17 +69,13 @@ export class DesktopManager
|
||||
|
||||
// All `components` should be installed
|
||||
syncComponentsInstallation(components: SNComponent[]) {
|
||||
if (!this.isDesktop) {
|
||||
return
|
||||
}
|
||||
|
||||
Promise.all(
|
||||
components.map((component) => {
|
||||
return this.convertComponentForTransmission(component)
|
||||
}),
|
||||
)
|
||||
.then((payloads) => {
|
||||
this.bridge.syncComponents(payloads)
|
||||
this.device.syncComponents(payloads)
|
||||
})
|
||||
.catch(console.error)
|
||||
}
|
||||
@@ -96,11 +91,8 @@ export class DesktopManager
|
||||
}
|
||||
|
||||
searchText(text?: string) {
|
||||
if (!this.isDesktop) {
|
||||
return
|
||||
}
|
||||
this.lastSearchedText = text
|
||||
this.bridge.onSearch(text)
|
||||
this.device.onSearch(text)
|
||||
}
|
||||
|
||||
redoSearch() {
|
||||
@@ -109,23 +101,27 @@ export class DesktopManager
|
||||
}
|
||||
}
|
||||
|
||||
desktop_updateAvailable(): void {
|
||||
updateAvailable(): void {
|
||||
this.webApplication.notifyWebEvent(WebAppEvent.NewUpdateAvailable)
|
||||
}
|
||||
|
||||
desktop_windowGainedFocus(): void {
|
||||
windowGainedFocus(): void {
|
||||
this.webApplication.notifyWebEvent(WebAppEvent.DesktopWindowGainedFocus)
|
||||
}
|
||||
|
||||
desktop_windowLostFocus(): void {
|
||||
windowLostFocus(): void {
|
||||
this.webApplication.notifyWebEvent(WebAppEvent.DesktopWindowLostFocus)
|
||||
}
|
||||
|
||||
async desktop_onComponentInstallationComplete(componentData: any, error: any) {
|
||||
async onComponentInstallationComplete(
|
||||
componentData: DecryptedTransferPayload<ComponentContent>,
|
||||
error: unknown,
|
||||
) {
|
||||
const component = this.application.items.findItem(componentData.uuid)
|
||||
if (!component) {
|
||||
return
|
||||
}
|
||||
|
||||
const updatedComponent = await this.application.mutator.changeAndSaveItem(
|
||||
component,
|
||||
(m) => {
|
||||
@@ -133,7 +129,9 @@ export class DesktopManager
|
||||
if (error) {
|
||||
mutator.setAppDataItem(AppDataField.ComponentInstallError, error)
|
||||
} else {
|
||||
mutator.local_url = componentData.content.local_url
|
||||
// eslint-disable-next-line camelcase
|
||||
mutator.local_url = componentData.content.local_url as string
|
||||
// eslint-disable-next-line camelcase
|
||||
mutator.package_info = componentData.content.package_info
|
||||
mutator.setAppDataItem(AppDataField.ComponentInstallError, undefined)
|
||||
}
|
||||
@@ -146,7 +144,7 @@ export class DesktopManager
|
||||
}
|
||||
}
|
||||
|
||||
async desktop_requestBackupFile(): Promise<string | undefined> {
|
||||
async requestBackupFile(): Promise<string | undefined> {
|
||||
const encrypted = this.application.hasProtectionSources()
|
||||
const data = encrypted
|
||||
? await this.application.createEncryptedBackupFileForAutomatedDesktopBackups()
|
||||
@@ -159,11 +157,11 @@ export class DesktopManager
|
||||
return undefined
|
||||
}
|
||||
|
||||
desktop_didBeginBackup() {
|
||||
didBeginBackup() {
|
||||
this.webApplication.getAppState().beganBackupDownload()
|
||||
}
|
||||
|
||||
desktop_didFinishBackup(success: boolean) {
|
||||
didFinishBackup(success: boolean) {
|
||||
this.webApplication.getAppState().endedBackupDownload(success)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ const DefaultThemeIdentifier = 'Default'
|
||||
|
||||
export class ThemeManager extends ApplicationService {
|
||||
private activeThemes: UuidString[] = []
|
||||
private unregisterDesktop!: () => void
|
||||
private unregisterDesktop?: () => void
|
||||
private unregisterStream!: () => void
|
||||
private lastUseDeviceThemeSettings = false
|
||||
|
||||
@@ -91,10 +91,12 @@ export class ThemeManager extends ApplicationService {
|
||||
|
||||
override deinit() {
|
||||
this.activeThemes.length = 0
|
||||
this.unregisterDesktop()
|
||||
|
||||
this.unregisterDesktop?.()
|
||||
this.unregisterStream()
|
||||
;(this.unregisterDesktop as unknown) = undefined
|
||||
;(this.unregisterStream as unknown) = undefined
|
||||
|
||||
window
|
||||
.matchMedia('(prefers-color-scheme: dark)')
|
||||
.removeEventListener('change', this.colorSchemeEventHandler)
|
||||
@@ -212,7 +214,7 @@ export class ThemeManager extends ApplicationService {
|
||||
private registerObservers() {
|
||||
this.unregisterDesktop = this.webApplication
|
||||
.getDesktopService()
|
||||
.registerUpdateObserver((component) => {
|
||||
?.registerUpdateObserver((component) => {
|
||||
if (component.active && component.isTheme()) {
|
||||
this.deactivateTheme(component.uuid)
|
||||
setTimeout(() => {
|
||||
|
||||
Reference in New Issue
Block a user