Merge pull request #6937 from cmgustavo/v4-04

V4 04
This commit is contained in:
Gustavo Maximiliano Cortez 2017-10-19 14:16:48 -03:00 committed by GitHub
commit 088f9f2165
21 changed files with 266 additions and 325 deletions

1
.gitignore vendored
View File

@ -19,7 +19,6 @@ npm-debug.log*
## App
/desktop
/chrome-app
/config.xml
/ionic.config.json

View File

@ -11,8 +11,7 @@ var templates = {
'manifest.ionic-template.json': 'src/',
'.desktop': 'desktop/',
'setup-win.iss': 'desktop/',
'build-macos.sh': 'desktop/',
'manifest-template.json': 'chrome-app/'
'build-macos.sh': 'desktop/'
};
var configDir = process.argv[2] || 'copay';
var JSONheader = ' { ' + "\n" + ' "//":"Changes to this file will be overwritten",' + "\n" + ' "//":" Modify it in the app-template directory", ' + "\n";
@ -75,7 +74,6 @@ Object.keys(templates).forEach(function(k) {
/////////////////
console.log('Copying ' + configDir + '/appConfig.json' + ' to assets');
configBlob = configBlob.replace('{', JSONheader);
fs.writeFileSync('../src/assets/appConfig.json', configBlob, 'utf8');
////////////////

View File

@ -2,7 +2,7 @@
"packageName": "bitpay",
"packageDescription": "Secure Bitcoin Wallet",
"packageNameId": "com.bitpay.wallet",
"statusBarColor": "#1e3186",
"themeColor": "#1e3186",
"userVisibleName": "BitPay",
"purposeLine": "Secure Bitcoin Wallet",
"bundleName": "wallet",

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,21 @@
/*
* BitPay Distribution SCSS overrides
*/
// Named Color Variables
// --------------------------------------------------
// Named colors makes it easy to reuse colors on various components.
// It's highly recommended to change the default colors
// to match your app's branding. Ionic uses a Sass map of
// colors so you can add, rename and remove colors as needed.
// The "primary" color is the only required color in the map.
$colors: (
primary: #1e3186,
secondary: #111b49,
danger: #ffa500,
light: #f4f4f4,
dark: #222
);
$text-color: #1e3186;

View File

@ -18,7 +18,7 @@
<preference name="DisallowOverscroll" value="true"/>
<preference name="HideKeyboardFormAccessoryBar" value="true"/>
<preference name="StatusBarBackgroundColor" value="*STATUSBARCOLOR*" />
<preference name="StatusBarBackgroundColor" value="*THEMECOLOR*" />
<preference name="BackupWebStorage" value="none"/>
<preference name="Orientation" value="default" />

View File

@ -2,7 +2,7 @@
"packageName": "copay",
"packageDescription": "Copay Bitcoin Wallet",
"packageNameId": "com.bitpay.copay",
"statusBarColor": "#192c3a",
"themeColor": "#192c3a",
"userVisibleName": "Copay",
"purposeLine": "Copay Bitcoin Wallet",
"bundleName": "copay",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -2,74 +2,21 @@
* Copay Distribution SCSS overrides
*/
/* Colors */
$v-primary-color: #192c3a;
$v-secondary-color: #31465b;
$v-accent-color: #1abb9b;
// Named Color Variables
// --------------------------------------------------
// Named colors makes it easy to reuse colors on various components.
// It's highly recommended to change the default colors
// to match your app's branding. Ionic uses a Sass map of
// colors so you can add, rename and remove colors as needed.
// The "primary" color is the only required color in the map.
$v-text-primary-color: #192c3a;
$v-text-secondary-color: #c2c9d1;
$v-text-accent-color: #1abb9b;
$colors: (
primary: #192c3a,
secondary: #31465b,
danger: #bb331a,
light: #f4f4f4,
dark: #222
);
$v-success-color: #1abb9b;
$v-warning-color: #bb331a;
$text-color: #192c3a;
/* Theme */
$v-default-wallet-color-index: 6;
$v-top-tabs-color: $v-accent-color;
$v-wallet-backup-phrase-color: $v-text-primary-color;
$v-wallet-backup-select-phrase-color: $v-secondary-color;
$v-wallet-backup-select-word-bg: $v-accent-color;
$v-wallet-backup-select-word-color: $v-text-primary-color;
$v-wallet-backup-select-word-disabled-color: $v-accent-color;
$v-tou-bg: $v-secondary-color;
$v-tou-color: $v-text-secondary-color;
$v-icon-border-radius: 3px;
$v-bitcoin-icon: url('../img/app/icon-bitcoin.svg');
$v-button-primary-outline-active-color: $v-text-primary-color;
$v-button-secondary-bg: $v-secondary-color;
$v-button-secondary-color: $v-accent-color;
$v-button-secondary-active-bg: darken($v-secondary-color, 10%);
$v-button-secondary-clear-color: $v-accent-color;
$v-button-secondary-outline-border: $v-accent-color;
$v-button-secondary-outline-color: $v-accent-color;
$v-button-secondary-outline-active-bg: darken($v-accent-color, 10%);
$v-button-secondary-outline-active-color: $v-accent-color;
/* Slide */
$v-slide-bg-color: $v-accent-color;
$v-slider-bg-color: #069074;
$v-slide-text-color: #FFFFFF;
/* Onboarding */
$v-onboarding-welcome-bg: none;
$v-onboarding-color: $v-text-secondary-color;
$v-onboarding-bar-header-color: $v-text-primary-color;
$v-onboarding-bar-header-button-color: $v-accent-color;
$v-onboarding-tour-phone-bg: url(../img/app/onboarding/tour-phone.svg);
$v-onboarding-tour-currency-bg: url(../img/app/onboarding/tour-currency.svg);
$v-onboarding-tour-control-bg: url(../img/app/onboarding/tour-control.svg);
$v-onboarding-push-notification-bg: url(../img/app/onboarding/push-notifications.svg);
$v-onboarding-backup-warning-bg: url(../img/app/backup-warning.svg);
$v-onboarding-button-back-color: $v-accent-color;
$v-onboarding-button-secondary-bg: $v-secondary-color;
$v-onboarding-button-secondary-color: $v-accent-color;
$v-onboarding-button-secondary-active-bg: darken($v-secondary-color, 10%);
$v-onboarding-button-secondary-clear-color: $v-accent-color;
$v-onboarding-button-secondary-outline-border: $v-accent-color;
$v-onboarding-button-secondary-outline-color: $v-accent-color;
$v-onboarding-button-secondary-outline-active-bg: darken($v-accent-color, 10%);
$v-onboarding-button-secondary-outline-active-color: $v-accent-color;
/* Main tabs */
$v-tab-home-selected-icon: url('../img/app/tab-icons/ico-home-selected.svg');
$v-tab-receive-selected-icon: url('../img/app/tab-icons/ico-receive-selected.svg');
$v-tab-settings-selected-icon: url('../img/app/tab-icons/ico-settings-selected.svg');
$v-tab-scan-selected-icon: url('../img/app/tab-icons/ico-scan-selected.svg');
$v-tab-send-selected-icon: url('../img/app/tab-icons/ico-send-selected.svg');

View File

@ -9,7 +9,7 @@
<link rel="icon" type="image/x-icon" href="assets/img/favicon.ico">
<link rel="manifest" href="manifest.json">
<meta name="theme-color" content="#4e8ef7">
<meta name="theme-color" content="*THEMECOLOR*">
<!-- cordova.js required for cordova apps -->
<script src="cordova.js"></script>
@ -28,14 +28,6 @@
</head>
<body>
<!-- Workaround to prevent autofill -->
<div style="display: none;">
<input type="text"
id="PreventChromeAutocomplete"
name="PreventChromeAutocomplete"
autocomplete="address-level4" />
</div>
<!-- Ionic's root component and where the app will load -->
<ion-app></ion-app>

View File

@ -1,21 +0,0 @@
{
"manifest_version": 2,
"name": "*PACKAGENAME*",
"description": "*DESCRIPTION*",
"version": "*VERSION*",
"permissions": [
"storage",
"unlimitedStorage",
"notifications",
"videoCapture",
"webview"
],
"app": {
"background": {
"scripts": ["initial.js"]
}
},
"icons": {
"128": "assets/img/icon-chrome-128.png"
}
}

View File

@ -5,9 +5,9 @@
"display": "standalone",
"icons": [{
"src": "assets/img/app/logo.png",
"sizes": "512x512",
"sizes": "150x65",
"type": "image/png"
}],
"background_color": "#4e8ef7",
"theme_color": "#4e8ef7"
"background_color": "*THEMECOLOR*",
"theme_color": "*THEMECOLOR*"
}

View File

@ -152,7 +152,7 @@ let providers: any = [
useFactory: persistenceProviderFactory,
deps: [PlatformProvider, Logger],
multi: false
},
}
];
export function declarationsComponents() {

View File

@ -8,39 +8,35 @@ import { ConfigProvider } from '../../providers/config/config';
import { TouchIdProvider } from '../../providers/touchid/touchid';
interface App {
WindowsStoreDisplayName: string;
WindowsStoreIdentityName: string;
androidVersion: string;
appDescription: string;
appUri: string;
packageName: string;
packageDescription: string;
packageNameId: string;
themeColor: string;
userVisibleName: string;
purposeLine: string;
bundleName: string;
commitHash: string;
description: string;
disclaimerUrl: string;
gitHubRepoBugs: string;
gitHubRepoName: string;
gitHubRepoUrl: string;
appUri: string;
name: string;
nameNoSpace: string;
nameCase: string;
nameCaseNoSpace: string;
nameNoSpace: string;
packageDescription: string;
packageName: string;
packageNameId: string;
purposeLine: string;
pushSenderId: string;
statusBarColor: string;
gitHubRepoName: string;
gitHubRepoUrl: string;
gitHubRepoBugs: string;
disclaimerUrl: string;
url: string;
userVisibleName: string;
version: string;
appDescription: string;
winAppName: string;
WindowsStoreIdentityName: string;
WindowsStoreDisplayName: string;
windowsAppId: string;
_enabledExtensions: {
amazon: boolean;
coinbase: boolean;
glidera: boolean;
}
pushSenderId: string;
description: string;
version: string;
androidVersion: string;
commitHash: string;
_extraCSS: string;
_enabledExtensions: object;
}
@Injectable()
@ -60,23 +56,21 @@ export class AppProvider {
public load() {
return new Promise((resolve, reject) => {
this.config.load().then((config) => {
// storage -> config -> language -> unit -> app
// Everything ok
this.language.init(config);
this.config.load().then(() => {
this.language.load();
this.touchid.init();
this.getInfo().subscribe((info) => {
this.info = info;
resolve(true);
resolve();
});
}).catch((err) => {
// Something may be wrong
reject(err);
this.logger.error(err);
reject();
});
});
}
getInfo() {
private getInfo() {
return this.http.get(this.jsonPath)
.map((res: Response) => res.json());
}

View File

@ -2,106 +2,193 @@ import { Injectable } from '@angular/core';
import { Logger } from '@nsalaun/ng-logger';
import { Events } from 'ionic-angular';
import { PersistenceProvider } from '../persistence/persistence';
import { PlatformProvider } from '../platform/platform';
import * as _ from "lodash";
@Injectable()
export class ConfigProvider {
private configCache: object;
private configDefault: object = {
// wallet limits
limits: {
totalCopayers: 6,
mPlusN: 100
},
interface Config {
limits: {
totalCopayers: number;
mPlusN: number;
};
// wallet default config
wallet: {
requiredCopayers: 2,
totalCopayers: 3,
spendUnconfirmed: false,
reconnectDelay: 5000,
idleDurationMin: 4,
wallet: {
requiredCopayers: number;
totalCopayers: number;
spendUnconfirmed: boolean;
reconnectDelay: number;
idleDurationMin: number;
settings: {
unitName: 'BTC',
unitToSatoshi: 100000000,
unitDecimals: 8,
unitCode: 'btc',
alternativeName: 'US Dollar',
alternativeIsoCode: 'USD'
}
},
unitName: string;
unitToSatoshi: number;
unitDecimals: number;
unitCode: string;
alternativeName: string;
alternativeIsoCode: string;
defaultLanguage: string;
};
};
// Bitcore wallet service URL
bws: {
url: 'https://bws.bitpay.com/bws/api'
},
bws: {
url: string;
};
download: {
bitpay: {
url: 'https://bitpay.com/wallet'
},
copay: {
url: 'https://copay.io/#download'
}
},
rateApp: {
bitpay: {
ios: 'http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=1149581638&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8',
android: 'https://play.google.com/store/apps/details?id=com.bitpay.wallet',
wp: ''
},
copay: {
ios: 'http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=951330296&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8',
android: 'https://play.google.com/store/apps/details?id=com.bitpay.copay',
wp: ''
}
},
lock: {
method: null,
value: null,
bannedUntil: null
},
// External services
recentTransactions: {
enabled: true
},
hideNextSteps: {
enabled: this.platform.isWP ? true : false
},
rates: {
url: 'https://insight.bitpay.com:443/api/rates'
},
release: {
url: 'https://api.github.com/repos/bitpay/copay/releases/latest'
},
pushNotificationsEnabled: true,
confirmedTxsNotifications: {
enabled: true
},
emailNotifications: {
enabled: false
},
log: {
filter: 'debug'
download: {
bitpay: {
url: string;
};
copay: {
url: string;
}
};
rateApp: {
bitpay: {
ios: string;
android: string;
wp: string;
};
copay: {
ios: string;
android: string;
wp: string;
};
};
lock: {
method: any;
value: any;
bannedUntil: any;
};
recentTransactions: {
enabled: boolean;
};
hideNextSteps: {
enabled: boolean;
};
rates: {
url: string;
};
release: {
url: string;
};
pushNotificationsEnabled: boolean;
confirmedTxsNotifications: {
enabled: boolean;
};
emailNotifications: {
enabled: boolean;
};
log: {
filter: string;
};
};
const configDefault: Config = {
// wallet limits
limits: {
totalCopayers: 6,
mPlusN: 100
},
// wallet default config
wallet: {
requiredCopayers: 2,
totalCopayers: 3,
spendUnconfirmed: false,
reconnectDelay: 5000,
idleDurationMin: 4,
settings: {
unitName: 'BTC',
unitToSatoshi: 100000000,
unitDecimals: 8,
unitCode: 'btc',
alternativeName: 'US Dollar',
alternativeIsoCode: 'USD',
defaultLanguage: ''
}
},
// Bitcore wallet service URL
bws: {
url: 'https://bws.bitpay.com/bws/api'
},
download: {
bitpay: {
url: 'https://bitpay.com/wallet'
},
copay: {
url: 'https://copay.io/#download'
}
},
rateApp: {
bitpay: {
ios: 'http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=1149581638&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8',
android: 'https://play.google.com/store/apps/details?id=com.bitpay.wallet',
wp: ''
},
copay: {
ios: 'http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=951330296&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8',
android: 'https://play.google.com/store/apps/details?id=com.bitpay.copay',
wp: ''
}
},
lock: {
method: null,
value: null,
bannedUntil: null
},
// External services
recentTransactions: {
enabled: true
},
hideNextSteps: {
enabled: false
},
rates: {
url: 'https://insight.bitpay.com:443/api/rates'
},
release: {
url: 'https://api.github.com/repos/bitpay/copay/releases/latest'
},
pushNotificationsEnabled: true,
confirmedTxsNotifications: {
enabled: true
},
emailNotifications: {
enabled: false
},
log: {
filter: 'debug'
}
};
@Injectable()
export class ConfigProvider {
private configCache: Config;
constructor(
private logger: Logger,
private events: Events,
private platform: PlatformProvider,
private persistence: PersistenceProvider
) {
this.logger.debug('ConfigProvider initialized.');
@ -109,16 +196,19 @@ export class ConfigProvider {
public load() {
return new Promise((resolve, reject) => {
this.persistence.getConfig().then((config: object) => {
this.persistence.getConfig().then((config: Config) => {
if (!_.isEmpty(config)) this.configCache = _.clone(config);
else this.configCache = _.clone(this.configDefault);
resolve(this.configCache);
else this.configCache = _.clone(configDefault);
resolve();
}).catch((err) => {
this.logger.error(err);
reject();
});
});
}
public set(newOpts: object) {
let config = _.cloneDeep(this.configDefault);
let config = _.cloneDeep(configDefault);
if (_.isString(newOpts)) {
newOpts = JSON.parse(newOpts);
@ -132,12 +222,12 @@ export class ConfigProvider {
});
}
public get(): Object {
public get(): Config {
return this.configCache;
}
public getDefaults(): Object {
return this.configDefault;
public getDefaults(): Config {
return configDefault;
}
}

View File

@ -56,14 +56,13 @@ export class LanguageProvider {
});
}
init(config: object) {
// Get from browser
let browserLang = this.translate.getBrowserLang();
let validBrowserLang = this.getName(browserLang) ? true : false;
let configLanguage = config['wallet']['settings']['defaultLanguage']; // TODO
if (configLanguage) this.current = configLanguage;
public load() {
let lang = this.config.get().wallet.settings.defaultLanguage;
if (!_.isEmpty(lang)) this.current = lang;
else {
// Get from browser
let browserLang = this.translate.getBrowserLang();
let validBrowserLang = this.getName(browserLang) ? true : false;
if (validBrowserLang) this.current = browserLang;
else this.current = this.getDefault();
}

View File

@ -7,7 +7,6 @@ import { PersistenceProvider } from './persistence';
import { IStorage, ISTORAGE } from './storage/istorage';
import { RamStorage } from './storage/ram-storage';
import { LocalStorage } from './storage/local-storage';
import { ChromeStorage } from './storage/chrome-storage';
import { FileStorage } from './storage/file-storage';
describe('Storage Service', () => {

View File

@ -1,12 +1,11 @@
import { Injectable } from '@angular/core';
import { InjectionToken, Inject } from '@angular/core';
import { Inject } from '@angular/core';
import { Logger } from '@nsalaun/ng-logger';
import * as _ from 'lodash';
import { IStorage, ISTORAGE } from './storage/istorage';
import { PlatformProvider } from '../platform/platform';
import { LocalStorage } from './storage/local-storage';
import { ChromeStorage } from './storage/chrome-storage';
import { FileStorage } from './storage/file-storage';
import { RamStorage } from './storage/ram-storage';

View File

@ -1,58 +0,0 @@
import { Injectable } from '@angular/core';
import { Logger } from '@nsalaun/ng-logger';
import * as _ from 'lodash';
import { IStorage, KeyAlreadyExistsError } from './istorage';
@Injectable()
export class ChromeStorage implements IStorage {
ls: chrome.storage.StorageArea;
constructor(private log: Logger) {
let chrome: any;
if (!chrome.storage || !chrome.storage.local) throw new Error('Chrome storage not supported');
this.ls = chrome.storage.local;
}
get(k: string): Promise<any> {
return new Promise(resolve => {
let v = this.ls.get(k, (v) => {
if (!v) return resolve(null);
if (!_.isString(v)) return resolve(v);
let parsed: any;
try {
parsed = JSON.parse(v);
} catch (e) {
}
resolve(parsed || v);
});
});
}
set(k: string, v: any): Promise<void> {
if (_.isObject(v)) {
v = JSON.stringify(v);
}
if (v && !_.isString(v)) {
v = v.toString();
}
let obj = {};
obj[k] = v;
return new Promise<void>(resolve => {
this.ls.set(obj, resolve);
});
}
remove(k: string): Promise<void> {
return new Promise<void>(resolve => {
this.ls.remove(k, resolve);
});
}
create(k: string, v: any): Promise<void> {
return this.get(k).then((data) => {
if (data) throw new KeyAlreadyExistsError();
this.set(k, v);
});
}
}

View File

@ -21,11 +21,10 @@ export class TxFormatProvider {
private filter: Filter
) {
console.log('Hello TxFormatProvider Provider');
console.log("configProvider", this.config.get());
}
formatAmount(satoshis: number, fullPrecision?: boolean) {
let settings = this.config.get()['wallet']['settings']; // TODO
let settings = this.config.get().wallet.settings;
if (settings.unitCode == 'sat') return satoshis;
@ -64,7 +63,7 @@ export class TxFormatProvider {
formatAlternativeStr(coin: string, satoshis: number) {
return new Promise((resolve, reject) => {
if (isNaN(satoshis)) resolve();
let settings = this.config.get()['wallet']['settings']; // TODO
let settings = this.config.get().wallet.settings;
var v1 = parseFloat((this.rate.toFiat(satoshis, settings.alternativeIsoCode, coin)).toFixed(2));
var v1FormatFiat = this.filter.formatFiatAmount(v1);

View File

@ -19,23 +19,6 @@ $app-direction: ltr;
// To view all the possible Ionic variables, see:
// http://ionicframework.com/docs/theming/overriding-ionic-variables/
// Named Color Variables
// --------------------------------------------------
// Named colors makes it easy to reuse colors on various components.
// It's highly recommended to change the default colors
// to match your app's branding. Ionic uses a Sass map of
// colors so you can add, rename and remove colors as needed.
// The "primary" color is the only required color in the map.
$colors: (
primary: #488aff,
secondary: #32db64,
danger: #f53d3d,
light: #f4f4f4,
dark: #222
);
// TODO: Custom variables (backward compatibilities). Will be REMOVED
$v-primary-color: #192c3a;
@ -67,12 +50,12 @@ $v-visible-radius: 6px !default;
// App Material Design Variables
// --------------------------------------------------
// Material Design only Sass variables can go here
// App Windows Variables
// --------------------------------------------------
// Windows only Sass variables can go here