diff --git a/package.json b/package.json index 4ffa0e0e0..a7f658f28 100644 --- a/package.json +++ b/package.json @@ -64,8 +64,8 @@ "@angular/cli": "1.3.0", "@biesbjerg/ngx-translate-extract": "2.3.2", "@ionic/app-scripts": "2.0.2", - "@ionic/cli-plugin-cordova": "1.5.0", - "@ionic/cli-plugin-ionic-angular": "1.4.0", + "@ionic/cli-plugin-cordova": "1.6.2", + "@ionic/cli-plugin-ionic-angular": "1.4.1", "@types/chrome": "0.0.47", "@types/jasmine": "2.5.53", "@types/lodash": "4.14.71", diff --git a/src/assets/img/logo-negative.svg b/src/assets/img/logo-negative.svg new file mode 100644 index 000000000..ab7e62a89 --- /dev/null +++ b/src/assets/img/logo-negative.svg @@ -0,0 +1,18 @@ + + + + Artboard 1 + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/img/onboarding-success.svg b/src/assets/img/onboarding-success.svg new file mode 100644 index 000000000..665a3fd01 --- /dev/null +++ b/src/assets/img/onboarding-success.svg @@ -0,0 +1,18 @@ + + + + Group 3 + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/img/tour-control.svg b/src/assets/img/tour-control.svg new file mode 100644 index 000000000..7a49991b1 --- /dev/null +++ b/src/assets/img/tour-control.svg @@ -0,0 +1,47 @@ + + + + tour-control + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/img/tour-currency.svg b/src/assets/img/tour-currency.svg new file mode 100644 index 000000000..85854559f --- /dev/null +++ b/src/assets/img/tour-currency.svg @@ -0,0 +1,33 @@ + + + + tour-currency + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/img/tour-phone.svg b/src/assets/img/tour-phone.svg new file mode 100644 index 000000000..9386356db --- /dev/null +++ b/src/assets/img/tour-phone.svg @@ -0,0 +1,39 @@ + + + + onboarding-tour-phone + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/img/warning.svg b/src/assets/img/warning.svg new file mode 100644 index 000000000..5f4b4a907 --- /dev/null +++ b/src/assets/img/warning.svg @@ -0,0 +1,18 @@ + + + + warning + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pages/home/home.html b/src/pages/home/home.html index 2899b3e98..f00526580 100644 --- a/src/pages/home/home.html +++ b/src/pages/home/home.html @@ -5,5 +5,5 @@ - + diff --git a/src/pages/home/home.ts b/src/pages/home/home.ts index 1d510dd2d..cf20e0a84 100644 --- a/src/pages/home/home.ts +++ b/src/pages/home/home.ts @@ -11,4 +11,7 @@ export class HomePage { } + showOnboardingFlow() { + this.navCtrl.push('WelcomePage'); + } } diff --git a/src/pages/onboarding/backup-request/backup-request.html b/src/pages/onboarding/backup-request/backup-request.html new file mode 100644 index 000000000..d08369a39 --- /dev/null +++ b/src/pages/onboarding/backup-request/backup-request.html @@ -0,0 +1,21 @@ + + + + + + + + + +
+ +
No backup, no bitcoin.
+
Since only you control your money, you’ll need to save your backup phrase in case this app is deleted.
+
+
+ +
Your wallet is never saved to cloud storage or standard device backups.
+ + +
+
diff --git a/src/pages/onboarding/backup-request/backup-request.module.ts b/src/pages/onboarding/backup-request/backup-request.module.ts new file mode 100644 index 000000000..698623ca5 --- /dev/null +++ b/src/pages/onboarding/backup-request/backup-request.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { BackupRequestPage } from './backup-request'; + +@NgModule({ + declarations: [ + BackupRequestPage, + ], + imports: [ + IonicPageModule.forChild(BackupRequestPage), + ], +}) +export class BackupRequestPageModule {} diff --git a/src/pages/onboarding/backup-request/backup-request.scss b/src/pages/onboarding/backup-request/backup-request.scss new file mode 100644 index 000000000..6e6013fa5 --- /dev/null +++ b/src/pages/onboarding/backup-request/backup-request.scss @@ -0,0 +1,64 @@ +page-backup-request { + .backup-request { + #warning { + padding-top: 15%; + display: block; + flex-direction: column; + height: calc(100vh - 320px); + justify-content: center; + align-content: center; + } + #alert-icon { + margin: 20px auto 5px; + height: 10vh; + } + #arrow-down { + font-size: 4.2rem; + color: $v-accent-color; + } + #backup-tldr { + font-size: 16px; + } + #backup-description { + max-width: 500px; + margin: auto; + padding: 1rem 0.5rem 0 1rem; + @media (max-height: 480px) { + padding-top: 40px; + } + } + .buttons { + position: absolute; + bottom: 0px; + padding: 15px; + } + @media (max-height: 568px) { + #warning { + padding-top: 5%; + } + #backup-description { + font-size: 14px; + } + #backup-tldr { + font-size: 14px; + } + } + @media (max-height: 480px) { + #warning { + padding-top: 5%; + } + #backup-description { + font-size: 14px; + } + #backup-tldr { + font-size: 14px; + } + #arrow-down { + display: none; + } + } + } + .header-md::after { + background: none; + } +} diff --git a/src/pages/onboarding/backup-request/backup-request.ts b/src/pages/onboarding/backup-request/backup-request.ts new file mode 100644 index 000000000..074946ba1 --- /dev/null +++ b/src/pages/onboarding/backup-request/backup-request.ts @@ -0,0 +1,51 @@ +import { Component } from '@angular/core'; +import { IonicPage, NavController, NavParams, AlertController} from 'ionic-angular'; + +@IonicPage() +@Component({ + selector: 'page-backup-request', + templateUrl: 'backup-request.html', +}) +export class BackupRequestPage { + private opts: any; + + constructor(public navCtrl: NavController, public navParams: NavParams, public alertCtrl: AlertController) { + this.opts = { + title: '', + message: '', + buttons: [], + } + } + + ionViewDidLoad() { + } + + initBackupFlow() { + // TODO navigate to backupFlow + this.navCtrl.push('BackupWarningPage'); + } + + later(confirmed: boolean) { + this.opts.title = !confirmed ? '¡Watch Out!' : 'Are you sure you want to skip it?'; + this.opts.message = !confirmed ? 'If this device is replaced or this app is deleted, neither you nor BitPay can recover your funds without a backup.' : 'You can create a backup later from your wallet settings.'; + this.opts.buttons = [{ + text: 'Go back', + role: 'destructor' + }, + { + text: !confirmed ? 'I understand' : 'Yes, skip', + handler: () => { + if (!confirmed) { + setTimeout(() => { + this.later(true); + }, 300); + } else { + this.navCtrl.push('DisclaimerPage'); + } + } + }] + let alert = this.alertCtrl.create(this.opts); + alert.present(); + } + +} diff --git a/src/pages/onboarding/disclaimer-modal/disclaimer-modal.html b/src/pages/onboarding/disclaimer-modal/disclaimer-modal.html new file mode 100644 index 000000000..a5736e01f --- /dev/null +++ b/src/pages/onboarding/disclaimer-modal/disclaimer-modal.html @@ -0,0 +1,70 @@ + + + + Term of use + + + + + + + + + +
+

+ This is a binding Agreement between BitPay, Inc. (“BitPay” or “We”) and the person, persons, or entity (“You” or “Your”) using the service, Software, or application (“Software”). +

+

+ RIGHTS AND OBLIGATIONS +

+

+ BitPay provides the Software solely on the terms and conditions set forth in this Agreement and on the condition that You accept and comply with them. By using the Software You (a) accept this Agreement and agree that You are legally bound by its terms; and (b) represent and warrant that: (i) You are of legal age to enter into a binding agreement; and (ii) if You are a corporation, governmental organization or other legal entity, You have the right, power and authority to enter into this Agreement on behalf of the corporation, governmental organization or other legal entity and bind them to these terms. +

+

+ This Software functions as a free, open source, and multi-signature digital wallet. The Software does not constitute an account where We or other third parties serve as financial intermediaries or custodians of Your bitcoin(s). +

+

+ While the Software has undergone beta testing and continues to be improved by feedback from the open-source user and developer community, We cannot guarantee there will not be bugs in the Software. You acknowledge that Your use of this Software is at Your own discretion and in compliance with all applicable laws. You are responsible for safekeeping Your passwords, private key pairs, PINs, and any other codes You use to access the Software. +

+

+ IF YOU LOSE ACCESS TO YOUR BITCOIN WALLET OR YOUR ENCRYPTED PRIVATE KEYS AND YOU HAVE NOT SEPARATELY STORED A BACKUP OF YOUR WALLET AND CORRESPONDING PASSWORD, YOU ACKNOWLEDGE AND AGREE THAT ANY BITCOIN YOU HAVE ASSOCIATED WITH THAT WALLET WILL BECOME INACCESSIBLE. All transaction requests are irreversible. The authors of the Software, employees and affiliates of BitPay, copyright holders, and BitPay, Inc. cannot retrieve Your private keys or passwords if You lose or forget them and cannot guarantee transaction confirmation as they do not have control over the bitcoin network. +

+

+ DISCLAIMER +

+

+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OF THE SOFTWARE, EMPLOYEES AND AFFILIATES OF BITPAY, COPYRIGHT HOLDERS, OR BITPAY, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

+

+ IN NO EVENT WILL BITPAY OR ITS AFFILIATES, OR ANY OF ITS OR THEIR RESPECTIVE SERVICE PROVIDERS, BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY USE, INTERRUPTION, DELAY OR INABILITY TO USE THE SOFTWARE, LOST REVENUES OR PROFITS, DELAYS, INTERRUPTION OR LOSS OF SERVICES, BUSINESS OR GOODWILL, LOSS OR CORRUPTION OF DATA, LOSS RESULTING FROM SYSTEM OR SYSTEM SERVICE FAILURE, MALFUNCTION OR SHUTDOWN, FAILURE TO ACCURATELY TRANSFER, READ OR TRANSMIT INFORMATION, FAILURE TO UPDATE OR PROVIDE CORRECT INFORMATION, SYSTEM INCOMPATIBILITY OR PROVISION OF INCORRECT COMPATIBILITY INFORMATION OR BREACHES IN SYSTEM SECURITY, OR FOR ANY CONSEQUENTIAL, INCIDENTAL, INDIRECT, EXEMPLARY, SPECIAL OR PUNITIVE DAMAGES, WHETHER ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT, BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE) OR OTHERWISE, REGARDLESS OF WHETHER SUCH DAMAGES WERE FORESEEABLE AND WHETHER OR NOT WE WERE ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +

+

+ INTELLECTUAL PROPERTY +

+

+ We retain all right, title, and interest in and to the Content and all of BitPay’s brands, logos, and trademarks, including, but not limited to, BitPay, Inc., BitPay, BitPay – Secure Bitcoin Wallet, BitPay Wallet, BitPay App, Copay, BitPay Prepaid Card, and variations of the wording of the aforementioned brands, logos, and trademarks. +

+

+ CHOICE OF LAW +

+

+ This Agreement, and its application and interpretation, shall be governed exclusively by the laws of the State of Georgia, without regard to its conflict of law rules. You consent to the exclusive jurisdiction of the federal and state courts located in or near Atlanta, Georgia for any dispute arising under this Agreement. +

+

+ SEVERABILITY +

+

+ In the event any court shall declare any section or sections of this Agreement invalid or void, such declaration shall not invalidate the entire Agreement and all other paragraphs of the Agreement shall remain in full force and effect. +

+

+ BINDING AGREEMENT +

+

+ The terms and provisions of this Agreement are binding upon Your heirs, successors, assigns, and other representatives. This Agreement may be executed in counterparts, each of which shall be considered to be an original, but both of which constitute the same Agreement. +

+

+ You assume any and all risks associated with the use of the Software. We reserve the right to modify this Agreement from time to time. +

+
+
diff --git a/src/pages/onboarding/disclaimer-modal/disclaimer-modal.module.ts b/src/pages/onboarding/disclaimer-modal/disclaimer-modal.module.ts new file mode 100644 index 000000000..9d5c3170a --- /dev/null +++ b/src/pages/onboarding/disclaimer-modal/disclaimer-modal.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { DisclaimerModalPage } from './disclaimer-modal'; + +@NgModule({ + declarations: [ + DisclaimerModalPage, + ], + imports: [ + IonicPageModule.forChild(DisclaimerModalPage), + ], +}) +export class DisclaimerModalPageModule {} diff --git a/src/pages/onboarding/disclaimer-modal/disclaimer-modal.scss b/src/pages/onboarding/disclaimer-modal/disclaimer-modal.scss new file mode 100644 index 000000000..66abc1f2d --- /dev/null +++ b/src/pages/onboarding/disclaimer-modal/disclaimer-modal.scss @@ -0,0 +1,3 @@ +page-disclaimer-modal { + +} diff --git a/src/pages/onboarding/disclaimer-modal/disclaimer-modal.ts b/src/pages/onboarding/disclaimer-modal/disclaimer-modal.ts new file mode 100644 index 000000000..a8dab0ffb --- /dev/null +++ b/src/pages/onboarding/disclaimer-modal/disclaimer-modal.ts @@ -0,0 +1,21 @@ +import { Component } from '@angular/core'; +import { IonicPage, NavParams, ViewController } from 'ionic-angular'; + +@IonicPage() +@Component({ + selector: 'page-disclaimer-modal', + templateUrl: 'disclaimer-modal.html', +}) +export class DisclaimerModalPage { + + constructor(public navParams: NavParams, private view: ViewController) { + } + + ionViewDidLoad() { + } + + closeModal() { + this.view.dismiss(); + } + +} diff --git a/src/pages/onboarding/disclaimer/disclaimer.html b/src/pages/onboarding/disclaimer/disclaimer.html new file mode 100644 index 000000000..3af1c0ccf --- /dev/null +++ b/src/pages/onboarding/disclaimer/disclaimer.html @@ -0,0 +1,35 @@ + + + + + + + + + +
+
Quick review!
+
Almost done! Let's review.
+
Bitcoin is different – it cannot be safely held with a bank or web service.
+
+ + I understand that my funds are held securely on this device, not by a company. + + + + I understand that if this app is moved to another device or deleted, my bitcoin can only be recovered with the backup phrase. + + +
+
+
+
+ + +
+ +
+
diff --git a/src/pages/onboarding/disclaimer/disclaimer.module.ts b/src/pages/onboarding/disclaimer/disclaimer.module.ts new file mode 100644 index 000000000..4e17e6827 --- /dev/null +++ b/src/pages/onboarding/disclaimer/disclaimer.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { DisclaimerPage } from './disclaimer'; + +@NgModule({ + declarations: [ + DisclaimerPage, + ], + imports: [ + IonicPageModule.forChild(DisclaimerPage), + ], +}) +export class DisclaimerPageModule {} diff --git a/src/pages/onboarding/disclaimer/disclaimer.scss b/src/pages/onboarding/disclaimer/disclaimer.scss new file mode 100644 index 000000000..d809d1431 --- /dev/null +++ b/src/pages/onboarding/disclaimer/disclaimer.scss @@ -0,0 +1,54 @@ +page-disclaimer { + .disclaimer { + .options { + padding-top: 20px; + } + .item { + background-color: transparent; + color: $v-onboarding-color; + } + .item-md.item-block .item-inner { + border-bottom: 0; + } + ion-label { + white-space: normal; + } + #agree-to-terms { + position: absolute; + bottom: 0; + width: 100%; + padding: 15px; + .item { + padding-left: 0px; + } + .terms-check { + text-align: left; + margin-bottom: 25px; + display: flex; + label { + font-size: 16px; + cursor: pointer; + } + a { + cursor: pointer; + } + .checkbox { + margin: auto; + padding: 5px; + } + .modal-text { + margin-left: 30px; + } + } + } + } + + .navbarc { + .bar-button { + color: $v-accent-color; + } + } + .header-md::after { + background: none; + } +} diff --git a/src/pages/onboarding/disclaimer/disclaimer.ts b/src/pages/onboarding/disclaimer/disclaimer.ts new file mode 100644 index 000000000..20f5a095c --- /dev/null +++ b/src/pages/onboarding/disclaimer/disclaimer.ts @@ -0,0 +1,39 @@ +import { Component } from '@angular/core'; +import { IonicPage, NavController, NavParams, ModalController} from 'ionic-angular'; + +@IonicPage() +@Component({ + selector: 'page-disclaimer', + templateUrl: 'disclaimer.html', +}) +export class DisclaimerPage { + public accepted: any; + public terms: any; + + constructor(public navCtrl: NavController, public navParams: NavParams, public modalCtrl: ModalController) { + this.accepted = { + first: false, + second: false, + }; + this.terms = { + accepted: false, + } + } + + ionViewDidLoad() { + } + + selectTerms() { + this.terms.accepted = !this.terms.accepted; + } + + openModal() { + const myModal = this.modalCtrl.create('DisclaimerModalPage'); + myModal.present(); + } + + confirm() { + // TODO accept disclaimer + this.navCtrl.popToRoot(); + } +} diff --git a/src/pages/onboarding/email/email.html b/src/pages/onboarding/email/email.html new file mode 100644 index 000000000..a97d90d83 --- /dev/null +++ b/src/pages/onboarding/email/email.html @@ -0,0 +1,46 @@ + + + + +
+ +
Wallet Created
+
+ +
+
+
Notifications by email
+
Where would you like to receive email notifications about payments?
+ +
+ + + Get news and updates from BitPay + + + +
+
+ +
+

Is this email address correct?

+

{{data.email}}

+
+
+ +
+
+ +
+
+
+
+ +
+ +
+
diff --git a/src/pages/onboarding/email/email.module.ts b/src/pages/onboarding/email/email.module.ts new file mode 100644 index 000000000..4284b01af --- /dev/null +++ b/src/pages/onboarding/email/email.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { EmailPage } from './email'; + +@NgModule({ + declarations: [ + EmailPage, + ], + imports: [ + IonicPageModule.forChild(EmailPage), + ], +}) +export class EmailPageModule {} diff --git a/src/pages/onboarding/email/email.scss b/src/pages/onboarding/email/email.scss new file mode 100644 index 000000000..3d632aa19 --- /dev/null +++ b/src/pages/onboarding/email/email.scss @@ -0,0 +1,201 @@ +page-email { + ion-label { + text-align: left !important; + white-space: normal; + } + .email { + color: $v-onboarding-color; + background: rgb(17, 209, 166) !important; + $relish-success: 1.3s; + + button { + &.primary { + border-color: transparent; + background-color: $v-accent-color; + color: $v-onboarding-color; + } + &.secondary { + background-color: transparent; + border-color: transparent; + color: $v-accent-color; + } + } + + #success-container { + text-align: center; + top: 41vh; + position: relative; + animation-name: emailCollectSlideUp; + animation-iteration-count: 1; + animation-timing-function: ease-in; + animation-duration: .5s; + animation-delay: $relish-success; + animation-fill-mode: forwards; + } + #success-image { + width: 13vh; + margin: 0 auto 2vh; + } + #success-message { + font-size: 3vh; + } + .collect-overlay { + position: absolute; + top:0; + left:0; + width:100%; + height: 100%; + background: rgba(0,0,0,.4); + z-index: 4; + animation-name: emailCollectOpacity; + animation-iteration-count: 1; + animation-timing-function: ease-in; + animation-duration: .2s; + animation-delay: $relish-success; + animation-fill-mode: forwards; + opacity: 0; + button { + position: absolute; + right: 0; + margin: 5% 1% 0 0; + background-color: transparent; + font-size: initial; + color: $v-light-gray; + text-transform: uppercase; + } + } + .heading { + text-align: center; + color: $v-dark-gray; + font-size: 2rem; + font-weight: bold; + margin: 2rem 0 1rem; + } + .prompt { + text-align: center; + margin: 1rem 1.5rem; + color: $v-mid-gray; + } + #email-form { + margin: 0 1.5rem 1rem; + } + #email-label { + border-radius: $v-visible-radius; + background: rgba(200, 200, 200, 0.20); + height: 3rem; + margin-top:0; + } + #collect-email { + opacity: 1; + background: #fff; + animation-name: topBottom; + animation-iteration-count: 1; + animation-timing-function: ease-in; + animation-duration: .4s; + animation-delay: $relish-success + .2s; + position: absolute; + bottom: -100%; + animation-fill-mode: forwards; + z-index: 5; + margin-top: 0; + width: 100%; + } + #collect-email-inner { + max-width: 400px; + margin: 0 auto; + input[type="email"] { + display: block; + padding-left: 0; + color: #445; + vertical-align: middle; + font-size: 16px; + line-height: 18px; + } + #email-label { + border-radius: 6px; + background: rgba(200, 200, 200, 0.2); + height: 4rem; + margin-top: 0; + } + } + + #collect-email-confirm { + text-align: center; + p.confirm { + margin: 2rem 0; + color: $v-mid-gray; + } + p.user-email { + color: $v-dark-gray; + margin-bottom: 2rem; + } + .row, .col { + padding: 0; + } + .button { + padding: 2.5rem; + margin-bottom: 0; + } + } + + #news-updates { + padding-top: 0; + } + .item { + border: none; + label { + background: none; + } + .checkbox input:before, + .checkbox .checkbox-icon:before { + border-radius: 50% !important; + background: none; + border-width: 2px; + padding: 12px; + position: relative; + right: 2px; + bottom: 2px; + } + .checkbox input:checked:after, + input:checked + .checkbox-icon:after { + border-color: $v-onboarding-checkbox-on-border; + top: 8px; + left: 6px; + } + .item-content { + color: $v-mid-gray; + text-align: left; + margin-left: 75px; + white-space: initial; + } + } + .item-checkbox { + padding: 1rem 0; + margin: 1rem 0; + } + .item-checkbox .checkbox { + margin-left: 15px; + } + .checkbox input:before, + .checkbox .checkbox-icon:before{ + border-color: $v-onboarding-checkbox-on-border; + } + .checkbox input:checked:before, + .checkbox input:checked + .checkbox-icon:before { + border-color: $v-onboarding-checkbox-on-border; + } + + @keyframes topBottom { + 0% { bottom: -100%; } + 100% { bottom: 0; } + } + @keyframes emailCollectOpacity { + 0% { opacity: 0; } + 100% { opacity: 1; } + } + @keyframes emailCollectSlideUp { + 0% { top: 41vh; } + 100% { top: calc((100vh - 20rem) / 2 - 11vh);} + } + } +} diff --git a/src/pages/onboarding/email/email.ts b/src/pages/onboarding/email/email.ts new file mode 100644 index 000000000..55e4a7b81 --- /dev/null +++ b/src/pages/onboarding/email/email.ts @@ -0,0 +1,49 @@ +import { Component } from '@angular/core'; +import { IonicPage, NavController, NavParams, ActionSheetController } from 'ionic-angular'; + +@IonicPage() +@Component({ + selector: 'page-email', + templateUrl: 'email.html', +}) +export class EmailPage { + public data: any; + public showConfirmForm: boolean; + + constructor(public navCtrl: NavController, public navParams: NavParams, public actionSheet: ActionSheetController) { + this.data = { + accept: true, + email: '', + }; + this.showConfirmForm = false; + } + + skip() { + this.navCtrl.push('BackupRequestPage'); + } + + showActionSheet() { + let actionSheet = this.actionSheet.create({ + buttons: [ + { + text: 'Continue', + role: 'destructor', + handler: () => { + console.log('Continue clicked'); + } + } + ] + }); + actionSheet.present(); + } + + showConfirm() { + if (!this.data.email) return; + this.showConfirmForm = !this.showConfirmForm; + } + + save() { + // TODO SAVE EMAIL + this.navCtrl.push('BackupRequestPage'); + } +} diff --git a/src/pages/onboarding/tour/tour.html b/src/pages/onboarding/tour/tour.html new file mode 100644 index 000000000..cc4ce0ee1 --- /dev/null +++ b/src/pages/onboarding/tour/tour.html @@ -0,0 +1,56 @@ + + + + + + + + + + + + + +
+

Bitcoin is secure,
digital money.

+

You can spend bitcoin at millions of websites and stores worldwide.

+
+
+ +
+
+
Just scan the code to pay.
+ +
+
+ + +
Bitcoin is a currency.
+
You can trade it for other currencies like US Dollars, Euros, or Pounds.
+ +
1 BTC = 2000 USD
+
+
The exchange rate changes with the market.
+ +
+
+ + +
You control your bitcoin.
+
This app stores your bitcoin with cutting-edge security.
+ +
+
Not even BitPay can access it.
+ +
+
+
+
diff --git a/src/pages/onboarding/tour/tour.module.ts b/src/pages/onboarding/tour/tour.module.ts new file mode 100644 index 000000000..bd78d6698 --- /dev/null +++ b/src/pages/onboarding/tour/tour.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { TourPage } from './tour'; + +@NgModule({ + declarations: [ + TourPage, + ], + imports: [ + IonicPageModule.forChild(TourPage), + ], +}) +export class TourPageModule { } diff --git a/src/pages/onboarding/tour/tour.scss b/src/pages/onboarding/tour/tour.scss new file mode 100644 index 000000000..8eed337c4 --- /dev/null +++ b/src/pages/onboarding/tour/tour.scss @@ -0,0 +1,32 @@ +page-tour { + .tour { + position: relative; + + .pages { + position: absolute; + } + .buttons { + padding: 15px; + width: 100%; + position: absolute; + bottom: 0px; + padding: 15px 15px 9vh 15px; + } + .slide-zoom { + height: inherit; + img { + padding-top: 10%; + width: 65%; + } + } + } + + .navbarc { + .bar-button { + color: $v-accent-color; + } + } + .header-md::after { + background: none; + } +} diff --git a/src/pages/onboarding/tour/tour.ts b/src/pages/onboarding/tour/tour.ts new file mode 100644 index 000000000..68e74cd3a --- /dev/null +++ b/src/pages/onboarding/tour/tour.ts @@ -0,0 +1,61 @@ +import { Component } from '@angular/core'; +import { IonicPage, NavController, NavParams, LoadingController } from 'ionic-angular'; +import { ViewChild } from '@angular/core'; +import { Slides, Navbar } from 'ionic-angular'; + +@IonicPage() +@Component({ + selector: 'page-tour', + templateUrl: 'tour.html', +}) +export class TourPage { + @ViewChild(Slides) slides: Slides; + @ViewChild(Navbar) navBar: Navbar; + + public currentIndex: number; + + constructor(public navCtrl: NavController, public navParams: NavParams, public loadingCtrl: LoadingController) { + } + + ionViewDidLoad() { + } + + ngOnInit() { + this.currentIndex = this.slides.getActiveIndex() || 0; + this.navBar.backButtonClick = (e: UIEvent) => { + this.slidePrev(); + } + } + + skip() { + this.navCtrl.push('EmailPage'); + } + + slidePrev() { + if (this.currentIndex == 0) this.navCtrl.pop(); + else { + this.slides.slidePrev(); + this.currentIndex = this.slides.getActiveIndex(); + } + } + + slideNext() { + this.slides.slideNext(); + this.currentIndex = this.slides.getActiveIndex(); + } + + createDefaultWallet() { + // TODO replace for bwc method + + let loading = this.loadingCtrl.create({ + content: 'Creating Personal Wallet...' + }); + loading.present(); + + setTimeout(() => { + loading.dismiss(); + this.navCtrl.push('EmailPage'); + }, 1500); + } + +} diff --git a/src/pages/onboarding/welcome/welcome.html b/src/pages/onboarding/welcome/welcome.html new file mode 100644 index 000000000..2638a87d4 --- /dev/null +++ b/src/pages/onboarding/welcome/welcome.html @@ -0,0 +1,14 @@ + + + + + +
+ +

Take control of your money,
get started with bitcoin.

+
+
+ + +
+
diff --git a/src/pages/onboarding/welcome/welcome.module.ts b/src/pages/onboarding/welcome/welcome.module.ts new file mode 100644 index 000000000..b503ff169 --- /dev/null +++ b/src/pages/onboarding/welcome/welcome.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { WelcomePage } from './welcome'; + +@NgModule({ + declarations: [ + WelcomePage, + ], + imports: [ + IonicPageModule.forChild(WelcomePage), + ], +}) +export class WelcomePageModule { } diff --git a/src/pages/onboarding/welcome/welcome.scss b/src/pages/onboarding/welcome/welcome.scss new file mode 100644 index 000000000..ed925aa5d --- /dev/null +++ b/src/pages/onboarding/welcome/welcome.scss @@ -0,0 +1,33 @@ +page-welcome { + .welcome { + position: relative; + + .logo-tagline { + position: absolute; + width: 100%; + height: 70%; + display: flex; + flex-direction: column; + justify-content: space-around; + + img { + width: 50%; + max-width: 200px; + margin: 5rem auto 0; + } + + p { + line-height: 1.6; + font-size: 18px; + text-align: center; + } + } + + .buttons { + width: 100%; + position: absolute; + bottom: 0px; + padding: 15px 15px 4vw 15px; + } + } +} diff --git a/src/pages/onboarding/welcome/welcome.ts b/src/pages/onboarding/welcome/welcome.ts new file mode 100644 index 000000000..672780af9 --- /dev/null +++ b/src/pages/onboarding/welcome/welcome.ts @@ -0,0 +1,26 @@ +import { Component } from '@angular/core'; +import { IonicPage, NavController, NavParams } from 'ionic-angular'; + +@IonicPage() +@Component({ + selector: 'page-welcome', + templateUrl: 'welcome.html', +}) +export class WelcomePage { + + constructor(public navCtrl: NavController, public navParams: NavParams) { + } + + ionViewDidLoad() { + } + + getStarted() { + this.navCtrl.push('TourPage'); + } + + initBackupFlow() { + // TODO navigate to backupFlow + this.navCtrl.push('BackupWarningPage'); + } + +} diff --git a/src/theme/variables.scss b/src/theme/variables.scss index 18276a461..fdc61d3ba 100644 --- a/src/theme/variables.scss +++ b/src/theme/variables.scss @@ -14,6 +14,26 @@ $app-direction: ltr; @import "ionic.globals"; +$v-primary-color: #192c3a; +$v-secondary-color: #31465b; +$v-accent-color: #1abb9b; + +$v-dark-gray: #445 !default; +$v-mid-gray: #667 !default; +$v-light-gray: #9b9bab !default; +$v-subtle-gray: darken(#ffffff, 5%) !default; + +$v-onboarding-color: #ffffff !default; +$v-onboarding-bar-header-color: #ffffff !default; +$v-onboarding-bar-header-button-color: #ffffff !default; +$v-onboarding-gradient-top-color: $v-primary-color !default; +$v-onboarding-gradient-bottom-color: $v-secondary-color !default; +$v-onboarding-checkbox-on-border: $v-accent-color; + +$v-button-primary-bg: $v-accent-color !default; + + +$v-visible-radius: 6px !default; // Shared Variables // -------------------------------------------------- @@ -86,3 +106,85 @@ $colors: ( @import "roboto"; @import "noto-sans"; + + +// Onboarding --------------------------------------- +.checkbox .checkbox-icon { + border-color: $v-accent-color !important; + position: relative !important; + width: 28px !important; + height: 28px !important; + display: block !important; + background: transparent !important; + -webkit-appearance: none !important; + border-radius: 50% !important; +} + +.checkbox .checkbox-checked .checkbox-inner { + left: 40% !important; + top: 15% !important; + height: 15px !important; + border-color: $v-accent-color !important; +} + +.onboarding { + color: $v-onboarding-color !important; + background: $v-onboarding-gradient-top-color; + background-image: linear-gradient(to bottom, $v-onboarding-gradient-top-color 0%, $v-onboarding-gradient-bottom-color 100%); + height: 100%; + text-align: center; + + .onboarding-topic, + .onboarding-description, + .onboarding-tldr { + margin-left: 3rem; + margin-right: 3rem; + } + .onboarding-topic { + font-size: 24px; + margin-top: .5rem; + line-height: 1.3; + @media(max-width: 350px) { + font-size: 20px; + } + } + .onboarding-description { + margin-top: 1rem; + font-size: 16px; + color: rgba(255,255,255,0.5); + line-height: 1.5; + @media(max-width: 350px) { + line-height: 1.3; + } + @media(max-height: 480px) { + font-size: 16px; + } + } + .onboarding-tldr { + font-size: 18px; + margin-top: 1rem; + margin-bottom: 1em; + line-height: 1.3; + @media(max-width: 350px) { + font-size: 16px; + } + @media(max-height: 480px) { + font-size: 14px; + } + } + button { + &.primary { + border-color: transparent; + background-color: $v-accent-color; + color: $v-onboarding-color; + } + &.secondary { + background-color: transparent; + border-color: transparent; + color: $v-accent-color; + } + } + .swiper-pagination-bullet { + background-color: $v-accent-color; + } +}