apply updates to native app

This commit is contained in:
ppc
2024-08-22 09:20:19 +01:00
parent 810207faa2
commit 0b969d569b
10 changed files with 32 additions and 76 deletions
+4 -3
View File
@@ -1,11 +1,11 @@
import {generateCardNumber} from "amnet-shared";
import {useModalStyles} from "../utils/ModalStyles";
import {useCallback, useLayoutEffect, useState} from "react";
import {TextInput, TouchableOpacity, View} from "react-native";
import {Button, Card, Divider, Paragraph, useTheme} from "react-native-paper";
import {useModalStyles} from "../utils/ModalStyles";
import {AMCard} from "../models/AMCard";
import RealmContext from "../models/RealmContext";
import {generateCardNumber} from "../models/AM-API";
const {useRealm} = RealmContext;
@@ -48,7 +48,8 @@ export default function CardAddModal({navigation}) {
const themeOptions = canSave ? modalStyles.headerText : {color: theme.colors.outline};
navigation.setOptions({
headerRight: () => <TouchableOpacity disabled={!canSave} onPress={() => cardAddCallback(cardNumber, cardName)}>
headerRight: () => <TouchableOpacity disabled={!canSave}
onPress={() => cardAddCallback(cardNumber, cardName)}>
<Paragraph style={{...themeOptions, fontWeight: "600"}}>Save</Paragraph>
</TouchableOpacity>
})
+4 -4
View File
@@ -1,14 +1,14 @@
import * as Clipboard from 'expo-clipboard';
import * as Clipboard from "expo-clipboard";
import {FlatList, View} from "react-native";
import React, {useCallback, useMemo} from "react";
import {Button, useTheme} from "react-native-paper";
import {CreditCard, Plus} from "lucide-react-native";
import ContextMenu from "react-native-context-menu-view";
import {AMCard} from "../models/AMCard";
import {AimeCard} from "../components/AimeCard";
import RealmContext from "../models/RealmContext";
import ContextMenu from "react-native-context-menu-view";
import {EmptyStatePlaceholder} from "../components/EmptyStatePlaceholder";
import {CreditCard, Plus} from "lucide-react-native";
import {Button, useTheme} from "react-native-paper";
const {useQuery, useRealm} = RealmContext;
+1 -1
View File
@@ -1,9 +1,9 @@
import {Plus} from "lucide-react-native";
import {TouchableOpacity} from "react-native";
import {useTheme} from "@react-navigation/native";
import {createNativeStackNavigator} from "@react-navigation/native-stack";
import CardManager from "./CardManager";
import {TouchableOpacity} from "react-native";
const Stack = createNativeStackNavigator();
+1 -1
View File
@@ -1,7 +1,7 @@
import {useModalStyles} from "../utils/ModalStyles";
import {Card, Paragraph, useTheme} from "react-native-paper";
import {TextInput, TouchableOpacity, View} from "react-native";
import {useCallback, useEffect, useLayoutEffect, useState} from "react";
import {useModalStyles} from "../utils/ModalStyles";
import RealmContext from "../models/RealmContext";
import {AMServer} from "../models/AMServer";
+6 -5
View File
@@ -1,7 +1,7 @@
import {BSON} from "realm";
import React, {useCallback, useEffect, useLayoutEffect, useMemo, useState} from "react";
import {Alert, RefreshControl, ScrollView, Share, StyleSheet, TouchableOpacity, View} from "react-native";
import {ActivityIndicator, Button, Card, Paragraph, Title, useTheme} from "react-native-paper";
import {Alert, RefreshControl, ScrollView, Share, StyleSheet, TouchableOpacity, View} from "react-native";
import {CircleCheck, CircleDot, CreditCard, Nfc, Plus, SmartphoneNfcIcon, WifiOff, Share as ShareIcon} from "lucide-react-native";
import {EmptyStatePlaceholder} from "../components/EmptyStatePlaceholder";
import {AimeCard} from "../components/AimeCard";
@@ -10,6 +10,7 @@ import RealmContext from "../models/RealmContext";
import {AMServer} from "../models/AMServer";
import {AMCard} from "../models/AMCard";
import ObjectId = BSON.ObjectId;
import {fetchServerInfo, performCardIn} from "../../amnet-shared/src";
const {useRealm, useQuery, useObject} = RealmContext;
@@ -86,7 +87,7 @@ export default function ServerCardIn({route, navigation}) {
}
const abortController = new AbortController();
server.getInfo(abortController.signal).then(r => {
fetchServerInfo(server.serverAddress, abortController.signal).then(r => {
if (r) {
setConnectionTestResult(true);
realm.write(() => {
@@ -107,11 +108,11 @@ export default function ServerCardIn({route, navigation}) {
}, [serverId, serverReloadCounter, realm]);
// card in callback
const performCardIn = useCallback(() => {
const cardInCallback = useCallback(() => {
setCardInCompleted(false);
const abortController = new AbortController();
server.submitCard(selectedCard.code, abortController.signal).then(async r => {
performCardIn(server.serverAddress, {cardId: selectedCard.code}, abortController.signal).then(async r => {
const now = new Date();
setCardInCompleted(r);
@@ -174,7 +175,7 @@ export default function ServerCardIn({route, navigation}) {
card={selectedCard}
actionIcon={<CircleCheck color="green" size={24}/>}/>
<Button textColor="white"
onPress={performCardIn}
onPress={cardInCallback}
disabled={disableCardIn}
contentStyle={{flexDirection: 'row-reverse'}}
mode={connectionTestResult ? "contained" : "outlined"}
-28
View File
@@ -1,28 +0,0 @@
export interface AMServerInfoResponse {
serverName: string;
apiVersion: number;
}
export interface AMCardInRequest {
cardId: string;
}
export function generateCardNumber(): string {
let cardId = '';
while (true) {
// don't start with a 3
const firstDigit = Math.floor(Math.random() * 10);
if (firstDigit !== 3) {
cardId = firstDigit.toString();
break;
}
}
for (let i = 0; i < 19; i++) {
cardId += Math.floor(Math.random() * 10).toString();
}
return cardId;
}
+1 -32
View File
@@ -1,5 +1,5 @@
import {Realm} from 'realm';
import {AMServerInfoResponse} from "./AM-API";
import {AMServerInfoResponse} from "amnet-shared";
export class AMServer extends Realm.Object<AMServer> implements AMServerInfoResponse {
_id!: Realm.BSON.ObjectId;
@@ -11,37 +11,6 @@ export class AMServer extends Realm.Object<AMServer> implements AMServerInfoResp
createdAt: Date;
apiVersion: number;
async getInfo(abort?: AbortSignal): Promise<AMServerInfoResponse> {
try {
const response = await fetch(this.serverAddress, {
signal: abort
});
return await response.json();
} catch {
return null;
}
}
async submitCard(cardId: string, abort?: AbortSignal): Promise<boolean> {
try {
const response = await fetch(`${this.serverAddress}/card`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
cardId: cardId
}),
signal: abort
});
return response.ok;
} catch {
return false;
}
}
static generate(serverAddress: string) {
return {
_id: new Realm.BSON.ObjectId(),
+12
View File
@@ -15,6 +15,7 @@
"@react-navigation/native-stack": "^6.11.0",
"@realm/react": "^0.9.0",
"@types/react": "~18.2.79",
"amnet-shared": "file:../amnet-shared",
"date-fns": "^3.6.0",
"expo": "^51.0.0",
"expo-blur": "~13.0.2",
@@ -41,6 +42,13 @@
"typescript": "~5.3.3"
}
},
"../amnet-shared": {
"version": "1.0.0",
"dependencies": {
"tsup": "^8.2.4",
"typescript": "^5.5.4"
}
},
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"license": "Apache-2.0",
@@ -4735,6 +4743,10 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/amnet-shared": {
"resolved": "../amnet-shared",
"link": true
},
"node_modules/anser": {
"version": "1.4.10",
"license": "MIT"
+3 -2
View File
@@ -15,12 +15,14 @@
"@react-navigation/native-stack": "^6.11.0",
"@realm/react": "^0.9.0",
"@types/react": "~18.2.79",
"amnet-shared": "file:../amnet-shared",
"date-fns": "^3.6.0",
"expo": "^51.0.0",
"expo-blur": "~13.0.2",
"expo-clipboard": "~6.0.3",
"expo-constants": "~16.0.2",
"expo-dev-client": "~4.0.10",
"expo-linking": "~6.3.1",
"expo-status-bar": "~1.12.1",
"expo-system-ui": "~3.0.7",
"lucide-react-native": "^0.427.0",
@@ -37,7 +39,6 @@
"react-native-svg": "^15.5.0",
"react-native-url-polyfill": "^2.0.0",
"realm": "^12.12.1",
"typescript": "~5.3.3",
"expo-linking": "~6.3.1"
"typescript": "~5.3.3"
}
}