test(android app): this is the start to the android app
43
mobileLst/.gitignore
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# Expo
|
||||
.expo/
|
||||
dist/
|
||||
web-build/
|
||||
expo-env.d.ts
|
||||
|
||||
# Native
|
||||
.kotlin/
|
||||
*.orig.*
|
||||
*.jks
|
||||
*.p8
|
||||
*.p12
|
||||
*.key
|
||||
*.mobileprovision
|
||||
|
||||
# Metro
|
||||
.metro-health-check*
|
||||
|
||||
# debug
|
||||
npm-debug.*
|
||||
yarn-debug.*
|
||||
yarn-error.*
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
|
||||
app-example
|
||||
|
||||
# generated native folders
|
||||
/ios
|
||||
/android
|
||||
50
mobileLst/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Welcome to your Expo app 👋
|
||||
|
||||
This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
|
||||
|
||||
## Get started
|
||||
|
||||
1. Install dependencies
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
2. Start the app
|
||||
|
||||
```bash
|
||||
npx expo start
|
||||
```
|
||||
|
||||
In the output, you'll find options to open the app in a
|
||||
|
||||
- [development build](https://docs.expo.dev/develop/development-builds/introduction/)
|
||||
- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
|
||||
- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
|
||||
- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
|
||||
|
||||
You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
|
||||
|
||||
## Get a fresh project
|
||||
|
||||
When you're ready, run:
|
||||
|
||||
```bash
|
||||
npm run reset-project
|
||||
```
|
||||
|
||||
This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
|
||||
|
||||
## Learn more
|
||||
|
||||
To learn more about developing your project with Expo, look at the following resources:
|
||||
|
||||
- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
|
||||
- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
|
||||
|
||||
## Join the community
|
||||
|
||||
Join our community of developers creating universal apps.
|
||||
|
||||
- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
|
||||
- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
|
||||
71
mobileLst/app.json
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "LSTScanner",
|
||||
"slug": "lst-scanner-app",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/icon.png",
|
||||
"scheme": "lstscanner",
|
||||
"userInterfaceStyle": "automatic",
|
||||
"newArchEnabled": true,
|
||||
"ios": {
|
||||
"supportsTablet": true
|
||||
},
|
||||
"updates": {
|
||||
"enabled": true,
|
||||
"url": "http://10.193.0.56:4000/api/mobile/updates",
|
||||
"fallbackToCacheTimeout": 30000,
|
||||
"codeSigningCertificate": "./certs/certificate.pem",
|
||||
"codeSigningMetadata": {
|
||||
"keyid": "self-hosted",
|
||||
"alg": "rsa-v1_5-sha256"
|
||||
}
|
||||
},
|
||||
"runtimeVersion": "1.0.0",
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"backgroundColor": "#E6F4FE",
|
||||
"foregroundImage": "./assets/images/android-icon-foreground.png",
|
||||
"backgroundImage": "./assets/images/android-icon-background.png",
|
||||
"monochromeImage": "./assets/images/android-icon-monochrome.png"
|
||||
},
|
||||
"package": "com.company.lstscanner",
|
||||
"versionCode": 1,
|
||||
"edgeToEdgeEnabled": true,
|
||||
"predictiveBackGestureEnabled": false
|
||||
},
|
||||
"web": {
|
||||
"output": "static",
|
||||
"favicon": "./assets/images/favicon.png"
|
||||
},
|
||||
"plugins": [
|
||||
"expo-router",
|
||||
"./plugins/androidCustomizations",
|
||||
[
|
||||
"expo-splash-screen",
|
||||
{
|
||||
"image": "./assets/icon.png",
|
||||
"imageWidth": 200,
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff",
|
||||
"dark": {
|
||||
"backgroundColor": "#000000"
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
"expo-build-properties",
|
||||
{
|
||||
"android": {
|
||||
"usesCleartextTraffic": true
|
||||
},
|
||||
"ios": {}
|
||||
}
|
||||
]
|
||||
],
|
||||
"experiments": {
|
||||
"typedRoutes": true,
|
||||
"reactCompiler": true
|
||||
}
|
||||
}
|
||||
}
|
||||
5
mobileLst/app/_layout.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Stack } from "expo-router";
|
||||
|
||||
export default function RootLayout() {
|
||||
return <Stack />;
|
||||
}
|
||||
122
mobileLst/app/index.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
FlatList,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
View,
|
||||
} from "react-native";
|
||||
import * as Updates from 'expo-updates';
|
||||
|
||||
export default function App() {
|
||||
const [buffer, setBuffer] = useState("");
|
||||
const [items, setItems] = useState<string[]>([]);
|
||||
const [status, setStatus] = useState("");
|
||||
|
||||
const [updates, setUpdates] = useState("")
|
||||
|
||||
const handleChange = (text: string) => {
|
||||
// Scanner "types" characters then appends Enter (\n)
|
||||
if (text.endsWith("\n")) {
|
||||
const code = text.trim(); // Remove newline
|
||||
handleScan(code);
|
||||
setBuffer(""); // Reset for next scan
|
||||
} else {
|
||||
setBuffer(text);
|
||||
}
|
||||
};
|
||||
|
||||
async function checkServerUpdate() {
|
||||
setUpdates('Checking for updates...');
|
||||
try {
|
||||
const res = await Updates.checkForUpdateAsync();
|
||||
if (res.isAvailable) {
|
||||
setUpdates('Update available! Fetching and reloading...');
|
||||
await Updates.fetchUpdateAsync();
|
||||
await Updates.reloadAsync();
|
||||
} else {
|
||||
setUpdates('No new update available.');
|
||||
}
|
||||
} catch (e:any) {
|
||||
setUpdates(`Update check failed: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const handleScan = (code: string) => {
|
||||
//console.log("Scanned:", code);
|
||||
|
||||
if (code.toUpperCase().startsWith("LOC")) {
|
||||
console.log("Triggered relocate to lane");
|
||||
performRelocate(code);
|
||||
} else {
|
||||
setItems((prev) => [...prev, code]);
|
||||
setStatus(`Added: ${code}`);
|
||||
}
|
||||
};
|
||||
|
||||
const performRelocate = (locationCode: string) => {
|
||||
if (items.length === 0) {
|
||||
setStatus(`Relocate to ${locationCode} requested, but no items`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Do your API call or whatever the "relocate" means
|
||||
console.log("Relocating", items, "to", locationCode);
|
||||
|
||||
setStatus(`Moved ${items.length} items to ${locationCode}`);
|
||||
setItems([]);
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Button
|
||||
title="Clear Items"
|
||||
onPress={() => {
|
||||
setItems([]);
|
||||
}}
|
||||
/>
|
||||
<Text style={styles.title}>Scan Barcodes</Text>
|
||||
|
||||
{/* The working input you already have */}
|
||||
<TextInput
|
||||
autoFocus
|
||||
value={buffer}
|
||||
onChangeText={handleChange}
|
||||
showSoftInputOnFocus={false}
|
||||
keyboardType="visible-password"
|
||||
style={{
|
||||
position: "absolute",
|
||||
opacity: 0, // invisible
|
||||
height: 0, // takes no space
|
||||
width: 0,
|
||||
}}
|
||||
/>
|
||||
<Pressable onPress={checkServerUpdate}style={{
|
||||
marginVertical: 12,
|
||||
padding: 12,
|
||||
backgroundColor: '#007AFF',
|
||||
borderRadius: 6,
|
||||
}}>
|
||||
<Text>Check Update</Text>
|
||||
</Pressable>
|
||||
<Text>Update Data</Text>
|
||||
<Text>{updates}</Text>
|
||||
<FlatList
|
||||
data={items}
|
||||
keyExtractor={(_, i) => i.toString()}
|
||||
renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
|
||||
/>
|
||||
|
||||
<Text style={styles.status}>{status}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: { flex: 1, padding: 16 },
|
||||
title: { fontWeight: "bold", fontSize: 20 },
|
||||
item: { paddingVertical: 4, fontSize: 16 },
|
||||
status: { marginTop: 20, fontStyle: "italic" },
|
||||
});
|
||||
BIN
mobileLst/assets/icon.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
mobileLst/assets/images/android-icon-background.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
mobileLst/assets/images/android-icon-foreground.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
mobileLst/assets/images/android-icon-monochrome.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
mobileLst/assets/images/favicon.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
mobileLst/assets/images/icon.png
Normal file
|
After Width: | Height: | Size: 384 KiB |
BIN
mobileLst/assets/images/partial-react-logo.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
mobileLst/assets/images/react-logo.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
mobileLst/assets/images/react-logo@2x.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
mobileLst/assets/images/react-logo@3x.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
mobileLst/assets/images/splash-icon.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
31
mobileLst/certFiles/raw/alpla_root_ca.crt
Normal file
@@ -0,0 +1,31 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
3z/B7cuoI5Eu0OU=
|
||||
-----END CERTIFICATE-----
|
||||
9
mobileLst/certFiles/xml/network_security_config.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates src="user" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
41
mobileLst/components/HiddenScanner.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { Text, TextInput, View } from "react-native";
|
||||
|
||||
export default function HiddenScannerListener({ onScan }: { onScan: any }) {
|
||||
const [buffer, setBuffer] = useState("");
|
||||
const inputRef = useRef<TextInput>(null);
|
||||
|
||||
// Keep focusing the invisible input
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
if (inputRef.current) inputRef.current.focus();
|
||||
}, 500);
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
const handleChange = (text: string) => {
|
||||
// Most scanners append '\n' (Enter) or '\t'; trim and send
|
||||
if (text.endsWith("\n") || text.endsWith("\t")) {
|
||||
const code = text.trim();
|
||||
if (code) onScan?.(code);
|
||||
setBuffer("");
|
||||
} else {
|
||||
setBuffer(text);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<TextInput
|
||||
ref={inputRef}
|
||||
value={buffer}
|
||||
onChangeText={handleChange}
|
||||
autoFocus
|
||||
style={{
|
||||
position: "absolute",
|
||||
opacity: 0, // invisible
|
||||
height: 0, // takes no space
|
||||
width: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
10
mobileLst/eslint.config.js
Normal file
@@ -0,0 +1,10 @@
|
||||
// https://docs.expo.dev/guides/using-eslint/
|
||||
const { defineConfig } = require('eslint/config');
|
||||
const expoConfig = require('eslint-config-expo/flat');
|
||||
|
||||
module.exports = defineConfig([
|
||||
expoConfig,
|
||||
{
|
||||
ignores: ['dist/*'],
|
||||
},
|
||||
]);
|
||||
13666
mobileLst/package-lock.json
generated
Normal file
58
mobileLst/package.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "mobilelst",
|
||||
"main": "expo-router/entry",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"reset-project": "node ./scripts/reset-project.js",
|
||||
"android": "expo run:android",
|
||||
"ios": "expo run:ios",
|
||||
"web": "expo start --web",
|
||||
"lint": "expo lint",
|
||||
"build:clean": "expo prebuild --clean && cd android && gradlew.bat assembleRelease && npm run ",
|
||||
"build:android": "cd android && gradlew.bat assembleRelease",
|
||||
"build:ota": "set EXPO_NO_EAS_UPDATE=1 && npx expo export --platform android --output-dir dist --experimental-bundle",
|
||||
"update": "adb install android/app/build/outputs/apk/release/app-release.apk",
|
||||
"debug": "adb logcat | Select-String \"Expo"
|
||||
},
|
||||
"dependencies": {
|
||||
"@expo/vector-icons": "^15.0.3",
|
||||
"@react-native-async-storage/async-storage": "2.2.0",
|
||||
"@react-navigation/bottom-tabs": "^7.4.0",
|
||||
"@react-navigation/elements": "^2.6.3",
|
||||
"@react-navigation/native": "^7.1.8",
|
||||
"axios": "^1.13.2",
|
||||
"expo": "~54.0.23",
|
||||
"expo-build-properties": "~1.0.9",
|
||||
"expo-camera": "~17.0.9",
|
||||
"expo-constants": "~18.0.10",
|
||||
"expo-font": "~14.0.9",
|
||||
"expo-haptics": "~15.0.7",
|
||||
"expo-image": "~3.0.10",
|
||||
"expo-linking": "~8.0.8",
|
||||
"expo-router": "~6.0.14",
|
||||
"expo-splash-screen": "~31.0.10",
|
||||
"expo-status-bar": "~3.0.8",
|
||||
"expo-symbols": "~1.0.7",
|
||||
"expo-system-ui": "~6.0.8",
|
||||
"expo-updates": "~29.0.12",
|
||||
"expo-web-browser": "~15.0.9",
|
||||
"expo-zebra-scanner": "^6.0.0",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"react-native": "0.81.5",
|
||||
"react-native-gesture-handler": "~2.28.0",
|
||||
"react-native-reanimated": "~4.1.1",
|
||||
"react-native-safe-area-context": "~5.6.0",
|
||||
"react-native-screens": "~4.16.0",
|
||||
"react-native-web": "~0.21.0",
|
||||
"react-native-worklets": "0.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "~19.1.0",
|
||||
"eslint": "^9.25.0",
|
||||
"eslint-config-expo": "~10.0.0",
|
||||
"typescript": "~5.9.2"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
94
mobileLst/plugins/androidCustomizations.js
Normal file
@@ -0,0 +1,94 @@
|
||||
const {
|
||||
withAndroidManifest,
|
||||
withDangerousMod,
|
||||
withGradleProperties,
|
||||
} = require("@expo/config-plugins");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
function withCustomAndroidConfig(config) {
|
||||
// Copy cert files
|
||||
config = withDangerousMod(config, [
|
||||
"android",
|
||||
async (config) => {
|
||||
const projectRoot = config.modRequest.projectRoot;
|
||||
const certSourceDir = path.join(projectRoot, "certFiles");
|
||||
const rawDestDir = path.join(
|
||||
projectRoot,
|
||||
"android/app/src/main/res/raw"
|
||||
);
|
||||
const xmlDestDir = path.join(
|
||||
projectRoot,
|
||||
"android/app/src/main/res/xml"
|
||||
);
|
||||
|
||||
// Create directories if they don't exist
|
||||
if (!fs.existsSync(rawDestDir)) {
|
||||
fs.mkdirSync(rawDestDir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(xmlDestDir)) {
|
||||
fs.mkdirSync(xmlDestDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Copy your cert files
|
||||
if (fs.existsSync(path.join(certSourceDir, "raw"))) {
|
||||
fs.cpSync(path.join(certSourceDir, "raw"), rawDestDir, {
|
||||
recursive: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (fs.existsSync(path.join(certSourceDir, "xml"))) {
|
||||
fs.cpSync(path.join(certSourceDir, "xml"), xmlDestDir, {
|
||||
recursive: true,
|
||||
});
|
||||
}
|
||||
|
||||
console.log("✅ Copied cert files to android/app/src/main/res");
|
||||
return config;
|
||||
},
|
||||
]);
|
||||
|
||||
// Modify AndroidManifest
|
||||
config = withAndroidManifest(config, (config) => {
|
||||
const mainApplication = config.modResults.manifest.application[0];
|
||||
|
||||
// Add network security config if not already present
|
||||
if (!mainApplication.$["android:networkSecurityConfig"]) {
|
||||
mainApplication.$["android:networkSecurityConfig"] =
|
||||
"@xml/network_security_config";
|
||||
}
|
||||
|
||||
console.log("✅ Modified AndroidManifest.xml");
|
||||
return config;
|
||||
});
|
||||
|
||||
// Update gradle.properties for better performance
|
||||
config = withGradleProperties(config, (config) => {
|
||||
// Remove existing jvmargs if present
|
||||
config.modResults = config.modResults.filter(
|
||||
(item) =>
|
||||
!(item.type === "property" && item.key === "org.gradle.jvmargs")
|
||||
);
|
||||
|
||||
// Add your custom jvmargs
|
||||
config.modResults.push(
|
||||
{
|
||||
type: "property",
|
||||
key: "org.gradle.jvmargs",
|
||||
value: "-Xmx16384m -XX:MaxMetaspaceSize=2024m",
|
||||
},
|
||||
{
|
||||
type: "property",
|
||||
key: "org.gradle.daemon",
|
||||
value: "false",
|
||||
}
|
||||
);
|
||||
|
||||
console.log("✅ Updated gradle.properties with 16GB heap");
|
||||
return config;
|
||||
});
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
module.exports = withCustomAndroidConfig;
|
||||
15
mobileLst/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"extends": "expo/tsconfig.base",
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx"
|
||||
]
|
||||
}
|
||||