Merge pull request #6534 from isocolsky/copay-v4

WIP: Migrate StorageProvider
This commit is contained in:
Gustavo Maximiliano Cortez 2017-08-07 14:34:07 -03:00 committed by GitHub
commit d18aa715a2
15 changed files with 286 additions and 62 deletions

View File

@ -14,19 +14,18 @@
},
"dependencies": {
"@angular/common": "4.1.3",
"@angular/compiler": "4.1.3",
"@angular/compiler-cli": "4.1.3",
"@angular/core": "4.1.3",
"@angular/forms": "4.1.3",
"@angular/http": "4.1.3",
"@angular/platform-browser": "4.1.3",
"@angular/platform-browser-dynamic": "4.1.3",
"@angular/tsc-wrapped": "^4.3.2",
"@ionic-native/core": "3.12.1",
"@ionic-native/splash-screen": "3.12.1",
"@ionic-native/status-bar": "3.12.1",
"@ionic/storage": "2.0.1",
"@nsalaun/ng-logger": "^2.0.1",
"@types/lodash": "^4.14.71",
"autoprefixer": "^7.1.2",
"ionic-angular": "3.5.3",
"ionicons": "3.0.0",
"lodash": "^4.17.4",
@ -36,17 +35,18 @@
"zone.js": "0.8.12"
},
"devDependencies": {
"@ionic/app-scripts": "2.0.2",
"@ionic/cli-plugin-cordova": "1.4.1",
"@ionic/cli-plugin-ionic-angular": "1.3.2",
"ionic": "3.6.0",
"typescript": "2.3.4",
"@angular/cli": "^1.2.5",
"@angular/compiler": "^4.3.1",
"@angular/compiler-cli": "^4.3.1",
"@ionic/app-scripts": "2.0.2",
"@ionic/cli-plugin-cordova": "1.5.0",
"@ionic/cli-plugin-ionic-angular": "1.4.0",
"@types/chrome": "0.0.47",
"@types/jasmine": "^2.5.53",
"@types/node": "^8.0.17",
"@types/lodash": "^4.14.71",
"@types/node": "^8.0.19",
"codecov": "^2.2.0",
"ionic": "3.6.0",
"jasmine-core": "^2.6.4",
"jasmine-spec-reporter": "^4.1.1",
"karma": "^1.7.0",
@ -56,7 +56,8 @@
"karma-remap-istanbul": "^0.6.0",
"ts-node": "^3.3.0",
"tslint": "^5.5.0",
"tslint-eslint-rules": "^4.1.1"
"tslint-eslint-rules": "^4.1.1",
"typescript": "2.3.4"
},
"description": "Copay Bitcoin Wallet"
}

View File

