([]);
+ const [isScanning, setIsScanning] = useState(false);
+ const { colors } = useTheme();
+
+ // Function to run Bluetooth Classic test and update logs
+ const runBluetoothTest = async () => {
+ // Classic not currently supported on iOS
+ if (window['cordova'].platformId == 'ios') {
+ displayErrorMsg('Sorry, iOS is not supported!', 'OSError');
+ return;
+ }
+
+ try {
+ let response = await window['cordova'].plugins.BEMDataCollection.bluetoothScanPermissions();
+ if (response != 'OK') {
+ displayErrorMsg('Please Enable Bluetooth!', 'Insufficient Permissions');
+ return;
+ }
+ } catch (e) {
+ displayError(e, 'Insufficient Permissions');
+ return;
+ }
+
+ try {
+ setIsScanning(true);
+ const newLogs = await gatherBluetoothData(t);
+ setLogs(newLogs);
+ } catch (error) {
+ logWarn(error);
+ } finally {
+ setIsScanning(false);
+ }
+ };
+
+ const BluetoothCardList = ({ devices }) => (
+
+ {devices.map((device) => {
+ if (device) {
+ return ;
+ }
+ return null;
+ })}
+
+ );
+
+ const BlueScanContent = () => (
+
+
+ {
+ props.onDismiss?.();
+ }}
+ />
+
+
+
+
+
+
+
+ );
+
+ return (
+ <>
+
+
+
+
+
+
+
+ >
+ );
+};
+
+const s = StyleSheet.create({
+ btnContainer: {
+ padding: 16,
+ justifyContent: 'center',
+ },
+ btn: {
+ height: 38,
+ fontSize: 11,
+ margin: 4,
+ },
+});
+
+export default BluetoothScanPage;
diff --git a/www/js/bluetooth/bluetoothScanner.ts b/www/js/bluetooth/bluetoothScanner.ts
new file mode 100644
index 000000000..2e77c30b0
--- /dev/null
+++ b/www/js/bluetooth/bluetoothScanner.ts
@@ -0,0 +1,54 @@
+import { logDebug, displayError } from '../plugin/logger';
+import { BluetoothClassicDevice } from '../types/bluetoothTypes';
+
+/**
+ * gatherBluetoothData scans for viewable Bluetooth Classic Devices
+ * @param t is the i18next translation function
+ * @returns an array of strings containing device data, formatted ['ID: id Name: name']
+ */
+export default function gatherBluetoothData(t): Promise {
+ return new Promise((resolve, reject) => {
+ logDebug('Running bluetooth discovery test!');
+
+ // Device List "I/O"
+ function updatePairingStatus(pairingType: boolean, devices: Array) {
+ devices.forEach((device) => {
+ device.is_paired = pairingType;
+ });
+ return devices;
+ }
+
+ // Plugin Calls
+ const unpairedDevicesPromise = new Promise((res, rej) => {
+ window['bluetoothClassicSerial'].discoverUnpaired(
+ (devices: Array) => {
+ res(updatePairingStatus(false, devices));
+ },
+ (e: Error) => {
+ displayError(e, 'Error');
+ rej(e);
+ },
+ );
+ });
+
+ const pairedDevicesPromise = new Promise((res, rej) => {
+ window['bluetoothClassicSerial'].list(
+ (devices: Array) => {
+ res(updatePairingStatus(true, devices));
+ },
+ (e: Error) => {
+ displayError(e, 'Error');
+ rej(e);
+ },
+ );
+ });
+
+ Promise.all([unpairedDevicesPromise, pairedDevicesPromise])
+ .then((logs: Array) => {
+ resolve(logs.flat());
+ })
+ .catch((e) => {
+ reject(e);
+ });
+ });
+}
diff --git a/www/js/control/BluetoothScanSettingRow.tsx b/www/js/control/BluetoothScanSettingRow.tsx
new file mode 100644
index 000000000..b32e4cdbf
--- /dev/null
+++ b/www/js/control/BluetoothScanSettingRow.tsx
@@ -0,0 +1,23 @@
+import React, { useState } from 'react';
+import SettingRow from './SettingRow';
+import BluetoothScanPage from '../bluetooth/BluetoothScanPage';
+
+const BluetoothScanSettingRow = ({}) => {
+ const [bluePageVisible, setBluePageVisible] = useState(false);
+
+ async function openPopover() {
+ setBluePageVisible(true);
+ }
+
+ return (
+ <>
+
+ setBluePageVisible(false)} />
+ >
+ );
+};
+
+export default BluetoothScanSettingRow;
diff --git a/www/js/control/ProfileSettings.tsx b/www/js/control/ProfileSettings.tsx
index c6ca8b848..f851a6651 100644
--- a/www/js/control/ProfileSettings.tsx
+++ b/www/js/control/ProfileSettings.tsx
@@ -6,6 +6,7 @@ import ExpansionSection from './ExpandMenu';
import SettingRow from './SettingRow';
import ControlDataTable from './ControlDataTable';
import DemographicsSettingRow from './DemographicsSettingRow';
+import BluetoothScanSettingRow from './BluetoothScanSettingRow';
import PopOpCode from './PopOpCode';
import ReminderTime from './ReminderTime';
import useAppConfig from '../useAppConfig';
@@ -433,8 +434,8 @@ const ProfileSettings = () => {
textKey="control.email-log"
iconName="email"
action={() => sendEmail('loggerDB')}>
-
+