xkeys-webhid
Version:
An npm module for interfacing with the X-keys panels in a browser
102 lines • 4.27 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupXkeysPanel = exports.getOpenedXKeysPanels = exports.requestXkeysPanels = void 0;
const core_1 = require("@xkeys-lib/core");
const web_hid_wrapper_1 = require("./web-hid-wrapper");
const globalConnectListener_1 = require("./globalConnectListener");
/** Prompts the user for which X-keys panel to select */
async function requestXkeysPanels() {
const allDevices = await navigator.hid.requestDevice({
filters: [
{
vendorId: core_1.XKEYS_VENDOR_ID,
},
],
});
const newDevices = allDevices.filter(isValidXkeysUsage);
if (newDevices.length > 0)
globalConnectListener_1.GlobalConnectListener.notifyConnectedDevice(); // A fix for when the 'connect' event isn't fired
return newDevices;
}
exports.requestXkeysPanels = requestXkeysPanels;
/**
* Reopen previously selected devices.
* The browser remembers what the user previously allowed your site to access, and this will open those without the request dialog
*/
async function getOpenedXKeysPanels() {
const allDevices = await navigator.hid.getDevices();
return allDevices.filter(isValidXkeysUsage);
}
exports.getOpenedXKeysPanels = getOpenedXKeysPanels;
function isValidXkeysUsage(device) {
if (device.vendorId !== core_1.XKEYS_VENDOR_ID)
return false;
return !!device.collections.find((collection) => {
var _a;
if (collection.usagePage !== 12)
return false;
// Check the write-length of the device is > 20
return !!((_a = collection.outputReports) === null || _a === void 0 ? void 0 : _a.find((report) => { var _a; return !!((_a = report.items) === null || _a === void 0 ? void 0 : _a.find((item) => { var _a; return (_a = item.reportCount) !== null && _a !== void 0 ? _a : 0 > 20; })); }));
});
}
/** Sets up a connection to a HID device (the X-keys panel) */
async function setupXkeysPanel(browserDevice) {
var _a;
if (!((_a = browserDevice === null || browserDevice === void 0 ? void 0 : browserDevice.collections) === null || _a === void 0 ? void 0 : _a.length))
throw Error(`device collections is empty`);
if (!isValidXkeysUsage(browserDevice))
throw new Error(`Device has incorrect usage/interface`);
if (!browserDevice.productId)
throw Error(`Device has no productId!`);
const vendorId = browserDevice.vendorId;
const productId = browserDevice.productId;
if (!browserDevice.opened) {
await browserDevice.open();
}
const deviceWrap = new web_hid_wrapper_1.WebHIDDevice(browserDevice);
const xkeys = new core_1.XKeys(deviceWrap, {
product: browserDevice.productName,
vendorId: vendorId,
productId: productId,
interface: null, // todo: Check what to use here (collection.usage?)
}, undefined);
// Setup listener for disconnect:
globalConnectListener_1.GlobalConnectListener.listenForDisconnectOnce(browserDevice, () => {
xkeys._handleDeviceDisconnected().catch((e) => {
console.error(`Xkeys: Error handling disconnect:`, e);
});
});
let alreadyRejected = false;
try {
await new Promise((resolve, reject) => {
const markRejected = (e) => {
reject(e);
alreadyRejected = true;
};
const xkeysStopgapErrorHandler = (e) => {
if (alreadyRejected) {
console.error(`Xkeys: Error emitted after setup already rejected:`, e);
return;
}
markRejected(e);
};
// Handle all error events until the instance is returned
xkeys.on('error', xkeysStopgapErrorHandler);
// Wait for the device to initialize:
xkeys
.init()
.then(() => {
resolve();
xkeys.removeListener('error', xkeysStopgapErrorHandler);
})
.catch(markRejected);
});
return xkeys;
}
catch (e) {
await deviceWrap.close();
throw e;
}
}
exports.setupXkeysPanel = setupXkeysPanel;
//# sourceMappingURL=methods.js.map