nativescript-barcodescanner
Advanced tools
Comparing version 3.0.1 to 3.0.2
@@ -9,81 +9,20 @@ import { ContentView } from "tns-core-modules/ui/content-view"; | ||
export interface CommonScanOptions { | ||
/** | ||
* A comma sep. string of barcode types: "QR_CODE,PDF_417" | ||
* Default: empty, so all types of codes can be scanned. | ||
*/ | ||
formats?: string; | ||
/** | ||
* By default the scanned object is returned in the Promise, | ||
* but if you want to scan continuously (until you call 'stop'), | ||
* you can provide a callback function that receives the same object | ||
* as the Promise would, but every time something is scanned. | ||
* | ||
* This function doesn't report duplicates in the same scanning session, | ||
* unless reportDuplicates is set to true. | ||
*/ | ||
continuousScanCallback?: (scanResult: ScanResult) => void; | ||
/** | ||
* Called when the user stopped/cancelled scanning, or in single scan mode when the scan was successful. | ||
*/ | ||
closeCallback?: () => void; | ||
/** | ||
* Wheter or not to report duplicate scan results during continuous scanning. | ||
* Default false. | ||
*/ | ||
reportDuplicates?: boolean; | ||
/** | ||
* Start the scanner with the front camera? | ||
* Default: false, so the back camera is used. | ||
*/ | ||
preferFrontCamera?: boolean; | ||
/** | ||
* While scanning for a barcode show a button to flip to the other camera (front or back). | ||
* Default: false | ||
*/ | ||
showFlipCameraButton?: boolean; | ||
/** | ||
* Default: false | ||
*/ | ||
showTorchButton?: boolean; | ||
/** | ||
* Launch the scanner with the flashlight turned on. | ||
*/ | ||
torchOn?: boolean; | ||
/** | ||
* Play a sound when a code was scanned. | ||
* Default: true | ||
*/ | ||
beepOnScan?: boolean; | ||
} | ||
export interface IOS extends CommonScanOptions { | ||
/** | ||
* The label of the button used to close the scanner. | ||
* Default: "Close". | ||
*/ | ||
cancelLabel?: string; | ||
/** | ||
* The background color of the button the label is drawn upon. | ||
* Default: "#000000" (black) | ||
*/ | ||
cancelLabelBackgroundColor?: string; | ||
/** | ||
* You can send the user to the settings app if access was previously denied. | ||
* Default: false | ||
*/ | ||
openSettingsIfPermissionWasPreviouslyDenied?: boolean; | ||
} | ||
export interface Android extends CommonScanOptions { | ||
/** | ||
* The message shown when looking for something to scan. | ||
* Default: "Place a barcode inside the viewfinder rectangle to scan it." | ||
*/ | ||
message?: string; | ||
/** | ||
* Optionally lock the orientation to 'portrait' or 'landscape'. | ||
* Default: "sensor", which follows the current device rotation. | ||
*/ | ||
orientation?: string; | ||
/** | ||
* Default is 1500, set to 0 o suppress the scanner echoing the scanned text. | ||
*/ | ||
resultDisplayDuration?: number; | ||
@@ -113,4 +52,3 @@ } | ||
} | ||
/**** View-related stuff below ****/ | ||
export declare const formatsProperty: Property<BarcodeScannerView, string>; | ||
export declare const formatsProperty: any; | ||
export declare const preferFrontCameraProperty: Property<BarcodeScannerView, boolean>; | ||
@@ -117,0 +55,0 @@ export declare const beepOnScanProperty: Property<BarcodeScannerView, boolean>; |
@@ -6,3 +6,2 @@ "use strict"; | ||
var view_base_1 = require("tns-core-modules/ui/core/view-base"); | ||
/**** View-related stuff below ****/ | ||
exports.formatsProperty = new properties_1.Property({ | ||
@@ -27,3 +26,3 @@ name: "formats", | ||
}); | ||
var BarcodeScannerView = /** @class */ (function (_super) { | ||
var BarcodeScannerView = (function (_super) { | ||
__extends(BarcodeScannerView, _super); | ||
@@ -53,1 +52,2 @@ function BarcodeScannerView() { | ||
exports.reportDuplicatesProperty.register(BarcodeScannerView); | ||
//# sourceMappingURL=barcodescanner-common.js.map |
@@ -8,4 +8,4 @@ import { ScanOptions, ScanResult } from "./barcodescanner-common"; | ||
constructor(); | ||
private wasCameraPermissionGranted(); | ||
private requestCameraPermissionInternal(onPermissionGranted, reject); | ||
private wasCameraPermissionGranted; | ||
private requestCameraPermissionInternal; | ||
available(): Promise<boolean>; | ||
@@ -12,0 +12,0 @@ hasCameraPermission(): Promise<boolean>; |
@@ -8,3 +8,3 @@ "use strict"; | ||
var _onContinuousScanResult = undefined; | ||
var BarcodeScanner = /** @class */ (function () { | ||
var BarcodeScanner = (function () { | ||
function BarcodeScanner() { | ||
@@ -32,3 +32,3 @@ var _this = this; | ||
BarcodeScanner.prototype.wasCameraPermissionGranted = function () { | ||
var hasPermission = android.os.Build.VERSION.SDK_INT < 23; // Android M. (6.0) | ||
var hasPermission = android.os.Build.VERSION.SDK_INT < 23; | ||
if (!hasPermission) { | ||
@@ -43,4 +43,3 @@ hasPermission = android.content.pm.PackageManager.PERMISSION_GRANTED === | ||
this.onPermissionRejected = reject; | ||
android.support.v4.app.ActivityCompat.requestPermissions(appModule.android.foregroundActivity, [android.Manifest.permission.CAMERA], 234 // irrelevant since we simply invoke onPermissionGranted | ||
); | ||
android.support.v4.app.ActivityCompat.requestPermissions(appModule.android.foregroundActivity, [android.Manifest.permission.CAMERA], 234); | ||
}; | ||
@@ -54,3 +53,2 @@ BarcodeScanner.prototype.available = function () { | ||
console.log("Error in barcodescanner.available: " + ex); | ||
// let's just assume it's ok | ||
resolve(true); | ||
@@ -104,8 +102,5 @@ } | ||
_this.uniquelyScannedCodes = []; | ||
// the intent name should match the filter name in AndroidManifest.xml, don't change it | ||
var intent = new android.content.Intent("com.google.zxing.client.android.SCAN"); | ||
// limit searching for a valid Intent to this package only | ||
intent.setPackage(appModule.android.context.getPackageName()); | ||
arg = arg || {}; | ||
// shown at the bottom of the scan UI, default is: "Place a barcode inside the viewfinder rectangle to scan it." | ||
if (arg.message) { | ||
@@ -115,3 +110,2 @@ intent.putExtra("PROMPT_MESSAGE", arg.message); | ||
if (arg.preferFrontCamera === true) { | ||
// if no front cam is found this will fall back to the back camera | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.CAMERA_ID, 1); | ||
@@ -126,3 +120,2 @@ } | ||
if (arg.orientation) { | ||
// if not set, sensor orientation is used (rotates with the device) | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.ORIENTATION_LOCK, arg.orientation); | ||
@@ -132,3 +125,2 @@ } | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.FORMATS, arg.formats); | ||
// intent.putExtra(com.google.zxing.client.android.Intents.Scan.MODE, com.google.zxing.client.android.Intents.Scan.QR_CODE_MODE); | ||
} | ||
@@ -140,10 +132,5 @@ if (arg.torchOn === true) { | ||
if (arg.resultDisplayDuration !== undefined) { | ||
// ZXing expects a String | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.RESULT_DISPLAY_DURATION_MS, "" + arg.resultDisplayDuration); | ||
} | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.SAVE_HISTORY, false); | ||
// rectangle size can be controlled as well (but don't bother as of yet) | ||
// intent.putExtra(com.google.zxing.client.android.Intents.Scan.WIDTH, 200); | ||
// intent.putExtra(com.google.zxing.client.android.Intents.Scan.HEIGHT, 200); | ||
// required for the 'stop' function | ||
if (!_this.broadcastManager) { | ||
@@ -160,3 +147,2 @@ _this.broadcastManager = android.support.v4.content.LocalBroadcastManager.getInstance(utils.ad.getApplicationContext()); | ||
var text = data.getStringExtra(com.google.zxing.client.android.Intents.Scan.RESULT); | ||
// don't report duplicates unless requested | ||
if (arg.reportDuplicates || _this.uniquelyScannedCodes.indexOf("[" + text + "][" + format + "]") === -1) { | ||
@@ -207,3 +193,2 @@ _this.uniquelyScannedCodes.push("[" + text + "][" + format + "]"); | ||
else { | ||
// this is next to impossible | ||
reject("Configuration error"); | ||
@@ -222,1 +207,2 @@ } | ||
exports.BarcodeScanner = BarcodeScanner; | ||
//# sourceMappingURL=barcodescanner.android.js.map |
@@ -21,8 +21,8 @@ import { BarcodeScannerView as BarcodeScannerBaseView, ScanOptions, ScanResult } from "./barcodescanner-common"; | ||
constructor(); | ||
private _hasCameraPermission(); | ||
private _hasDeniedCameraPermission(); | ||
private _addVolumeObserver(); | ||
private _removeVolumeObserver(); | ||
private _enableTorch(); | ||
private _disableTorch(); | ||
private _hasCameraPermission; | ||
private _hasDeniedCameraPermission; | ||
private _addVolumeObserver; | ||
private _removeVolumeObserver; | ||
private _enableTorch; | ||
private _disableTorch; | ||
available(): Promise<boolean>; | ||
@@ -33,2 +33,4 @@ hasCameraPermission(): Promise<boolean>; | ||
scan(arg: ScanOptions): Promise<ScanResult>; | ||
private isPresentingModally; | ||
private getViewControllerToPresentFrom; | ||
} |
@@ -5,3 +5,3 @@ "use strict"; | ||
var utils = require("tns-core-modules/utils/utils"); | ||
var BarcodeScannerView = /** @class */ (function (_super) { | ||
var BarcodeScannerView = (function (_super) { | ||
__extends(BarcodeScannerView, _super); | ||
@@ -32,3 +32,3 @@ function BarcodeScannerView() { | ||
this._scanner = QRCodeReaderViewController.readerWithCancelButtonTitleCodeReaderStartScanningAtLoadShowSwitchCameraButtonShowTorchButtonCancelButtonBackgroundColor(closeButtonLabel, this._reader, true, flip, torch, cancelLabelBackgroundColor); | ||
this._scanner.modalPresentationStyle = 3 /* CurrentContext */; | ||
this._scanner.modalPresentationStyle = 3; | ||
var that = this; | ||
@@ -61,3 +61,3 @@ var delegate = QRCodeReaderDelegateImpl.initWithOwner(new WeakRef(this)); | ||
exports.BarcodeScannerView = BarcodeScannerView; | ||
var BarcodeScanner = /** @class */ (function () { | ||
var BarcodeScanner = (function () { | ||
function BarcodeScanner() { | ||
@@ -72,7 +72,7 @@ this._device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo); | ||
var authStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo); | ||
return authStatus === 3 /* Authorized */; | ||
return authStatus === 3; | ||
}; | ||
BarcodeScanner.prototype._hasDeniedCameraPermission = function () { | ||
var authStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo); | ||
return authStatus === 2 /* Denied */ || authStatus === 1 /* Restricted */; | ||
return authStatus === 2 || authStatus === 1; | ||
}; | ||
@@ -104,3 +104,3 @@ BarcodeScanner.prototype._addVolumeObserver = function () { | ||
this._device.setTorchModeOnWithLevelError(AVCaptureMaxAvailableTorchLevel); | ||
this._device.flashMode = 1 /* On */; | ||
this._device.flashMode = 1; | ||
this._device.unlockForConfiguration(); | ||
@@ -110,4 +110,4 @@ }; | ||
this._device.lockForConfiguration(); | ||
this._device.torchMode = 0 /* Off */; | ||
this._device.flashMode = 0 /* Off */; | ||
this._device.torchMode = 0; | ||
this._device.flashMode = 0; | ||
this._device.unlockForConfiguration(); | ||
@@ -129,3 +129,2 @@ }; | ||
return new Promise(function (resolve) { | ||
// this will trigger the prompt on iOS 10+ | ||
QRCodeReader.isAvailable(); | ||
@@ -139,4 +138,3 @@ resolve(); | ||
try { | ||
var app_1 = utils.ios.getter(UIApplication, UIApplication.sharedApplication); | ||
app_1.keyWindow.rootViewController.dismissViewControllerAnimatedCompletion(true, null); | ||
_this.getViewControllerToPresentFrom().dismissViewControllerAnimatedCompletion(true, null); | ||
_this._removeVolumeObserver(); | ||
@@ -155,3 +153,2 @@ _this._closeCallback && _this._closeCallback(); | ||
try { | ||
// only need for denied permission as conveniently, this method will auto-request permission upon scan | ||
if (_this._hasDeniedCameraPermission()) { | ||
@@ -178,7 +175,6 @@ if (arg.openSettingsIfPermissionWasPreviouslyDenied) { | ||
_this._scanner = QRCodeReaderViewController.readerWithCancelButtonTitleCodeReaderStartScanningAtLoadShowSwitchCameraButtonShowTorchButtonCancelButtonBackgroundColor(closeButtonLabel, reader, startScanningAtLoad, flip, torch, arg.cancelLabelBackgroundColor); | ||
_this._scanner.modalPresentationStyle = 2 /* FormSheet */; | ||
_this._scanner.modalPresentationStyle = 2; | ||
_this._scanDelegate = QRCodeReaderDelegateImpl.initWithOwner(new WeakRef(_this)); | ||
_this._scanner.delegate = _this._scanDelegate; | ||
_this._scanDelegate.setCallback(arg.beepOnScan !== false, isContinuous_1, arg.reportDuplicates, arg.formats, function (text, format) { | ||
// invoke the callback / promise | ||
if (text === undefined) { | ||
@@ -212,3 +208,3 @@ _this._removeVolumeObserver(); | ||
_this._device.lockForConfiguration(); | ||
_this._device.autoFocusRangeRestriction = 1 /* Near */; | ||
_this._device.autoFocusRangeRestriction = 1; | ||
if (_this._device.smoothAutoFocusSupported) { | ||
@@ -219,8 +215,9 @@ _this._device.smoothAutoFocusEnabled = true; | ||
} | ||
var app_2 = utils.ios.getter(UIApplication, UIApplication.sharedApplication); | ||
app_2.keyWindow.rootViewController.presentViewControllerAnimatedCompletion(_this._scanner, true, function () { | ||
if (arg.torchOn) { | ||
_this._enableTorch(); | ||
} | ||
}); | ||
setTimeout(function () { | ||
_this.getViewControllerToPresentFrom().presentViewControllerAnimatedCompletion(_this._scanner, true, function () { | ||
if (arg.torchOn) { | ||
_this._enableTorch(); | ||
} | ||
}); | ||
}, _this.isPresentingModally() ? 650 : 0); | ||
} | ||
@@ -233,2 +230,37 @@ catch (ex) { | ||
}; | ||
BarcodeScanner.prototype.isPresentingModally = function () { | ||
var frame = require("tns-core-modules/ui/frame"); | ||
var viewController; | ||
var topMostFrame = frame.topmost(); | ||
if (frame.topmost()) { | ||
viewController = topMostFrame.currentPage && topMostFrame.currentPage.ios; | ||
if (viewController) { | ||
while (viewController.parentViewController) { | ||
viewController = viewController.parentViewController; | ||
} | ||
return !!viewController.presentedViewController; | ||
} | ||
} | ||
return false; | ||
}; | ||
BarcodeScanner.prototype.getViewControllerToPresentFrom = function () { | ||
var frame = require("tns-core-modules/ui/frame"); | ||
var viewController; | ||
var topMostFrame = frame.topmost(); | ||
if (topMostFrame) { | ||
viewController = topMostFrame.currentPage && topMostFrame.currentPage.ios; | ||
if (viewController) { | ||
while (viewController.parentViewController) { | ||
viewController = viewController.parentViewController; | ||
} | ||
while (viewController.presentedViewController) { | ||
viewController = viewController.presentedViewController; | ||
} | ||
} | ||
} | ||
if (!viewController) { | ||
viewController = UIApplication.sharedApplication.keyWindow.rootViewController; | ||
} | ||
return viewController; | ||
}; | ||
return BarcodeScanner; | ||
@@ -240,4 +272,2 @@ }()); | ||
value.indexOf("0") === 0; | ||
// why not add the line below? see https://github.com/EddyVerbruggen/nativescript-barcodescanner/issues/176 | ||
// && (!requestedFormats || requestedFormats.indexOf("UPC_A") > -1); | ||
}; | ||
@@ -312,7 +342,6 @@ var getBarcodeFormat = function (nativeFormat) { | ||
}; | ||
var QRCodeReaderDelegateImpl = /** @class */ (function (_super) { | ||
var QRCodeReaderDelegateImpl = (function (_super) { | ||
__extends(QRCodeReaderDelegateImpl, _super); | ||
function QRCodeReaderDelegateImpl() { | ||
var _this = _super !== null && _super.apply(this, arguments) || this; | ||
// initializing this value may prevent recognizing too quickly | ||
_this._lastScanResultTs = new Date().getTime(); | ||
@@ -336,3 +365,3 @@ return _this; | ||
this._player.numberOfLoops = 1; | ||
this._player.volume = 0.7; // this is not the actual volume, as that really depends on the device volume | ||
this._player.volume = 0.7; | ||
this._player.prepareToPlay(); | ||
@@ -342,4 +371,3 @@ } | ||
QRCodeReaderDelegateImpl.prototype.readerDidCancel = function (reader) { | ||
var app = utils.ios.getter(UIApplication, UIApplication.sharedApplication); | ||
app.keyWindow.rootViewController.dismissViewControllerAnimatedCompletion(true, null); | ||
this._owner.get().getViewControllerToPresentFrom().dismissViewControllerAnimatedCompletion(true, null); | ||
this._callback(); | ||
@@ -359,7 +387,5 @@ }; | ||
} | ||
// don't report duplicates unless explicitly requested | ||
var newResult = this._scannedArray.indexOf("[" + value + "][" + barcodeFormat + "]") === -1; | ||
if (newResult || this._reportDuplicates) { | ||
var now = new Date().getTime(); | ||
// prevent flooding the callback | ||
if (now - this._lastScanResultTs < 1700) { | ||
@@ -371,3 +397,3 @@ return; | ||
this._scannedArray.push("[" + value + "][" + barcodeFormat + "]"); | ||
this._callback(value, barcodeFormat); // TODO if type is EAN13, but it actually a UPC_A, return UPC_A | ||
this._callback(value, barcodeFormat); | ||
} | ||
@@ -377,5 +403,4 @@ } | ||
validResult = true; | ||
var app_3 = utils.ios.getter(UIApplication, UIApplication.sharedApplication); | ||
app_3.keyWindow.rootViewController.dismissViewControllerAnimatedCompletion(true, null); | ||
this._callback(value, barcodeFormat); // TODO if type is EAN13, but it actually a UPC_A, return UPC_A | ||
this._owner.get().getViewControllerToPresentFrom().dismissViewControllerAnimatedCompletion(true, null); | ||
this._callback(value, barcodeFormat); | ||
} | ||
@@ -389,3 +414,3 @@ if (validResult && this._player) { | ||
}(NSObject)); | ||
var VolumeObserverClass = /** @class */ (function (_super) { | ||
var VolumeObserverClass = (function (_super) { | ||
__extends(VolumeObserverClass, _super); | ||
@@ -399,7 +424,5 @@ function VolumeObserverClass() { | ||
if (volumeLevel > this["_owner"]._currentVolume) { | ||
// volume up button pressed, so enable torch | ||
this["_owner"]._enableTorch(); | ||
} | ||
else { | ||
// volume down button pressed, so disable torch | ||
this["_owner"]._disableTorch(); | ||
@@ -412,1 +435,2 @@ } | ||
}(NSObject)); | ||
//# sourceMappingURL=barcodescanner.ios.js.map |
{ | ||
"name": "nativescript-barcodescanner", | ||
"version": "3.0.1", | ||
"version": "3.0.2", | ||
"description": "Scan QR/barcodes with your NativeScript app.", | ||
@@ -20,3 +20,3 @@ "main": "barcodescanner", | ||
"test.ios": "npm i && npm run tsc && npm run tslint && cd ../demo && tns build ios && tns test ios --justlaunch", | ||
"tslint": "cd .. && tslint \"**/*.ts\" --config tslint.json --exclude \"**/node_modules/**\"", | ||
"tslint": "cd .. && tslint \"**/*.ts\" --config tslint.json --exclude '**/platforms/**' --exclude '**/tns_modules/**' --exclude '**/node_modules/**' --exclude '**/typings/**'", | ||
"plugin.link": "npm link && cd ../demo && npm link nativescript-barcodescanner && cd ../src", | ||
@@ -73,9 +73,10 @@ "plugin.link.ng": "npm link && cd ../demo-ng && npm link nativescript-barcodescanner && cd ../src", | ||
"devDependencies": { | ||
"nativescript-dev-typescript": "libs", | ||
"rimraf": "^2.5.0", | ||
"tns-core-modules": "~3.4.0", | ||
"tns-platform-declarations": "~3.4.0", | ||
"tslint": "^5.0.0", | ||
"typescript": "~2.6.0" | ||
"tns-core-modules": "~5.1.2", | ||
"tns-platform-declarations": "~5.1.2", | ||
"typescript": "~3.1.2", | ||
"prompt": "^1.0.0", | ||
"rimraf": "^2.6.2", | ||
"tslint": "^5.11.0", | ||
"semver": "^5.6.0" | ||
} | ||
} |
@@ -121,4 +121,28 @@ # NativeScript BarcodeScanner | ||
See the 'demo-ng' for details. Do not run it for Android, because embedding a view is not supported on that platform. | ||
See 'demo-ng' for details. Do not run it for Android, because embedding a view is not supported on that platform. | ||
### Embedding in Vue | ||
main.ts: | ||
```typescript | ||
Vue.registerElement('BarcodeScanner', () => require('nativescript-barcodescanner').BarcodeScannerView) | ||
``` | ||
View: | ||
```html | ||
<BarcodeScanner | ||
row="1" | ||
height="300" | ||
formats="QR_CODE, EAN_13, UPC_A" | ||
beepOnScan="true" | ||
reportDuplicates="true" | ||
preferFrontCamera="false" | ||
@scanResult="onScanResult" | ||
v-if="isIOS"> | ||
</BarcodeScanner> | ||
``` | ||
See 'demo-vue' for details. | ||
## iOS runtime permission reason | ||
@@ -125,0 +149,0 @@ You've probably seen a permission popup like this before (this plugin will trigger one as well, automatically): |
382
1709466
7
768