test 优化

This commit is contained in:
2026-03-24 16:47:37 +08:00
parent f0e21a2715
commit 9c220f1322
16 changed files with 669 additions and 603 deletions

44
App.tsx
View File

@@ -1,11 +1,32 @@
import React from 'react'; import React from 'react';
import { Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native'; import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { SafeAreaProvider } from 'react-native-safe-area-context'; import { SafeAreaProvider } from 'react-native-safe-area-context';
import Svg, { Path, Circle, Rect } from 'react-native-svg';
import HomeScreen from './screens/HomeScreen'; import HomeScreen from './screens/HomeScreen';
import TestScreen from './screens/TestScreen';
import MessageScreen from './screens/MessageScreen'; import MessageScreen from './screens/MessageScreen';
const WalletIcon = ({ color, size }: { color: string; size: number }) => (
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
<Rect x="2" y="5" width="20" height="15" rx="2" stroke={color} strokeWidth="1.8" />
<Path d="M2 10h20" stroke={color} strokeWidth="1.8" />
<Circle cx="17" cy="15" r="1.5" fill={color} />
</Svg>
);
const ToolIcon = ({ color, size }: { color: string; size: number }) => (
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
<Path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3-3a6 6 0 0 1-7 7l-6.4 6.4a2 2 0 1 1-2.8-2.8L10.9 10a6 6 0 0 1 7-7l-3.2 3.3z" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
</Svg>
);
const MessageIcon = ({ color, size }: { color: string; size: number }) => (
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
<Path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
</Svg>
);
const Tab = createBottomTabNavigator(); const Tab = createBottomTabNavigator();
export default function App() { export default function App() {
@@ -30,11 +51,18 @@ export default function App() {
name="Home" name="Home"
component={HomeScreen} component={HomeScreen}
options={{ options={{
title: '首页', title: '钱包列表',
tabBarLabel: '首页', tabBarLabel: '钱包列表',
tabBarIcon: ({ color, size }) => ( tabBarIcon: ({ color, size }) => <WalletIcon color={color} size={size} />,
<Text style={{ fontSize: size, color }}>🏠</Text> }}
), />
<Tab.Screen
name="Test"
component={TestScreen}
options={{
title: '测试',
tabBarLabel: '测试',
tabBarIcon: ({ color, size }) => <ToolIcon color={color} size={size} />,
}} }}
/> />
<Tab.Screen <Tab.Screen
@@ -43,9 +71,7 @@ export default function App() {
options={{ options={{
title: 'IM消息', title: 'IM消息',
tabBarLabel: 'IM消息', tabBarLabel: 'IM消息',
tabBarIcon: ({ color, size }) => ( tabBarIcon: ({ color, size }) => <MessageIcon color={color} size={size} />,
<Text style={{ fontSize: size, color }}>💬</Text>
),
}} }}
/> />
</Tab.Navigator> </Tab.Navigator>

6
declarations.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
declare module '*.svg' {
import React from 'react';
import { SvgProps } from 'react-native-svg';
const content: React.FC<SvgProps>;
export default content;
}

View File

@@ -1,11 +1,16 @@
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
/** const defaultConfig = getDefaultConfig(__dirname);
* Metro configuration const { assetExts, sourceExts } = defaultConfig.resolver;
* https://facebook.github.io/metro/docs/configuration
*
* @type {import('metro-config').MetroConfig}
*/
const config = {};
module.exports = mergeConfig(getDefaultConfig(__dirname), config); const config = {
transformer: {
babelTransformerPath: require.resolve('react-native-svg-transformer'),
},
resolver: {
assetExts: assetExts.filter(ext => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg'],
},
};
module.exports = mergeConfig(defaultConfig, config);

View File

@@ -25,6 +25,8 @@
"react-native-gesture-handler": "~2.9.0", "react-native-gesture-handler": "~2.9.0",
"react-native-safe-area-context": "^4.4.1", "react-native-safe-area-context": "^4.4.1",
"react-native-screens": "~3.36.0", "react-native-screens": "~3.36.0",
"react-native-svg": "^14.1.0",
"react-native-svg-transformer": "^1.5.3",
"react-native-tcp-socket": "^6.4.1", "react-native-tcp-socket": "^6.4.1",
"react-native-webview": "13.6.2", "react-native-webview": "13.6.2",
"rnauto": "./libs/rnauto", "rnauto": "./libs/rnauto",

BIN
res/bharatpe-business.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
res/freecharge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
res/googlepay-business.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
res/mobikwik.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
res/paytm-business.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
res/paytm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
res/phonepe-business.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
res/phonepe.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

File diff suppressed because it is too large Load Diff

69
screens/TestScreen.tsx Normal file
View File

@@ -0,0 +1,69 @@
import React, { useEffect, useRef } from 'react';
import { Alert, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { onProxyMessage, proxySendMessage, paytmPay } from 'rnwalletman';
export default function TestScreen() {
const subRef = useRef<ReturnType<typeof onProxyMessage> | null>(null);
useEffect(() => {
subRef.current = onProxyMessage((msg) => {
if (msg.type === 'echo') {
Alert.alert('Echo 回来了', JSON.stringify(msg.data));
}
});
return () => {
subRef.current?.remove();
};
}, []);
const handlePaytmPay = () => {
paytmPay('100', 'Gurvir singh', '296001000405', 'ICIC0002960', 'ABCDEF')
.then(result => console.log(result))
.catch(error => Alert.alert('代付失败', String(error)));
};
const handleEcho = () => {
proxySendMessage({ type: 'echo', messageId: `echo_${Date.now()}`, data: { text: `hello_${Date.now()}` } });
};
return (
<View style={styles.container}>
<Text style={styles.sectionTitle}></Text>
<TouchableOpacity style={[styles.btn, { backgroundColor: '#2ecc71' }]} onPress={handlePaytmPay}>
<Text style={styles.btnText}>Paytm Pay </Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.btn, { backgroundColor: '#3498db' }]} onPress={handleEcho}>
<Text style={styles.btnText}>Echo </Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f0f0',
padding: 20,
alignItems: 'center',
},
sectionTitle: {
fontSize: 16,
fontWeight: '600',
color: '#333',
alignSelf: 'flex-start',
marginBottom: 16,
marginTop: 8,
},
btn: {
width: '100%',
paddingVertical: 14,
borderRadius: 8,
alignItems: 'center',
marginBottom: 12,
},
btnText: {
color: '#fff',
fontSize: 15,
fontWeight: '600',
},
});

View File

@@ -1,6 +1,14 @@
import { WalletType } from 'rnwalletman'; import { WalletType } from 'rnwalletman';
import AsyncStorage from '@react-native-async-storage/async-storage'; import AsyncStorage from '@react-native-async-storage/async-storage';
export interface WalletItem {
id: string;
walletType: string;
upi?: string;
phone?: string;
status?: string;
}
const DEFAULT_DOMAIN = 'aa.pfgame.org'; const DEFAULT_DOMAIN = 'aa.pfgame.org';
const STORAGE_KEY = 'server_domain'; const STORAGE_KEY = 'server_domain';
const HTTPS_KEY = 'server_https'; const HTTPS_KEY = 'server_https';
@@ -117,6 +125,44 @@ class Api {
if (!data.success) throw new Error(data.message); if (!data.success) throw new Error(data.message);
return data; return data;
} }
public async listWallets(): Promise<WalletItem[]> {
const res = await fetch(`${Api.BASE_URL}/wallets`, { headers: this.headers() });
const data = await res.json();
if (!data.success) throw new Error(data.message);
return data.data?.wallets ?? [];
}
public async getWalletVpas(walletId: string): Promise<string[]> {
const res = await fetch(`${Api.BASE_URL}/wallet/vpas?walletId=${encodeURIComponent(walletId)}`, {
headers: this.headers(),
});
const data = await res.json();
if (!data.success) throw new Error(data.message);
return data.data?.vpas ?? [];
}
public async setCurrentVpa(walletId: string, vpaIndex: number): Promise<string> {
const res = await fetch(`${Api.BASE_URL}/wallet/set-vpa`, {
method: 'POST',
headers: this.headers(),
body: JSON.stringify({ walletId, vpaIndex }),
});
const data = await res.json();
if (!data.success) throw new Error(data.message);
return data.data?.vpa ?? '';
}
public async generateLink(walletId: string, amount: string): Promise<{ link: string; orderId: string }> {
const res = await fetch(`${Api.BASE_URL}/generate-link`, {
method: 'POST',
headers: this.headers(),
body: JSON.stringify({ walletId, amount }),
});
const data = await res.json();
if (!data.success) throw new Error(data.message);
return { link: data.data?.link, orderId: data.data?.orderId };
}
} }
export default Api; export default Api;