Skip to content

Commit

Permalink
feature: add platform layer
Browse files Browse the repository at this point in the history
  • Loading branch information
arielsvg committed Aug 12, 2020
1 parent d9e204f commit 78031ee
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 87 deletions.
151 changes: 81 additions & 70 deletions app/assets/javascripts/app.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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,
},
});
}
}
24 changes: 12 additions & 12 deletions app/assets/javascripts/interface.ts
Original file line number Diff line number Diff line change
@@ -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()),
Expand Down Expand Up @@ -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) {
Expand Down
24 changes: 24 additions & 0 deletions app/assets/javascripts/services/platform.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
10 changes: 8 additions & 2 deletions app/assets/javascripts/ui_models/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()),
Expand Down
7 changes: 5 additions & 2 deletions app/assets/javascripts/ui_models/application_group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ThemeManager
} from '@/services';
import { AppState } from '@/ui_models/app_state';
import { Platform } from '@/services/platform';

type AppManagerChangeCallback = () => void

Expand All @@ -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;
Expand Down Expand Up @@ -68,7 +70,8 @@ export class ApplicationGroup {
this.$compile,
this.$timeout,
scope,
this.onApplicationDeinit
this.onApplicationDeinit,
this.platform
);
const appState = new AppState(
this.$rootScope,
Expand Down
3 changes: 2 additions & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 78031ee

Please sign in to comment.