init commit
This commit is contained in:
339
src/services/provider/scan.js
Normal file
339
src/services/provider/scan.js
Normal file
@@ -0,0 +1,339 @@
|
||||
import { inRuntime, bridgeAsync } from "../bridge/appbridge";
|
||||
import { isSupportWebScan, startScanForWeb, stopScanForWeb, isSupportImageScan, startScanForImage } from "../web";
|
||||
import { isSupportWxScan, startScanForWx } from "../wx";
|
||||
import { startScanner, stopScanner } from "../scanner";
|
||||
import { getConfig } from "../config";
|
||||
|
||||
let _scan_status = "closed";
|
||||
let _scan_status_listener = null;
|
||||
let _scan_listener_list = [];
|
||||
let _scan_resolve = null;
|
||||
let _scan_closing = false;
|
||||
let _scan_next_start_time = 0;
|
||||
|
||||
const SCAN_RESTART_DELAY = 2000;
|
||||
|
||||
function __checkScanner() {
|
||||
if (_scan_listener_list.length > 0) {
|
||||
startScanner((result) => {
|
||||
__scannerResult(result);
|
||||
});
|
||||
} else {
|
||||
stopScanner();
|
||||
}
|
||||
}
|
||||
|
||||
function __match(result, match) {
|
||||
let reg = null;
|
||||
if (!!match && typeof match === "string") {
|
||||
reg = new RegExp(match);
|
||||
}
|
||||
if (!!reg) {
|
||||
return reg.test(result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function __result(result) {
|
||||
let matched = false;
|
||||
for (let i = 0; i < _scan_listener_list.length; i++) {
|
||||
const item = _scan_listener_list[i];
|
||||
if (item.listener && __match(result, item.match)) {
|
||||
matched = true;
|
||||
item.listener({ result, key: item.key });
|
||||
console.log("__result", { result, key: item.key });
|
||||
}
|
||||
}
|
||||
if (matched) {
|
||||
_scan_next_start_time = Date.now() + SCAN_RESTART_DELAY;
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
function __hasMatchedListener(result) {
|
||||
for (let i = 0; i < _scan_listener_list.length; i++) {
|
||||
const item = _scan_listener_list[i];
|
||||
if (item.listener && __match(result, item.match)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function __scanning() {
|
||||
if (_scan_status !== "scanning") {
|
||||
_scan_status = "scanning";
|
||||
if (_scan_status_listener) {
|
||||
_scan_status_listener({ status: "scanning" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function __closed() {
|
||||
if (_scan_status !== "closed") {
|
||||
_scan_status = "closed";
|
||||
if (_scan_status_listener) {
|
||||
_scan_status_listener({ status: "closed" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function __finishScan() {
|
||||
const resolve = _scan_resolve;
|
||||
_scan_resolve = null;
|
||||
__closed();
|
||||
return resolve;
|
||||
}
|
||||
|
||||
function __stopCurrentScan() {
|
||||
if (inRuntime()) {
|
||||
return bridgeAsync("stopScan").catch(() => {
|
||||
// no thing
|
||||
});
|
||||
} else if (isSupportWebScan()) {
|
||||
return stopScanForWeb().catch(() => {
|
||||
// no thing
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function __scannerResult(result) {
|
||||
if (!__hasMatchedListener(result)) {
|
||||
return;
|
||||
}
|
||||
if (isScanning()) {
|
||||
const resolve = __finishScan();
|
||||
_scan_closing = true;
|
||||
__stopCurrentScan().then(() => {
|
||||
setTimeout(() => {
|
||||
_scan_closing = false;
|
||||
}, 0);
|
||||
});
|
||||
__result(result);
|
||||
resolve && resolve({
|
||||
result
|
||||
});
|
||||
return;
|
||||
}
|
||||
__result(result);
|
||||
}
|
||||
|
||||
function __startBridgeScan() {
|
||||
return bridgeAsync("startScan", {
|
||||
closeable: true
|
||||
}).then(resp => {
|
||||
if (!isScanning()) {
|
||||
return resp;
|
||||
}
|
||||
if (!resp || !resp.result) {
|
||||
return resp;
|
||||
}
|
||||
if (__result(resp.result)) {
|
||||
return resp;
|
||||
}
|
||||
if (isScanning()) {
|
||||
return __startBridgeScan();
|
||||
}
|
||||
return resp;
|
||||
}).catch(err => {
|
||||
if (!isScanning()) {
|
||||
return err;
|
||||
}
|
||||
if (!err || !err.result) {
|
||||
return err;
|
||||
}
|
||||
if (__result(err.result)) {
|
||||
return err;
|
||||
}
|
||||
if (isScanning()) {
|
||||
return __startBridgeScan();
|
||||
}
|
||||
return err;
|
||||
});
|
||||
}
|
||||
|
||||
function __startWxScan() {
|
||||
return startScanForWx({
|
||||
needResult: 1,
|
||||
scanType: ["qrCode", "barCode"]
|
||||
}).then(resp => {
|
||||
if (!isScanning()) {
|
||||
return resp;
|
||||
}
|
||||
if (!resp || !resp.result) {
|
||||
return resp;
|
||||
}
|
||||
if (__result(resp.result)) {
|
||||
return resp;
|
||||
}
|
||||
if (isScanning()) {
|
||||
return __startWxScan();
|
||||
}
|
||||
return resp;
|
||||
}).catch(err => {
|
||||
if (!isScanning()) {
|
||||
return err;
|
||||
}
|
||||
if (!err || !err.result) {
|
||||
return err;
|
||||
}
|
||||
if (__result(err.result)) {
|
||||
return err;
|
||||
}
|
||||
if (isScanning()) {
|
||||
return __startWxScan();
|
||||
}
|
||||
return err;
|
||||
});
|
||||
}
|
||||
|
||||
function __startImageScan() {
|
||||
return startScanForImage().then(resp => {
|
||||
if (!isScanning()) {
|
||||
return resp;
|
||||
}
|
||||
if (!resp || !resp.result) {
|
||||
return resp;
|
||||
}
|
||||
if (__result(resp.result)) {
|
||||
return resp;
|
||||
}
|
||||
if (isScanning()) {
|
||||
return __startImageScan();
|
||||
}
|
||||
return resp;
|
||||
}).catch(err => {
|
||||
if (!isScanning()) {
|
||||
return err;
|
||||
}
|
||||
if (!err || !err.result) {
|
||||
return err;
|
||||
}
|
||||
if (__result(err.result)) {
|
||||
return err;
|
||||
}
|
||||
if (isScanning()) {
|
||||
return __startImageScan();
|
||||
}
|
||||
return err;
|
||||
});
|
||||
}
|
||||
|
||||
export function isScanning() {
|
||||
return _scan_status === "scanning";
|
||||
}
|
||||
|
||||
export function clear() {
|
||||
for (let i = 0; i < _scan_listener_list.length; i++) {
|
||||
const item = _scan_listener_list[i];
|
||||
item.cancel();
|
||||
}
|
||||
_scan_listener_list.length = 0;
|
||||
__checkScanner();
|
||||
}
|
||||
|
||||
export function onScanListener(listener, key, match, level) {
|
||||
if (typeof listener !== 'function') {
|
||||
return;
|
||||
}
|
||||
let item = null;
|
||||
for (let i = 0; i < _scan_listener_list.length; i++) {
|
||||
const _i = _scan_listener_list[i];
|
||||
if (_i.listener === listener) {
|
||||
item = _i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (item) {
|
||||
item.key = key;
|
||||
item.level = level;
|
||||
item.match = match;
|
||||
} else {
|
||||
item = {
|
||||
key,
|
||||
match,
|
||||
level,
|
||||
listener,
|
||||
cancel: () => {
|
||||
const index = _scan_listener_list.indexOf(item);
|
||||
if (index !== -1) {
|
||||
const items = _scan_listener_list.splice(index, 1);
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
item.listener && item.listener({ cancel: 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
_scan_listener_list.push(item);
|
||||
}
|
||||
// 根据level排序
|
||||
_scan_listener_list.sort((a, b) => b.level - a.level);
|
||||
__checkScanner();
|
||||
return item;
|
||||
}
|
||||
|
||||
export function offScanListener(listener) {
|
||||
for (let i = 0; i < _scan_listener_list.length; i++) {
|
||||
const _i = _scan_listener_list[i];
|
||||
if (_i.listener === listener) {
|
||||
_i.cancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
__checkScanner();
|
||||
}
|
||||
|
||||
export function setStatusListener(listener) {
|
||||
if (typeof listener !== 'function') {
|
||||
return;
|
||||
}
|
||||
_scan_status_listener = listener;
|
||||
}
|
||||
|
||||
export function getStatus() {
|
||||
return _scan_status;
|
||||
}
|
||||
|
||||
export function stopScan() {
|
||||
if (!isScanning()) {
|
||||
return;
|
||||
}
|
||||
__stopCurrentScan().then(() => {
|
||||
__closed();
|
||||
});
|
||||
}
|
||||
|
||||
export function startScan() {
|
||||
if (isScanning() || _scan_closing || Date.now() < _scan_next_start_time) {
|
||||
return;
|
||||
}
|
||||
Promise.resolve().then(() => {
|
||||
__scanning();
|
||||
let scannerPromise = new Promise(resolve => {
|
||||
_scan_resolve = resolve;
|
||||
});
|
||||
let scanPromise = Promise.resolve();
|
||||
if (inRuntime()) {
|
||||
console.log("startScanForBridge");
|
||||
scanPromise = __startBridgeScan();
|
||||
} else if (isSupportWxScan()) {
|
||||
console.log("startScanForWx");
|
||||
scanPromise = __startWxScan();
|
||||
} else if (isSupportWebScan()) {
|
||||
console.log("startScanForWeb");
|
||||
scanPromise = startScanForWeb(getConfig("webCanvasStyle"), __result);
|
||||
} else if (isSupportImageScan()) {
|
||||
console.log("startScanForImage");
|
||||
scanPromise = __startImageScan();
|
||||
} else {
|
||||
console.log("not support scanner");
|
||||
}
|
||||
return Promise.race([scanPromise, scannerPromise]);
|
||||
}).finally(() => {
|
||||
_scan_resolve = null;
|
||||
__closed();
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user