From 1403c3115c9aee9ed747c74a39b534185fe4751d Mon Sep 17 00:00:00 2001 From: admin Date: Fri, 18 Jul 2025 05:27:49 +0300 Subject: [PATCH] feat: scanner shit --- android/app/build.gradle | 6 +- android/app/src/debug/AndroidManifest.xml | 9 + android/app/src/main/AndroidManifest.xml | 5 +- .../com/anonymous/Assemblr/MainActivity.kt | 115 ++++++---- .../com/anonymous/Assemblr/MainApplication.kt | 7 +- android/settings.gradle | 7 + app.json | 2 +- package.json | 4 + src/App.tsx | 5 +- src/assets/icons/scanner.png | Bin 0 -> 16695 bytes src/components/SearchBar/ScanModal.tsx | 4 +- src/css/colors.tsx | 4 +- src/features/scannerState/scannerState.ts | 30 +++ src/redux/store.ts | 4 +- src/screens/CommonPage/CommonPage.tsx | 1 + src/screens/LoginScreen/LoginScreen.tsx | 1 - src/screens/MainScreen/MainScreen.tsx | 2 +- src/screens/MoneyScreen/MoneyScreen.tsx | 200 +++++++++++++----- 18 files changed, 296 insertions(+), 110 deletions(-) create mode 100644 src/assets/icons/scanner.png create mode 100644 src/features/scannerState/scannerState.ts diff --git a/android/app/build.gradle b/android/app/build.gradle index e5c4585..50aaf4c 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -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()}") diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 3ec2507..f3b51e8 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,7 +1,16 @@ + + + + + + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 403ab21..45f79d2 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -6,7 +6,10 @@ - + + + + diff --git a/android/app/src/main/java/com/anonymous/Assemblr/MainActivity.kt b/android/app/src/main/java/com/anonymous/Assemblr/MainActivity.kt index fefb5d8..d6aa57a 100644 --- a/android/app/src/main/java/com/anonymous/Assemblr/MainActivity.kt +++ b/android/app/src/main/java/com/anonymous/Assemblr/MainActivity.kt @@ -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 onBackPressed - */ - 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 onBackPressed + */ + 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) + } } diff --git a/android/app/src/main/java/com/anonymous/Assemblr/MainApplication.kt b/android/app/src/main/java/com/anonymous/Assemblr/MainApplication.kt index 53604c8..9883a26 100644 --- a/android/app/src/main/java/com/anonymous/Assemblr/MainApplication.kt +++ b/android/app/src/main/java/com/anonymous/Assemblr/MainApplication.kt @@ -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) } + } diff --git a/android/settings.gradle b/android/settings.gradle index 1c15b7d..ce268e8 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -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') \ No newline at end of file diff --git a/app.json b/app.json index 2cf7eb1..748147a 100644 --- a/app.json +++ b/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", diff --git a/package.json b/package.json index 5f2a7ec..25d0e25 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/App.tsx b/src/App.tsx index 35666fc..65cf771 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -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 ( + <> + diff --git a/src/assets/icons/scanner.png b/src/assets/icons/scanner.png new file mode 100644 index 0000000000000000000000000000000000000000..58a88281825f0f33c77cd89012d6646c9d74661e GIT binary patch literal 16695 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 V--BtZb&yU#O-cK4se;w({}12fnEC(! literal 0 HcmV?d00001 diff --git a/src/components/SearchBar/ScanModal.tsx b/src/components/SearchBar/ScanModal.tsx index b8be305..fbf3680 100644 --- a/src/components/SearchBar/ScanModal.tsx +++ b/src/components/SearchBar/ScanModal.tsx @@ -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(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 ( diff --git a/src/css/colors.tsx b/src/css/colors.tsx index dcd1e47..ad80b20 100644 --- a/src/css/colors.tsx +++ b/src/css/colors.tsx @@ -1,3 +1,5 @@ export const background = "#F5F5F5"; export const blue = "#2478F8"; -export const gray = '#A5A5A5'; \ No newline at end of file +export const gray = '#A5A5A5'; +export const red = "#e03131" +export const blueButton = '#2478F8' \ No newline at end of file diff --git a/src/features/scannerState/scannerState.ts b/src/features/scannerState/scannerState.ts new file mode 100644 index 0000000..6c27061 --- /dev/null +++ b/src/features/scannerState/scannerState.ts @@ -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 \ No newline at end of file diff --git a/src/redux/store.ts b/src/redux/store.ts index 5acf8c5..be25fe3 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -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 }, }); diff --git a/src/screens/CommonPage/CommonPage.tsx b/src/screens/CommonPage/CommonPage.tsx index f57e09c..5a5731e 100644 --- a/src/screens/CommonPage/CommonPage.tsx +++ b/src/screens/CommonPage/CommonPage.tsx @@ -66,6 +66,7 @@ function CommonPage() { }) } const checkUpdates = async () => { + return const currentVersion = Application.nativeApplicationVersion; applicationApi.getVersion('assemblr').then(({latest_version}) => { diff --git a/src/screens/LoginScreen/LoginScreen.tsx b/src/screens/LoginScreen/LoginScreen.tsx index 771a4f7..bbf867b 100644 --- a/src/screens/LoginScreen/LoginScreen.tsx +++ b/src/screens/LoginScreen/LoginScreen.tsx @@ -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(); diff --git a/src/screens/MainScreen/MainScreen.tsx b/src/screens/MainScreen/MainScreen.tsx index aaf3e96..bb8794a 100644 --- a/src/screens/MainScreen/MainScreen.tsx +++ b/src/screens/MainScreen/MainScreen.tsx @@ -70,7 +70,7 @@ function MainScreen() { { name: "Money", component: moneyScreen, - icon: require('assets/icons/money.png'), + icon: require('assets/icons/scanner.png'), hidden: false }, { diff --git a/src/screens/MoneyScreen/MoneyScreen.tsx b/src/screens/MoneyScreen/MoneyScreen.tsx index e8ca5c1..6da1255 100644 --- a/src/screens/MoneyScreen/MoneyScreen.tsx +++ b/src/screens/MoneyScreen/MoneyScreen.tsx @@ -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(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 ( - - Money - onPress()} label={"test"}/> + + + Блютуз включен: {state.enabled ? "да" : "нет"} + + + + {state.devices.map(device => ( + setSelectedDevice(device)} key={device.address}> + + + {device.name} + + + + ))} + + + ) }