@ -4,7 +4,7 @@ import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { Logger } from '@nsalaun/ng-logger';
import { AppService } from '../providers/app-service/app-service';
import { AppProvider } from '../providers/app/app';
import { TabsPage } from '../pages/tabs/tabs';
@ -12,23 +12,23 @@ import { TabsPage } from '../pages/tabs/tabs';
templateUrl: 'app.html'
})
export class Copay {
rootPage:any = TabsPage;
rootPage: any = TabsPage;
constructor(
platform: Platform,
statusBar: StatusBar,
splashScreen: SplashScreen,
log: Logger,
appSrv: AppService
app: AppProvider
) {
platform.ready().then(() => {
appSrv.getName().subscribe((name) => {
app.getName().subscribe((name) => {
log.info('Name: ' + name);
});
appSrv.getVersion().subscribe((version) => {
app.getVersion().subscribe((version) => {
log.info('Version: ' + version);
});
appSrv.getCommitHash().subscribe((commit) => {
app.getCommitHash().subscribe((commit) => {
log.info('Commit Hash: #' + commit);
});
log.info('Platform: ' + platform.platforms());

View File

@ -19,14 +19,15 @@ import { TermsOfUsePage } from '../pages/terms-of-use/terms-of-use';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { WalletService } from '../providers/wallet-service/wallet-service';
import { StorageService } from '../providers/storage-service/storage-service';
import { AppService } from '../providers/app-service/app-service';
import { WalletProvider } from '../providers/wallet/wallet';
import { StorageProvider } from '../providers/storage/storage';
import { AppProvider } from '../providers/app/app';
import { PlatformProvider } from '../providers/platform/platform';
// Set different log level depending on environment.
const LOG_LEVEL = Level.LOG;
if (isDevMode()){
const LOG_LEVEL = Level.ERROR;
if (isDevMode()) {
const LOG_LEVEL = Level.ERROR;
}
@NgModule({
@ -60,10 +61,11 @@ if (isDevMode()){
providers: [
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler},
WalletService,
StorageService,
AppService
{ provide: ErrorHandler, useClass: IonicErrorHandler },
WalletProvider,
StorageProvider,
AppProvider,
PlatformProvider
]
})
export class AppModule {}
export class AppModule { }

View File

@ -5,7 +5,7 @@ import { Logger } from '@nsalaun/ng-logger';
import { TermsOfUsePage } from '../terms-of-use/terms-of-use';
import { AppService } from '../../providers/app-service/app-service';
import { AppProvider } from '../../providers/app/app';
@Component({
selector: 'page-about',
@ -18,16 +18,16 @@ export class AboutPage {
constructor(
public navCtrl: NavController,
public navParams: NavParams,
private appSrv: AppService,
private app: AppProvider,
private log: Logger
) {}
) { }
ionViewDidLoad() {
this.log.log('ionViewDidLoad AboutPage');
this.appSrv.getCommitHash().subscribe((data) => {
this.app.getCommitHash().subscribe((data) => {
this.commitHash = data;
});
this.appSrv.getVersion().subscribe((data) => {
this.app.getVersion().subscribe((data) => {
this.version = data;
});
}

View File

@ -1,7 +1,7 @@
import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { AppService } from '../../providers/app-service/app-service';
import { AppProvider } from '../../providers/app/app';
import { AboutPage } from '../about/about';
@ -15,9 +15,9 @@ export class SettingPage {
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public appSrv: AppService
public app: AppProvider
) {
appSrv.getName().subscribe((data) => {
app.getName().subscribe((data) => {
this.appName = data;
});
}

View File

@ -3,7 +3,7 @@ import { Http, Response } from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class AppService {
export class AppProvider {
private jsonPath: string = '../assets/appConfig.json';
constructor(public http: Http) {}

View File

@ -0,0 +1,93 @@
import { Injectable } from '@angular/core';
import { Platform } from 'ionic-angular';
import { Logger } from '@nsalaun/ng-logger';
@Injectable()
export class PlatformProvider {
isAndroid: boolean;
isIOS: boolean;
isWP: boolean;
isSafari: boolean;
isCordova: boolean;
isNW: boolean;
ua: string;
isMobile: boolean;
isChromeApp: boolean;
isDevel: boolean;
supportsLedger: boolean;
supportsTrezor: boolean;
versionIntelTEE: string;
supportsIntelTEE: boolean;
constructor(private platform: Platform, private log: Logger) {
var ua = navigator ? navigator.userAgent : null;
if (!ua) {
console.log('Could not determine navigator. Using fixed string');
ua = 'dummy user-agent';
}
// Fixes IOS WebKit UA
ua = ua.replace(/\(\d+\)$/, '');
this.isAndroid = platform.is('android');
this.isIOS = platform.is('ios');
this.isWP = platform.is('windows') && platform.is('mobile');
this.ua = ua;
this.isCordova = platform.is('cordova');
this.isNW = this.isNodeWebkit();
this.isMobile = platform.is('mobile');
this.isChromeApp = this.getBrowserName() == 'chrome' && chrome && chrome.runtime && chrome.runtime.id && !this.isNW;
this.isDevel = !this.isMobile && !this.isChromeApp && !this.isNW;
this.supportsLedger = this.isChromeApp;
this.supportsTrezor = this.isChromeApp || this.isDevel;
this.versionIntelTEE = this.getVersionIntelTee();
this.supportsIntelTEE = this.versionIntelTEE.length > 0;
}
getBrowserName(): string {
let userAgent = window.navigator.userAgent;
let browsers = { chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer/i };
for (let key in browsers) {
if (browsers[key].test(userAgent)) {
return key;
}
};
return 'unknown';
}
isNodeWebkit(): boolean {
let isNode = (typeof process !== "undefined" && typeof require !== "undefined");
if (isNode) {
try {
return (typeof require('nw.gui') !== "undefined");
} catch (e) {
return false;
}
}
}
getVersionIntelTee(): string {
let v = '';
let isWindows = navigator.platform.indexOf('Win') > -1;
if (!this.isNodeWebkit() || !isWindows) {
return v;
}
try {
var IntelWallet = require('intelWalletCon');
if (IntelWallet.getVersion) {
v = IntelWallet.getVersion();
} else {
v = 'Alpha';
}
if (v.length > 0) {
this.log.info('Intel TEE library ' + v);
}
} catch (e) { }
return v;
}
}

View File

@ -1,11 +0,0 @@
import { StorageService } from './storage-service';
describe('Storage Service', () => {
it('should do nothing', () => {
expect(true).toBeTruthy();
});
it('should get', () => {
var storage = new StorageService();
expect(storage.get('myKey')).toEqual('myKey');
});
});

View File

@ -1,13 +0,0 @@
import { Injectable } from '@angular/core';
@Injectable()
export class StorageService {
constructor() {
console.log('Hello StorageService Provider');
}
public get(key:string):string {
return key;
}
}

View File

@ -0,0 +1,10 @@
import { InjectionToken } from '@angular/core';
export interface IStorage {
get(k: string, cb: (err: Error, v: string) => void);
set(k: string, v: any, cb: (err: Error) => void);
remove(k: string, cb: (err: Error) => void);
create(k: string, v: any, cb: (err: Error) => void);
}
export let ISTORAGE = new InjectionToken<IStorage>('storage');

View File

@ -0,0 +1,53 @@
import { Injectable } from '@angular/core';
import { PlatformProvider } from '../platform/platform';
import { Logger } from '@nsalaun/ng-logger';
import * as _ from 'lodash';
import { IStorage } from './istorage';
export class KeyAlreadyExistsError extends Error {
constructor() {
super('Key already exists');
}
}
@Injectable()
export class LocalStorage implements IStorage {
ls: Storage;
constructor(private platform: PlatformProvider, private log: Logger) {
this.ls = (typeof window.localStorage !== "undefined") ? window.localStorage : null;
if (!this.ls) throw new Error('localstorage not available');
}
get(k: string, cb: (err: Error, v: string) => void) {
return cb(null, this.ls.getItem(k));
}
set(k: string, v: any, cb: (err: Error) => void) {
if (_.isObject(v)) {
v = JSON.stringify(v);
}
if (v && !_.isString(v)) {
v = v.toString();
}
this.ls.setItem(k, v);
return cb(null);
}
remove(k: string, cb: (err: Error) => void) {
this.ls.removeItem(k);
return cb(null);
}
create(k: string, v: any, cb: (err: Error) => void) {
this.get(k,
function (err, data) {
if (data) {
return cb(new KeyAlreadyExistsError());
} else {
return this.set(k, v, cb);
}
})
}
}

View File

@ -0,0 +1,52 @@
import { TestBed, inject } from '@angular/core/testing';
import { StorageProvider } from './storage';
import { LocalStorage, KeyAlreadyExistsError } from './local-storage';
import { IStorage, ISTORAGE } from './istorage';
class StorageMock implements IStorage {
hash = {};
get(k: string, cb: (err: Error, v: string) => void) {
return cb(null, this.hash[k]);
};
set(k: string, v: any, cb: (err: Error) => void) {
this.hash[k] = v.toString();
return cb(null);
};
remove(k: string, cb: (err: Error) => void) {
delete this.hash[k];
return cb(null);
};
create(k: string, v: any, cb: (err: Error) => void) {
this.get(k,
function (err, data) {
if (data) {
return cb(new KeyAlreadyExistsError());
} else {
this.set(k, v, cb);
}
})
};
}
describe('Storage Service', () => {
let storage: IStorage = new StorageMock();
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
StorageProvider,
{ provide: ISTORAGE, useValue: storage },
]
});
});
it('should do nothing', inject([StorageProvider], (service: StorageProvider) => {
storage.set('profile', { name: 'john doe' }, (err) => {
service.getProfile((err, profile) => {
expect(err).toBeNull;
console.log(JSON.stringify(profile));
expect(profile.name).toEqual('john doe');
});
});
}));
});

View File

@ -0,0 +1,32 @@
import { Injectable } from '@angular/core';
import { InjectionToken, Inject } from '@angular/core';
import { IStorage, ISTORAGE } from './istorage';
@Injectable()
export class StorageProvider {
constructor( @Inject(ISTORAGE) private storage: IStorage) {
}
storeNewProfile(profile, cb) {
this.storage.create('profile', profile.toObj(), cb);
};
storeProfile(profile, cb) {
this.storage.set('profile', profile.toObj(), cb);
};
getProfile(cb) {
this.storage.get('profile', cb);
// decryptOnMobile(str, function (err, str) {
// if (err) return cb(err);
// var p, err;
// try {
// p = Profile.fromString(str);
// } catch (e) {
// $log.debug('Could not read profile:', e);
// err = new Error('Could not read profile:' + p);
// }
// return cb(err, p);
// });
};
}

View File

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
@Injectable()
export class WalletService {
export class WalletProvider {
constructor() {
console.log('Hello WalletService Provider');

View File

@ -22,5 +22,10 @@
"compileOnSave": false,
"atom": {
"rewriteTsconfig": false
}
}
},
"types": [
"chrome",
"lodash"
"node"
]
}