import RNBluetoothClassic, { BluetoothDevice, } from "react-native-bluetooth-classic"; import { Ionicons } from "@expo/vector-icons"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { Alert, AppState, Linking, PermissionsAndroid, Platform, Text, View, } from "react-native"; import { CustomBottomSheet, CustomBottomSheetHandle, CustomBottomSheetSelect, CustomBottomSheetTitle, TabButton, } from "ayasofyazilim-mobile-ui"; export function BluetoothDeviceSelectModal({ onDeviceSelected, handleSheetClose, }: { onDeviceSelected: (deviceId: string) => Promise; handleSheetClose?: () => void; }) { const [bondedDevices, setBondedDevices] = useState( [] ); const [connectedDevice, setConnectedDevice] = useState(null); const [isBluetoothPermissionsGranted, setIsBluetoothPermissionsGranted] = useState(false); const [isBluetoothEnabled, setIsBluetoothEnabled] = useState(false); const [isPrinting, setIsPrinting] = useState(false); const bondedDeviceList = useMemo(() => { return bondedDevices.map((device) => ({ id: device.id, icon: "bluetooth" as const, name: device.name || device.address, subTitle: device.address, })); }, [bondedDevices]); const sheetRef = useRef(null); const requestBluetoothPermissions = async (): Promise => { if (Platform.OS !== "android") return true; const sdkInt = Platform.Version; const permissions = sdkInt >= 31 ? [ PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN, PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT, ] : [PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION]; const granted = await PermissionsAndroid.requestMultiple(permissions); const deniedPermissions = Object.entries(granted).filter( ([_, status]) => status !== PermissionsAndroid.RESULTS.GRANTED ); if (deniedPermissions.length === 0) { setIsBluetoothPermissionsGranted(true); return true; } return false; }; const loadBluetoothDevices = async () => { try { const isEnabled = await RNBluetoothClassic.isBluetoothEnabled(); if (isEnabled) setIsBluetoothEnabled(isEnabled); else { setIsBluetoothEnabled(false); } const bonded = await RNBluetoothClassic.getBondedDevices(); setBondedDevices(bonded); for (const device of bonded) { try { const isConnected = await device.isConnected(); if (isConnected) { setConnectedDevice(device); break; } } catch (error) { console.error("Error checking device connection:", error); } } } catch (error) { console.error("Error fetching bonded devices:", error); return; } }; function checkPermission() { requestBluetoothPermissions().then((granted) => { if (granted) { loadBluetoothDevices(); } }); } useEffect(() => { RNBluetoothClassic.isBluetoothEnabled().then((isEnabled) => { setIsBluetoothEnabled(isEnabled); if (isEnabled) { checkPermission(); } }); const listener = RNBluetoothClassic.onStateChanged((state) => { if (state.enabled) { setIsBluetoothEnabled(true); checkPermission(); return; } setIsBluetoothEnabled(false); setBondedDevices([]); setConnectedDevice(null); }); const sub = AppState.addEventListener("change", (state) => { if (state === "active") { checkPermission(); } }); return () => { listener.remove(); sub.remove(); }; }, []); const handleOnPress = useCallback( (deviceId: string) => { setIsPrinting(true); const device = bondedDevices.find((d) => d.id === deviceId); if (device) { onDeviceSelected(device.id).then(async () => { setIsPrinting(false); if (sheetRef.current) { sheetRef.current.hideSheet(); } }); } else { Alert.alert( "Devices Not Found", "Selected device not found in bonded devices.", [ { text: "Ok", onPress: () => { sheetRef.current?.hideSheet(); setIsPrinting(false); }, }, ] ); } }, [bondedDevices, onDeviceSelected, connectedDevice] ); return ( {!connectedDevice && bondedDevices.length === 0 && isBluetoothPermissionsGranted && isBluetoothEnabled && ( No paired device found Pair your Bluetooth printer from phone settings )} {!isBluetoothPermissionsGranted && isBluetoothEnabled && ( Linking.openSettings()}> Open Settings )} {!isBluetoothEnabled && ( Linking.openSettings()}> Enable Bluetooth )} {isPrinting ? ( ) : ( )} ); }