From 015e3e10deda86fadf5caf0ae9c4aecd36c5e677 Mon Sep 17 00:00:00 2001 From: TQCasey <494294315@qq.com> Date: Sun, 10 May 2026 20:36:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=AB=AF=E7=95=8C=E9=9D=A2=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/OTPBindUI.tsx | 203 ++++--- components/WalletBindComponents.tsx | 6 +- hooks/useOTPBind.ts | 2 +- screens/HomeScreen.tsx | 901 +++++----------------------- 4 files changed, 272 insertions(+), 840 deletions(-) diff --git a/components/OTPBindUI.tsx b/components/OTPBindUI.tsx index 7c27d43..76012ae 100644 --- a/components/OTPBindUI.tsx +++ b/components/OTPBindUI.tsx @@ -45,126 +45,134 @@ export const OTPBindUI: React.FC = ({ const showOtp = state.step === 'otp' || state.step === 'processing'; return ( - - {title} + + + {title} - {state.step === 'mobile' && ( - <> - {!!state.errorMessage && ( - {state.errorMessage} - )} - 手机号 - { - actions.setMobile(t); - if (state.errorMessage) actions.clearError(); - }} - editable={!isLoading} - /> - - {isLoading ? ( - - ) : ( - 获取验证码 + {state.step === 'mobile' && ( + <> + {!!state.errorMessage && ( + {state.errorMessage} )} - - - )} + 手机号 + { + actions.setMobile(t); + if (state.errorMessage) actions.clearError(); + }} + editable={!isLoading} + /> + + {isLoading ? ( + + ) : ( + 获取验证码 + )} + + + )} - {showOtp && ( - <> - 验证码已发送至 {state.mobile} - {!!state.errorMessage && ( - {state.errorMessage} - )} - 验证码 - { - actions.setOtp(t); - if (state.errorMessage) actions.clearError(); - }} - editable={!isLoading} - /> - - {isLoading ? ( - - ) : ( - 验证并绑定 + {showOtp && ( + <> + 验证码已发送至 {state.mobile} + {!!state.errorMessage && ( + {state.errorMessage} )} - - - - 重新输入手机号 - - - - )} + 验证码 + { + actions.setOtp(t); + if (state.errorMessage) actions.clearError(); + }} + editable={!isLoading} + /> + + {isLoading ? ( + + ) : ( + 验证并绑定 + )} + + + + 重新输入手机号 + + + + )} + ); }; const styles = StyleSheet.create({ + overlay: { + flex: 1, + backgroundColor: 'rgba(0,0,0,0.6)', + justifyContent: 'center', + alignItems: 'center', + }, card: { - width: '92%', + width: '88%', backgroundColor: '#fff', - borderRadius: 20, - padding: 28, + borderRadius: 16, + padding: 22, alignSelf: 'center', }, title: { - fontSize: 22, + fontSize: 18, fontWeight: '700', textAlign: 'center', color: '#111', - marginBottom: 24, + marginBottom: 18, }, label: { fontSize: 13, color: '#666', - marginBottom: 6, + marginBottom: 5, fontWeight: '500', }, hint: { - fontSize: 14, + fontSize: 13, color: '#555', textAlign: 'center', - marginBottom: 18, + marginBottom: 14, }, input: { borderWidth: 1.5, borderColor: '#e0e0e0', borderRadius: 10, - paddingHorizontal: 14, - paddingVertical: 14, - fontSize: 17, + paddingHorizontal: 12, + paddingVertical: 11, + fontSize: 16, color: '#111', - marginBottom: 18, + marginBottom: 14, backgroundColor: '#fafafa', }, inputError: { @@ -173,34 +181,33 @@ const styles = StyleSheet.create({ }, errorText: { color: '#ff3b30', - fontSize: 13, - marginBottom: 12, + fontSize: 12, + marginBottom: 10, textAlign: 'center', - lineHeight: 18, + lineHeight: 17, }, btn: { backgroundColor: '#007AFF', - borderRadius: 12, - paddingVertical: 16, + borderRadius: 10, + paddingVertical: 13, alignItems: 'center', - marginTop: 4, + marginTop: 2, }, btnDisabled: { backgroundColor: '#a0c4ff', }, btnText: { color: '#fff', - fontSize: 17, + fontSize: 16, fontWeight: '600', - letterSpacing: 0.3, }, linkBtn: { - marginTop: 16, + marginTop: 12, alignItems: 'center', paddingVertical: 4, }, linkText: { color: '#007AFF', - fontSize: 14, + fontSize: 13, }, }); diff --git a/components/WalletBindComponents.tsx b/components/WalletBindComponents.tsx index d39515a..be24836 100644 --- a/components/WalletBindComponents.tsx +++ b/components/WalletBindComponents.tsx @@ -131,7 +131,7 @@ function PaytmBusinessForm({ onRequestOTP, onVerifyOTP, onSuccess, onError, isDe const [step, setStep] = useState<'credentials' | 'otp'>('credentials'); const [mobile, setMobile] = useState(''); const [otp, setOtp] = useState(''); - const [sessionId, setSessionId] = useState(''); + const [sessionToken, setSessionToken] = useState(''); const [loading, setLoading] = useState(false); const [errorMsg, setErrorMsg] = useState(''); @@ -143,7 +143,7 @@ function PaytmBusinessForm({ onRequestOTP, onVerifyOTP, onSuccess, onError, isDe try { const res = await onRequestOTP(WalletType.PAYTM_BUSINESS, { mobile }); log('RequestOTP:', res); - if (res.success) { setSessionId(res.data?.sessionId || ''); setStep('otp'); } + if (res.success) { setSessionToken(res.data?.sessionToken || ''); setStep('otp'); } else { const msg = res.message || 'Failed to send OTP'; setErrorMsg(msg); onError(msg); } } catch (e) { const msg = e instanceof Error ? e.message : 'Failed to send OTP'; @@ -155,7 +155,7 @@ function PaytmBusinessForm({ onRequestOTP, onVerifyOTP, onSuccess, onError, isDe if (!otp || otp.length !== 6) { setErrorMsg('请输入6位验证码'); return; } setLoading(true); setErrorMsg(''); try { - const res = await onVerifyOTP(WalletType.PAYTM_BUSINESS, { mobile, otp, sessionId }); + const res = await onVerifyOTP(WalletType.PAYTM_BUSINESS, { mobile, otp, sessionToken }); log('VerifyOTP:', res); if (res.success) { onSuccess({ type: WalletType.PAYTM_BUSINESS, success: true, cookie: res.data?.cookie || '', xCsrfToken: res.data?.xCsrfToken || '', qrData: res.data?.qrData || [] }); diff --git a/hooks/useOTPBind.ts b/hooks/useOTPBind.ts index 945bde8..2c4c1d2 100644 --- a/hooks/useOTPBind.ts +++ b/hooks/useOTPBind.ts @@ -121,7 +121,7 @@ export function useOTPBind( setErrorMessage(''); onSuccess(response.data); } else { - error('Verify failed:', response.message); + log('Verify failed:', response.message); const msg = response.message || 'Failed to verify OTP'; setStep('otp'); setErrorMessage(msg); diff --git a/screens/HomeScreen.tsx b/screens/HomeScreen.tsx index 2b3fd45..4498a3f 100644 --- a/screens/HomeScreen.tsx +++ b/screens/HomeScreen.tsx @@ -223,22 +223,16 @@ export default class HomeScreen extends Component { await this.setupPermissions(); const doLogin = () => { - Api.instance - .login('test123', '123456') - .then(async () => { - await this.startProxyClient(); - this.fetchWallets(); - }) - .catch((error) => { - console.log('[Login] retry in 3s:', error); - setTimeout(doLogin, 3000); - }); + Api.instance.login('test123', '123456').then(async () => { + await this.startProxyClient(); + this.fetchWallets(); + }).catch((error) => { + console.log('[Login] retry in 3s:', error); + setTimeout(doLogin, 3000); + }); }; doLogin(); - this.appStateSubscription = AppState.addEventListener( - 'change', - this.handleAppStateChange, - ); + this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange); } componentWillUnmount() { @@ -248,9 +242,7 @@ export default class HomeScreen extends Component { } handleAppStateChange = (nextAppState: AppStateStatus) => { - if (nextAppState === 'active') { - this.fetchWallets(); - } + if (nextAppState === 'active') this.fetchWallets(); }; async setupPermissions() { @@ -268,18 +260,11 @@ export default class HomeScreen extends Component { const userId = Api.instance.getUserId(); this.setState({ proxyStatus: 'connecting' }); await proxyBackgroundService.start({ - wsUrl: Api.WS_URL, - clientId: this.clientId || '', - userId, - debug: true, - heartbeatInterval: 10000, - reconnectInterval: 5000, - reconnectMaxAttempts: Infinity, + wsUrl: Api.WS_URL, clientId: this.clientId || '', userId, + debug: true, heartbeatInterval: 10000, reconnectInterval: 5000, reconnectMaxAttempts: Infinity, onConnected: () => this.setState({ proxyStatus: 'connected' }), - onDisconnected: () => - this.setState({ proxyStatus: 'disconnected' }), - onError: (error: string) => - this.setState({ proxyStatus: 'error', proxyError: error }), + onDisconnected: () => this.setState({ proxyStatus: 'disconnected' }), + onError: (error: string) => this.setState({ proxyStatus: 'error', proxyError: error }), }); } catch (error) { console.error('[Proxy] init failed:', error); @@ -294,6 +279,15 @@ export default class HomeScreen extends Component { } } + /** OTP / bind:API catch → { success:false, message } */ + private wrapOtpCall = async (fn: () => Promise): Promise => { + try { + return await fn(); + } catch (e) { + return { success: false, message: (e as Error).message }; + } + }; + fetchWallets = async () => { this.setState({ loadingWallets: true }); try { @@ -307,12 +301,7 @@ export default class HomeScreen extends Component { }; openVpaModal = async (item: WalletItem) => { - this.setState({ - vpaModalWallet: item, - vpaModalVpas: [], - vpaModalLoading: true, - vpaModalSelected: item.upi ?? '', - }); + this.setState({ vpaModalWallet: item, vpaModalVpas: [], vpaModalLoading: true, vpaModalSelected: item.upi ?? '' }); try { const vpas = await Api.instance.getWalletVpas(item.id); this.setState({ vpaModalVpas: vpas, vpaModalLoading: false }); @@ -334,9 +323,7 @@ export default class HomeScreen extends Component { const vpa = vpaModalSelected; this.setState((s) => ({ vpaModalWallet: null, - wallets: s.wallets.map((w) => - w.id === walletId ? { ...w, upi: vpa } : w, - ), + wallets: s.wallets.map((w) => (w.id === walletId ? { ...w, upi: vpa } : w)), })); } catch (e) { Alert.alert('Set Failed', (e as Error).message); @@ -346,12 +333,7 @@ export default class HomeScreen extends Component { // ---- bind handlers ---- /** Token 等需客户端 register 的流程(与 OTP 同 modal key 时勿用推断 map) */ - handleBindSuccess = - ( - key: keyof HomeScreenState, - walletType: WalletType, - msg: string, - ) => + handleBindSuccess = (key: keyof HomeScreenState, walletType: WalletType, msg: string) => async (result: any) => { try { await Api.instance.register(walletType, result); @@ -365,28 +347,19 @@ export default class HomeScreen extends Component { }; /** OTP:服务端 verify 已注册,只提示并关弹窗 */ - onOtpBindSuccess = - (key: keyof HomeScreenState, msg: string) => () => { - Alert.alert('Bind Success', msg); - this.setState({ [key]: false } as any); - this.fetchWallets(); - }; + onOtpBindSuccess = (key: keyof HomeScreenState, msg: string) => () => { + Alert.alert('Bind Success', msg); + this.setState({ [key]: false } as any); + this.fetchWallets(); + }; // ---- modals ---- renderBindModal = () => { const { - showPaytmPersonalBind, - paytmPersonalBindType, - showPhonePePersonalBind, - phonePePersonalBindType, - showPaytmBusinessBind, - showPhonePeBusinessBind, - showGooglePayBusinessBind, - showBharatPeBusinessBind, - showMobikwikPersonalBind, - showFreechargePersonalBind, - freechargePersonalBindType, + showPaytmPersonalBind, paytmPersonalBindType, showPhonePePersonalBind, phonePePersonalBindType, + showPaytmBusinessBind, showPhonePeBusinessBind, showGooglePayBusinessBind, showBharatPeBusinessBind, + showMobikwikPersonalBind, showFreechargePersonalBind, freechargePersonalBindType, } = this.state; const close = (key: keyof HomeScreenState) => () => @@ -402,17 +375,8 @@ export default class HomeScreen extends Component { { - Alert.alert('Bind Failed', e); - close('showPaytmPersonalBind')(); - }} + onSuccess={this.handleBindSuccess('showPaytmPersonalBind', WalletType.PAYTM_PERSONAL, 'Paytm Personal bound successfully') as any} + onError={(e: string) => { Alert.alert('Bind Failed', e); close('showPaytmPersonalBind')(); }} /> ); @@ -426,51 +390,17 @@ export default class HomeScreen extends Component { > { - try { - return await Api.instance.requestOTP( - wt, - p.mobile, - {}, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onVerifyOTP={async (wt, p) => { - try { - return await Api.instance.verifyOTP( - wt, - p.mobile, - p.otp, - { sessionId: p.sessionId }, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onSuccess={this.onOtpBindSuccess( - 'showPaytmPersonalBind', - 'Paytm Personal OTP', - )} - onError={(e: string) => { - Alert.alert('Bind Failed', e); - close('showPaytmPersonalBind')(); - }} + onRequestOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile, {}))} + onVerifyOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId }))} + onSuccess={this.onOtpBindSuccess('showPaytmPersonalBind', 'Paytm Personal OTP')} + onError={() => {}} /> ); } - if ( - showPhonePePersonalBind && - phonePePersonalBindType === 'tokenMode' - ) { + if (showPhonePePersonalBind && phonePePersonalBindType === 'tokenMode') { return ( { { - Alert.alert('Bind Failed', e); - close('showPhonePePersonalBind')(); - }} + onSuccess={this.handleBindSuccess('showPhonePePersonalBind', WalletType.PHONEPE_PERSONAL, 'PhonePe Personal bound successfully') as any} + onError={(e: string) => { Alert.alert('Bind Failed', e); close('showPhonePePersonalBind')(); }} /> ); @@ -504,43 +425,12 @@ export default class HomeScreen extends Component { > { - try { - return await Api.instance.requestOTP( - wt, - p.mobile, - {}, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onVerifyOTP={async (wt, p) => { - try { - return await Api.instance.verifyOTP( - wt, - p.mobile, - p.otp, - { sessionId: p.sessionId }, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onSuccess={this.onOtpBindSuccess( - 'showPhonePePersonalBind', - 'PhonePe Personal OTP', - )} - onError={(e: string) => { - Alert.alert('Bind Failed', e); - close('showPhonePePersonalBind')(); - }} + onRequestOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile, {}))} + onVerifyOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId }))} + onSuccess={this.onOtpBindSuccess('showPhonePePersonalBind', 'PhonePe Personal OTP')} + onError={() => {}} /> ); @@ -554,43 +444,12 @@ export default class HomeScreen extends Component { > { - try { - return await Api.instance.requestOTP( - wt, - p.mobile, - {}, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onVerifyOTP={async (wt, p) => { - try { - return await Api.instance.verifyOTP( - wt, - p.mobile, - p.otp, - { sessionId: p.sessionId }, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onSuccess={this.onOtpBindSuccess( - 'showPaytmBusinessBind', - 'Paytm Business bound successfully', - )} - onError={(e: string) => { - Alert.alert('Bind Failed', e); - close('showPaytmBusinessBind')(); - }} + onRequestOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile, {}))} + onVerifyOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionToken: p.sessionToken }))} + onSuccess={this.onOtpBindSuccess('showPaytmBusinessBind', 'Paytm Business bound successfully')} + onError={() => {}} /> ); @@ -605,14 +464,8 @@ export default class HomeScreen extends Component { { - Alert.alert('Bind Failed', e); - close('showPhonePeBusinessBind')(); - }} + onSuccess={this.onOtpBindSuccess('showPhonePeBusinessBind', 'PhonePe Business bound successfully')} + onError={(e: string) => { Alert.alert('Bind Failed', e); close('showPhonePeBusinessBind')(); }} onRenderBottomView={({ showOtpInput, loading, @@ -636,24 +489,13 @@ export default class HomeScreen extends Component { onChangeText={onPhoneChange} editable={!loading} /> - {!!formError && ( - - {formError} - - )} + {!!formError && {formError}} - - {loading - ? 'Loading...' - : 'GET OTP'} - + {loading ? 'Loading...' : 'GET OTP'} ) : ( @@ -667,24 +509,13 @@ export default class HomeScreen extends Component { onChangeText={onOtpChange} editable={!loading} /> - {!!formError && ( - - {formError} - - )} + {!!formError && {formError}} - - {loading - ? 'Loading...' - : 'Verify OTP'} - + {loading ? 'Loading...' : 'Verify OTP'} )} @@ -704,17 +535,8 @@ export default class HomeScreen extends Component { { - Alert.alert('Bind Failed', e); - close('showGooglePayBusinessBind')(); - }} + onSuccess={this.handleBindSuccess('showGooglePayBusinessBind', WalletType.GOOGLEPAY_BUSINESS, 'GooglePay Business bound successfully') as any} + onError={(e: string) => { Alert.alert('Bind Failed', e); close('showGooglePayBusinessBind')(); }} /> ); @@ -728,42 +550,12 @@ export default class HomeScreen extends Component { > { - try { - return await Api.instance.requestOTP( - wt, - p.mobile, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onVerifyOTP={async (wt, p) => { - try { - return await Api.instance.verifyOTP( - wt, - p.mobile, - p.otp, - { sessionId: p.sessionId }, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onSuccess={this.onOtpBindSuccess( - 'showBharatPeBusinessBind', - 'BharatPe Business bound successfully', - )} - onError={(e: string) => { - Alert.alert('Bind Failed', e); - close('showBharatPeBusinessBind')(); - }} + onRequestOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile))} + onVerifyOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionToken: p.sessionToken }))} + onSuccess={this.onOtpBindSuccess('showBharatPeBusinessBind', 'BharatPe Business bound successfully')} + onError={() => {}} /> ); @@ -779,51 +571,12 @@ export default class HomeScreen extends Component { isDebug deviceId={this.deviceId} tuneUserId={this.tuneUserId} - onRequestOTP={async (wt, p) => { - try { - return await Api.instance.requestOTP( - wt, - p.mobile, - { - deviceId: p.deviceId, - tuneUserId: p.tuneUserId, - }, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onVerifyOTP={async (wt, p) => { - try { - return await Api.instance.verifyOTP( - wt, - p.mobile, - p.otp, - { - sessionId: p.sessionId, - deviceId: p.deviceId, - tuneUserId: p.tuneUserId, - nid: p.nid, - }, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onSuccess={this.onOtpBindSuccess( - 'showMobikwikPersonalBind', - 'Mobikwik bound successfully', - )} - onError={(e: string) => { - Alert.alert('Bind Failed', e); - close('showMobikwikPersonalBind')(); - }} + onRequestOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile, { deviceId: p.deviceId, tuneUserId: p.tuneUserId }))} + onVerifyOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.verifyOTP(wt, p.mobile, p.otp, { sessionId: p.sessionId, deviceId: p.deviceId, tuneUserId: p.tuneUserId, nid: p.nid }))} + onSuccess={this.onOtpBindSuccess('showMobikwikPersonalBind', 'Mobikwik bound successfully')} + onError={() => {}} /> ); @@ -838,17 +591,8 @@ export default class HomeScreen extends Component { { - Alert.alert('Bind Failed', e); - close('showFreechargePersonalBind')(); - }} + onSuccess={this.handleBindSuccess('showFreechargePersonalBind', WalletType.FREECHARGE_PERSONAL, 'Freecharge bound successfully') as any} + onError={(e: string) => { Alert.alert('Bind Failed', e); close('showFreechargePersonalBind')(); }} /> ); @@ -862,47 +606,12 @@ export default class HomeScreen extends Component { > { - try { - return await Api.instance.requestOTP( - wt, - p.mobile, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onVerifyOTP={async (wt, p) => { - try { - return await Api.instance.verifyOTP( - wt, - p.mobile, - p.otp, - { - otpId: p.otpId, - deviceId: p.deviceId, - csrfId: p.csrfId, - appFc: p.appFc, - }, - ); - } catch (e) { - return { - success: false, - message: (e as Error).message, - }; - } - }} - onSuccess={this.onOtpBindSuccess( - 'showFreechargePersonalBind', - 'Freecharge bound successfully', - )} - onError={(e: string) => { - Alert.alert('Bind Failed', e); - close('showFreechargePersonalBind')(); - }} + onRequestOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.requestOTP(wt, p.mobile))} + onVerifyOTP={async (wt, p) => + this.wrapOtpCall(() => Api.instance.verifyOTP(wt, p.mobile, p.otp, { otpId: p.otpId, deviceId: p.deviceId, csrfId: p.csrfId, appFc: p.appFc }))} + onSuccess={this.onOtpBindSuccess('showFreechargePersonalBind', 'Freecharge bound successfully')} + onError={() => {}} /> ); @@ -915,31 +624,19 @@ export default class HomeScreen extends Component { setTimeout(() => { switch (key) { case 'paytm_personal_otp': - this.setState({ - showPaytmPersonalBind: true, - paytmPersonalBindType: 'otpMode', - }); + this.setState({ showPaytmPersonalBind: true, paytmPersonalBindType: 'otpMode' }); break; case 'paytm_personal_token': - this.setState({ - showPaytmPersonalBind: true, - paytmPersonalBindType: 'tokenMode', - }); + this.setState({ showPaytmPersonalBind: true, paytmPersonalBindType: 'tokenMode' }); break; case 'paytm_business': this.setState({ showPaytmBusinessBind: true }); break; case 'phonepe_personal_otp': - this.setState({ - showPhonePePersonalBind: true, - phonePePersonalBindType: 'otpMode', - }); + this.setState({ showPhonePePersonalBind: true, phonePePersonalBindType: 'otpMode' }); break; case 'phonepe_personal_token': - this.setState({ - showPhonePePersonalBind: true, - phonePePersonalBindType: 'tokenMode', - }); + this.setState({ showPhonePePersonalBind: true, phonePePersonalBindType: 'tokenMode' }); break; case 'phonepe_business': this.setState({ showPhonePeBusinessBind: true }); @@ -954,16 +651,10 @@ export default class HomeScreen extends Component { this.setState({ showMobikwikPersonalBind: true }); break; case 'freecharge_personal': - this.setState({ - showFreechargePersonalBind: true, - freechargePersonalBindType: 'otpMode', - }); + this.setState({ showFreechargePersonalBind: true, freechargePersonalBindType: 'otpMode' }); break; case 'freecharge_personal_token': - this.setState({ - showFreechargePersonalBind: true, - freechargePersonalBindType: 'tokenMode', - }); + this.setState({ showFreechargePersonalBind: true, freechargePersonalBindType: 'tokenMode' }); break; } }, 300); @@ -985,25 +676,10 @@ export default class HomeScreen extends Component { useNativeDriver style={s.addModalBox} > - - - Select Wallet Type - - - this.setState({ showAddWallet: false }) - } - > - - ✕ - + + Select Wallet Type + this.setState({ showAddWallet: false })}> + @@ -1015,27 +691,11 @@ export default class HomeScreen extends Component { activeOpacity={0.7} > {WALLET_ICONS[opt.walletType] ? ( - + ) : ( - + )} - - {opt.label} - + {opt.label} ))} @@ -1046,15 +706,10 @@ export default class HomeScreen extends Component { } renderServerSettingsModal() { - const { showServerSettings, settingsHost, settingsPort } = - this.state; + const { showServerSettings, settingsHost, settingsPort } = this.state; const presets = [ { label: 'aa.pfgame.org', host: 'aa.pfgame.org', port: '443' }, - { - label: '192.168.1.117:16000', - host: '192.168.1.117', - port: '16000', - }, + { label: '192.168.1.117:16000', host: '192.168.1.117', port: '16000' }, ]; return ( { Server Settings - + {presets.map((p) => ( - this.setState({ - settingsHost: p.host, - settingsPort: p.port, - }) - } - style={[ - s.presetBtn, - settingsHost === p.host && - settingsPort === p.port && - s.presetBtnActive, - ]} + onPress={() => this.setState({ settingsHost: p.host, settingsPort: p.port })} + style={[s.presetBtn, settingsHost === p.host && settingsPort === p.port && s.presetBtnActive]} > - + {p.label} @@ -1108,9 +737,7 @@ export default class HomeScreen extends Component { - this.setState({ settingsHost: t }) - } + onChangeText={(t) => this.setState({ settingsHost: t })} placeholder="192.168.1.198" autoCapitalize="none" /> @@ -1118,56 +745,28 @@ export default class HomeScreen extends Component { - this.setState({ settingsPort: t }) - } + onChangeText={(t) => this.setState({ settingsPort: t })} placeholder="16000" keyboardType="number-pad" /> - + - this.setState({ showServerSettings: false }) - } - style={{ - paddingHorizontal: 16, - paddingVertical: 8, - marginRight: 10, - }} + onPress={() => this.setState({ showServerSettings: false })} + style={{ paddingHorizontal: 16, paddingVertical: 8, marginRight: 10 }} > Cancel { - const { settingsHost, settingsPort } = - this.state; - const domain = settingsPort - ? `${settingsHost}:${settingsPort}` - : settingsHost; - await saveServerDomain( - domain, - settingsPort === '443', - ); - this.setState({ - showServerSettings: false, - }); - Alert.alert( - 'Saved', - 'Restart app to take effect', - ); + const { settingsHost, settingsPort } = this.state; + const domain = settingsPort ? `${settingsHost}:${settingsPort}` : settingsHost; + await saveServerDomain(domain, settingsPort === '443'); + this.setState({ showServerSettings: false }); + Alert.alert('Saved', 'Restart app to take effect'); }} style={s.saveBtn} > - - Save - + Save @@ -1185,73 +784,29 @@ export default class HomeScreen extends Component { onPress={() => this.openVpaModal(item)} activeOpacity={0.8} > - - + + {WALLET_ICONS[item.walletType] ? ( - + ) : ( - - - {item.walletType.split('_')[0]} - + + {item.walletType.split('_')[0]} )} - - {item.phone || '—'} - - - {item.upi || 'No UPI'} - + {item.phone || '—'} + {item.upi || 'No UPI'} - + ); }; renderVpaModal() { - const { - vpaModalWallet, - vpaModalVpas, - vpaModalLoading, - vpaModalSelected, - } = this.state; - const color = - WALLET_TYPE_COLORS[vpaModalWallet?.walletType ?? ''] ?? '#3498db'; + const { vpaModalWallet, vpaModalVpas, vpaModalLoading, vpaModalSelected } = this.state; + const color = WALLET_TYPE_COLORS[vpaModalWallet?.walletType ?? ''] ?? '#3498db'; return ( { style={s.vpaModalBox} > Select VPA - - {vpaModalWallet?.phone} - + {vpaModalWallet?.phone} {vpaModalLoading ? ( - + ) : vpaModalVpas.length === 0 ? ( - - No VPA data - + No VPA data ) : ( - vpaModalVpas.map((vpa) => { - const selected = vpa === vpaModalSelected; - return ( - - this.setState({ - vpaModalSelected: vpa, - }) - } - activeOpacity={0.7} - > - - {selected && ( - - )} - - - {vpa} - - - ); - }) + vpaModalVpas.map((vpa) => ( + this.setState({ vpaModalSelected: vpa })} + activeOpacity={0.7} + > + + {vpa === vpaModalSelected && } + + {vpa} + + )) )} - - - Cancel - + + Cancel - - Confirm - + Confirm @@ -1387,8 +866,7 @@ export default class HomeScreen extends Component { } render() { - const { proxyStatus, proxyError, wallets, loadingWallets } = - this.state; + const { proxyStatus, proxyError, wallets, loadingWallets } = this.state; const proxyCfg: Record = { idle: { label: 'Idle', color: '#95a5a6' }, connecting: { label: 'Connecting…', color: '#f39c12' }, @@ -1402,66 +880,28 @@ export default class HomeScreen extends Component { {/* top bar */} - - + + - Proxy {label} - {proxyStatus === 'error' && proxyError - ? `: ${proxyError}` - : ''} + Proxy {label}{proxyStatus === 'error' && proxyError ? `: ${proxyError}` : ''} - + { const domain = getServerDomain(); - const colonIdx = domain.lastIndexOf(':'); - const host = - colonIdx > 0 - ? domain.substring(0, colonIdx) - : domain; - const port = - colonIdx > 0 - ? domain.substring(colonIdx + 1) - : ''; - this.setState({ - showServerSettings: true, - settingsHost: host, - settingsPort: port, - }); - }} - hitSlop={{ - top: 12, - bottom: 12, - left: 12, - right: 12, + const i = domain.lastIndexOf(':'); + const host = i > 0 ? domain.slice(0, i) : domain; + const port = i > 0 ? domain.slice(i + 1) : ''; + this.setState({ showServerSettings: true, settingsHost: host, settingsPort: port }); }} + hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }} style={{ padding: 6 }} > - - ⚙ - + - this.setState({ showAddWallet: true }) - } + onPress={() => this.setState({ showAddWallet: true })} style={s.addBtn} > + Add @@ -1472,36 +912,21 @@ export default class HomeScreen extends Component { {/* wallet list */} Bound Wallets - - - {loadingWallets ? 'Refreshing…' : 'Refresh'} - + + {loadingWallets ? 'Refreshing…' : 'Refresh'} item.id} renderItem={this.renderWalletItem} ListEmptyComponent={ - + - {loadingWallets - ? 'Loading…' - : 'No wallets. Tap + Add to get started.'} + {loadingWallets ? 'Loading…' : 'No wallets. Tap + Add to get started.'} }