Skip to content

Commit

Permalink
[iOS & Angular] Open barcode scanner from a modal page not working #183
Browse files Browse the repository at this point in the history
  • Loading branch information
EddyVerbruggen committed Feb 5, 2019
1 parent 3d0592b commit eab6b7d
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 26 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# Changelog

## [2.8.0](https://github.com/EddyVerbruggen/nativescript-barcodescanner/tree/3.0.0) (2019-01-10)
## [3.0.2](https://github.com/EddyVerbruggen/nativescript-barcodescanner/tree/3.0.2) (2019-02-05)
[Full Changelog](https://github.com/EddyVerbruggen/nativescript-barcodescanner/milestone/34?closed=1)


## [3.0.0](https://github.com/EddyVerbruggen/nativescript-barcodescanner/tree/3.0.0) (2019-01-10)
[Full Changelog](https://github.com/EddyVerbruggen/nativescript-barcodescanner/milestone/33?closed=1)

> Breaking change: see https://github.com/EddyVerbruggen/nativescript-barcodescanner#a-note-about-upc_a-and-ean_13

## [2.7.9](https://github.com/EddyVerbruggen/nativescript-barcodescanner/tree/2.7.9) (2018-11-16)
[Full Changelog](https://github.com/EddyVerbruggen/nativescript-barcodescanner/milestone/32?closed=1)

Expand Down
7 changes: 5 additions & 2 deletions demo-ng/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ItemDetailComponent } from "./item/item-detail.component";
// import { NativeScriptHttpModule } from "nativescript-angular/http";
import { registerElement } from "nativescript-angular/element-registry";
import { BarcodeScanner } from "nativescript-barcodescanner";
import { ModalComponent } from "~/item/modal/modal.component";
registerElement("BarcodeScanner", () => require("nativescript-barcodescanner").BarcodeScannerView);

@NgModule({
Expand All @@ -27,15 +28,17 @@ registerElement("BarcodeScanner", () => require("nativescript-barcodescanner").B
declarations: [
AppComponent,
ItemsComponent,
ItemDetailComponent
ItemDetailComponent,
ModalComponent
],
providers: [
ItemService,
BarcodeScanner
],
schemas: [
NO_ERRORS_SCHEMA
]
],
entryComponents: [ModalComponent],
})
/*
Pass your application module to the bootstrapModule function located in main.ts to start your app
Expand Down
11 changes: 7 additions & 4 deletions demo-ng/app/item/items.component.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
<!--
The template defines the view of the component - what is actually rendered.
In NativeScript applications the template is defined with XML using NativeScript UI elements.
The template defines the view of the component - what is actually rendered.
In NativeScript applications the template is defined with XML using NativeScript UI elements.
It is different from HTML. So instead of <input>, <span>, <div> etc. - we have <TextField>, <Label> and layouts.
The important thing is that although the elements are different - all of the Angular’s template syntax works exactly the same.
The important thing is that although the elements are different - all of the Angular’s template syntax works exactly the same.
So you can still use template expressions, bindings, templates as well as all the built-in directives.
-->

<!--
The ActionBar is the NativeScript common abstraction over the Android ActionBar and iOS NavigationBar.
http://docs.nativescript.org/ui/action-bar
-->
<ActionBar title="My App" class="action-bar">
<ActionBar class="action-bar">
<StackLayout>
<Button (tap)="openModal()" text="open modal"></Button>
</StackLayout>
</ActionBar>

<!--
Expand Down
19 changes: 17 additions & 2 deletions demo-ng/app/item/items.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Component, OnInit } from "@angular/core";
import { Component, OnInit, ViewContainerRef } from "@angular/core";

import { Item } from "./item";
import { ItemService } from "./item.service";
import { ModalDialogOptions, ModalDialogService } from "nativescript-angular";
import { ModalComponent } from "~/item/modal/modal.component";

@Component({
selector: "ns-items",
Expand All @@ -11,10 +13,23 @@ import { ItemService } from "./item.service";
export class ItemsComponent implements OnInit {
items: Item[];

constructor(private itemService: ItemService) {
constructor(private itemService: ItemService,
private modalService: ModalDialogService,
private vcRef: ViewContainerRef) {
}

ngOnInit(): void {
this.items = this.itemService.getItems();
}

openModal(): void {
const options: ModalDialogOptions = {
viewContainerRef: this.vcRef,
context: {},
fullscreen: true
};

this.modalService.showModal(ModalComponent, options);

}
}
Empty file.
5 changes: 5 additions & 0 deletions demo-ng/app/item/modal/modal.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<GridLayout rows="auto, auto, auto" backgroundColor="white">
<label row="0" text="Modal dialog"></label>
<button row="1" text="close" (tap)="close()"></button>
<button row="2" text="QR scanner" (tap)="openNotification()" class="btn btn-primary"></button>
</GridLayout>
60 changes: 60 additions & 0 deletions demo-ng/app/item/modal/modal.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Component } from "@angular/core";
import { ModalDialogParams } from "nativescript-angular/modal-dialog";
import { BarcodeScanner } from "nativescript-barcodescanner";

@Component({
selector: "modal",
moduleId: module.id,
templateUrl: "./modal.component.html",
styleUrls: ["./modal.component.css"],

})

export class ModalComponent {
barcodescanner: any;

constructor(private params: ModalDialogParams) {
this.barcodescanner = new BarcodeScanner();
}

close() {
this.params.closeCallback();
}

public onScanResult(evt) {
// console.log(evt.object);
console.log(`onScanResult: ${evt.text} (${evt.format})`);
}

openNotification() {
console.log("OPEN NOTIFICATION!");
this.close();

this.barcodescanner.scan({
formats: "QR_CODE, EAN_13",
cancelLabel: "EXIT. Also, try the volume buttons!", // iOS only, default 'Close'
cancelLabelBackgroundColor: "#333333", // iOS only, default '#000000' (black)

showFlipCameraButton: true, // default false
preferFrontCamera: false, // default false
showTorchButton: true, // default false
beepOnScan: true, // Play or Suppress beep on scan (default true)
torchOn: false, // launch with the flashlight on (default false)
closeCallback: () => {
console.log("Scanner closed");
}, // invoked when the scanner was closed (success or abort)

openSettingsIfPermissionWasPreviouslyDenied: true // On iOS you can send the user to the settings app if access was previously denied
}).then((result) => {
// Note that this Promise is never invoked when a 'continuousScanCallback' function is provided
console.log({
title: "Scan result",
message: "Format: " + result.format + ",\nValue: " + result.text,
okButtonText: "OK"
});
}, (errorMessage) => {
console.log("No scan. " + errorMessage);
}
);
}
}
76 changes: 61 additions & 15 deletions src/barcodescanner.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,7 @@ export class BarcodeScanner {
public stop(): Promise<any> {
return new Promise((resolve, reject) => {
try {
const app = utils.ios.getter(UIApplication, UIApplication.sharedApplication);
app.keyWindow.rootViewController.dismissViewControllerAnimatedCompletion(true, null);
this.getViewControllerToPresentFrom().dismissViewControllerAnimatedCompletion(true, null);
this._removeVolumeObserver();
this._closeCallback && this._closeCallback();
resolve();
Expand Down Expand Up @@ -259,25 +258,74 @@ export class BarcodeScanner {
this._device.unlockForConfiguration();
}

const app = utils.ios.getter(UIApplication, UIApplication.sharedApplication);
app.keyWindow.rootViewController.presentViewControllerAnimatedCompletion(this._scanner, true, () => {
if (arg.torchOn) {
this._enableTorch();
}
});
setTimeout(() => {
this.getViewControllerToPresentFrom().presentViewControllerAnimatedCompletion(this._scanner, true, () => {
if (arg.torchOn) {
this._enableTorch();
}
});
}, this.isPresentingModally() ? 650 : 0);

} catch (ex) {
console.log("Error in barcodescanner.scan: " + ex);
reject(ex);
}
});
}

private isPresentingModally(): boolean {
let frame = require("tns-core-modules/ui/frame");
let viewController: UIViewController;
let 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;
}

private getViewControllerToPresentFrom(): UIViewController {
let frame = require("tns-core-modules/ui/frame");
let viewController: UIViewController;
let topMostFrame = frame.topmost();

if (topMostFrame) {
viewController = topMostFrame.currentPage && topMostFrame.currentPage.ios;

if (viewController) {
while (viewController.parentViewController) {
// find top-most view controler
viewController = viewController.parentViewController;
}

while (viewController.presentedViewController) {
// find last presented modal
viewController = viewController.presentedViewController;
}
}
}

if (!viewController) {
viewController = UIApplication.sharedApplication.keyWindow.rootViewController;
}

return viewController;
}
}

const shouldReturnEAN13AsUPCA = (barcodeFormat: BarcodeFormat, value: string, requestedFormats?: string): boolean => {
return barcodeFormat === "EAN_13" &&
value.indexOf("0") === 0;
// why not add the line below? see https://github.com/EddyVerbruggen/nativescript-barcodescanner/issues/176
// why not add the line below? Well, see https://github.com/EddyVerbruggen/nativescript-barcodescanner/issues/176
// && (!requestedFormats || requestedFormats.indexOf("UPC_A") > -1);
};

Expand Down Expand Up @@ -366,8 +414,7 @@ class QRCodeReaderDelegateImpl extends NSObject implements QRCodeReaderDelegate
}

public readerDidCancel(reader: QRCodeReaderViewController): void {
let app = utils.ios.getter(UIApplication, UIApplication.sharedApplication);
app.keyWindow.rootViewController.dismissViewControllerAnimatedCompletion(true, null);
this._owner.get().getViewControllerToPresentFrom().dismissViewControllerAnimatedCompletion(true, null);
this._callback();
}

Expand Down Expand Up @@ -397,13 +444,12 @@ class QRCodeReaderDelegateImpl extends NSObject implements QRCodeReaderDelegate
this._lastScanResultTs = now;
validResult = true;
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);
}
} else {
validResult = true;
let app = utils.ios.getter(UIApplication, UIApplication.sharedApplication);
app.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);
}

if (validResult && this._player) {
Expand Down
2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nativescript-barcodescanner",
"version": "3.0.1",
"version": "3.0.2",
"description": "Scan QR/barcodes with your NativeScript app.",
"main": "barcodescanner",
"typings": "index.d.ts",
Expand Down

0 comments on commit eab6b7d

Please sign in to comment.