mirror of https://github.com/BTCPrivate/copay.git
implement slide to pay
This commit is contained in:
parent
039712fa54
commit
777c2efc32
|
@ -128,6 +128,7 @@ module.exports = function(grunt) {
|
||||||
'bower_components/angular-clipboard/angular-clipboard.js',
|
'bower_components/angular-clipboard/angular-clipboard.js',
|
||||||
'bower_components/angular-md5/angular-md5.js',
|
'bower_components/angular-md5/angular-md5.js',
|
||||||
'bower_components/angular-mocks/angular-mocks.js',
|
'bower_components/angular-mocks/angular-mocks.js',
|
||||||
|
'bower_components/ngtouch/src/ngTouch.js',
|
||||||
'angular-pbkdf2/angular-pbkdf2.js',
|
'angular-pbkdf2/angular-pbkdf2.js',
|
||||||
'angular-bitcore-wallet-client/angular-bitcore-wallet-client.js'
|
'angular-bitcore-wallet-client/angular-bitcore-wallet-client.js'
|
||||||
],
|
],
|
||||||
|
@ -148,6 +149,7 @@ module.exports = function(grunt) {
|
||||||
'src/js/init.js',
|
'src/js/init.js',
|
||||||
'src/js/trezor-url.js',
|
'src/js/trezor-url.js',
|
||||||
'bower_components/trezor-connect/login.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'
|
'node_modules/cordova-plugin-qrscanner/dist/cordova-plugin-qrscanner-lib.min.js'
|
||||||
],
|
],
|
||||||
dest: 'www/js/copay.js'
|
dest: 'www/js/copay.js'
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
"ng-csv": "~0.3.6",
|
"ng-csv": "~0.3.6",
|
||||||
"ionic-toast": "^0.4.1",
|
"ionic-toast": "^0.4.1",
|
||||||
"angular-clipboard": "^1.4.2",
|
"angular-clipboard": "^1.4.2",
|
||||||
"angular-md5": "^0.1.10"
|
"angular-md5": "^0.1.10",
|
||||||
|
"ngtouch": "^1.0.1"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"angular": "1.5.3"
|
"angular": "1.5.3"
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
"adm-zip": "^0.4.7",
|
"adm-zip": "^0.4.7",
|
||||||
"angular": "1.4.6",
|
"angular": "1.4.6",
|
||||||
"angular-mocks": "1.4.10",
|
"angular-mocks": "1.4.10",
|
||||||
|
"bezier-easing": "^2.0.3",
|
||||||
"bhttp": "^1.2.1",
|
"bhttp": "^1.2.1",
|
||||||
"bitcore-wallet-client": "4.2.1",
|
"bitcore-wallet-client": "4.2.1",
|
||||||
"bower": "^1.7.9",
|
"bower": "^1.7.9",
|
||||||
|
|
|
@ -7,6 +7,7 @@ var modules = [
|
||||||
'ionic',
|
'ionic',
|
||||||
'ionic-toast',
|
'ionic-toast',
|
||||||
'angular-clipboard',
|
'angular-clipboard',
|
||||||
|
'ngTouch',
|
||||||
'ngLodash',
|
'ngLodash',
|
||||||
'ngCsv',
|
'ngCsv',
|
||||||
'angular-md5',
|
'angular-md5',
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'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 cachedTxp = {};
|
||||||
var isChromeApp = platformInfo.isChromeApp;
|
var isChromeApp = platformInfo.isChromeApp;
|
||||||
|
|
||||||
|
@ -273,9 +273,10 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
if (err) return setSendError(err);
|
if (err) return setSendError(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ongoingProcess.set('creatingTx', true);
|
|
||||||
|
ongoingProcess.set('creatingTx', true, onSendStatusChange);
|
||||||
createTx(wallet, false, function(err, txp) {
|
createTx(wallet, false, function(err, txp) {
|
||||||
ongoingProcess.set('creatingTx', false);
|
ongoingProcess.set('creatingTx', false, onSendStatusChange);
|
||||||
if (err) return;
|
if (err) return;
|
||||||
|
|
||||||
var config = configService.getSync();
|
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) {
|
function publishAndSign(wallet, txp) {
|
||||||
walletService.publishAndSign(wallet, txp, function(err, txp) {
|
walletService.publishAndSign(wallet, txp, function(err, txp) {
|
||||||
if (err) return setSendError(err);
|
if (err) return setSendError(err);
|
||||||
});
|
}, onSendStatusChange);
|
||||||
};
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -44,10 +44,11 @@ angular.module('copayApp.controllers').controller('tourController',
|
||||||
};
|
};
|
||||||
ongoingProcess.set('creatingWallet', false);
|
ongoingProcess.set('creatingWallet', false);
|
||||||
var wallet = walletClient;
|
var wallet = walletClient;
|
||||||
$state.go('onboarding.collectEmail', {
|
// $state.go('onboarding.collectEmail', {
|
||||||
fromOnboarding: true,
|
// fromOnboarding: true,
|
||||||
walletId: wallet.credentials.walletId
|
// walletId: wallet.credentials.walletId
|
||||||
});
|
// });
|
||||||
|
$state.go('tabs.home');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
|
@ -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';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
|
@ -32,6 +32,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
|
||||||
// NAV BACK-BUTTON TEXT/ICON
|
// NAV BACK-BUTTON TEXT/ICON
|
||||||
$ionicConfigProvider.backButton.icon('icon ion-ios-arrow-thin-left').text('');
|
$ionicConfigProvider.backButton.icon('icon ion-ios-arrow-thin-left').text('');
|
||||||
$ionicConfigProvider.backButton.previousTitleText(false);
|
$ionicConfigProvider.backButton.previousTitleText(false);
|
||||||
|
$ionicConfigProvider.views.swipeBackEnabled(false);
|
||||||
|
|
||||||
$logProvider.debugEnabled(true);
|
$logProvider.debugEnabled(true);
|
||||||
$provide.decorator('$log', ['$delegate', 'platformInfo',
|
$provide.decorator('$log', ['$delegate', 'platformInfo',
|
||||||
|
|
|
@ -48,7 +48,7 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
|
||||||
return ongoingProcess[processName];
|
return ongoingProcess[processName];
|
||||||
};
|
};
|
||||||
|
|
||||||
root.set = function(processName, isOn) {
|
root.set = function(processName, isOn, customHandler) {
|
||||||
$log.debug('ongoingProcess', processName, isOn);
|
$log.debug('ongoingProcess', processName, isOn);
|
||||||
root[processName] = isOn;
|
root[processName] = isOn;
|
||||||
ongoingProcess[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);
|
var showName = $filter('translate')(processNames[name] || name);
|
||||||
|
|
||||||
if (root.onGoingProcessName) {
|
if(customHandler) {
|
||||||
|
customHandler(processName, showName, isOn);
|
||||||
|
} else if (root.onGoingProcessName) {
|
||||||
if (isCordova) {
|
if (isCordova) {
|
||||||
window.plugins.spinnerDialog.show(null, showName, true);
|
window.plugins.spinnerDialog.show(null, showName, true);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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;
|
var publishFn = root.publishTx;
|
||||||
|
|
||||||
|
@ -929,12 +929,13 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
root.prepare(wallet, function(err, password) {
|
root.prepare(wallet, function(err, password) {
|
||||||
if (err) return cb('Prepare error: ' + err);
|
if (err) return cb('Prepare error: ' + err);
|
||||||
|
|
||||||
ongoingProcess.set('sendingTx', true);
|
ongoingProcess.set('sendingTx', true, customStatusHandler);
|
||||||
|
|
||||||
publishFn(wallet, txp, function(err, publishedTxp) {
|
publishFn(wallet, txp, function(err, publishedTxp) {
|
||||||
ongoingProcess.set('sendingTx', false);
|
ongoingProcess.set('sendingTx', false, customStatusHandler);
|
||||||
if (err) return cb('Send Error: ' + err);
|
if (err) return cb('Send Error: ' + err);
|
||||||
|
|
||||||
ongoingProcess.set('signingTx', true);
|
ongoingProcess.set('signingTx', true, customStatusHandler);
|
||||||
root.signTx(wallet, publishedTxp, password, function(err, signedTxp) {
|
root.signTx(wallet, publishedTxp, password, function(err, signedTxp) {
|
||||||
ongoingProcess.set('signingTx', false);
|
ongoingProcess.set('signingTx', false);
|
||||||
root.invalidateCache(wallet);
|
root.invalidateCache(wallet);
|
||||||
|
@ -952,22 +953,29 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signedTxp.status == 'accepted') {
|
if (signedTxp.status == 'accepted') {
|
||||||
ongoingProcess.set('broadcastingTx', true);
|
ongoingProcess.set('broadcastingTx', true, customStatusHandler);
|
||||||
root.broadcastTx(wallet, signedTxp, function(err, broadcastedTxp) {
|
root.broadcastTx(wallet, signedTxp, function(err, broadcastedTxp) {
|
||||||
ongoingProcess.set('broadcastingTx', false);
|
ongoingProcess.set('broadcastingTx', false, customStatusHandler);
|
||||||
if (err) return cb('sign error' + err);
|
if (err) return cb('sign error' + err);
|
||||||
|
|
||||||
$rootScope.$emit('Local/TxAction', wallet.id);
|
$rootScope.$emit('Local/TxAction', wallet.id);
|
||||||
var type = root.getViewStatus(wallet, broadcastedTxp);
|
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 {
|
} else {
|
||||||
$rootScope.$emit('Local/TxAction', wallet.id);
|
$rootScope.$emit('Local/TxAction', wallet.id);
|
||||||
|
|
||||||
var type = root.getViewStatus(wallet, signedTxp);
|
var type = root.getViewStatus(wallet, signedTxp);
|
||||||
|
|
||||||
|
if(!customStatusHandler) {
|
||||||
root.openStatusModal(type, signedTxp, function() {});
|
root.openStatusModal(type, signedTxp, function() {});
|
||||||
|
}
|
||||||
|
|
||||||
return cb(null, signedTxp);
|
return cb(null, signedTxp);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,8 @@
|
||||||
@import "includes/walletActivity";
|
@import "includes/walletActivity";
|
||||||
@import "includes/wallets";
|
@import "includes/wallets";
|
||||||
@import "includes/modals/modals";
|
@import "includes/modals/modals";
|
||||||
|
@import "includes/slideToAccept";
|
||||||
|
@import "includes/slideToAcceptSuccess";
|
||||||
@import "includes/tx-details";
|
@import "includes/tx-details";
|
||||||
@import "includes/txp-details";
|
@import "includes/txp-details";
|
||||||
@import "includes/tx-status";
|
@import "includes/tx-status";
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="22px" height="16px" viewBox="0 0 22 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 40.1 (33804) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>arrows-24px-outline-1_tail-right</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="Button/Slide-to-complete" transform="translate(-330.000000, -41.000000)" stroke-width="2" stroke="#FFFFFF">
|
||||||
|
<g id="arrows-24px-outline-1_tail-right" transform="translate(330.000000, 42.000000)">
|
||||||
|
<g id="Group">
|
||||||
|
<path d="M0,7 L20,7" id="Shape"></path>
|
||||||
|
<polyline id="Shape" points="13 0 20 7 13 14"></polyline>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 916 B |
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="22px" height="32px" viewBox="0 0 22 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 40.1 (33804) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>Imported Layers</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.229999989">
|
||||||
|
<g id="Button/Slide-to-complete" transform="translate(-21.000000, -30.000000)" fill="#FFFFFF">
|
||||||
|
<g id="Imported-Layers-+-Imported-Layers" transform="translate(29.296522, 45.671231) rotate(-13.000000) translate(-29.296522, -45.671231) translate(5.796522, 21.671231)">
|
||||||
|
<path d="M33.836573,25.7756997 C34.7704654,25.0754201 35.4853422,24.0606858 35.7717349,22.8201828 C36.673248,18.9153006 34.9235595,16.0435455 31.105899,15.1621691 L31.1083424,15.1627332 L32.1877147,10.4763105 C32.2275616,10.3037147 32.2072923,10.361553 32.2545315,10.1569372 L30.1219459,9.67034919 C29.9573284,9.63234424 29.8275684,9.59662857 29.8275684,9.59662857 L28.6650396,14.5986523 L26.2217369,14.0345715 L27.3011093,9.34814878 C27.3409562,9.17555298 27.3311499,9.21524176 27.3738817,9.03015035 L24.9336331,8.46677457 C24.8693732,8.74511457 24.9080695,8.60746054 24.8630626,8.77244875 L23.7784342,13.4704906 L18.2691133,12.1942861 C18.2691133,12.1942861 18.2452251,12.3409526 18.2048311,12.5124349 L17.6912795,14.6971594 L18.311573,14.8403654 C19.6608869,15.1518791 20.4965381,16.5234293 20.1779073,17.9035709 L17.8733934,27.9008449 C17.5718192,29.207106 17.2972414,30.3330336 15.693824,29.9628555 C15.5637181,29.9328182 14.6597278,29.7295447 14.242992,29.6333337 L13.7475204,31.7794569 C13.7159762,31.9049424 13.6506979,32.1988413 13.6506979,32.1988413 C13.6506979,32.1988413 13.960357,32.2621057 14.0544242,32.2838228 L19.1627593,33.4631749 L18.0063793,38.46086 L20.449682,39.0249409 L20.5218031,38.7125503 L21.6060621,34.0272558 L24.0493648,34.5913367 L22.8953655,39.6232981 L25.0088224,40.1112281 L25.3223287,40.1836067 L26.4926675,35.1554175 L27.7118755,35.4368939 C31.529536,36.3182703 34.3610402,34.5041668 35.2625533,30.5992846 C35.684858,28.7700816 35.0727322,26.9723687 33.836573,25.7756997 L33.836573,25.7756997 Z M25.3513718,17.7831539 L29.0163259,18.6292752 C30.3656398,18.9407888 31.201291,20.3123391 30.8826602,21.6924806 C30.5640294,23.0726222 29.211703,23.939038 27.8623891,23.6275243 L24.197435,22.781403 L25.3513718,17.7831539 L25.3513718,17.7831539 Z M27.3581643,31.4071903 L22.4715589,30.2790286 L23.6254956,25.2807794 L28.512101,26.4089411 C29.861415,26.7204548 30.6970662,28.0920051 30.3784354,29.4721466 C30.0598046,30.8522882 28.7074782,31.718704 27.3581643,31.4071903 L27.3581643,31.4071903 Z" id="Imported-Layers"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 407 B |
|
@ -61,5 +61,16 @@
|
||||||
</div>
|
</div>
|
||||||
<button class="button button-block button-positive" ng-click="approve()" ng-if="!isCordova" translate>Click to pay</button>
|
<button class="button button-block button-positive" ng-click="approve()" ng-if="!isCordova" translate>Click to pay</button>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
<accept class="accept-slide" ng-if="isCordova"></accept>
|
<slide-to-accept
|
||||||
|
ng-if="isCordova || true"
|
||||||
|
slide-on-confirm="onConfirm()"
|
||||||
|
slide-send-status="sendStatus">
|
||||||
|
Slide to pay
|
||||||
|
</slide-to-accept>
|
||||||
|
<slide-to-accept-success
|
||||||
|
slide-success-show="sendStatus === 'success'"
|
||||||
|
slide-success-on-confirm="onSuccessConfirm()"
|
||||||
|
>
|
||||||
|
Payment Sent
|
||||||
|
</slide-to-accept-success>
|
||||||
</ion-view>
|
</ion-view>
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
<ion-slides options="{loop: false, effect: 'flip', speed: 500, pagination: false, initialSlide: 1}" slider="data.slider">
|
|
||||||
<ion-slide-page></ion-slide-page>
|
|
||||||
<ion-slide-page>
|
|
||||||
<div>
|
|
||||||
<i class="icon ion-ios-arrow-thin-right"></i>
|
|
||||||
<span translate>Slide to accept</span>
|
|
||||||
</div>
|
|
||||||
</ion-slide-page>
|
|
||||||
</ion-slides>
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<div class="slide__listener"
|
||||||
|
ng-touchstart="onTouchstart($event);"
|
||||||
|
ng-touchmove="onTouchmove($event);"
|
||||||
|
ng-touchend="onTouchend($event);"
|
||||||
|
ng-mousedown="onTouchstart($event);"
|
||||||
|
ng-mousemove="onTouchmove($event);"
|
||||||
|
ng-mouseup="onTouchend($event);"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="slide__slider"
|
||||||
|
ng-style="sliderStyle"
|
||||||
|
>
|
||||||
|
<div class="slide__slider__tip"></div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="slide__bitcoin"
|
||||||
|
ng-style="bitcoinStyle"
|
||||||
|
>
|
||||||
|
<img src="img/icon-bitcoin-white.svg">
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="slide__button-text"
|
||||||
|
ng-style="textStyle"
|
||||||
|
>
|
||||||
|
<ng-transclude></ng-transclude>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="slide__status-text"
|
||||||
|
ng-class="{enter: isSlidFully}"
|
||||||
|
ng-hide="sendStatus === 'success'"
|
||||||
|
>
|
||||||
|
<img src="img/spinner.png">
|
||||||
|
{{displaySendStatus}}
|
||||||
|
</div>
|
||||||
|
<div class="slide__arrow">
|
||||||
|
<img src="img/icon-arrow-right.svg">
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<div
|
||||||
|
class="slide-success__background"
|
||||||
|
ng-class="{'fill-screen': fillScreen}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="slide-success__content">
|
||||||
|
<img src="img/onboarding-success.svg" ng-class="{reveal: fillScreen}">
|
||||||
|
<div class="slide-success__content__header" ng-class="{reveal: fillScreen}">
|
||||||
|
<ng-transclude>Payment Sent</ng-transclude>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="slide-success__footer" ng-class="{reveal: fillScreen}">
|
||||||
|
<a class="slide-success__footer__btn" ng-click="onConfirmButtonClick()">OK</a>
|
||||||
|
</div>
|
Loading…
Reference in New Issue