mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-10 02:54:15 +00:00
support native nfc
This commit is contained in:
parent
2bd2d3a274
commit
5353780c67
@ -1,40 +1,137 @@
|
|||||||
import Core from "evite/src/core"
|
import Core from "evite/src/core"
|
||||||
import TapShareDialog from "components/TapShare/Dialog"
|
import TapShareDialog from "components/TapShare/Dialog"
|
||||||
import { Nfc, NfcUtils, NfcTagTechType } from "@capawesome-team/capacitor-nfc"
|
|
||||||
|
const RecordTypes = {
|
||||||
|
"T": "text",
|
||||||
|
"U": "url"
|
||||||
|
}
|
||||||
|
|
||||||
|
function decodePayload(record) {
|
||||||
|
let recordType = nfc.bytesToString(record.type)
|
||||||
|
|
||||||
|
let payload = {
|
||||||
|
recordId: nfc.bytesToHexString(record.id),
|
||||||
|
recordType: RecordTypes[recordType],
|
||||||
|
data: null
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (recordType) {
|
||||||
|
case "T": {
|
||||||
|
let langCodeLength = record.payload[0]
|
||||||
|
|
||||||
|
payload.data = record.payload.slice((1 + langCodeLength), record.payload.length)
|
||||||
|
|
||||||
|
payload.data = nfc.bytesToString(text)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "U": {
|
||||||
|
let identifierCode = record.payload.shift()
|
||||||
|
|
||||||
|
payload.data = nfc.bytesToString(record.payload)
|
||||||
|
|
||||||
|
switch (identifierCode) {
|
||||||
|
case 4: {
|
||||||
|
payload.data = `https://${payload.data}`
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
payload.data = `http://${payload.data}`
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
payload.data = nfc.bytesToString(record.payload)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveSerialNumber(tag) {
|
||||||
|
let serialNumber = null
|
||||||
|
|
||||||
|
serialNumber = nfc.bytesToHexString(tag.id)
|
||||||
|
|
||||||
|
// transform serialNumber to contain a ":" every 2 bytes
|
||||||
|
serialNumber = serialNumber.replace(/(.{2})/g, "$1:")
|
||||||
|
|
||||||
|
// remove the last :
|
||||||
|
serialNumber = serialNumber.slice(0, -1)
|
||||||
|
|
||||||
|
return serialNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseNdefMessage(ndefMessage) {
|
||||||
|
let message = []
|
||||||
|
|
||||||
|
ndefMessage.forEach((ndefRecord) => {
|
||||||
|
message.push(decodePayload(ndefRecord))
|
||||||
|
})
|
||||||
|
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
export default class NFC extends Core {
|
export default class NFC extends Core {
|
||||||
static refName = "NFC"
|
static refName = "NFC"
|
||||||
|
|
||||||
static namespace = "nfc"
|
static namespace = "nfc"
|
||||||
|
|
||||||
|
isNativeMode = false
|
||||||
|
|
||||||
instance = null
|
instance = null
|
||||||
|
|
||||||
subscribers = []
|
subscribers = []
|
||||||
|
|
||||||
public = {
|
public = {
|
||||||
incompatible: null,
|
incompatible: true,
|
||||||
scanning: false,
|
scanning: false,
|
||||||
startScanning: this.startScanning.bind(this),
|
writeNdef: this.writeNdef.bind(this),
|
||||||
instance: function () { return this.instance }.bind(this),
|
instance: function () { return this.instance }.bind(this),
|
||||||
subscribe: this.subscribe.bind(this),
|
subscribe: this.subscribe.bind(this),
|
||||||
unsubscribe: this.unsubscribe.bind(this),
|
unsubscribe: this.unsubscribe.bind(this),
|
||||||
}
|
}
|
||||||
|
|
||||||
async onInitialize() {
|
subscribe(callback) {
|
||||||
if ("NDEFReader" in window === false) {
|
// check if scan service is available, if not try to initialize
|
||||||
return this.public.incompatible = true
|
if (this.public.scanning === false) {
|
||||||
|
this.startScanning()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.instance = new NDEFReader()
|
this.subscribers.push(callback)
|
||||||
|
}
|
||||||
|
|
||||||
this.startScanning()
|
unsubscribe(callback) {
|
||||||
|
this.subscribers = this.subscribers.filter((subscriber) => {
|
||||||
|
return subscriber !== callback
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async onInitialize() {
|
||||||
|
if (window.nfc) {
|
||||||
|
this.instance = window.nfc
|
||||||
|
|
||||||
|
this.isNativeMode = true
|
||||||
|
|
||||||
|
return this.startNativeScanning()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("NDEFReader" in window) {
|
||||||
|
this.instance = new NDEFReader()
|
||||||
|
|
||||||
|
return this.startScanning()
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.public.incompatible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
async startScanning() {
|
async startScanning() {
|
||||||
try {
|
try {
|
||||||
//await navigator.permissions.query({ name: "nfc" })
|
await this.instance.scan()
|
||||||
|
|
||||||
this.instance.scan()
|
|
||||||
|
|
||||||
this.public.scanning = true
|
this.public.scanning = true
|
||||||
this.public.incompatible = false
|
this.public.incompatible = false
|
||||||
@ -48,23 +145,11 @@ export default class NFC extends Core {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(callback) {
|
startNativeScanning() {
|
||||||
// check if scan service is available, if not try to initialize
|
this.public.scanning = true
|
||||||
if (this.public.scanning === false) {
|
this.public.incompatible = false
|
||||||
this.startScanning()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.subscribers.push(callback)
|
return this.registerNativeEventListeners()
|
||||||
|
|
||||||
console.debug(`[NFC] SUBSCRIBED >`, this.subscribers.length)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsubscribe(callback) {
|
|
||||||
this.subscribers = this.subscribers.filter((subscriber) => {
|
|
||||||
return subscriber !== callback
|
|
||||||
})
|
|
||||||
|
|
||||||
console.debug(`[NFC] UNSUBSCRIBED >`, this.subscribers.length)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRead(tag) {
|
handleRead(tag) {
|
||||||
@ -75,8 +160,6 @@ export default class NFC extends Core {
|
|||||||
subscriber(null, tag)
|
subscriber(null, tag)
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(this.subscribers)
|
|
||||||
|
|
||||||
if (this.subscribers.length === 0) {
|
if (this.subscribers.length === 0) {
|
||||||
if (tag.message.records?.length > 0) {
|
if (tag.message.records?.length > 0) {
|
||||||
// open dialog
|
// open dialog
|
||||||
@ -89,6 +172,32 @@ export default class NFC extends Core {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleNativeRead(tag) {
|
||||||
|
console.debug(`[NFC] NATIVE READ >`, tag)
|
||||||
|
|
||||||
|
tag.serialNumber = resolveSerialNumber(tag)
|
||||||
|
|
||||||
|
if (tag.ndefMessage) {
|
||||||
|
tag.message = {}
|
||||||
|
tag.message.records = parseNdefMessage(tag.ndefMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.subscribers.forEach((subscriber) => {
|
||||||
|
subscriber(null, tag)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.subscribers.length === 0 && tag.message?.records) {
|
||||||
|
if (tag.message.records?.length > 0) {
|
||||||
|
// open dialog
|
||||||
|
app.DrawerController.open("nfc_card_dialog", TapShareDialog, {
|
||||||
|
componentProps: {
|
||||||
|
tag: tag,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleError(error) {
|
handleError(error) {
|
||||||
this.subscribers.forEach((subscriber) => {
|
this.subscribers.forEach((subscriber) => {
|
||||||
subscriber(error, null)
|
subscriber(error, null)
|
||||||
@ -99,4 +208,57 @@ export default class NFC extends Core {
|
|||||||
this.instance.addEventListener("reading", this.handleRead.bind(this))
|
this.instance.addEventListener("reading", this.handleRead.bind(this))
|
||||||
this.instance.addEventListener("error", this.handleError.bind(this))
|
this.instance.addEventListener("error", this.handleError.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerNativeEventListeners() {
|
||||||
|
nfc.addTagDiscoveredListener(
|
||||||
|
(e) => this.handleNativeRead(e.tag),
|
||||||
|
() => {
|
||||||
|
this.public.scanning = true
|
||||||
|
this.public.incompatible = false
|
||||||
|
},
|
||||||
|
this.handleError
|
||||||
|
)
|
||||||
|
|
||||||
|
nfc.addNdefListener(
|
||||||
|
(e) => this.handleNativeRead(e.tag),
|
||||||
|
() => {
|
||||||
|
this.public.scanning = true
|
||||||
|
this.public.incompatible = false
|
||||||
|
},
|
||||||
|
this.handleError
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async writeNdef(payload, options) {
|
||||||
|
console.debug(`[NFC] WRITE >`, payload)
|
||||||
|
|
||||||
|
if (!this.isNativeMode) {
|
||||||
|
return this.instance.write(payload, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = []
|
||||||
|
|
||||||
|
const { records } = payload
|
||||||
|
|
||||||
|
if (!Array.isArray(records)) {
|
||||||
|
throw new Error("records must be an array")
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const record of records) {
|
||||||
|
switch (record.recordType) {
|
||||||
|
case "text": {
|
||||||
|
message.push(ndef.textRecord(record.data))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case "url": {
|
||||||
|
message.push(ndef.uriRecord(record.data))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
this.instance.write(message, resolve, reject)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user