feature: add platform layer
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
declare const __VERSION__: string
|
||||
declare const __VERSION__: string;
|
||||
declare const __PLATFORM_WEB__: boolean;
|
||||
|
||||
import angular from 'angular';
|
||||
import { configRoutes } from './routes';
|
||||
@@ -50,74 +51,84 @@ import {
|
||||
|
||||
import { trusted } from './filters';
|
||||
import { isDev } from './utils';
|
||||
import { Platform, WebPlatform } from './services/platform';
|
||||
|
||||
angular.module('app', ['ngSanitize']);
|
||||
|
||||
// Config
|
||||
angular
|
||||
.module('app')
|
||||
.config(configRoutes)
|
||||
.constant('appVersion', __VERSION__);
|
||||
|
||||
// Controllers
|
||||
angular
|
||||
.module('app')
|
||||
.directive('applicationGroupView', () => new ApplicationGroupView())
|
||||
.directive('applicationView', () => new ApplicationView())
|
||||
.directive('editorGroupView', () => new EditorGroupView())
|
||||
.directive('editorView', () => new EditorView())
|
||||
.directive('tagsView', () => new TagsView())
|
||||
.directive('notesView', () => new NotesView())
|
||||
.directive('footerView', () => new FooterView())
|
||||
|
||||
// Directives - Functional
|
||||
angular
|
||||
.module('app')
|
||||
.directive('snAutofocus', ['$timeout', autofocus])
|
||||
.directive('clickOutside', ['$document', clickOutside])
|
||||
.directive('delayHide', delayHide)
|
||||
.directive('elemReady', elemReady)
|
||||
.directive('fileChange', fileChange)
|
||||
.directive('infiniteScroll', [infiniteScroll])
|
||||
.directive('lowercase', lowercase)
|
||||
.directive('selectOnFocus', ['$window', selectOnFocus])
|
||||
.directive('snEnter', snEnter);
|
||||
|
||||
// Directives - Views
|
||||
angular
|
||||
.module('app')
|
||||
.directive('accountMenu', () => new AccountMenu())
|
||||
.directive('actionsMenu', () => new ActionsMenu())
|
||||
.directive('challengeModal', () => new ChallengeModal())
|
||||
.directive('componentModal', () => new ComponentModal())
|
||||
.directive('componentView', () => new ComponentView())
|
||||
.directive('editorMenu', () => new EditorMenu())
|
||||
.directive('inputModal', () => new InputModal())
|
||||
.directive('menuRow', () => new MenuRow())
|
||||
.directive('panelResizer', () => new PanelResizer())
|
||||
.directive('passwordWizard', () => new PasswordWizard())
|
||||
.directive('permissionsModal', () => new PermissionsModal())
|
||||
.directive('privilegesAuthModal', () => new PrivilegesAuthModal())
|
||||
.directive('privilegesManagementModal', () => new PrivilegesManagementModal())
|
||||
.directive('revisionPreviewModal', () => new RevisionPreviewModal())
|
||||
.directive('sessionHistoryMenu', () => new SessionHistoryMenu())
|
||||
.directive('syncResolutionMenu', () => new SyncResolutionMenu());
|
||||
|
||||
// Filters
|
||||
angular
|
||||
.module('app')
|
||||
.filter('trusted', ['$sce', trusted]);
|
||||
|
||||
// Services
|
||||
angular.module('app').service('mainApplicationGroup', ApplicationGroup);
|
||||
|
||||
// Debug
|
||||
if (isDev) {
|
||||
Object.defineProperties(window, {
|
||||
application: {
|
||||
get: () =>
|
||||
(angular.element(document).injector().get('mainApplicationGroup') as any)
|
||||
.application,
|
||||
},
|
||||
});
|
||||
if (__PLATFORM_WEB__) {
|
||||
startApplication(new WebPlatform());
|
||||
} else {
|
||||
(window as any).startApplication = startApplication;
|
||||
}
|
||||
|
||||
function startApplication(platform: Platform) {
|
||||
angular.module('app', ['ngSanitize']);
|
||||
|
||||
// Config
|
||||
angular
|
||||
.module('app')
|
||||
.config(configRoutes)
|
||||
.constant('platform', platform)
|
||||
.constant('appVersion', __VERSION__);
|
||||
|
||||
// Controllers
|
||||
angular
|
||||
.module('app')
|
||||
.directive('applicationGroupView', () => new ApplicationGroupView())
|
||||
.directive('applicationView', () => new ApplicationView())
|
||||
.directive('editorGroupView', () => new EditorGroupView())
|
||||
.directive('editorView', () => new EditorView())
|
||||
.directive('tagsView', () => new TagsView())
|
||||
.directive('notesView', () => new NotesView())
|
||||
.directive('footerView', () => new FooterView())
|
||||
|
||||
// Directives - Functional
|
||||
angular
|
||||
.module('app')
|
||||
.directive('snAutofocus', ['$timeout', autofocus])
|
||||
.directive('clickOutside', ['$document', clickOutside])
|
||||
.directive('delayHide', delayHide)
|
||||
.directive('elemReady', elemReady)
|
||||
.directive('fileChange', fileChange)
|
||||
.directive('infiniteScroll', [infiniteScroll])
|
||||
.directive('lowercase', lowercase)
|
||||
.directive('selectOnFocus', ['$window', selectOnFocus])
|
||||
.directive('snEnter', snEnter);
|
||||
|
||||
// Directives - Views
|
||||
angular
|
||||
.module('app')
|
||||
.directive('accountMenu', () => new AccountMenu())
|
||||
.directive('actionsMenu', () => new ActionsMenu())
|
||||
.directive('challengeModal', () => new ChallengeModal())
|
||||
.directive('componentModal', () => new ComponentModal())
|
||||
.directive('componentView', () => new ComponentView())
|
||||
.directive('editorMenu', () => new EditorMenu())
|
||||
.directive('inputModal', () => new InputModal())
|
||||
.directive('menuRow', () => new MenuRow())
|
||||
.directive('panelResizer', () => new PanelResizer())
|
||||
.directive('passwordWizard', () => new PasswordWizard())
|
||||
.directive('permissionsModal', () => new PermissionsModal())
|
||||
.directive('privilegesAuthModal', () => new PrivilegesAuthModal())
|
||||
.directive('privilegesManagementModal', () => new PrivilegesManagementModal())
|
||||
.directive('revisionPreviewModal', () => new RevisionPreviewModal())
|
||||
.directive('sessionHistoryMenu', () => new SessionHistoryMenu())
|
||||
.directive('syncResolutionMenu', () => new SyncResolutionMenu());
|
||||
|
||||
// Filters
|
||||
angular
|
||||
.module('app')
|
||||
.filter('trusted', ['$sce', trusted]);
|
||||
|
||||
// Services
|
||||
angular.module('app').service('mainApplicationGroup', ApplicationGroup);
|
||||
|
||||
// Debug
|
||||
if (isDev) {
|
||||
Object.defineProperties(window, {
|
||||
application: {
|
||||
get: () =>
|
||||
(angular.element(document).injector().get('mainApplicationGroup') as any)
|
||||
.application,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { DeviceInterface, getGlobalScope, SNApplication } from 'snjs';
|
||||
import { Database } from '@/database';
|
||||
|
||||
const KEYCHAIN_STORAGE_KEY = 'keychain';
|
||||
import { Platform } from './services/platform';
|
||||
|
||||
export class WebDeviceInterface extends DeviceInterface {
|
||||
|
||||
private database: Database
|
||||
|
||||
constructor(namespace: string, timeout: any) {
|
||||
constructor(
|
||||
namespace: string,
|
||||
timeout: any,
|
||||
private platform: Platform
|
||||
) {
|
||||
super(
|
||||
namespace,
|
||||
timeout || setTimeout.bind(getGlobalScope()),
|
||||
@@ -97,19 +100,16 @@ export class WebDeviceInterface extends DeviceInterface {
|
||||
return this.database.clearAllPayloads();
|
||||
}
|
||||
|
||||
async getKeychainValue() {
|
||||
const value = localStorage.getItem(KEYCHAIN_STORAGE_KEY);
|
||||
if (value) {
|
||||
return JSON.parse(value);
|
||||
}
|
||||
getKeychainValue(): Promise<unknown> {
|
||||
return this.platform.getKeychainValue();
|
||||
}
|
||||
|
||||
async setKeychainValue(value: any) {
|
||||
localStorage.setItem(KEYCHAIN_STORAGE_KEY, JSON.stringify(value));
|
||||
setKeychainValue(value: any) {
|
||||
return this.platform.setKeychainValue(value);
|
||||
}
|
||||
|
||||
async clearKeychainValue() {
|
||||
localStorage.removeItem(KEYCHAIN_STORAGE_KEY);
|
||||
clearKeychainValue() {
|
||||
return this.platform.clearKeychainValue();
|
||||
}
|
||||
|
||||
openUrl(url: string) {
|
||||
|
||||
24
app/assets/javascripts/services/platform.ts
Normal file
24
app/assets/javascripts/services/platform.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/** Platform-specific (i-e desktop/web) behavior is handled by a Platform object. */
|
||||
export interface Platform {
|
||||
getKeychainValue(): Promise<unknown>;
|
||||
setKeychainValue(value: any): Promise<void>;
|
||||
clearKeychainValue(): Promise<void>;
|
||||
}
|
||||
|
||||
const KEYCHAIN_STORAGE_KEY = 'keychain';
|
||||
|
||||
export class WebPlatform implements Platform {
|
||||
async getKeychainValue(): Promise<unknown> {
|
||||
const value = localStorage.getItem(KEYCHAIN_STORAGE_KEY);
|
||||
if (value) {
|
||||
return JSON.parse(value);
|
||||
}
|
||||
}
|
||||
async setKeychainValue(value: any): Promise<void> {
|
||||
localStorage.setItem(KEYCHAIN_STORAGE_KEY, JSON.stringify(value));
|
||||
}
|
||||
|
||||
async clearKeychainValue(): Promise<void> {
|
||||
localStorage.removeItem(KEYCHAIN_STORAGE_KEY);
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
} from '@/services';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { SNWebCrypto } from 'sncrypto/dist/sncrypto-web';
|
||||
import { Platform } from '@/services/platform';
|
||||
|
||||
type WebServices = {
|
||||
appState: AppState
|
||||
@@ -54,10 +55,15 @@ export class WebApplication extends SNApplication {
|
||||
$compile: ng.ICompileService,
|
||||
$timeout: ng.ITimeoutService,
|
||||
scope: ng.IScope,
|
||||
onDeinit: (app: WebApplication) => void
|
||||
onDeinit: (app: WebApplication) => void,
|
||||
platform: Platform,
|
||||
) {
|
||||
const namespace = '';
|
||||
const deviceInterface = new WebDeviceInterface(namespace, $timeout);
|
||||
const deviceInterface = new WebDeviceInterface(
|
||||
namespace,
|
||||
$timeout,
|
||||
platform
|
||||
);
|
||||
super(
|
||||
Environment.Web,
|
||||
platformFromString(getPlatformString()),
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
ThemeManager
|
||||
} from '@/services';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { Platform } from '@/services/platform';
|
||||
|
||||
type AppManagerChangeCallback = () => void
|
||||
|
||||
@@ -27,7 +28,8 @@ export class ApplicationGroup {
|
||||
constructor(
|
||||
$compile: ng.ICompileService,
|
||||
$rootScope: ng.IRootScopeService,
|
||||
$timeout: ng.ITimeoutService
|
||||
$timeout: ng.ITimeoutService,
|
||||
private platform: Platform
|
||||
) {
|
||||
this.$compile = $compile;
|
||||
this.$timeout = $timeout;
|
||||
@@ -68,7 +70,8 @@ export class ApplicationGroup {
|
||||
this.$compile,
|
||||
this.$timeout,
|
||||
scope,
|
||||
this.onApplicationDeinit
|
||||
this.onApplicationDeinit,
|
||||
this.platform
|
||||
);
|
||||
const appState = new AppState(
|
||||
this.$rootScope,
|
||||
|
||||
@@ -9,7 +9,8 @@ module.exports = {
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
__VERSION__: JSON.stringify(require('./package.json').version)
|
||||
__VERSION__: JSON.stringify(require('./package.json').version),
|
||||
__PLATFORM_WEB__: JSON.stringify(true),
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
// Options similar to the same options in webpackOptions.output
|
||||
|
||||
Reference in New Issue
Block a user