unfc/simplepwa/universal-nfc/dist/nfc.js
2025-03-04 20:28:22 +01:00

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);
}
}
}
}
}