168 lines
5.6 KiB
JavaScript
168 lines
5.6 KiB
JavaScript
import { NfcErrorType, } from "./definitions.js";
|
|
import { WebNfc } from "./web.js";
|
|
/**
|
|
* Main NFC class that provides access to NFC functionality.
|
|
* It automatically chooses the appropriate implementation for the current platform.
|
|
*/
|
|
export class Nfc {
|
|
constructor() {
|
|
this.listeners = new Map();
|
|
// Currently we only have the Web implementation
|
|
this.implementation = new WebNfc();
|
|
// Set up status monitoring to track NFC availability
|
|
this.monitorNfcStatus();
|
|
}
|
|
/**
|
|
* Internal method to monitor NFC status changes
|
|
*/
|
|
async monitorNfcStatus() {
|
|
try {
|
|
// Set up listener for NFC status changes from implementation
|
|
await this.implementation.addListener("nfcStatusChanged", (status) => {
|
|
// Propagate to our own listeners
|
|
this.notifyListeners("nfcStatusChanged", status);
|
|
});
|
|
}
|
|
catch (error) {
|
|
console.warn("Failed to set up NFC status monitoring:", error);
|
|
}
|
|
}
|
|
/**
|
|
* Check if NFC is enabled (Android) or available (iOS/Web).
|
|
* @returns Promise resolving to an object with an `enabled` boolean property
|
|
*/
|
|
async isEnabled() {
|
|
try {
|
|
return await this.implementation.isEnabled();
|
|
}
|
|
catch (error) {
|
|
console.error("Error checking NFC status:", error);
|
|
return { enabled: false };
|
|
}
|
|
}
|
|
/**
|
|
* Open NFC settings (Android) or app settings (iOS) or shows guidance (Web).
|
|
* This helps users enable NFC if it's disabled.
|
|
*/
|
|
async openSettings() {
|
|
return this.implementation.openSettings();
|
|
}
|
|
/**
|
|
* Start scanning for NFC tags.
|
|
* @param options Configuration options for the scan session
|
|
*/
|
|
async startScanSession(options) {
|
|
var _a, _b, _c;
|
|
try {
|
|
return await this.implementation.startScanSession(options);
|
|
}
|
|
catch (error) {
|
|
// Convert to a standardized error object if possible
|
|
const nfcError = new Error(error.message || "Failed to start NFC scan");
|
|
if (((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes("not supported")) ||
|
|
error.name === "NotSupportedError") {
|
|
nfcError.code = NfcErrorType.NOT_SUPPORTED;
|
|
}
|
|
else if (((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes("permission")) ||
|
|
error.name === "NotAllowedError") {
|
|
nfcError.code = NfcErrorType.PERMISSION_DENIED;
|
|
}
|
|
else if ((_c = error.message) === null || _c === void 0 ? void 0 : _c.includes("not enabled")) {
|
|
nfcError.code = NfcErrorType.NOT_ENABLED;
|
|
}
|
|
else {
|
|
nfcError.code = NfcErrorType.UNEXPECTED_ERROR;
|
|
}
|
|
throw nfcError;
|
|
}
|
|
}
|
|
/**
|
|
* Stop the current NFC scan session.
|
|
*/
|
|
async stopScanSession() {
|
|
return this.implementation.stopScanSession();
|
|
}
|
|
/**
|
|
* Write an NDEF message to an NFC tag.
|
|
* @param options Object containing the NDEF message to write
|
|
*/
|
|
async write(options) {
|
|
return this.implementation.write(options);
|
|
}
|
|
/**
|
|
* Make an NFC tag read-only.
|
|
* WARNING: This is a permanent operation that cannot be undone.
|
|
*/
|
|
async makeReadOnly() {
|
|
return this.implementation.makeReadOnly();
|
|
}
|
|
/**
|
|
* Format an NFC tag, erasing its contents and preparing it for writing.
|
|
*/
|
|
async format() {
|
|
return this.implementation.format();
|
|
}
|
|
/**
|
|
* Erase the contents of an NFC tag.
|
|
*/
|
|
async erase() {
|
|
return this.implementation.erase();
|
|
}
|
|
/**
|
|
* Share NDEF data via NFC (Android only, not available on iOS or Web).
|
|
* @param options Object containing the NDEF message to share
|
|
*/
|
|
async share(options) {
|
|
return this.implementation.share(options);
|
|
}
|
|
/**
|
|
* Stop sharing NDEF data via NFC (Android only).
|
|
*/
|
|
async stopSharing() {
|
|
return this.implementation.stopSharing();
|
|
}
|
|
async addListener(eventName, listenerFunc) {
|
|
var _a;
|
|
// Add to our internal listener registry
|
|
if (!this.listeners.has(eventName)) {
|
|
this.listeners.set(eventName, new Set());
|
|
}
|
|
(_a = this.listeners.get(eventName)) === null || _a === void 0 ? void 0 : _a.add(listenerFunc);
|
|
// Register with the implementation
|
|
const handle = await this.implementation.addListener(eventName, listenerFunc);
|
|
// Return a handle that will clean up properly
|
|
return {
|
|
remove: async () => {
|
|
var _a;
|
|
(_a = this.listeners.get(eventName)) === null || _a === void 0 ? void 0 : _a.delete(listenerFunc);
|
|
return handle.remove();
|
|
},
|
|
};
|
|
}
|
|
/**
|
|
* Remove all event listeners registered for this plugin.
|
|
*/
|
|
async removeAllListeners() {
|
|
// Clear our internal listener registry
|
|
this.listeners.clear();
|
|
// Remove listeners from the implementation
|
|
return this.implementation.removeAllListeners();
|
|
}
|
|
/**
|
|
* Internal method to notify listeners of events
|
|
*/
|
|
notifyListeners(eventName, data) {
|
|
const listeners = this.listeners.get(eventName);
|
|
if (listeners) {
|
|
for (const listener of listeners) {
|
|
try {
|
|
listener(data);
|
|
}
|
|
catch (error) {
|
|
console.error(`Error in ${eventName} listener:`, error);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|