diff --git a/Gruntfile.js b/Gruntfile.js
index 52c0f1338..b094c4edb 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -128,6 +128,7 @@ module.exports = function(grunt) {
'bower_components/angular-clipboard/angular-clipboard.js',
'bower_components/angular-md5/angular-md5.js',
'bower_components/angular-mocks/angular-mocks.js',
+ 'bower_components/ngtouch/src/ngTouch.js',
'angular-pbkdf2/angular-pbkdf2.js',
'angular-bitcore-wallet-client/angular-bitcore-wallet-client.js'
],
@@ -148,6 +149,7 @@ module.exports = function(grunt) {
'src/js/init.js',
'src/js/trezor-url.js',
'bower_components/trezor-connect/login.js',
+ 'node_modules/bezier-easing/dist/bezier-easing.min.js',
'node_modules/cordova-plugin-qrscanner/dist/cordova-plugin-qrscanner-lib.min.js'
],
dest: 'www/js/copay.js'
diff --git a/bower.json b/bower.json
index ed6b9bd64..912826903 100644
--- a/bower.json
+++ b/bower.json
@@ -19,7 +19,8 @@
"ng-csv": "~0.3.6",
"ionic-toast": "^0.4.1",
"angular-clipboard": "^1.4.2",
- "angular-md5": "^0.1.10"
+ "angular-md5": "^0.1.10",
+ "ngtouch": "^1.0.1"
},
"resolutions": {
"angular": "1.5.3"
diff --git a/package.json b/package.json
index 40253d2d0..e474ad514 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
"adm-zip": "^0.4.7",
"angular": "1.4.6",
"angular-mocks": "1.4.10",
+ "bezier-easing": "^2.0.3",
"bhttp": "^1.2.1",
"bitcore-wallet-client": "4.2.1",
"bower": "^1.7.9",
diff --git a/src/js/app.js b/src/js/app.js
index 001bf9826..91466a757 100644
--- a/src/js/app.js
+++ b/src/js/app.js
@@ -7,6 +7,7 @@ var modules = [
'ionic',
'ionic-toast',
'angular-clipboard',
+ 'ngTouch',
'ngLodash',
'ngCsv',
'angular-md5',
diff --git a/src/js/controllers/confirm.js b/src/js/controllers/confirm.js
index 868a45856..05fc6a322 100644
--- a/src/js/controllers/confirm.js
+++ b/src/js/controllers/confirm.js
@@ -1,6 +1,6 @@
'use strict';
-angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, profileService, bitcore, gettext, txFormatService, ongoingProcess, $ionicModal, popupService) {
+angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, profileService, bitcore, gettext, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory) {
var cachedTxp = {};
var isChromeApp = platformInfo.isChromeApp;
@@ -273,9 +273,10 @@ angular.module('copayApp.controllers').controller('confirmController', function(
if (err) return setSendError(err);
});
}
- ongoingProcess.set('creatingTx', true);
+
+ ongoingProcess.set('creatingTx', true, onSendStatusChange);
createTx(wallet, false, function(err, txp) {
- ongoingProcess.set('creatingTx', false);
+ ongoingProcess.set('creatingTx', false, onSendStatusChange);
if (err) return;
var config = configService.getSync();
@@ -308,9 +309,29 @@ angular.module('copayApp.controllers').controller('confirmController', function(
});
};
+ function onSendStatusChange(processName, showName, isOn) {
+ if(processName === 'broadcastingTx' && !isOn) {
+ $scope.sendStatus = 'success';
+ $scope.$digest();
+ } else if(showName) {
+ $scope.sendStatus = showName;
+ }
+ }
+
+ $scope.onConfirm = function() {
+ $scope.approve(true);
+ };
+
+ $scope.onSuccessConfirm = function() {
+ $ionicHistory.nextViewOptions({
+ disableAnimate: true
+ });
+ $state.go('tabs.send');
+ };
+
function publishAndSign(wallet, txp) {
walletService.publishAndSign(wallet, txp, function(err, txp) {
if (err) return setSendError(err);
- });
- };
+ }, onSendStatusChange);
+ }
});
diff --git a/src/js/controllers/onboarding/tour.js b/src/js/controllers/onboarding/tour.js
index aa2cdd92e..71d516145 100644
--- a/src/js/controllers/onboarding/tour.js
+++ b/src/js/controllers/onboarding/tour.js
@@ -44,10 +44,11 @@ angular.module('copayApp.controllers').controller('tourController',
};
ongoingProcess.set('creatingWallet', false);
var wallet = walletClient;
- $state.go('onboarding.collectEmail', {
- fromOnboarding: true,
- walletId: wallet.credentials.walletId
- });
+ // $state.go('onboarding.collectEmail', {
+ // fromOnboarding: true,
+ // walletId: wallet.credentials.walletId
+ // });
+ $state.go('tabs.home');
});
};
diff --git a/src/js/directives/directives.js b/src/js/directives/directives.js
index e20643e9f..ecf849b10 100644
--- a/src/js/directives/directives.js
+++ b/src/js/directives/directives.js
@@ -162,23 +162,4 @@ angular.module('copayApp.directives')
});
}
}
- })
- .directive('accept', function() {
- return {
- restrict: 'E',
- templateUrl: 'views/includes/acceptSlide.html',
- scope: {},
- link: function(scope, element, attrs) {
- scope.$on("$ionicSlides.sliderInitialized", function(event, data) {
- scope.slider = data.slider;
- });
-
- scope.$on("$ionicSlides.slideChangeEnd", function(event, data) {
- if (data.slider.activeIndex == 0) {
- scope.slider.slideNext();
- scope.$emit('accepted');
- }
- });
- }
- }
});
diff --git a/src/js/directives/slideToAccept.js b/src/js/directives/slideToAccept.js
new file mode 100644
index 000000000..f47a60d70
--- /dev/null
+++ b/src/js/directives/slideToAccept.js
@@ -0,0 +1,249 @@
+'use strict';
+
+angular.module('copayApp.directives')
+ .directive('slideToAccept', function($timeout, $window, $q) {
+ return {
+ restrict: 'E',
+ templateUrl: 'views/includes/slideToAccept.html',
+ transclude: true,
+ scope: {
+ sendStatus: '=slideSendStatus',
+ onConfirm: '&slideOnConfirm'
+ },
+ link: function(scope, element, attrs) {
+
+ var KNOB_WIDTH = 71;
+ var MAX_SLIDE_START_PERCENTAGE = 50;
+ var FULLY_SLID_PERCENTAGE = 72;
+ var PERCENTAGE_BUMP = 5;
+ var JIGGLE_EASING = linear;
+ var JIGGLE_DURATION = 100;
+ var RECEDE_DURATION = 250;
+ var INITIAL_TAP_EASE_DURATION = 75;
+
+ var elm = element[0];
+ var isSliding = false;
+ var curSliderPct = getKnobWidthPercentage();
+ var curBitcoinPct = 0;
+ var curTextPct = 0;
+ var currentEaseStartTime;
+ var bezier = $window.BezierEasing(0.175, 0.885, 0.320, 1.275);
+
+ scope.isSlidFully = false;
+ scope.displaySendStatus = '';
+
+ scope.$watch('sendStatus', function() {
+ if(scope.sendStatus === 'success') {
+ scope.displaySendStatus = '';
+ reset();
+ } else {
+ scope.displaySendStatus = scope.sendStatus;
+ }
+ });
+
+ function easePosition(fromPct, pct, duration, easeFx, animateFx) {
+ var deferred = $q.defer();
+ currentEaseStartTime = Date.now();
+ var startTime = currentEaseStartTime;
+ var initialPct = fromPct;
+ var distance = pct - fromPct;
+ function ease() {
+ if(startTime !== currentEaseStartTime) {
+ return;
+ }
+ $window.requestAnimationFrame(function() {
+ var now = Date.now();
+ var elapsed = now - startTime;
+ var normalizedElapsedTime = elapsed/duration;
+ var newVal = easeFx(normalizedElapsedTime);
+ var newPct = newVal*distance + initialPct;
+ animateFx(newPct);
+ scope.$digest();
+ if(elapsed < duration) {
+ ease();
+ } else {
+ deferred.resolve();
+ }
+ });
+ }
+ ease();
+ return deferred.promise;
+ }
+
+ function linear(t) {
+ return t;
+ }
+
+ function easeInOutBack(t) {
+ return bezier(t);
+ }
+
+ function reset() {
+ $timeout(function() {
+ scope.isSlidFully = false;
+ isSliding = false;
+ setNewSliderStyle(getKnobWidthPercentage());
+ setNewBitcoinStyle(0);
+ setNewTextStyle(0);
+ }, 500);
+ }
+
+ function setNewSliderStyle(pct) {
+ var knobWidthPct = getKnobWidthPercentage();
+ var translatePct = pct - knobWidthPct;
+ if(isSliding) {
+ translatePct += 0.35*pct;
+ }
+ scope.sliderStyle = getTransformStyle(translatePct);
+ curSliderPct = pct;
+ }
+
+ function setNewBitcoinStyle(pct) {
+ var translatePct = -2.25*pct;
+ scope.bitcoinStyle = getTransformStyle(translatePct);
+ curBitcoinPct = pct;
+ }
+
+ function setNewTextStyle(pct) {
+ var translatePct = -0.1*pct;
+ scope.textStyle = getTransformStyle(translatePct);
+ curTextPct = pct;
+ }
+
+ function getTransformStyle(translatePct) {
+ return {'transform': 'translateX(' + translatePct + '%)'};
+ }
+
+ function getKnobWidthPercentage() {
+ var knobWidthPct = (KNOB_WIDTH/elm.clientWidth)*100;
+ return knobWidthPct;
+ }
+
+ function setSliderPosition(pct) {
+ setNewSliderStyle(pct);
+ setNewBitcoinStyle(pct);
+ setNewTextStyle(pct);
+ }
+
+ function easeSliderPosition(pct) {
+ var duration = INITIAL_TAP_EASE_DURATION;
+ easePosition(curSliderPct, pct, duration, JIGGLE_EASING, function(pct) {
+ setNewSliderStyle(pct);
+ });
+ easePosition(curBitcoinPct, pct, duration, JIGGLE_EASING, function(pct) {
+ setNewBitcoinStyle(pct);
+ });
+ easePosition(curTextPct, pct, duration, JIGGLE_EASING, function(pct) {
+ setNewTextStyle(pct);
+ });
+ }
+
+ function jiggleSlider() {
+ var pct = getKnobWidthPercentage() + PERCENTAGE_BUMP;
+ var duration = JIGGLE_DURATION;
+ var p1 = easePosition(curSliderPct, pct, duration, JIGGLE_EASING, function(pct) {
+ setNewSliderStyle(pct);
+ });
+ var p2 = easePosition(curBitcoinPct, pct, duration, JIGGLE_EASING, function(pct) {
+ setNewBitcoinStyle(pct);
+ });
+
+ $q.all([p1, p2]).then(function() {
+ recede();
+ });
+ }
+
+ function recede() {
+ var duration = RECEDE_DURATION;
+ easePosition(curSliderPct, getKnobWidthPercentage(), duration, easeInOutBack, function(pct) {
+ setNewSliderStyle(pct);
+ });
+ easePosition(curBitcoinPct, 0, duration, easeInOutBack, function(pct) {
+ setNewBitcoinStyle(pct);
+ });
+ easePosition(curTextPct, 0, duration, easeInOutBack, function(pct) {
+ setNewTextStyle(pct);
+ });
+ }
+
+ function alertSlidFully() {
+ scope.isSlidFully = true;
+ scope.onConfirm();
+ }
+
+ function getTouchXPosition($event) {
+ var x;
+ if($event.touches || $event.changedTouches) {
+ if($event.touches.length) {
+ x = $event.touches[0].clientX;
+ } else {
+ x = $event.changedTouches[0].clientX;
+ }
+ } else {
+ x = $event.clientX;
+ }
+ return x;
+ }
+
+ function getSlidPercentage($event) {
+ var x = getTouchXPosition($event);
+ var width = elm.clientWidth;
+ var pct = (x/width)*100;
+ if(x >= width) {
+ pct = 100;
+ }
+ return pct;
+ }
+
+ scope.onTouchstart = function($event) {
+ if(scope.isSlidFully) {
+ return;
+ }
+ if(!isSliding) {
+ var pct = getSlidPercentage($event);
+ if (pct > MAX_SLIDE_START_PERCENTAGE) {
+ jiggleSlider();
+ return;
+ } else {
+ isSliding = true;
+ var knobWidthPct = getKnobWidthPercentage();
+ if(pct < knobWidthPct) {
+ pct = knobWidthPct;
+ }
+ pct += PERCENTAGE_BUMP;
+ easeSliderPosition(pct);
+ }
+ }
+ };
+
+ scope.onTouchmove = function($event) {
+ if(!isSliding || scope.isSlidFully) {
+ return;
+ }
+ var pct = getSlidPercentage($event);
+ var knobWidthPct = getKnobWidthPercentage();
+ if(pct < knobWidthPct) {
+ pct = knobWidthPct;
+ }
+ pct += PERCENTAGE_BUMP;
+ currentEaseStartTime = null;
+ setSliderPosition(pct);
+ };
+
+ scope.onTouchend = function($event) {
+ if(scope.isSlidFully) {
+ return;
+ }
+ var pct = getSlidPercentage($event);
+ if(isSliding && pct > FULLY_SLID_PERCENTAGE) {
+ pct = 100;
+ setSliderPosition(pct);
+ alertSlidFully();
+ } else {
+ recede();
+ }
+ isSliding = false;
+ };
+ }
+ };
+ });
diff --git a/src/js/directives/slideToAcceptSuccess.js b/src/js/directives/slideToAcceptSuccess.js
new file mode 100644
index 000000000..4a7312703
--- /dev/null
+++ b/src/js/directives/slideToAcceptSuccess.js
@@ -0,0 +1,31 @@
+'use strict';
+
+angular.module('copayApp.directives')
+ .directive('slideToAcceptSuccess', function($timeout) {
+ return {
+ restrict: 'E',
+ templateUrl: 'views/includes/slideToAcceptSuccess.html',
+ transclude: true,
+ scope: {
+ isShown: '=slideSuccessShow',
+ onConfirm: '&slideSuccessOnConfirm'
+ },
+ link: function(scope, element, attrs) {
+ var elm = element[0];
+ elm.style.display = 'none';
+ scope.$watch('isShown', function() {
+ if(scope.isShown) {
+ elm.style.display = 'flex';
+ $timeout(function() {
+ scope.fillScreen = true;
+ }, 10);
+ }
+ });
+ scope.onConfirmButtonClick = function() {
+ scope.onConfirm();
+ scope.fillScreen = false;
+ elm.style.display = 'none';
+ };
+ }
+ };
+ });
diff --git a/src/js/routes.js b/src/js/routes.js
index a69f00072..183e5eab3 100644
--- a/src/js/routes.js
+++ b/src/js/routes.js
@@ -32,6 +32,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
// NAV BACK-BUTTON TEXT/ICON
$ionicConfigProvider.backButton.icon('icon ion-ios-arrow-thin-left').text('');
$ionicConfigProvider.backButton.previousTitleText(false);
+ $ionicConfigProvider.views.swipeBackEnabled(false);
$logProvider.debugEnabled(true);
$provide.decorator('$log', ['$delegate', 'platformInfo',
diff --git a/src/js/services/onGoingProcess.js b/src/js/services/onGoingProcess.js
index 642051951..d1bcf2fe0 100644
--- a/src/js/services/onGoingProcess.js
+++ b/src/js/services/onGoingProcess.js
@@ -48,7 +48,7 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
return ongoingProcess[processName];
};
- root.set = function(processName, isOn) {
+ root.set = function(processName, isOn, customHandler) {
$log.debug('ongoingProcess', processName, isOn);
root[processName] = isOn;
ongoingProcess[processName] = isOn;
@@ -64,7 +64,9 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
var showName = $filter('translate')(processNames[name] || name);
- if (root.onGoingProcessName) {
+ if(customHandler) {
+ customHandler(processName, showName, isOn);
+ } else if (root.onGoingProcessName) {
if (isCordova) {
window.plugins.spinnerDialog.show(null, showName, true);
} else {
diff --git a/src/js/services/walletService.js b/src/js/services/walletService.js
index 84bfea06a..a3218b90c 100644
--- a/src/js/services/walletService.js
+++ b/src/js/services/walletService.js
@@ -915,7 +915,7 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
});
};
- root.publishAndSign = function(wallet, txp, cb) {
+ root.publishAndSign = function(wallet, txp, cb, customStatusHandler) {
var publishFn = root.publishTx;
@@ -929,12 +929,13 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
root.prepare(wallet, function(err, password) {
if (err) return cb('Prepare error: ' + err);
- ongoingProcess.set('sendingTx', true);
+ ongoingProcess.set('sendingTx', true, customStatusHandler);
+
publishFn(wallet, txp, function(err, publishedTxp) {
- ongoingProcess.set('sendingTx', false);
+ ongoingProcess.set('sendingTx', false, customStatusHandler);
if (err) return cb('Send Error: ' + err);
- ongoingProcess.set('signingTx', true);
+ ongoingProcess.set('signingTx', true, customStatusHandler);
root.signTx(wallet, publishedTxp, password, function(err, signedTxp) {
ongoingProcess.set('signingTx', false);
root.invalidateCache(wallet);
@@ -952,22 +953,29 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
}
if (signedTxp.status == 'accepted') {
- ongoingProcess.set('broadcastingTx', true);
+ ongoingProcess.set('broadcastingTx', true, customStatusHandler);
root.broadcastTx(wallet, signedTxp, function(err, broadcastedTxp) {
- ongoingProcess.set('broadcastingTx', false);
+ ongoingProcess.set('broadcastingTx', false, customStatusHandler);
if (err) return cb('sign error' + err);
$rootScope.$emit('Local/TxAction', wallet.id);
var type = root.getViewStatus(wallet, broadcastedTxp);
- root.openStatusModal(type, broadcastedTxp, function() {});
- return cb(null, broadcastedTxp)
+ if(!customStatusHandler) {
+ root.openStatusModal(type, broadcastedTxp, function() {});
+ }
+
+ return cb(null, broadcastedTxp);
});
} else {
$rootScope.$emit('Local/TxAction', wallet.id);
var type = root.getViewStatus(wallet, signedTxp);
- root.openStatusModal(type, signedTxp, function() {});
+
+ if(!customStatusHandler) {
+ root.openStatusModal(type, signedTxp, function() {});
+ }
+
return cb(null, signedTxp);
}
});
diff --git a/src/sass/views/includes/slideToAccept.scss b/src/sass/views/includes/slideToAccept.scss
new file mode 100644
index 000000000..4257097b8
--- /dev/null
+++ b/src/sass/views/includes/slideToAccept.scss
@@ -0,0 +1,126 @@
+slide-to-accept {
+ $slide-bg-color: #647CE8;
+ $slider-bg-color: #5063B9;
+ $slide-text-color: #FFFFFF;
+ position: fixed;
+ bottom: 0;
+ height: 92px;
+ width: 100%;
+ background: $slide-bg-color;
+
+ @mixin center-vertically {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ position: absolute;
+ }
+
+ .slide {
+ &__listener {
+ height: 100%;
+ width: 100%;
+ overflow: hidden;
+ position: relative;
+ }
+ &__slider {
+ @include center-vertically;
+ height: 100%;
+ width: 100%;
+ background: $slider-bg-color;
+ transform: translateX(0);
+ margin-left: -100%;
+ z-index: 2;
+
+ &::before {
+ @include center-vertically;
+ content: '';
+ width: 10000px;
+ left: -10000px + 1;
+ background: $slider-bg-color;
+ }
+
+ &::after {
+ @include center-vertically;
+ content: '';
+ width: 15px;
+ right: -10px;
+ background: $slider-bg-color;
+ }
+
+ &__tip {
+ @include center-vertically;
+ width: 124px;
+ height: 116px;
+ background: $slider-bg-color;
+ right: -71px;
+ border-radius: 50%;
+ top: 50%;
+ transform: translateY(-47%);
+ }
+
+ }
+ &__bitcoin {
+ @include center-vertically;
+ left: 20px;
+ z-index: 3;
+
+ > img {
+ transform: rotateZ(-5deg);
+ }
+ }
+ &__button-text {
+ @include center-vertically;
+
+ justify-content: center;
+ top: 0;
+ left: 0;
+ width: 100%;
+ color: $slide-text-color;
+ font-size: 18px;
+ font-weight: 600;
+ letter-spacing: .03rem;
+ z-index: 1;
+ }
+
+ &__status-text {
+ @include center-vertically;
+ justify-content: center;
+ color: $slide-text-color;
+ z-index: 4;
+ width: 100%;
+ font-size: 17px;
+ letter-spacing: 0.02rem;
+ text-transform: capitalize;
+ transform: translateY(2rem);
+ opacity: 0;
+ transition: transform 250ms ease, opacity 250ms ease;
+
+ &.enter {
+ transform: translateY(0);
+ opacity: 1;
+ }
+
+ > img {
+ margin-right: 10px;
+ animation-name: spin;
+ animation-duration: 500ms;
+ animation-iteration-count: infinite;
+ animation-timing-function: linear;
+ }
+ }
+
+ &__arrow {
+ @include center-vertically;
+ right: 20px;
+ }
+ }
+
+ @keyframes spin {
+ from {
+ transform:rotate(0deg);
+ }
+ to {
+ transform:rotate(360deg);
+ }
+ }
+}
diff --git a/src/sass/views/includes/slideToAcceptSuccess.scss b/src/sass/views/includes/slideToAcceptSuccess.scss
new file mode 100644
index 000000000..fe9b75969
--- /dev/null
+++ b/src/sass/views/includes/slideToAcceptSuccess.scss
@@ -0,0 +1,96 @@
+slide-to-accept-success {
+ $slider-bg-color: #5063B9;
+ $success-bg-color: #11D1A6;
+ height: 100%;
+ width: 100%;
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 99999;
+ text-align: center;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ .slide-success {
+ $duration: 400ms;
+ &__background {
+ $start-radius: 5;
+ $scale-factor: 20;
+ height: 10vmax;
+ width: 10vmax;
+ background: $slider-bg-color;
+ bottom: 0;
+ position: absolute;
+ left: calc(50% - 5vmax);
+ border-radius: 50%;
+ transition: transform $duration*1.5 ease, background $duration*1.5 ease;
+
+ &.fill-screen {
+ transform: scale3d($scale-factor, $scale-factor, 1) translateY(-40%);
+ background: $success-bg-color;
+ }
+ }
+
+ &__content {
+ position: relative;
+ z-index: 1;
+ margin-top: -20vh;
+
+ > img {
+ margin-bottom: 1.8rem;
+ transform: translateY(5rem);
+ opacity: 0;
+ transition: transform $duration ease, opacity $duration ease;
+ transition-delay: 200ms;
+
+ &.reveal {
+ transform: translateY(0);
+ opacity: 1;
+ }
+ }
+
+ &__header {
+ color: #FFFFFF;
+ font-size: 26px;
+ transform: translateY(5rem);
+ opacity: 0;
+ transition: transform $duration ease, opacity $duration ease;
+ transition-delay: 250ms;
+
+ &.reveal {
+ transform: translateY(0);
+ opacity: 1;
+ }
+ }
+ }
+
+ &__footer {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ padding: 0 1.75rem;
+ width: 100%;
+ transform: translateY(5rem);
+ opacity: 0;
+ transition: transform $duration ease, opacity $duration ease;
+ transition-delay: 250ms;
+
+ &.reveal {
+ transform: translateY(0);
+ opacity: 1;
+ }
+
+ &__btn {
+ display: block;
+ color: #FFFFFF;
+ font-size: 18px;
+ font-weight: 600;
+ letter-spacing: 2.86px;
+ padding: 1rem 0 1.1rem;
+ border-top: 1px solid rgba(255, 255, 255, .45);
+ cursor: pointer;
+ }
+ }
+ }
+}
diff --git a/src/sass/views/views.scss b/src/sass/views/views.scss
index ee6645bbb..d7d4cb891 100644
--- a/src/sass/views/views.scss
+++ b/src/sass/views/views.scss
@@ -19,6 +19,8 @@
@import "includes/walletActivity";
@import "includes/wallets";
@import "includes/modals/modals";
+@import "includes/slideToAccept";
+@import "includes/slideToAcceptSuccess";
@import "includes/tx-details";
@import "includes/txp-details";
@import "includes/tx-status";
diff --git a/www/img/icon-arrow-right.svg b/www/img/icon-arrow-right.svg
new file mode 100644
index 000000000..3381555ca
--- /dev/null
+++ b/www/img/icon-arrow-right.svg
@@ -0,0 +1,17 @@
+
+
\ No newline at end of file
diff --git a/www/img/icon-bitcoin-white.svg b/www/img/icon-bitcoin-white.svg
new file mode 100644
index 000000000..ef8cee901
--- /dev/null
+++ b/www/img/icon-bitcoin-white.svg
@@ -0,0 +1,14 @@
+
+
\ No newline at end of file
diff --git a/www/img/spinner.png b/www/img/spinner.png
new file mode 100644
index 000000000..591bc204f
Binary files /dev/null and b/www/img/spinner.png differ
diff --git a/www/views/confirm.html b/www/views/confirm.html
index aa039f4b4..541a43d1b 100644
--- a/www/views/confirm.html
+++ b/www/views/confirm.html
@@ -61,5 +61,16 @@
-