feat: scanner shit
This commit is contained in:
@@ -93,7 +93,7 @@ android {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.4.3"
|
||||
versionName "1.5.3"
|
||||
}
|
||||
signingConfigs {
|
||||
debug {
|
||||
@@ -154,7 +154,11 @@ dependencies {
|
||||
def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
|
||||
def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true";
|
||||
def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "true";
|
||||
|
||||
implementation project(':react-native-tcp-socket')
|
||||
implementation project(':react-native-keyevent')
|
||||
implementation project(':react-native-bluetooth-classic')
|
||||
|
||||
if (isGifEnabled) {
|
||||
// For animated gif support
|
||||
implementation("com.facebook.fresco:animated-gif:${expoLibs.versions.fresco.get()}")
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
|
||||
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" tools:replace="android:usesCleartextTraffic" />
|
||||
</manifest>
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
@@ -1,65 +1,88 @@
|
||||
package com.anonymous.Assemblr
|
||||
|
||||
import expo.modules.splashscreen.SplashScreenManager
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
|
||||
import com.facebook.react.ReactActivity
|
||||
import com.facebook.react.ReactActivityDelegate
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
|
||||
import com.facebook.react.defaults.DefaultReactActivityDelegate
|
||||
import com.github.kevinejohn.keyevent.KeyEventModule
|
||||
|
||||
import expo.modules.ReactActivityDelegateWrapper
|
||||
|
||||
class MainActivity : ReactActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
// Set the theme to AppTheme BEFORE onCreate to support
|
||||
// coloring the background, status bar, and navigation bar.
|
||||
// This is required for expo-splash-screen.
|
||||
// setTheme(R.style.AppTheme);
|
||||
// @generated begin expo-splashscreen - expo prebuild (DO NOT MODIFY) sync-f3ff59a738c56c9a6119210cb55f0b613eb8b6af
|
||||
SplashScreenManager.registerOnActivity(this)
|
||||
// @generated end expo-splashscreen
|
||||
super.onCreate(null)
|
||||
}
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
// Set the theme to AppTheme BEFORE onCreate to support
|
||||
// coloring the background, status bar, and navigation bar.
|
||||
// This is required for expo-splash-screen.
|
||||
// setTheme(R.style.AppTheme);
|
||||
// @generated begin expo-splashscreen - expo prebuild (DO NOT MODIFY) sync-f3ff59a738c56c9a6119210cb55f0b613eb8b6af
|
||||
SplashScreenManager.registerOnActivity(this)
|
||||
// @generated end expo-splashscreen
|
||||
super.onCreate(null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the main component registered from JavaScript. This is used to schedule
|
||||
* rendering of the component.
|
||||
*/
|
||||
override fun getMainComponentName(): String = "main"
|
||||
/**
|
||||
* Returns the name of the main component registered from JavaScript. This is used to schedule
|
||||
* rendering of the component.
|
||||
*/
|
||||
override fun getMainComponentName(): String = "main"
|
||||
|
||||
/**
|
||||
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
|
||||
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
|
||||
*/
|
||||
override fun createReactActivityDelegate(): ReactActivityDelegate {
|
||||
return ReactActivityDelegateWrapper(
|
||||
this,
|
||||
BuildConfig.IS_NEW_ARCHITECTURE_ENABLED,
|
||||
object : DefaultReactActivityDelegate(
|
||||
this,
|
||||
mainComponentName,
|
||||
fabricEnabled
|
||||
){})
|
||||
}
|
||||
/**
|
||||
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
|
||||
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
|
||||
*/
|
||||
override fun createReactActivityDelegate(): ReactActivityDelegate {
|
||||
return ReactActivityDelegateWrapper(
|
||||
this,
|
||||
BuildConfig.IS_NEW_ARCHITECTURE_ENABLED,
|
||||
object : DefaultReactActivityDelegate(
|
||||
this,
|
||||
mainComponentName,
|
||||
fabricEnabled
|
||||
) {})
|
||||
}
|
||||
|
||||
/**
|
||||
* Align the back button behavior with Android S
|
||||
* where moving root activities to background instead of finishing activities.
|
||||
* @see <a href="https://developer.android.com/reference/android/app/Activity#onBackPressed()">onBackPressed</a>
|
||||
*/
|
||||
override fun invokeDefaultOnBackPressed() {
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
|
||||
if (!moveTaskToBack(false)) {
|
||||
// For non-root activities, use the default implementation to finish them.
|
||||
super.invokeDefaultOnBackPressed()
|
||||
}
|
||||
return
|
||||
}
|
||||
/**
|
||||
* Align the back button behavior with Android S
|
||||
* where moving root activities to background instead of finishing activities.
|
||||
* @see <a href="https://developer.android.com/reference/android/app/Activity#onBackPressed()">onBackPressed</a>
|
||||
*/
|
||||
override fun invokeDefaultOnBackPressed() {
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
|
||||
if (!moveTaskToBack(false)) {
|
||||
// For non-root activities, use the default implementation to finish them.
|
||||
super.invokeDefaultOnBackPressed()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Use the default back button implementation on Android S
|
||||
// because it's doing more than [Activity.moveTaskToBack] in fact.
|
||||
super.invokeDefaultOnBackPressed()
|
||||
}
|
||||
// Use the default back button implementation on Android S
|
||||
// because it's doing more than [Activity.moveTaskToBack] in fact.
|
||||
super.invokeDefaultOnBackPressed()
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
KeyEventModule.getInstance().onKeyDownEvent(keyCode, event)
|
||||
// super.onKeyDown(keyCode, event)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
KeyEventModule.getInstance().onKeyUpEvent(keyCode, event);
|
||||
// super.onKeyUp(keyCode, event)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
override fun onKeyMultiple(keyCode: Int, repeatCount: Int, event: KeyEvent): Boolean {
|
||||
KeyEventModule.getInstance().onKeyMultipleEvent(keyCode, repeatCount, event)
|
||||
return true;
|
||||
// return super.onKeyMultiple(keyCode, repeatCount, event)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
|
||||
import com.facebook.react.defaults.DefaultReactNativeHost
|
||||
import com.facebook.react.soloader.OpenSourceMergedSoMapping
|
||||
import com.facebook.soloader.SoLoader
|
||||
|
||||
import com.github.kevinejohn.keyevent.KeyEventPackage
|
||||
import expo.modules.ApplicationLifecycleDispatcher
|
||||
import expo.modules.ReactNativeHostWrapper
|
||||
import com.asterinet.react.tcpsocket.TcpSocketPackage;
|
||||
import kjd.reactnative.bluetooth.RNBluetoothClassicPackage;
|
||||
|
||||
class MainApplication : Application(), ReactApplication {
|
||||
|
||||
override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper(
|
||||
@@ -26,6 +28,8 @@ class MainApplication : Application(), ReactApplication {
|
||||
packages.add(PdfToBitmapPackage())
|
||||
packages.add(TcpSocketPackage())
|
||||
packages.add(MyTcpSocketPackage())
|
||||
packages.add(KeyEventPackage())
|
||||
packages.add(RNBluetoothClassicPackage())
|
||||
return packages
|
||||
}
|
||||
|
||||
@@ -55,4 +59,5 @@ class MainApplication : Application(), ReactApplication {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,5 +37,12 @@ expoAutolinking.useExpoVersionCatalog()
|
||||
|
||||
include ':app'
|
||||
includeBuild(expoAutolinking.reactNativeGradlePlugin)
|
||||
|
||||
include ':react-native-tcp-socket'
|
||||
project(':react-native-tcp-socket').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-tcp-socket/android')
|
||||
|
||||
include ':react-native-keyevent'
|
||||
project(':react-native-keyevent').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keyevent/android')
|
||||
|
||||
include ':react-native-bluetooth-classic'
|
||||
project(':react-native-bluetooth-classic').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-bluetooth-classic/android')
|
||||
2
app.json
2
app.json
@@ -12,7 +12,7 @@
|
||||
],
|
||||
"name": "Assemblr",
|
||||
"slug": "Assemblr",
|
||||
"version": "1.4.3",
|
||||
"version": "1.5.3",
|
||||
"orientation": "portrait",
|
||||
"icon": "./src/assets/icon.png",
|
||||
"userInterfaceStyle": "light",
|
||||
|
||||
@@ -46,9 +46,12 @@
|
||||
"react-hook-form": "^7.57.0",
|
||||
"react-native": "0.79.2",
|
||||
"react-native-animatable": "^1.4.0",
|
||||
"react-native-bluetooth-classic": "^1.73.0-rc.13",
|
||||
"react-native-bluetooth-serial": "lucassouza16/react-native-bluetooth-serial",
|
||||
"react-native-gesture-handler": "~2.24.0",
|
||||
"react-native-image-pan-zoom": "^2.1.12",
|
||||
"react-native-image-zoom-viewer": "^3.0.1",
|
||||
"react-native-keyevent": "^0.3.2",
|
||||
"react-native-modal": "^13.0.1",
|
||||
"react-native-paper": "^5.12.5",
|
||||
"react-native-picker-select": "^9.3.1",
|
||||
@@ -60,6 +63,7 @@
|
||||
"react-native-responsive-fontsize": "^0.5.1",
|
||||
"react-native-safe-area-context": "5.4.0",
|
||||
"react-native-screens": "~4.10.0",
|
||||
"react-native-serialport-bluetooth": "^0.4.11",
|
||||
"react-native-svg": "15.11.2",
|
||||
"react-native-tcp-socket": "^6.3.0",
|
||||
"react-native-toast-message": "^2.2.1",
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import {StyleSheet} from 'react-native';
|
||||
import {Provider} from "react-redux";
|
||||
import {store} from "./redux/store";
|
||||
import React from "react";
|
||||
import React, {useEffect} from "react";
|
||||
import CommonPage from "./screens/CommonPage/CommonPage";
|
||||
import {BottomSheetModalProvider} from "@gorhom/bottom-sheet";
|
||||
import {GestureHandlerRootView} from "react-native-gesture-handler";
|
||||
import KeyEvent from "react-native-keyevent";
|
||||
|
||||
export default function App() {
|
||||
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<>
|
||||
</>
|
||||
<GestureHandlerRootView style={{flex: 1}}>
|
||||
<BottomSheetModalProvider>
|
||||
<CommonPage/>
|
||||
|
||||
BIN
src/assets/icons/scanner.png
Normal file
BIN
src/assets/icons/scanner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@@ -1,5 +1,5 @@
|
||||
import {FC, useEffect, useRef} from "react";
|
||||
import {GestureResponderEvent, StyleSheet, Text, TextInput, View} from "react-native";
|
||||
import {StyleSheet, TextInput, View} from "react-native";
|
||||
import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
|
||||
import {RFPercentage} from "react-native-responsive-fontsize";
|
||||
import Modal from "react-native-modal";
|
||||
@@ -11,12 +11,14 @@ import {closeScanModal, setScannedData} from "../../features/scanModal/scanModal
|
||||
|
||||
const ScanModal: FC = () => {
|
||||
const inputRef = useRef<TextInput | null>(null);
|
||||
const scannerState = useSelector((state: RootState) => state.scanner);
|
||||
const state = useSelector((state: RootState) => state.scanModal);
|
||||
const getDefaultLabel = () => "Наведите сканер на штрихкод товара или заказа";
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
if (state.isVisible) inputRef.current?.focus();
|
||||
}, [state.isVisible]);
|
||||
|
||||
return (
|
||||
<Modal isVisible={state.isVisible}>
|
||||
<View style={styles.container}>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export const background = "#F5F5F5";
|
||||
export const blue = "#2478F8";
|
||||
export const gray = '#A5A5A5';
|
||||
export const gray = '#A5A5A5';
|
||||
export const red = "#e03131"
|
||||
export const blueButton = '#2478F8'
|
||||
30
src/features/scannerState/scannerState.ts
Normal file
30
src/features/scannerState/scannerState.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import {BluetoothDevice} from "react-native-bluetooth-classic";
|
||||
import {createSlice, PayloadAction} from "@reduxjs/toolkit";
|
||||
|
||||
export interface ScannerState {
|
||||
isConnected: boolean;
|
||||
deviceAddress?: string;
|
||||
}
|
||||
|
||||
const initialState: ScannerState = {
|
||||
isConnected: false,
|
||||
deviceAddress: undefined
|
||||
}
|
||||
|
||||
export const scannerSlice = createSlice({
|
||||
name: "scannerState",
|
||||
initialState,
|
||||
reducers: {
|
||||
setDevice(state, action: PayloadAction<{ deviceAddress: string }>) {
|
||||
state.deviceAddress = action.payload.deviceAddress;
|
||||
},
|
||||
setIsConnected(state, action: PayloadAction<{ isConnected: boolean }>) {
|
||||
state.isConnected = action.payload.isConnected
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
export const {setDevice, setIsConnected} = scannerSlice.actions
|
||||
export default scannerSlice.reducer
|
||||
@@ -15,6 +15,7 @@ import cancelAssemblyModal from 'features/cancelAssemblyModal/cancelAssemblyModa
|
||||
import balanceReducer from 'features/balance/balanceSlice';
|
||||
import animationsReducer from 'features/animations/animationsSlice';
|
||||
import filterReducer from 'features/filterSlice/filterSlice';
|
||||
import scannerReducer from 'features/scannerState/scannerState';
|
||||
import {useDispatch} from "react-redux";
|
||||
|
||||
export const store = configureStore({
|
||||
@@ -33,7 +34,8 @@ export const store = configureStore({
|
||||
cancelAssemblyModal: cancelAssemblyModal,
|
||||
balance: balanceReducer,
|
||||
animations: animationsReducer,
|
||||
filter:filterReducer
|
||||
filter: filterReducer,
|
||||
scanner: scannerReducer
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ function CommonPage() {
|
||||
})
|
||||
}
|
||||
const checkUpdates = async () => {
|
||||
return
|
||||
const currentVersion = Application.nativeApplicationVersion;
|
||||
applicationApi.getVersion('assemblr').then(({latest_version}) => {
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import {useDispatch} from "react-redux";
|
||||
import {login} from "../../features/auth/authSlice";
|
||||
import Toast from "react-native-toast-message";
|
||||
import * as SecureStore from 'expo-secure-store';
|
||||
import KeyEvent from "react-native-keyevent";
|
||||
|
||||
function LoginScreen() {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
@@ -70,7 +70,7 @@ function MainScreen() {
|
||||
{
|
||||
name: "Money",
|
||||
component: moneyScreen,
|
||||
icon: require('assets/icons/money.png'),
|
||||
icon: require('assets/icons/scanner.png'),
|
||||
hidden: false
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,65 +1,157 @@
|
||||
import {Text, View} from "react-native";
|
||||
import {PermissionsAndroid, Platform, Text, TouchableOpacity, View} from "react-native";
|
||||
import {useEffect, useState} from "react";
|
||||
import {Permission} from "react-native/Libraries/PermissionsAndroid/PermissionsAndroid";
|
||||
import RNBluetoothClassic, {BluetoothDevice} from "react-native-bluetooth-classic";
|
||||
import {RFPercentage} from "react-native-responsive-fontsize";
|
||||
import {responsiveWidth} from "react-native-responsive-dimensions";
|
||||
import {blue, blueButton, red} from "../../css/colors";
|
||||
import BasicButton from "../../components/BasicButton/BasicButton";
|
||||
import {useScanningContext} from "../../providers/ScanProvider";
|
||||
import printingApi from "../../api/printingApi";
|
||||
import {Zpl} from "react-native-zpl-code";
|
||||
import PrintingService from "../../utils/PrintingService";
|
||||
import {useSelector} from "react-redux";
|
||||
import {RootState, useAppDispatch} from "../../redux/store";
|
||||
import {setDevice, setIsConnected} from "../../features/scannerState/scannerState";
|
||||
import {closeScanModal, setScannedData} from "../../features/scanModal/scanModalSlice";
|
||||
|
||||
async function generateZplCodes(images: string[]) {
|
||||
const zplCodes = [];
|
||||
|
||||
for (const image of images) {
|
||||
const zplBuilder = new Zpl.Builder();
|
||||
zplBuilder.setup({
|
||||
size: {
|
||||
heightDots: 320, // 40mm at 203 DPI
|
||||
widthDots: 464, // 58mm at 203 DPI
|
||||
},
|
||||
labelHome: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
labelTop: 0,
|
||||
labeShift: 0,
|
||||
orientation: "NORMAL",
|
||||
media: {
|
||||
type: "MARK_SENSING",
|
||||
dots: 0,
|
||||
},
|
||||
});
|
||||
|
||||
zplBuilder.image({
|
||||
uri: `data:image/png;base64,${image}`,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 464,
|
||||
height: 320,
|
||||
dither: true,
|
||||
});
|
||||
|
||||
const zplCode = await zplBuilder.build();
|
||||
zplCodes.push(zplCode);
|
||||
}
|
||||
|
||||
return zplCodes;
|
||||
type BluetoothSettingsState = {
|
||||
enabled: boolean;
|
||||
devices: BluetoothDevice[]
|
||||
}
|
||||
const DEFAULT_BLUETOOTH_SETTINGS_STATE: BluetoothSettingsState = {
|
||||
enabled: false,
|
||||
devices: []
|
||||
}
|
||||
|
||||
function MoneyScreen() {
|
||||
const {scan} = useScanningContext();
|
||||
const a = "123";
|
||||
const onPress = () => {
|
||||
printingApi.getLabel(391845).then(async result => {
|
||||
PrintingService.getInstance().printPdf("", result).then(() => {
|
||||
}
|
||||
).catch(error => {
|
||||
console.error("Error printing:", error);
|
||||
});
|
||||
});
|
||||
const [state, setState] = useState<BluetoothSettingsState>(DEFAULT_BLUETOOTH_SETTINGS_STATE);
|
||||
const scannerState = useSelector((state: RootState) => state.scanner);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
async function requestBluetoothPermissions() {
|
||||
if (Platform.OS === 'android') {
|
||||
const permissions: Permission[] = [];
|
||||
|
||||
if (Platform.Version >= 31) { // Android 12+
|
||||
permissions.push(
|
||||
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
|
||||
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
|
||||
PermissionsAndroid.PERMISSIONS.BLUETOOTH_ADVERTISE,
|
||||
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
|
||||
);
|
||||
console.log("android12")
|
||||
} else { // Below Android 12
|
||||
permissions.push(
|
||||
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
|
||||
);
|
||||
}
|
||||
|
||||
const granted = await PermissionsAndroid.requestMultiple(permissions);
|
||||
|
||||
|
||||
const hasBluetoothPermission =
|
||||
(Platform.Version >= 31 &&
|
||||
granted['android.permission.BLUETOOTH_SCAN'] === PermissionsAndroid.RESULTS.GRANTED &&
|
||||
granted['android.permission.BLUETOOTH_CONNECT'] === PermissionsAndroid.RESULTS.GRANTED) ||
|
||||
(Platform.Version < 31 &&
|
||||
granted['android.permission.ACCESS_FINE_LOCATION'] === PermissionsAndroid.RESULTS.GRANTED);
|
||||
|
||||
if (hasBluetoothPermission) {
|
||||
console.log('Bluetooth permissions granted');
|
||||
} else {
|
||||
console.warn('Bluetooth permissions denied');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const initialize = async () => {
|
||||
const isEnabled = await RNBluetoothClassic.isBluetoothEnabled();
|
||||
const devices = isEnabled ? await RNBluetoothClassic.getBondedDevices() : []
|
||||
setState(prevState => {
|
||||
return {
|
||||
...prevState,
|
||||
enabled: isEnabled,
|
||||
devices: devices
|
||||
}
|
||||
})
|
||||
}
|
||||
const setSelectedDevice = (device: BluetoothDevice) => {
|
||||
dispatch(setDevice({deviceAddress: device.address}));
|
||||
}
|
||||
const onConnectPress = async () => {
|
||||
|
||||
if (!scannerState.deviceAddress) return;
|
||||
if (scannerState.isConnected) {
|
||||
console.log("connected")
|
||||
await RNBluetoothClassic.disconnectFromDevice(scannerState.deviceAddress);
|
||||
return
|
||||
}
|
||||
console.log("connecting")
|
||||
const connected = await RNBluetoothClassic.connectToDevice(scannerState.deviceAddress, {
|
||||
secureSocket: false,
|
||||
charset: "UTF-8",
|
||||
delimiter: "\r\r"
|
||||
});
|
||||
const isConnected = await connected.isConnected();
|
||||
dispatch(setIsConnected({isConnected}));
|
||||
if (isConnected) {
|
||||
RNBluetoothClassic.onDeviceRead(connected.address, event => {
|
||||
dispatch(setScannedData(event.data));
|
||||
dispatch(closeScanModal())
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
const interval = setInterval(initialize, 1000);
|
||||
|
||||
const {remove: removeOnConnectedListener} = RNBluetoothClassic.onDeviceConnected(event => {
|
||||
console.log("Connected event")
|
||||
dispatch(setIsConnected({isConnected: true}));
|
||||
|
||||
})
|
||||
const {remove: removeOnDisconnectedListener} = RNBluetoothClassic.onDeviceDisconnected(event => {
|
||||
dispatch(setIsConnected({isConnected: false}));
|
||||
|
||||
})
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
removeOnConnectedListener();
|
||||
removeOnDisconnectedListener()
|
||||
}
|
||||
|
||||
}, []);
|
||||
return (
|
||||
<View>
|
||||
<Text style={{fontSize: 36}}>Money</Text>
|
||||
<BasicButton onPress={() => onPress()} label={"test"}/>
|
||||
<View style={{padding: "5%"}}>
|
||||
<Text>
|
||||
Блютуз включен: {state.enabled ? "да" : "нет"}
|
||||
</Text>
|
||||
<View
|
||||
pointerEvents={scannerState.isConnected ? "none" : "auto"}
|
||||
style={{opacity: scannerState.isConnected ? 0.4 : 1}}
|
||||
>
|
||||
|
||||
{state.devices.map(device => (
|
||||
<TouchableOpacity onPress={() => setSelectedDevice(device)} key={device.address}>
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: scannerState.deviceAddress == device.address ? blue : "white",
|
||||
padding: RFPercentage(2),
|
||||
borderRadius: responsiveWidth(2.5),
|
||||
marginBottom: 10,
|
||||
|
||||
}}>
|
||||
<Text style={{fontSize: RFPercentage(2)}}>
|
||||
{device.name}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
|
||||
<BasicButton
|
||||
onPress={onConnectPress}
|
||||
label={scannerState.isConnected ? "Отключить" : "Подключить"}
|
||||
style={{borderRadius: responsiveWidth(3), backgroundColor: scannerState.isConnected ? red : blueButton}}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user