From 421216bf1bed699c194e9f8909ff90a0c187dda6 Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Mon, 13 Apr 2020 09:00:09 -0500 Subject: [PATCH] Desktop manager TS --- .../filters/{index.js => index.ts} | 0 app/assets/javascripts/filters/trusted.js | 6 - app/assets/javascripts/filters/trusted.ts | 6 + .../{alertService.js => alertService.ts} | 26 +- .../javascripts/services/archiveManager.js | 149 ----------- .../javascripts/services/archiveManager.ts | 154 +++++++++++ .../javascripts/services/desktopManager.js | 215 --------------- .../javascripts/services/desktopManager.ts | 245 ++++++++++++++++++ .../javascripts/services/themeManager.js | 4 +- app/assets/javascripts/typings/stylekit.d.ts | 1 + 10 files changed, 421 insertions(+), 385 deletions(-) rename app/assets/javascripts/filters/{index.js => index.ts} (100%) delete mode 100644 app/assets/javascripts/filters/trusted.js create mode 100644 app/assets/javascripts/filters/trusted.ts rename app/assets/javascripts/services/{alertService.js => alertService.ts} (74%) delete mode 100644 app/assets/javascripts/services/archiveManager.js create mode 100644 app/assets/javascripts/services/archiveManager.ts delete mode 100644 app/assets/javascripts/services/desktopManager.js create mode 100644 app/assets/javascripts/services/desktopManager.ts create mode 100644 app/assets/javascripts/typings/stylekit.d.ts diff --git a/app/assets/javascripts/filters/index.js b/app/assets/javascripts/filters/index.ts similarity index 100% rename from app/assets/javascripts/filters/index.js rename to app/assets/javascripts/filters/index.ts diff --git a/app/assets/javascripts/filters/trusted.js b/app/assets/javascripts/filters/trusted.js deleted file mode 100644 index 3ebbd7c96..000000000 --- a/app/assets/javascripts/filters/trusted.js +++ /dev/null @@ -1,6 +0,0 @@ -/* @ngInject */ -export function trusted($sce) { - return function(url) { - return $sce.trustAsResourceUrl(url); - }; -} diff --git a/app/assets/javascripts/filters/trusted.ts b/app/assets/javascripts/filters/trusted.ts new file mode 100644 index 000000000..43d77d16b --- /dev/null +++ b/app/assets/javascripts/filters/trusted.ts @@ -0,0 +1,6 @@ +/* @ngInject */ +export function trusted($sce: ng.ISCEService) { + return function(url: string) { + return $sce.trustAsResourceUrl(url); + }; +} diff --git a/app/assets/javascripts/services/alertService.js b/app/assets/javascripts/services/alertService.ts similarity index 74% rename from app/assets/javascripts/services/alertService.js rename to app/assets/javascripts/services/alertService.ts index 55eaf5899..a35fe3102 100644 --- a/app/assets/javascripts/services/alertService.js +++ b/app/assets/javascripts/services/alertService.ts @@ -4,10 +4,10 @@ import { SKAlert } from 'sn-stylekit'; export class AlertService extends SNAlertService { async alert( - title, - text, - closeButtonText = "OK", - onClose + title: string, + text: string, + closeButtonText = 'OK', + onClose: () => void ) { return new Promise((resolve) => { const buttons = [ @@ -16,7 +16,7 @@ export class AlertService extends SNAlertService { style: "neutral", action: async () => { if (onClose) { - this.deviceInterface.timeout(onClose); + this.deviceInterface!.timeout(onClose); } resolve(true); } @@ -28,12 +28,12 @@ export class AlertService extends SNAlertService { } async confirm( - title, - text, - confirmButtonText = "Confirm", - cancelButtonText = "Cancel", - onConfirm, - onCancel, + title: string, + text: string, + confirmButtonText = 'Confirm', + cancelButtonText = 'Cancel', + onConfirm: () => void, + onCancel: () => void, destructive = false ) { return new Promise((resolve, reject) => { @@ -43,7 +43,7 @@ export class AlertService extends SNAlertService { style: "neutral", action: async () => { if (onCancel) { - this.deviceInterface.timeout(onCancel); + this.deviceInterface!.timeout(onCancel); } reject(false); } @@ -53,7 +53,7 @@ export class AlertService extends SNAlertService { style: destructive ? "danger" : "info", action: async () => { if (onConfirm) { - this.deviceInterface.timeout(onConfirm); + this.deviceInterface!.timeout(onConfirm); } resolve(true); } diff --git a/app/assets/javascripts/services/archiveManager.js b/app/assets/javascripts/services/archiveManager.js deleted file mode 100644 index 1e5d503a5..000000000 --- a/app/assets/javascripts/services/archiveManager.js +++ /dev/null @@ -1,149 +0,0 @@ -import { EncryptionIntents, ProtectedAction } from 'snjs'; - -export class ArchiveManager { - constructor(application) { - this.application = application; - } - - /** @public */ - async downloadBackup(encrypted) { - return this.downloadBackupOfItems(this.application.modelManager.allItems, encrypted); - } - - /** @public */ - async downloadBackupOfItems(items, encrypted) { - const run = async () => { - // download in Standard Notes format - const intent = encrypted - ? EncryptionIntents.FileEncrypted - : EncryptionIntents.FileDecrypted; - this.itemsData(items, intent).then((data) => { - const modifier = encrypted ? "Encrypted" : "Decrypted"; - this.downloadData( - data, - `Standard Notes ${modifier} Backup - ${this.formattedDate()}.txt` - ); - // download as zipped plain text files - if (!encrypted) { - this.downloadZippedItems(items); - } - }); - }; - - if (await this.application.privilegesService.actionRequiresPrivilege(ProtectedAction.ManageBackups)) { - this.application.presentPrivilegesModal(ProtectedAction.ManageBackups, () => { - run(); - }); - } else { - run(); - } - } - - /** @private */ - formattedDate() { - var string = `${new Date()}`; - // Match up to the first parenthesis, i.e do not include '(Central Standard Time)' - var matches = string.match(/^(.*?) \(/); - if (matches.length >= 2) { - return matches[1]; - } - return string; - } - - /** @private */ - async itemsData(items, intent) { - const data = await this.application.createBackupFile({ - subItems: items, - intent: intent - }); - const blobData = new Blob([data], { type: 'text/json' }); - return blobData; - } - - /** @private */ - async loadZip() { - if (window.zip) { - return; - } - - var scriptTag = document.createElement('script'); - scriptTag.src = "/assets/zip/zip.js"; - scriptTag.async = false; - var headTag = document.getElementsByTagName('head')[0]; - headTag.appendChild(scriptTag); - return new Promise((resolve, reject) => { - scriptTag.onload = function () { - zip.workerScriptsPath = "assets/zip/"; - resolve(); - }; - }); - } - - /** @private */ - async downloadZippedItems(items) { - await this.loadZip(); - zip.createWriter(new zip.BlobWriter("application/zip"), (zipWriter) => { - var index = 0; - - const nextFile = () => { - var item = items[index]; - var name, contents; - - if (item.content_type === "Note") { - name = item.content.title; - contents = item.content.text; - } else { - name = item.content_type; - contents = JSON.stringify(item.content, null, 2); - } - - if (!name) { - name = ""; - } - - const blob = new Blob([contents], { type: 'text/plain' }); - let filePrefix = name.replace(/\//g, "").replace(/\\+/g, ""); - const fileSuffix = `-${item.uuid.split("-")[0]}.txt`; - // Standard max filename length is 255. Slice the note name down to allow filenameEnd - filePrefix = filePrefix.slice(0, (255 - fileSuffix.length)); - const fileName = `${item.content_type}/${filePrefix}${fileSuffix}`; - zipWriter.add(fileName, new zip.BlobReader(blob), () => { - index++; - if (index < items.length) { - nextFile(); - } else { - zipWriter.close((blob) => { - this.downloadData(blob, `Standard Notes Backup - ${this.formattedDate()}.zip`); - zipWriter = null; - }); - } - }); - }; - - nextFile(); - }, onerror); - } - - - /** @private */ - hrefForData(data) { - // If we are replacing a previously generated file we need to - // manually revoke the object URL to avoid memory leaks. - if (this.textFile !== null) { - window.URL.revokeObjectURL(this.textFile); - } - this.textFile = window.URL.createObjectURL(data); - // returns a URL you can use as a href - return this.textFile; - } - - /** @private */ - downloadData(data, fileName) { - var link = document.createElement('a'); - link.setAttribute('download', fileName); - link.href = this.hrefForData(data); - document.body.appendChild(link); - link.click(); - link.remove(); - } -} diff --git a/app/assets/javascripts/services/archiveManager.ts b/app/assets/javascripts/services/archiveManager.ts new file mode 100644 index 000000000..2a53ad02b --- /dev/null +++ b/app/assets/javascripts/services/archiveManager.ts @@ -0,0 +1,154 @@ +import { WebApplication } from '@/application'; +import { EncryptionIntent, ProtectedAction, SNItem, ContentType, SNNote } from 'snjs'; + +export class ArchiveManager { + + private readonly application: WebApplication + private textFile?: string + + constructor(application: WebApplication) { + this.application = application; + } + + public async downloadBackup(encrypted: boolean) { + return this.downloadBackupOfItems(this.application.allItems(), encrypted); + } + + public async downloadBackupOfItems(items: SNItem[], encrypted: boolean) { + const run = async () => { + // download in Standard Notes format + const intent = encrypted + ? EncryptionIntent.FileEncrypted + : EncryptionIntent.FileDecrypted; + this.itemsData(items, intent).then((data) => { + const modifier = encrypted ? 'Encrypted' : 'Decrypted'; + this.downloadData( + data!, + `Standard Notes ${modifier} Backup - ${this.formattedDate()}.txt` + ); + // download as zipped plain text files + if (!encrypted) { + this.downloadZippedItems(items); + } + }); + }; + + if ( + await this.application.privilegesService! + .actionRequiresPrivilege(ProtectedAction.ManageBackups) + ) { + this.application.presentPrivilegesModal( + ProtectedAction.ManageBackups, + () => { + run(); + }); + } else { + run(); + } + } + + private formattedDate() { + const string = `${new Date()}`; + // Match up to the first parenthesis, i.e do not include '(Central Standard Time)' + const matches = string.match(/^(.*?) \(/); + if (matches && matches.length >= 2) { + return matches[1]; + } + return string; + } + + private async itemsData(items: SNItem[], intent: EncryptionIntent) { + const data = await this.application.createBackupFile(items, intent); + if (!data) { + return undefined; + } + const blobData = new Blob([data], { type: 'text/json' }); + return blobData; + } + + private get zip() { + return (window as any).zip; + } + + private async loadZip() { + if (this.zip) { + return; + } + const scriptTag = document.createElement('script'); + scriptTag.src = '/assets/zip/zip.js'; + scriptTag.async = false; + const headTag = document.getElementsByTagName('head')[0]; + headTag.appendChild(scriptTag); + return new Promise((resolve) => { + scriptTag.onload = () => { + this.zip.workerScriptsPath = 'assets/zip/'; + resolve(); + }; + }); + } + + private async downloadZippedItems(items: SNItem[]) { + await this.loadZip(); + this.zip.createWriter( + new this.zip.BlobWriter('application/zip'), + (zipWriter: any) => { + let index = 0; + const nextFile = () => { + const item = items[index]; + let name, contents; + if (item.content_type === ContentType.Note) { + const note = item as SNNote; + name = note.title; + contents = note.text; + } else { + name = item.content_type; + contents = JSON.stringify(item.content, null, 2); + } + if (!name) { + name = ''; + } + const blob = new Blob([contents], { type: 'text/plain' }); + let filePrefix = name.replace(/\//g, '').replace(/\\+/g, ''); + const fileSuffix = `-${item.uuid.split('-')[0]}.txt`; + // Standard max filename length is 255. Slice the note name down to allow filenameEnd + filePrefix = filePrefix.slice(0, (255 - fileSuffix.length)); + const fileName = `${item.content_type}/${filePrefix}${fileSuffix}`; + zipWriter.add(fileName, new this.zip.BlobReader(blob), () => { + index++; + if (index < items.length) { + nextFile(); + } else { + zipWriter.close((blob: any) => { + this.downloadData( + blob, + `Standard Notes Backup - ${this.formattedDate()}.zip` + ); + zipWriter = null; + }); + } + }); + }; + nextFile(); + }, onerror); + } + + private hrefForData(data: Blob) { + // If we are replacing a previously generated file we need to + // manually revoke the object URL to avoid memory leaks. + if (this.textFile) { + window.URL.revokeObjectURL(this.textFile); + } + this.textFile = window.URL.createObjectURL(data); + // returns a URL you can use as a href + return this.textFile; + } + + private downloadData(data: Blob, fileName: string) { + const link = document.createElement('a'); + link.setAttribute('download', fileName); + link.href = this.hrefForData(data); + document.body.appendChild(link); + link.click(); + link.remove(); + } +} diff --git a/app/assets/javascripts/services/desktopManager.js b/app/assets/javascripts/services/desktopManager.js deleted file mode 100644 index e84411d35..000000000 --- a/app/assets/javascripts/services/desktopManager.js +++ /dev/null @@ -1,215 +0,0 @@ -/* eslint-disable camelcase */ -// An interface used by the Desktop app to interact with SN -import { isDesktopApplication } from '@/utils'; -import { EncryptionIntents, ApplicationService, ApplicationEvent, removeFromArray } from 'snjs'; - -const COMPONENT_DATA_KEY_INSTALL_ERROR = 'installError'; -const COMPONENT_CONTENT_KEY_PACKAGE_INFO = 'package_info'; -const COMPONENT_CONTENT_KEY_LOCAL_URL = 'local_url'; - -export class DesktopManager extends ApplicationService { - constructor( - $rootScope, - $timeout, - application - ) { - super(application); - this.$rootScope = $rootScope; - this.$timeout = $timeout; - this.componentActivationObservers = []; - this.updateObservers = []; - this.isDesktop = isDesktopApplication(); - } - - deinit() { - this.componentActivationObservers.length = 0; - this.updateObservers.length = 0; - super.deinit(); - } - - /** @override */ - onAppEvent(eventName) { - super.onAppEvent(eventName); - if (eventName === ApplicationEvent.LocalDataLoaded) { - this.dataLoaded = true; - if (this.dataLoadHandler) { - this.dataLoadHandler(); - } - } else if (eventName === ApplicationEvent.MajorDataChange) { - if (this.majorDataChangeHandler) { - this.majorDataChangeHandler(); - } - } - } - - saveBackup() { - this.majorDataChangeHandler && this.majorDataChangeHandler(); - } - - getExtServerHost() { - console.assert( - this.extServerHost, - 'extServerHost is null' - ); - return this.extServerHost; - } - - /** - * Sending a component in its raw state is really slow for the desktop app - * Keys are not passed into ItemParams, so the result is not encrypted - */ - async convertComponentForTransmission(component) { - return this.application.protocolService.payloadByEncryptingPayload({ - payload: component.payloadRepresentation(), - intent: EncryptionIntents.FileDecrypted - }); - } - - // All `components` should be installed - syncComponentsInstallation(components) { - if (!this.isDesktop) { - return; - } - Promise.all(components.map((component) => { - return this.convertComponentForTransmission(component); - })).then((data) => { - this.installationSyncHandler(data); - }); - } - - async installComponent(component) { - this.installComponentHandler( - await this.convertComponentForTransmission(component) - ); - } - - registerUpdateObserver(callback) { - const observer = { - callback: callback - }; - this.updateObservers.push(observer); - return () => { - removeFromArray(this.updateObservers, observer); - }; - } - - searchText(text) { - if (!this.isDesktop) { - return; - } - this.lastSearchedText = text; - this.searchHandler && this.searchHandler(text); - } - - redoSearch() { - if (this.lastSearchedText) { - this.searchText(this.lastSearchedText); - } - } - - // Pass null to cancel search - desktop_setSearchHandler(handler) { - this.searchHandler = handler; - } - - desktop_windowGainedFocus() { - this.$rootScope.$broadcast('window-gained-focus'); - } - - desktop_windowLostFocus() { - this.$rootScope.$broadcast('window-lost-focus'); - } - - async desktop_onComponentInstallationComplete(componentData, error) { - const component = await this.application.findItem({ uuid: componentData.uuid }); - if (!component) { - return; - } - if (error) { - component.setAppDataItem( - COMPONENT_DATA_KEY_INSTALL_ERROR, - error - ); - } else { - const permissableKeys = [ - COMPONENT_CONTENT_KEY_PACKAGE_INFO, - COMPONENT_CONTENT_KEY_LOCAL_URL - ]; - for (const key of permissableKeys) { - component[key] = componentData.content[key]; - } - component.setAppDataItem( - COMPONENT_DATA_KEY_INSTALL_ERROR, - null - ); - } - this.application.saveItem({ item: component }); - this.$timeout(() => { - for (const observer of this.updateObservers) { - observer.callback(component); - } - }); - } - - desktop_registerComponentActivationObserver(callback) { - const observer = { id: Math.random, callback: callback }; - this.componentActivationObservers.push(observer); - return observer; - } - - desktop_deregisterComponentActivationObserver(observer) { - removeFromArray(this.componentActivationObservers, observer); - } - - /* Notify observers that a component has been registered/activated */ - async notifyComponentActivation(component) { - const serializedComponent = await this.convertComponentForTransmission( - component - ); - this.$timeout(() => { - for (const observer of this.componentActivationObservers) { - observer.callback(serializedComponent); - } - }); - } - - /* Used to resolve 'sn://' */ - desktop_setExtServerHost(host) { - this.extServerHost = host; - this.application.getAppState().desktopExtensionsReady(); - } - - desktop_setComponentInstallationSyncHandler(handler) { - this.installationSyncHandler = handler; - } - - desktop_setInstallComponentHandler(handler) { - this.installComponentHandler = handler; - } - - desktop_setInitialDataLoadHandler(handler) { - this.dataLoadHandler = handler; - if (this.dataLoaded) { - this.dataLoadHandler(); - } - } - - async desktop_requestBackupFile(callback) { - const data = await this.application.createBackupFile({ - returnIfEmpty: true - }); - callback(data); - } - - desktop_setMajorDataChangeHandler(handler) { - this.majorDataChangeHandler = handler; - } - - desktop_didBeginBackup() { - this.application.getAppState().beganBackupDownload(); - } - - desktop_didFinishBackup(success) { - this.application.getAppState().endedBackupDownload(success); - } -} diff --git a/app/assets/javascripts/services/desktopManager.ts b/app/assets/javascripts/services/desktopManager.ts new file mode 100644 index 000000000..ba7f0f7e4 --- /dev/null +++ b/app/assets/javascripts/services/desktopManager.ts @@ -0,0 +1,245 @@ +import { SNComponent, PurePayload } from 'snjs'; +/* eslint-disable camelcase */ +import { WebApplication } from '@/application'; +// An interface used by the Desktop app to interact with SN +import { isDesktopApplication } from '@/utils'; +import { EncryptionIntent, ApplicationService, ApplicationEvent, removeFromArray } from 'snjs'; +import { ComponentMutator } from '@/../../../../snjs/dist/@types/models'; +import { AppDataField } from '@/../../../../snjs/dist/@types/models/core/item'; + +type UpdateObserverCallback = (component: SNComponent) => void +type ComponentActivationCallback = (payload: PurePayload) => void +type ComponentActivationObserver = { + id: string, + callback: ComponentActivationCallback +} + +export class DesktopManager extends ApplicationService { + + $rootScope: ng.IRootScopeService + $timeout: ng.ITimeoutService + componentActivationObservers: ComponentActivationObserver[] = [] + updateObservers: { + callback: UpdateObserverCallback + }[] = [] + isDesktop = isDesktopApplication(); + + dataLoaded = false + dataLoadHandler?: () => void + majorDataChangeHandler?: () => void + extServerHost?: string + installationSyncHandler?: (payloads: PurePayload[]) => void + installComponentHandler?: (payload: PurePayload) => void + lastSearchedText?: string + searchHandler?: (text: string) => void + + constructor( + $rootScope: ng.IRootScopeService, + $timeout: ng.ITimeoutService, + application: WebApplication + ) { + super(application); + this.$rootScope = $rootScope; + this.$timeout = $timeout; + } + + get webApplication() { + return this.application as WebApplication; + } + + deinit() { + this.componentActivationObservers.length = 0; + this.updateObservers.length = 0; + super.deinit(); + } + + async onAppEvent(eventName: ApplicationEvent) { + super.onAppEvent(eventName); + if (eventName === ApplicationEvent.LocalDataLoaded) { + this.dataLoaded = true; + if (this.dataLoadHandler) { + this.dataLoadHandler(); + } + } else if (eventName === ApplicationEvent.MajorDataChange) { + if (this.majorDataChangeHandler) { + this.majorDataChangeHandler(); + } + } + } + + saveBackup() { + this.majorDataChangeHandler && this.majorDataChangeHandler(); + } + + getExtServerHost() { + console.assert( + this.extServerHost, + 'extServerHost is null' + ); + return this.extServerHost; + } + + /** + * Sending a component in its raw state is really slow for the desktop app + * Keys are not passed into ItemParams, so the result is not encrypted + */ + async convertComponentForTransmission(component: SNComponent) { + return this.application!.protocolService!.payloadByEncryptingPayload( + component.payloadRepresentation(), + EncryptionIntent.FileDecrypted + ); + } + + // All `components` should be installed + syncComponentsInstallation(components: SNComponent[]) { + if (!this.isDesktop) { + return; + } + Promise.all(components.map((component) => { + return this.convertComponentForTransmission(component); + })).then((payloads) => { + this.installationSyncHandler!(payloads); + }); + } + + async installComponent(component: SNComponent) { + this.installComponentHandler!( + await this.convertComponentForTransmission(component) + ); + } + + registerUpdateObserver(callback: UpdateObserverCallback) { + const observer = { + callback: callback + }; + this.updateObservers.push(observer); + return () => { + removeFromArray(this.updateObservers, observer); + }; + } + + searchText(text: string) { + if (!this.isDesktop) { + return; + } + this.lastSearchedText = text; + this.searchHandler && this.searchHandler(text); + } + + redoSearch() { + if (this.lastSearchedText) { + this.searchText(this.lastSearchedText); + } + } + + // Pass null to cancel search + desktop_setSearchHandler(handler: (text: string) => void) { + this.searchHandler = handler; + } + + desktop_windowGainedFocus() { + this.$rootScope.$broadcast('window-gained-focus'); + } + + desktop_windowLostFocus() { + this.$rootScope.$broadcast('window-lost-focus'); + } + + async desktop_onComponentInstallationComplete( + componentData: any, + error: any + ) { + const component = this.application!.findItem(componentData.uuid); + if (!component) { + return; + } + const updatedComponent = await this.application!.changeAndSaveItem( + component.uuid, + (m) => { + const mutator = m as ComponentMutator; + if (error) { + mutator.setAppDataItem( + AppDataField.ComponentInstallError, + error + ); + } else { + mutator.local_url = componentData.content.local_url; + mutator.package_info = componentData.content.package_info; + mutator.setAppDataItem( + AppDataField.ComponentInstallError, + undefined + ); + } + }) + + this.$timeout(() => { + for (const observer of this.updateObservers) { + observer.callback(updatedComponent as SNComponent); + } + }); + } + + desktop_registerComponentActivationObserver(callback: ComponentActivationCallback) { + const observer = { id: `${Math.random}`, callback: callback }; + this.componentActivationObservers.push(observer); + return observer; + } + + desktop_deregisterComponentActivationObserver(observer: ComponentActivationObserver) { + removeFromArray(this.componentActivationObservers, observer); + } + + /* Notify observers that a component has been registered/activated */ + async notifyComponentActivation(component: SNComponent) { + const serializedComponent = await this.convertComponentForTransmission( + component + ); + this.$timeout(() => { + for (const observer of this.componentActivationObservers) { + observer.callback(serializedComponent); + } + }); + } + + /* Used to resolve 'sn://' */ + desktop_setExtServerHost(host: string) { + this.extServerHost = host; + this.webApplication.getAppState().desktopExtensionsReady(); + } + + desktop_setComponentInstallationSyncHandler(handler: (payloads: PurePayload[]) => void) { + this.installationSyncHandler = handler; + } + + desktop_setInstallComponentHandler(handler: (payload: PurePayload) => void) { + this.installComponentHandler = handler; + } + + desktop_setInitialDataLoadHandler(handler: () => void) { + this.dataLoadHandler = handler; + if (this.dataLoaded) { + this.dataLoadHandler(); + } + } + + async desktop_requestBackupFile(callback: (data: any) => void) { + const data = await this.application!.createBackupFile( + undefined, + undefined, + true + ); + callback(data); + } + + desktop_setMajorDataChangeHandler(handler: () => void) { + this.majorDataChangeHandler = handler; + } + + desktop_didBeginBackup() { + this.webApplication.getAppState().beganBackupDownload(); + } + + desktop_didFinishBackup(success: boolean) { + this.webApplication.getAppState().endedBackupDownload(success); + } +} diff --git a/app/assets/javascripts/services/themeManager.js b/app/assets/javascripts/services/themeManager.js index fdc01924d..69b3eb746 100644 --- a/app/assets/javascripts/services/themeManager.js +++ b/app/assets/javascripts/services/themeManager.js @@ -2,7 +2,7 @@ import _ from 'lodash'; import { ApplicationEvent, StorageValueModes, - EncryptionIntents, + EncryptionIntent, ApplicationService, } from 'snjs'; import { AppStateEvent } from '@/services/state'; @@ -123,7 +123,7 @@ export class ThemeManager extends ApplicationService { const payload = theme.payloadRepresentation(); const processedPayload = await this.application.protocolService.payloadByEncryptingPayload({ payload: payload, - intent: EncryptionIntents.LocalStorageDecrypted + intent: EncryptionIntent.LocalStorageDecrypted }); return processedPayload; })); diff --git a/app/assets/javascripts/typings/stylekit.d.ts b/app/assets/javascripts/typings/stylekit.d.ts new file mode 100644 index 000000000..b7950135e --- /dev/null +++ b/app/assets/javascripts/typings/stylekit.d.ts @@ -0,0 +1 @@ +declare module "sn-stylekit"; \ No newline at end of file