feat(scan): first iteration of full scan view implementation
This commit is contained in:
parent
845534c727
commit
c0d4fbe5bb
5 changed files with 106 additions and 50 deletions
|
|
@ -23,57 +23,71 @@ angular.module('copayApp.controllers').controller('tabScanController', function(
|
||||||
}
|
}
|
||||||
|
|
||||||
function _handleCapabilities(){
|
function _handleCapabilities(){
|
||||||
if(!$scope.scannerIsAvailable){
|
// always update the view
|
||||||
$scope.currentState = scannerStates.unavailable;
|
$timeout(function(){
|
||||||
} else if($scope.scannerIsDenied){
|
if(!scannerService.isInitialized()){
|
||||||
$scope.currentState = scannerStates.denied;
|
$scope.currentState = scannerStates.loading;
|
||||||
} else if($scope.scannerIsRestricted){
|
} else if(!$scope.scannerIsAvailable){
|
||||||
$scope.currentState = scannerStates.denied;
|
$scope.currentState = scannerStates.unavailable;
|
||||||
} else if(!$scope.scannerHasPermission){
|
} else if($scope.scannerIsDenied){
|
||||||
$scope.currentState = scannerStates.unauthorized;
|
$scope.currentState = scannerStates.denied;
|
||||||
} else if($scope.scannerHasPermission){
|
} else if($scope.scannerIsRestricted){
|
||||||
|
$scope.currentState = scannerStates.denied;
|
||||||
|
} else if(!$scope.scannerHasPermission){
|
||||||
|
$scope.currentState = scannerStates.unauthorized;
|
||||||
|
}
|
||||||
|
$log.debug('Scan view state set to: ' + $scope.currentState);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function _refreshScanView(){
|
||||||
|
_updateCapabilities();
|
||||||
|
_handleCapabilities();
|
||||||
|
if($scope.scannerHasPermission){
|
||||||
activate();
|
activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _initScanView(){
|
|
||||||
_updateCapabilities();
|
|
||||||
_handleCapabilities();
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.$on("$ionicView.beforeEnter", function() {
|
|
||||||
$scope.currentState = scannerStates.loading;
|
|
||||||
});
|
|
||||||
|
|
||||||
// This could be much cleaner with a Promise API
|
// This could be much cleaner with a Promise API
|
||||||
// (needs a polyfill for some platforms)
|
// (needs a polyfill for some platforms)
|
||||||
$rootScope.$on('scannerServiceInitialized', function(){
|
$rootScope.$on('scannerServiceInitialized', function(){
|
||||||
$log.debug('Scanner initialization finished, reinitializing scan view...');
|
$log.debug('Scanner initialization finished, reinitializing scan view...');
|
||||||
_initScanView();
|
_refreshScanView();
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on("$ionicView.afterEnter", function() {
|
$scope.$on("$ionicView.afterEnter", function() {
|
||||||
if(scannerService.isInitialized()){
|
// try initializing and refreshing status any time the view is entered
|
||||||
_initScanView();
|
scannerService.gentleInitialize();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function activate(){
|
function activate(){
|
||||||
scannerService.activate(function(){
|
scannerService.activate(function(){
|
||||||
|
_updateCapabilities();
|
||||||
|
_handleCapabilities();
|
||||||
$log.debug('Scanner activated, setting to visible...');
|
$log.debug('Scanner activated, setting to visible...');
|
||||||
$scope.currentState = scannerStates.visible;
|
$scope.currentState = scannerStates.visible;
|
||||||
scannerService.scan(function(err, contents){
|
// pause to update the view
|
||||||
if(err){
|
$timeout(function(){
|
||||||
$log.debug('Scan canceled.');
|
scannerService.scan(function(err, contents){
|
||||||
} else if ($state.params.passthroughMode) {
|
if(err){
|
||||||
$rootScope.scanResult = contents;
|
$log.debug('Scan canceled.');
|
||||||
goBack();
|
} else if ($state.params.passthroughMode) {
|
||||||
} else {
|
$rootScope.scanResult = contents;
|
||||||
handleSuccessfulScan(contents);
|
goBack();
|
||||||
}
|
} else {
|
||||||
});
|
handleSuccessfulScan(contents);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
$scope.activate = activate;
|
||||||
|
|
||||||
|
$scope.authorize = function(){
|
||||||
|
scannerService.initialize(function(){
|
||||||
|
_refreshScanView();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$scope.$on("$ionicView.afterLeave", function() {
|
$scope.$on("$ionicView.afterLeave", function() {
|
||||||
scannerService.deactivate();
|
scannerService.deactivate();
|
||||||
|
|
@ -84,6 +98,14 @@ angular.module('copayApp.controllers').controller('tabScanController', function(
|
||||||
incomingData.redir(contents);
|
incomingData.redir(contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.openSettings = function(){
|
||||||
|
scannerService.openSettings();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.attemptToReactivate = function(){
|
||||||
|
scannerService.reinitialize();
|
||||||
|
};
|
||||||
|
|
||||||
$scope.toggleLight = function(){
|
$scope.toggleLight = function(){
|
||||||
scannerService.toggleLight(function(lightEnabled){
|
scannerService.toggleLight(function(lightEnabled){
|
||||||
$scope.lightActive = lightEnabled;
|
$scope.lightActive = lightEnabled;
|
||||||
|
|
@ -98,7 +120,7 @@ angular.module('copayApp.controllers').controller('tabScanController', function(
|
||||||
$timeout(function(){
|
$timeout(function(){
|
||||||
$scope.cameraToggleActive = false;
|
$scope.cameraToggleActive = false;
|
||||||
$log.debug('Camera toggle control deactivated.');
|
$log.debug('Camera toggle control deactivated.');
|
||||||
}, 600);
|
}, 200);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -106,6 +128,9 @@ angular.module('copayApp.controllers').controller('tabScanController', function(
|
||||||
return $state.params.passthroughMode;
|
return $state.params.passthroughMode;
|
||||||
}
|
}
|
||||||
function goBack(){
|
function goBack(){
|
||||||
|
$ionicHistory.nextViewOptions({
|
||||||
|
disableAnimate: true
|
||||||
|
});
|
||||||
$ionicHistory.backView().go();
|
$ionicHistory.backView().go();
|
||||||
}
|
}
|
||||||
$scope.goBack = goBack;
|
$scope.goBack = goBack;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('copayApp.directives')
|
angular.module('copayApp.directives')
|
||||||
.directive('qrScanner', function($state, $rootScope, $log) {
|
.directive('qrScanner', function($state, $rootScope, $log, $ionicHistory) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
|
|
@ -9,11 +9,14 @@ angular.module('copayApp.directives')
|
||||||
onScan: "&"
|
onScan: "&"
|
||||||
},
|
},
|
||||||
replace: true,
|
replace: true,
|
||||||
template: '<a on-tap="openScanner()"><i class="icon ion-qr-scanner"></i></a>',
|
template: '<a on-tap="openScanner()" nav-transition="none"><i class="icon ion-qr-scanner"></i></a>',
|
||||||
link: function(scope, el, attrs) {
|
link: function(scope, el, attrs) {
|
||||||
|
|
||||||
scope.openScanner = function() {
|
scope.openScanner = function() {
|
||||||
$log.debug('Opening scanner by directive...');
|
$log.debug('Opening scanner by directive...');
|
||||||
|
$ionicHistory.nextViewOptions({
|
||||||
|
disableAnimate: true
|
||||||
|
});
|
||||||
$state.go('scanner', { passthroughMode: 1 });
|
$state.go('scanner', { passthroughMode: 1 });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,8 @@ angular.module('copayApp.services').service('scannerService', function($log, $ti
|
||||||
var backCamera = true; // the plugin defaults to the back camera
|
var backCamera = true; // the plugin defaults to the back camera
|
||||||
|
|
||||||
// Initalize known capabilities
|
// Initalize known capabilities
|
||||||
var isAvailable = false;
|
var isAvailable = isDesktop? false: true; // assume camera exists on mobile
|
||||||
var hasPermission = isDesktop? true: false;
|
var hasPermission = isDesktop? true: false; // assume desktop has permission
|
||||||
var isAuthorized = false;
|
|
||||||
var isDenied = false;
|
var isDenied = false;
|
||||||
var isRestricted = false;
|
var isRestricted = false;
|
||||||
var canEnableLight = false;
|
var canEnableLight = false;
|
||||||
|
|
@ -59,6 +58,7 @@ angular.module('copayApp.services').service('scannerService', function($log, $ti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var initializeStarted = false;
|
||||||
/**
|
/**
|
||||||
* If camera access has been granted, pre-initialize the QRScanner. This method
|
* If camera access has been granted, pre-initialize the QRScanner. This method
|
||||||
* can be safely called before the scanner is visible to improve perceived
|
* can be safely called before the scanner is visible to improve perceived
|
||||||
|
|
@ -67,27 +67,32 @@ angular.module('copayApp.services').service('scannerService', function($log, $ti
|
||||||
* The `status` of QRScanner is returned to the callback.
|
* The `status` of QRScanner is returned to the callback.
|
||||||
*/
|
*/
|
||||||
this.gentleInitialize = function(callback) {
|
this.gentleInitialize = function(callback) {
|
||||||
|
if(initializeStarted){
|
||||||
|
QRScanner.getStatus(function(status){
|
||||||
|
_completeInitialization(status, callback);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initializeStarted = true;
|
||||||
$log.debug('Trying to pre-initialize QRScanner.');
|
$log.debug('Trying to pre-initialize QRScanner.');
|
||||||
if(!isDesktop){
|
if(!isDesktop){
|
||||||
QRScanner.getStatus(function(status){
|
QRScanner.getStatus(function(status){
|
||||||
_checkCapabilities(status);
|
_checkCapabilities(status);
|
||||||
if(status.authorized){
|
if(status.authorized){
|
||||||
$log.debug('Camera permission already granted.');
|
$log.debug('Camera permission already granted.');
|
||||||
_initalize(callback);
|
initialize(callback);
|
||||||
} else {
|
} else {
|
||||||
$log.debug('QRScanner not authorized, waiting to initalize.');
|
$log.debug('QRScanner not authorized, waiting to initalize.');
|
||||||
if(typeof callback === "function"){
|
_completeInitialization(status, callback);
|
||||||
callback && callback(status);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$log.debug('Camera permission assumed on desktop.');
|
$log.debug('Camera permission assumed on desktop.');
|
||||||
_initalize(callback);
|
initialize(callback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function _initalize(callback){
|
function initialize(callback){
|
||||||
$log.debug('Initializing scanner...');
|
$log.debug('Initializing scanner...');
|
||||||
QRScanner.prepare(function(err, status){
|
QRScanner.prepare(function(err, status){
|
||||||
if(err){
|
if(err){
|
||||||
|
|
@ -103,19 +108,25 @@ angular.module('copayApp.services').service('scannerService', function($log, $ti
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
this.initialize = initialize;
|
||||||
|
|
||||||
// This could be much cleaner with a Promise API
|
// This could be much cleaner with a Promise API
|
||||||
// (needs a polyfill for some platforms)
|
// (needs a polyfill for some platforms)
|
||||||
var initializeCompleted = false;
|
var initializeCompleted = false;
|
||||||
function _completeInitialization(status, callback){
|
function _completeInitialization(status, callback){
|
||||||
_checkCapabilities(status);
|
_checkCapabilities(status);
|
||||||
$rootScope.$emit('scannerServiceInitialized');
|
|
||||||
initializeCompleted = true;
|
initializeCompleted = true;
|
||||||
callback && callback(status);
|
$rootScope.$emit('scannerServiceInitialized');
|
||||||
|
if(typeof callback === "function"){
|
||||||
|
callback(status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.isInitialized = function(){
|
this.isInitialized = function(){
|
||||||
return initializeCompleted;
|
return initializeCompleted;
|
||||||
}
|
}
|
||||||
|
this.initializeStarted = function(){
|
||||||
|
return initializeStarted;
|
||||||
|
}
|
||||||
|
|
||||||
var nextHide = null;
|
var nextHide = null;
|
||||||
var nextDestroy = null;
|
var nextDestroy = null;
|
||||||
|
|
@ -132,7 +143,9 @@ angular.module('copayApp.services').service('scannerService', function($log, $ti
|
||||||
$log.debug('Activating scanner...');
|
$log.debug('Activating scanner...');
|
||||||
QRScanner.show(function(status){
|
QRScanner.show(function(status){
|
||||||
_checkCapabilities(status);
|
_checkCapabilities(status);
|
||||||
callback(status);
|
if(typeof callback === "function"){
|
||||||
|
callback(status);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if(nextHide !== null){
|
if(nextHide !== null){
|
||||||
$timeout.cancel(nextHide);
|
$timeout.cancel(nextHide);
|
||||||
|
|
@ -183,6 +196,12 @@ angular.module('copayApp.services').service('scannerService', function($log, $ti
|
||||||
QRScanner.destroy();
|
QRScanner.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.reinitialize = function(callback){
|
||||||
|
initializeCompleted = false;
|
||||||
|
QRScanner.destroy();
|
||||||
|
initialize(callback);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle the device light (if available).
|
* Toggle the device light (if available).
|
||||||
*
|
*
|
||||||
|
|
@ -228,4 +247,9 @@ angular.module('copayApp.services').service('scannerService', function($log, $ti
|
||||||
callback(status);
|
callback(status);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.openSettings = function() {
|
||||||
|
$log.debug('Attempting to open device settings...');
|
||||||
|
QRScanner.openSettings();
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ $scannerBackgroundColor: #060d2d;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: transparent none;
|
background: transparent none;
|
||||||
|
.bar-header {
|
||||||
|
opacity: .9;
|
||||||
|
}
|
||||||
&-has-problems,
|
&-has-problems,
|
||||||
&-loading-camera {
|
&-loading-camera {
|
||||||
background-color: $scannerBackgroundColor;
|
background-color: $scannerBackgroundColor;
|
||||||
|
|
@ -50,7 +53,8 @@ $scannerBackgroundColor: #060d2d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&-loading-camera {
|
&-loading-camera {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%
|
||||||
}
|
}
|
||||||
&-camera-ready {
|
&-camera-ready {
|
||||||
// view background is transparent to show video preview
|
// view background is transparent to show video preview
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<ion-content scroll="false">
|
<ion-content scroll="false">
|
||||||
<div class="ng-hide" id="tab-scan-has-problems" ng-show="currentState === scannerStates.unauthorized || currentState === scannerStates.denied || currentState === scannerStates.unavailable">
|
<div class="ng-hide" id="tab-scan-has-problems" ng-show="currentState === scannerStates.unauthorized || currentState === scannerStates.denied || currentState === scannerStates.unavailable">
|
||||||
<i class="icon zero-state-icon">
|
<i class="icon zero-state-icon">
|
||||||
<img src="img/tab-icons/ico-receive.svg" />
|
<img src="img/tab-icons/ico-receive.svg"/>
|
||||||
</i>
|
</i>
|
||||||
<div class="zero-state-heading" translate>Scan QR Codes</div>
|
<div class="zero-state-heading" translate>Scan QR Codes</div>
|
||||||
<div class="zero-state-description" translate>You can scan bitcoin addresses, payment requests, paper wallets, and more.</div>
|
<div class="zero-state-description" translate>You can scan bitcoin addresses, payment requests, paper wallets, and more.</div>
|
||||||
|
|
@ -18,9 +18,9 @@
|
||||||
<div class="ng-hide zero-state-tldr" ng-show="currentState === scannerStates.unauthorized" translate>Enable the camera to get started.</div>
|
<div class="ng-hide zero-state-tldr" ng-show="currentState === scannerStates.unauthorized" translate>Enable the camera to get started.</div>
|
||||||
<div class="ng-hide zero-state-tldr" ng-show="currentState === scannerStates.denied" translate>Enable camera access in your device settings to get started.</div>
|
<div class="ng-hide zero-state-tldr" ng-show="currentState === scannerStates.denied" translate>Enable camera access in your device settings to get started.</div>
|
||||||
<div class="ng-hide zero-state-tldr" ng-show="currentState === scannerStates.unavailable" translate>Please connect a camera to get started.</div>
|
<div class="ng-hide zero-state-tldr" ng-show="currentState === scannerStates.unavailable" translate>Please connect a camera to get started.</div>
|
||||||
<button ng-show="currentState === scannerStates.unauthorized" class="ng-hide button button-standard button-primary" ng-click="attemptActivate">Allow Camera Access</button>
|
<button ng-show="currentState === scannerStates.unauthorized" class="ng-hide button button-standard button-primary" ng-click="authorize()">Allow Camera Access</button>
|
||||||
<button ng-show="currentState === scannerStates.denied && canOpenSettings" class="ng-hide button button-standard button-primary" ng-click="openSettings">Open Settings</button>
|
<button ng-show="currentState === scannerStates.denied && canOpenSettings" class="ng-hide button button-standard button-primary" ng-click="openSettings()">Open Settings</button>
|
||||||
<button ng-show="currentState === scannerStates.unavailable" class="ng-hide button button-standard button-primary">Retry Camera</button>
|
<button ng-show="currentState === scannerStates.unavailable" class="ng-hide button button-standard button-primary" ng-click="attemptToReactivate()">Retry Camera</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ng-show" id="tab-scan-loading-camera" ng-show="currentState === scannerStates.loading"></div>
|
<div class="ng-show" id="tab-scan-loading-camera" ng-show="currentState === scannerStates.loading"></div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue