Merge pull request #327 from msalcala11/slideToPayComponent
Implement Slide to Pay
This commit is contained in:
commit
8607867d71
30 changed files with 842 additions and 164 deletions
|
|
@ -127,6 +127,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'
|
||||||
],
|
],
|
||||||
|
|
@ -147,6 +148,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,9 +1,11 @@
|
||||||
'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, $ionicConfig) {
|
||||||
var cachedTxp = {};
|
var cachedTxp = {};
|
||||||
var isChromeApp = platformInfo.isChromeApp;
|
var isChromeApp = platformInfo.isChromeApp;
|
||||||
|
|
||||||
|
$ionicConfig.views.swipeBackEnabled(false);
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||||
$scope.isWallet = data.stateParams.isWallet;
|
$scope.isWallet = data.stateParams.isWallet;
|
||||||
$scope.isCard = data.stateParams.isCard;
|
$scope.isCard = data.stateParams.isCard;
|
||||||
|
|
@ -30,6 +32,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
throw ('bad params');
|
throw ('bad params');
|
||||||
}
|
}
|
||||||
$scope.isCordova = platformInfo.isCordova;
|
$scope.isCordova = platformInfo.isCordova;
|
||||||
|
$scope.hasClick = platformInfo.hasClick;
|
||||||
$scope.data = {};
|
$scope.data = {};
|
||||||
|
|
||||||
var config = configService.getSync().wallet;
|
var config = configService.getSync().wallet;
|
||||||
|
|
@ -54,7 +57,8 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
}
|
}
|
||||||
|
|
||||||
var filteredWallets = [];
|
var filteredWallets = [];
|
||||||
var index = 0, enoughFunds = false;
|
var index = 0;
|
||||||
|
var enoughFunds = false;
|
||||||
|
|
||||||
lodash.each(wallets, function(w) {
|
lodash.each(wallets, function(w) {
|
||||||
walletService.getStatus(w, {}, function(err, status) {
|
walletService.getStatus(w, {}, function(err, status) {
|
||||||
|
|
@ -198,6 +202,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
};
|
};
|
||||||
|
|
||||||
var setSendError = function(msg) {
|
var setSendError = function(msg) {
|
||||||
|
$scope.sendStatus = '';
|
||||||
popupService.showAlert(gettextCatalog.getString('Error at confirm:'), msg);
|
popupService.showAlert(gettextCatalog.getString('Error at confirm:'), msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -205,7 +210,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
$scope.fee = txFormatService.formatAmountStr(txp.fee);
|
$scope.fee = txFormatService.formatAmountStr(txp.fee);
|
||||||
$scope.txp = txp;
|
$scope.txp = txp;
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
};
|
}
|
||||||
|
|
||||||
var createTx = function(wallet, dryRun, cb) {
|
var createTx = function(wallet, dryRun, cb) {
|
||||||
var config = configService.getSync().wallet;
|
var config = configService.getSync().wallet;
|
||||||
|
|
@ -270,7 +275,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.approve = function() {
|
$scope.approve = function(onSendStatusChange) {
|
||||||
var wallet = $scope.wallet;
|
var wallet = $scope.wallet;
|
||||||
if (!wallet) {
|
if (!wallet) {
|
||||||
return setSendError(gettextCatalog.getString('No wallet selected'));
|
return setSendError(gettextCatalog.getString('No wallet selected'));
|
||||||
|
|
@ -284,9 +289,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();
|
||||||
|
|
@ -304,24 +310,57 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
||||||
if (!spendingPassEnabled && !touchIdEnabled) {
|
if (!spendingPassEnabled && !touchIdEnabled) {
|
||||||
if (isCordova && bigAmount) {
|
if (isCordova && bigAmount) {
|
||||||
popupService.showConfirm(null, message, okText, cancelText, function(ok) {
|
popupService.showConfirm(null, message, okText, cancelText, function(ok) {
|
||||||
if (!ok) return;
|
if (!ok) {
|
||||||
publishAndSign(wallet, txp);
|
$scope.sendStatus = '';
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$apply();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
publishAndSign(wallet, txp, onSendStatusChange);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
popupService.showConfirm(null, message, okText, cancelText, function(ok) {
|
popupService.showConfirm(null, message, okText, cancelText, function(ok) {
|
||||||
if (!ok) return;
|
if (!ok) {
|
||||||
publishAndSign(wallet, txp);
|
$scope.sendStatus = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
publishAndSign(wallet, txp, onSendStatusChange);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else publishAndSign(wallet, txp);
|
else publishAndSign(wallet, txp, onSendStatusChange);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function publishAndSign(wallet, txp) {
|
function statusChangeHandler(processName, showName, isOn) {
|
||||||
|
$log.debug('statusChangeHandler: ', processName, showName, isOn);
|
||||||
|
if ((processName === 'broadcastingTx' || ((processName === 'signingTx') && $scope.wallet.m > 1)) && !isOn) {
|
||||||
|
$scope.sendStatus = 'success';
|
||||||
|
$scope.$digest();
|
||||||
|
} else if (showName) {
|
||||||
|
$scope.sendStatus = showName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.statusChangeHandler = statusChangeHandler;
|
||||||
|
|
||||||
|
$scope.onConfirm = function() {
|
||||||
|
$scope.approve(statusChangeHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.onSuccessConfirm = function() {
|
||||||
|
$ionicHistory.nextViewOptions({
|
||||||
|
disableAnimate: true
|
||||||
|
});
|
||||||
|
$scope.sendStatus = '';
|
||||||
|
$state.go('tabs.send');
|
||||||
|
};
|
||||||
|
|
||||||
|
function publishAndSign(wallet, txp, onSendStatusChange) {
|
||||||
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);
|
||||||
};
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,11 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('txStatusController', function($scope, $timeout, $state, $stateParams, $ionicHistory, $log, addressbookService) {
|
angular.module('copayApp.controllers').controller('txStatusController', function($scope, $timeout) {
|
||||||
|
|
||||||
if ($scope.cb) $timeout($scope.cb, 100);
|
if ($scope.cb) $timeout($scope.cb, 100);
|
||||||
|
|
||||||
var previousView = $ionicHistory.viewHistory().backView && $ionicHistory.viewHistory().backView.stateName;
|
|
||||||
$scope.fromSendTab = previousView.match(/tabs.send/) ? true : false;
|
|
||||||
$scope.fromBitPayCard = previousView.match(/tabs.bitpayCard/) ? true : false;
|
|
||||||
$scope.fromPayPro = $stateParams.paypro ? true : false;
|
|
||||||
|
|
||||||
$scope.cancel = function() {
|
$scope.cancel = function() {
|
||||||
$scope.txStatusModal.hide();
|
$scope.txStatusModal.hide();
|
||||||
if ($scope.fromSendTab) {
|
|
||||||
$ionicHistory.removeBackView();
|
|
||||||
$state.go('tabs.send');
|
|
||||||
$timeout(function() {
|
|
||||||
$state.transitionTo('tabs.home');
|
|
||||||
}, 100);
|
|
||||||
} else if ($scope.fromBitPayCard) {
|
|
||||||
$ionicHistory.removeBackView();
|
|
||||||
$timeout(function() {
|
|
||||||
$state.transitionTo('tabs.bitpayCard');
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.save = function(addressbookEntry) {
|
|
||||||
$scope.txStatusModal.hide();
|
|
||||||
$ionicHistory.nextViewOptions({
|
|
||||||
disableAnimate: true,
|
|
||||||
disableBack: true
|
|
||||||
});
|
|
||||||
$ionicHistory.removeBackView();
|
|
||||||
$state.go('tabs.send.addressbook', {
|
|
||||||
fromSendTab: $scope.fromSendTab,
|
|
||||||
addressbookEntry: addressbookEntry
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addressbookService.list(function(err, ab) {
|
|
||||||
if (err) $log.error(err);
|
|
||||||
if (ab[$scope.tx.toAddress]) {
|
|
||||||
$scope.entryExist = true;
|
|
||||||
$log.debug('Entry already exist');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.controllers').controller('txpDetailsController', function($scope, $rootScope, $timeout, $interval, $ionicModal, ongoingProcess, platformInfo, $ionicScrollDelegate, txFormatService, fingerprintService, bwcError, gettextCatalog, lodash, walletService, popupService) {
|
angular.module('copayApp.controllers').controller('txpDetailsController', function($scope, $rootScope, $timeout, $interval, $ionicModal, $log, ongoingProcess, platformInfo, $ionicScrollDelegate, txFormatService, fingerprintService, bwcError, gettextCatalog, lodash, walletService, popupService, $state, $ionicHistory) {
|
||||||
var self = $scope.self;
|
var self = $scope.self;
|
||||||
var tx = $scope.tx;
|
var tx = $scope.tx;
|
||||||
var copayers = $scope.copayers;
|
var copayers = $scope.copayers;
|
||||||
|
|
@ -17,7 +17,7 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
|
||||||
$scope.canSign = $scope.wallet.canSign() || $scope.wallet.isPrivKeyExternal();
|
$scope.canSign = $scope.wallet.canSign() || $scope.wallet.isPrivKeyExternal();
|
||||||
$scope.color = $scope.wallet.color;
|
$scope.color = $scope.wallet.color;
|
||||||
$scope.data = {};
|
$scope.data = {};
|
||||||
|
$scope.hasClick = platformInfo.hasClick;
|
||||||
initActionList();
|
initActionList();
|
||||||
checkPaypro();
|
checkPaypro();
|
||||||
}
|
}
|
||||||
|
|
@ -66,17 +66,18 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
|
||||||
}
|
}
|
||||||
|
|
||||||
var setSendError = function(msg) {
|
var setSendError = function(msg) {
|
||||||
|
$scope.sendStatus = '';
|
||||||
var error = msg || gettextCatalog.getString('Could not send payment');
|
var error = msg || gettextCatalog.getString('Could not send payment');
|
||||||
popupService.showAlert(gettextCatalog.getString('Error'), error);
|
popupService.showAlert(gettextCatalog.getString('Error'), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.sign = function() {
|
$scope.sign = function(onSendStatusChange) {
|
||||||
$scope.loading = true;
|
$scope.loading = true;
|
||||||
walletService.publishAndSign($scope.wallet, $scope.tx, function(err, txp) {
|
walletService.publishAndSign($scope.wallet, $scope.tx, function(err, txp) {
|
||||||
$scope.$emit('UpdateTx');
|
$scope.$emit('UpdateTx');
|
||||||
if (err) return setSendError(err);
|
if (err) return setSendError(err);
|
||||||
$scope.close();
|
success();
|
||||||
});
|
}, onSendStatusChange);
|
||||||
};
|
};
|
||||||
|
|
||||||
function setError(err, prefix) {
|
function setError(err, prefix) {
|
||||||
|
|
@ -213,6 +214,31 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function statusChangeHandler(processName, showName, isOn) {
|
||||||
|
$log.debug('statusChangeHandler: ', processName, showName, isOn);
|
||||||
|
if (showName) {
|
||||||
|
$scope.sendStatus = showName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function success() {
|
||||||
|
$scope.sendStatus = 'success';
|
||||||
|
$scope.$digest();
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.statusChangeHandler = statusChangeHandler;
|
||||||
|
|
||||||
|
$scope.onConfirm = function() {
|
||||||
|
$scope.sign(statusChangeHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.onSuccessConfirm = function() {
|
||||||
|
$ionicHistory.nextViewOptions({
|
||||||
|
disableAnimate: true
|
||||||
|
});
|
||||||
|
$scope.close();
|
||||||
|
};
|
||||||
|
|
||||||
$scope.close = function() {
|
$scope.close = function() {
|
||||||
$scope.loading = null;
|
$scope.loading = null;
|
||||||
$scope.txpDetailsModal.hide();
|
$scope.txpDetailsModal.hide();
|
||||||
|
|
|
||||||
20
src/js/directives/clickToAccept.js
Normal file
20
src/js/directives/clickToAccept.js
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('copayApp.directives')
|
||||||
|
.directive('clickToAccept', function() {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
templateUrl: 'views/includes/clickToAccept.html',
|
||||||
|
transclude: true,
|
||||||
|
scope: {
|
||||||
|
sendStatus: '=clickSendStatus',
|
||||||
|
},
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
scope.$watch('sendStatus', function() {
|
||||||
|
if(scope.sendStatus !== 'success') {
|
||||||
|
scope.displaySendStatus = scope.sendStatus;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
@ -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');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
251
src/js/directives/slideToAccept.js
Normal file
251
src/js/directives/slideToAccept.js
Normal file
|
|
@ -0,0 +1,251 @@
|
||||||
|
'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) {
|
||||||
|
reset();
|
||||||
|
} else if(scope.sendStatus === 'success') {
|
||||||
|
scope.displaySendStatus = '';
|
||||||
|
$timeout(function() {
|
||||||
|
reset();
|
||||||
|
}, 500);
|
||||||
|
} 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() {
|
||||||
|
scope.isSlidFully = false;
|
||||||
|
isSliding = false;
|
||||||
|
setNewSliderStyle(getKnobWidthPercentage());
|
||||||
|
setNewBitcoinStyle(0);
|
||||||
|
setNewTextStyle(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
34
src/js/directives/slideToAcceptSuccess.js
Normal file
34
src/js/directives/slideToAcceptSuccess.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
'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',
|
||||||
|
hideOnConfirm: '=slideSuccessHideOnConfirm'
|
||||||
|
},
|
||||||
|
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();
|
||||||
|
if(scope.hideOnConfirm) {
|
||||||
|
scope.fillScreen = false;
|
||||||
|
elm.style.display = 'none';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -39,5 +39,21 @@ angular.module('copayApp.services').factory('platformInfo', function($window) {
|
||||||
ret.isChromeApp = $window.chrome && chrome.runtime && chrome.runtime.id && !ret.isNW;
|
ret.isChromeApp = $window.chrome && chrome.runtime && chrome.runtime.id && !ret.isNW;
|
||||||
ret.isDevel = !ret.isMobile && !ret.isChromeApp && !ret.isNW;
|
ret.isDevel = !ret.isMobile && !ret.isChromeApp && !ret.isNW;
|
||||||
|
|
||||||
|
ret.hasClick = false;
|
||||||
|
|
||||||
|
if($window.sessionStorage.getItem('hasClick')) {
|
||||||
|
ret.hasClick = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$window.addEventListener('mousedown', function() {
|
||||||
|
ret.hasClick = true;
|
||||||
|
$window.sessionStorage.setItem('hasClick', 'true');
|
||||||
|
});
|
||||||
|
|
||||||
|
$window.addEventListener('touchstart', function() {
|
||||||
|
ret.hasClick = false;
|
||||||
|
$window.sessionStorage.removeItem('hasClick');
|
||||||
|
});
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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,14 +929,15 @@ 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, customStatusHandler);
|
||||||
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);
|
||||||
root.openStatusModal(type, signedTxp, function() {});
|
|
||||||
|
if(!customStatusHandler) {
|
||||||
|
root.openStatusModal(type, signedTxp, function() {});
|
||||||
|
}
|
||||||
|
|
||||||
return cb(null, signedTxp);
|
return cb(null, signedTxp);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -385,6 +385,10 @@ input[type=number] {
|
||||||
text-transform: lowercase;
|
text-transform: lowercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.text-light {
|
.text-light {
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
src/sass/views/includes/clickToAccept.scss
Normal file
40
src/sass/views/includes/clickToAccept.scss
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
click-to-accept {
|
||||||
|
|
||||||
|
.click-to-accept {
|
||||||
|
&__status-text {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 4;
|
||||||
|
text-transform: capitalize;
|
||||||
|
transform: translateY(2rem);
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
&.enter {
|
||||||
|
transition: transform 250ms ease, opacity 250ms ease;
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> img {
|
||||||
|
margin-right: 10px;
|
||||||
|
animation-name: spin;
|
||||||
|
animation-duration: 500ms;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
transform:rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform:rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
126
src/sass/views/includes/slideToAccept.scss
Normal file
126
src/sass/views/includes/slideToAccept.scss
Normal file
|
|
@ -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;
|
||||||
|
|
||||||
|
&.enter {
|
||||||
|
transition: transform 250ms ease, opacity 250ms ease;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
96
src/sass/views/includes/slideToAcceptSuccess.scss
Normal file
96
src/sass/views/includes/slideToAcceptSuccess.scss
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,29 +1,4 @@
|
||||||
#tx-status {
|
#tx-status {
|
||||||
.address {
|
|
||||||
display: flex;
|
|
||||||
padding: 5px 15px;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
margin-top: 10px;
|
|
||||||
i {
|
|
||||||
color: grey;
|
|
||||||
padding-right: 10px;
|
|
||||||
border-right: 1px solid;
|
|
||||||
border-color: grey;
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
contact {
|
|
||||||
margin-left: 15px;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.collect-address {
|
|
||||||
bottom: 0;
|
|
||||||
background: #fff;
|
|
||||||
color: #6c6c6c;
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.popup-txsent {
|
.popup-txsent {
|
||||||
font-size: 5rem;
|
font-size: 5rem;
|
||||||
color: #4A90E2;
|
color: #4A90E2;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@
|
||||||
@import "includes/walletActivity";
|
@import "includes/walletActivity";
|
||||||
@import "includes/wallets";
|
@import "includes/wallets";
|
||||||
@import "includes/modals/modals";
|
@import "includes/modals/modals";
|
||||||
|
@import "includes/clickToAccept";
|
||||||
|
@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";
|
||||||
|
|
|
||||||
17
www/img/icon-arrow-right.svg
Normal file
17
www/img/icon-arrow-right.svg
Normal file
|
|
@ -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 |
14
www/img/icon-bitcoin-white.svg
Normal file
14
www/img/icon-bitcoin-white.svg
Normal file
|
|
@ -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 |
BIN
www/img/spinner.png
Normal file
BIN
www/img/spinner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 407 B |
|
|
@ -65,7 +65,25 @@
|
||||||
<i ng-show="!description" class="icon ion-ios-plus-empty size-21"></i>
|
<i ng-show="!description" class="icon ion-ios-plus-empty size-21"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button ng-show="wallets[0]" class="button button-block button-positive" ng-click="approve()" ng-if="!isCordova" translate>Click to pay</button>
|
<click-to-accept
|
||||||
|
ng-click="approve(statusChangeHandler)"
|
||||||
|
ng-if="hasClick && wallets[0]"
|
||||||
|
click-send-status="sendStatus">
|
||||||
|
Click to pay
|
||||||
|
</click-to-accept>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
<accept class="accept-slide" ng-if="isCordova"></accept>
|
<slide-to-accept
|
||||||
|
ng-if="!hasClick && wallets[0]"
|
||||||
|
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()"
|
||||||
|
slide-success-hide-on-confirm="true"
|
||||||
|
>
|
||||||
|
<span ng-hide="wallet.m > 1">Payment Sent</span>
|
||||||
|
<span ng-show="wallet.m > 1">Proposal Created</span>
|
||||||
|
</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>
|
|
||||||
9
www/views/includes/clickToAccept.html
Normal file
9
www/views/includes/clickToAccept.html
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<button class="button button-block button-positive" ng-disabled="sendStatus">
|
||||||
|
<span ng-if="!sendStatus">
|
||||||
|
<ng-transclude></ng-transclude>
|
||||||
|
</span>
|
||||||
|
<span class="click-to-accept__status-text" ng-class="{enter: sendStatus}">
|
||||||
|
<img src="img/spinner.png">
|
||||||
|
{{displaySendStatus}}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
38
www/views/includes/slideToAccept.html
Normal file
38
www/views/includes/slideToAccept.html
Normal file
|
|
@ -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>
|
||||||
15
www/views/includes/slideToAcceptSuccess.html
Normal file
15
www/views/includes/slideToAcceptSuccess.html
Normal file
|
|
@ -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>
|
||||||
|
|
@ -1,41 +1,15 @@
|
||||||
<ion-modal-view id="tx-status" ng-controller="txStatusController">
|
<ion-modal-view id="tx-status" ng-controller="txStatusController">
|
||||||
<div ng-if="type == 'broadcasted'">
|
<div ng-if="type == 'broadcasted'">
|
||||||
<div class="popup-txsent text-center m30tp">
|
<div class="popup-txsent text-center m30tp">
|
||||||
<i class="icon ion-checkmark-round"></i>
|
<i class="icon ion-checkmark-round"></i>
|
||||||
<div ng-show="tx.amountStr" class="m20t size-36">
|
<div ng-show="tx.amountStr" class="m20t size-36">
|
||||||
{{tx.amountStr}}
|
{{tx.amountStr}}
|
||||||
</div>
|
|
||||||
<div class="size-24 text-gray m20v">
|
|
||||||
<span ng-if="!fromBitPayCard" translate>Sent</span>
|
|
||||||
<span ng-if="fromBitPayCard" translate>Funds sent</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-center m20t" ng-if="entryExist || !fromSendTab || fromPayPro">
|
|
||||||
<a class="button button-positive" ng-click="cancel()" translate>OKAY</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="collect-address" ng-if="!entryExist && fromSendTab && !fromPayPro">
|
|
||||||
<div class="row">
|
|
||||||
<p translate class="col">Would you like to add this address to your address book?</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="size-24 text-gray m20v">
|
||||||
<div class="col">
|
<span translate>Sent</span>
|
||||||
<span class="address">
|
|
||||||
<i class="icon ion-social-bitcoin"></i>
|
|
||||||
<contact class="enable_text_select ellipsis" address="{{tx.toAddress}}"></contact>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="text-center m20t">
|
||||||
<div class="col col-50">
|
<a class="button button-positive" ng-click="cancel()" translate>OKAY</a>
|
||||||
<button class="button button-block button-stable" ng-click="cancel()">
|
|
||||||
{{'Skip' | translate}}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="col col-50">
|
|
||||||
<button class="button button-block button-stable" ng-click="save(tx.toAddress)">
|
|
||||||
{{'Add Address' | translate}}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -149,11 +149,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="button button-block button-positive"
|
|
||||||
ng-click="sign()"
|
<click-to-accept
|
||||||
ng-if="tx.pendingForUs && canSign && !loading && !paymentExpired && !isCordova" translate>
|
ng-click="onConfirm(statusChangeHandler)"
|
||||||
|
ng-if="tx.pendingForUs && canSign && !paymentExpired && hasClick"
|
||||||
|
click-send-status="sendStatus">
|
||||||
Click to accept
|
Click to accept
|
||||||
</button>
|
</click-to-accept>
|
||||||
<div class="m30t text-center" ng-if="tx.canBeRemoved || (tx.status == 'accepted' && !tx.broadcastedOn)">
|
<div class="m30t text-center" ng-if="tx.canBeRemoved || (tx.status == 'accepted' && !tx.broadcastedOn)">
|
||||||
<div class="size-12 padding" ng-show="!tx.isGlidera && isShared" translate>
|
<div class="size-12 padding" ng-show="!tx.isGlidera && isShared" translate>
|
||||||
* A payment proposal can be deleted if 1) you are the creator, and no other copayer has signed, or 2) 24 hours have passed since the proposal was created.
|
* A payment proposal can be deleted if 1) you are the creator, and no other copayer has signed, or 2) 24 hours have passed since the proposal was created.
|
||||||
|
|
@ -164,5 +166,17 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
<accept class="accept-slide" ng-if="tx.pendingForUs && canSign && !loading && !paymentExpired && isCordova"></accept>
|
|
||||||
|
<slide-to-accept
|
||||||
|
ng-if="tx.pendingForUs && canSign && !paymentExpired && !hasClick"
|
||||||
|
slide-on-confirm="onConfirm()"
|
||||||
|
slide-send-status="sendStatus">
|
||||||
|
Slide to accept
|
||||||
|
</slide-to-accept>
|
||||||
|
<slide-to-accept-success
|
||||||
|
slide-success-show="sendStatus === 'success'"
|
||||||
|
slide-success-on-confirm="onSuccessConfirm()"
|
||||||
|
>
|
||||||
|
Payment Sent
|
||||||
|
</slide-to-accept-success>
|
||||||
</ion-modal-view>
|
</ion-modal-view>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue