From 8a16739a3906d4c11e4d2a124c35645d77945be7 Mon Sep 17 00:00:00 2001 From: Collins Edim Date: Wed, 19 Nov 2025 02:51:16 +0100 Subject: [PATCH 1/2] fix(RNPSW): respect safe areas and update deps --- development/PaystackProvider.tsx | 179 +++++++++++++++---------------- package.json | 34 +++--- 2 files changed, 106 insertions(+), 107 deletions(-) diff --git a/development/PaystackProvider.tsx b/development/PaystackProvider.tsx index 5304397..60f1821 100644 --- a/development/PaystackProvider.tsx +++ b/development/PaystackProvider.tsx @@ -1,108 +1,107 @@ import React, { createContext, useCallback, useMemo, useState } from 'react'; -import { Modal, SafeAreaView, ActivityIndicator, } from 'react-native'; +import { Modal, ActivityIndicator } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; + import { WebView, WebViewMessageEvent } from 'react-native-webview'; -import { - PaystackParams, - PaystackProviderProps, -} from './types'; +import { PaystackParams, PaystackProviderProps } from './types'; import { validateParams, paystackHtmlContent, generatePaystackParams, handlePaystackMessage } from './utils'; import { styles } from './styles'; export const PaystackContext = createContext<{ - popup: { - checkout: (params: PaystackParams) => void; - newTransaction: (params: PaystackParams) => void; - }; + popup: { + checkout: (params: PaystackParams) => void; + newTransaction: (params: PaystackParams) => void; + }; } | null>(null); export const PaystackProvider: React.FC = ({ - publicKey, - currency, - defaultChannels = ['card'], - debug = false, - children, - onGlobalSuccess, - onGlobalCancel, + publicKey, + currency, + defaultChannels = ['card'], + debug = false, + children, + onGlobalSuccess, + onGlobalCancel, }) => { - const [visible, setVisible] = useState(false); - const [params, setParams] = useState(null); - const [method, setMethod] = useState<'checkout' | 'newTransaction'>('checkout'); + const [visible, setVisible] = useState(false); + const [params, setParams] = useState(null); + const [method, setMethod] = useState<'checkout' | 'newTransaction'>('checkout'); - const fallbackRef = useMemo(() => `ref_${Date.now()}`, []); + const fallbackRef = useMemo(() => `ref_${Date.now()}`, []); - const open = useCallback( - (params: PaystackParams, selectedMethod: 'checkout' | 'newTransaction') => { - if (debug) console.log(`[Paystack] Opening modal with method: ${selectedMethod}`); - if (!validateParams(params, debug)) return; - setParams(params); - setMethod(selectedMethod); - setVisible(true); - }, - [debug] - ); + const open = useCallback( + (params: PaystackParams, selectedMethod: 'checkout' | 'newTransaction') => { + if (debug) console.log(`[Paystack] Opening modal with method: ${selectedMethod}`); + if (!validateParams(params, debug)) return; + setParams(params); + setMethod(selectedMethod); + setVisible(true); + }, + [debug], + ); - const checkout = (params: PaystackParams) => open(params, 'checkout'); - const newTransaction = (params: PaystackParams) => open(params, 'newTransaction'); + const checkout = (params: PaystackParams) => open(params, 'checkout'); + const newTransaction = (params: PaystackParams) => open(params, 'newTransaction'); - const close = () => { - setVisible(false); - setParams(null); - } + const close = () => { + setVisible(false); + setParams(null); + }; - const handleMessage = (event: WebViewMessageEvent) => { - handlePaystackMessage({ - event, - debug, - params, - onGlobalSuccess, - onGlobalCancel, - close, - }); - }; + const handleMessage = (event: WebViewMessageEvent) => { + handlePaystackMessage({ + event, + debug, + params, + onGlobalSuccess, + onGlobalCancel, + close, + }); + }; - const paystackHTML = useMemo(() => { - if (!params) return ''; - return paystackHtmlContent( - generatePaystackParams({ - publicKey, - email: params.email, - amount: params.amount, - reference: params.reference || fallbackRef, - metadata: params.metadata, - ...(currency && { currency }), - channels: defaultChannels, - plan: params.plan, - invoice_limit: params.invoice_limit, - subaccount: params.subaccount, - split: params.split, - split_code: params.split_code, - }), - method - ); - }, [params, method]); + const paystackHTML = useMemo(() => { + if (!params) return ''; + return paystackHtmlContent( + generatePaystackParams({ + publicKey, + email: params.email, + amount: params.amount, + reference: params.reference || fallbackRef, + metadata: params.metadata, + ...(currency && { currency }), + channels: defaultChannels, + plan: params.plan, + invoice_limit: params.invoice_limit, + subaccount: params.subaccount, + split: params.split, + split_code: params.split_code, + }), + method, + ); + }, [params, method]); - if (debug && visible) { - console.log('[Paystack] HTML Injected:', paystackHTML); - } + if (debug && visible) { + console.log('[Paystack] HTML Injected:', paystackHTML); + } - return ( - - {children} - - - debug && console.log('[Paystack] WebView Load Start')} - onLoadEnd={() => debug && console.log('[Paystack] WebView Load End')} - renderLoading={() => } - /> - - - - ); -}; \ No newline at end of file + return ( + + {children} + + + debug && console.log('[Paystack] WebView Load Start')} + onLoadEnd={() => debug && console.log('[Paystack] WebView Load End')} + renderLoading={() => } + /> + + + + ); +}; diff --git a/package.json b/package.json index f3e9635..6059e18 100644 --- a/package.json +++ b/package.json @@ -33,25 +33,24 @@ "semantic-release": "semantic-release" }, "devDependencies": { - "@babel/core": "^7.22.0", - "@babel/runtime": "^7.14.6", - "@react-native-community/eslint-config": "^3.0.0", + "@babel/core": "^7.28.5", + "@babel/runtime": "^7.28.4", + "@react-native-community/eslint-config": "^3.2.0", "@testing-library/jest-native": "^5.4.3", - "@testing-library/react-native": "^13.0.0", + "@testing-library/react-native": "^13.3.3", "@types/jest": "^29.5.14", - "@types/react-native": "^0.64.12", - "@types/validator": "^13.6.3", + "@types/react-native": "^0.64.38", "babel-jest": "^26.6.3", - "eslint": "^7.30.0", + "eslint": "^7.32.0", "eslint-plugin-simple-import-sort": "^7.0.0", "jest": "^29.7.0", "jest-react-native": "^18.0.0", - "metro-react-native-babel-preset": "^0.66.1", - "react": "^17.0.1", - "react-native": "^0.64.2", - "react-test-renderer": "^19.0.0", - "semantic-release": "^24.0.0", - "typescript": "^4.3.5" + "metro-react-native-babel-preset": "^0.66.2", + "react": "^19.2.0", + "react-native": "^0.82.1", + "react-test-renderer": "^19.2.0", + "semantic-release": "^24.2.9", + "typescript": "^5.9.3" }, "peerDependencies": { "react": "*", @@ -59,9 +58,10 @@ "react-native-webview": "*" }, "dependencies": { - "@types/validator": "^13.6.3", - "react-native-webview": "*", - "validator": "^13.6.0" + "@types/validator": "^13.15.10", + "react-native-safe-area-context": "^5.6.2", + "react-native-webview": "^13.16.0", + "validator": "^13.15.23" }, "files": [ "production", @@ -70,4 +70,4 @@ "package.json", "contributing.md" ] -} \ No newline at end of file +} From e074b5edaaeb027762f5dfd78fa42fae81d67ce0 Mon Sep 17 00:00:00 2001 From: Collins Edim Date: Sat, 29 Nov 2025 23:20:33 +0100 Subject: [PATCH 2/2] fix(RNPSW): respect safe areas and align webview version for Expo SDK 54 compatibility --- development/PaystackProvider.tsx | 176 ++++++++++++++++--------------- package.json | 2 +- 2 files changed, 90 insertions(+), 88 deletions(-) diff --git a/development/PaystackProvider.tsx b/development/PaystackProvider.tsx index 60f1821..a107c39 100644 --- a/development/PaystackProvider.tsx +++ b/development/PaystackProvider.tsx @@ -1,107 +1,109 @@ import React, { createContext, useCallback, useMemo, useState } from 'react'; -import { Modal, ActivityIndicator } from 'react-native'; +import { Modal, ActivityIndicator, } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; - import { WebView, WebViewMessageEvent } from 'react-native-webview'; -import { PaystackParams, PaystackProviderProps } from './types'; +import { + PaystackParams, + PaystackProviderProps, +} from './types'; import { validateParams, paystackHtmlContent, generatePaystackParams, handlePaystackMessage } from './utils'; import { styles } from './styles'; export const PaystackContext = createContext<{ - popup: { - checkout: (params: PaystackParams) => void; - newTransaction: (params: PaystackParams) => void; - }; + popup: { + checkout: (params: PaystackParams) => void; + newTransaction: (params: PaystackParams) => void; + }; } | null>(null); export const PaystackProvider: React.FC = ({ - publicKey, - currency, - defaultChannels = ['card'], - debug = false, - children, - onGlobalSuccess, - onGlobalCancel, + publicKey, + currency, + defaultChannels = ['card'], + debug = false, + children, + onGlobalSuccess, + onGlobalCancel, }) => { - const [visible, setVisible] = useState(false); - const [params, setParams] = useState(null); - const [method, setMethod] = useState<'checkout' | 'newTransaction'>('checkout'); + const [visible, setVisible] = useState(false); + const [params, setParams] = useState(null); + const [method, setMethod] = useState<'checkout' | 'newTransaction'>('checkout'); - const fallbackRef = useMemo(() => `ref_${Date.now()}`, []); + const fallbackRef = useMemo(() => `ref_${Date.now()}`, []); - const open = useCallback( - (params: PaystackParams, selectedMethod: 'checkout' | 'newTransaction') => { - if (debug) console.log(`[Paystack] Opening modal with method: ${selectedMethod}`); - if (!validateParams(params, debug)) return; - setParams(params); - setMethod(selectedMethod); - setVisible(true); - }, - [debug], - ); + const open = useCallback( + (params: PaystackParams, selectedMethod: 'checkout' | 'newTransaction') => { + if (debug) console.log(`[Paystack] Opening modal with method: ${selectedMethod}`); + if (!validateParams(params, debug)) return; + setParams(params); + setMethod(selectedMethod); + setVisible(true); + }, + [debug] + ); - const checkout = (params: PaystackParams) => open(params, 'checkout'); - const newTransaction = (params: PaystackParams) => open(params, 'newTransaction'); + const checkout = (params: PaystackParams) => open(params, 'checkout'); + const newTransaction = (params: PaystackParams) => open(params, 'newTransaction'); - const close = () => { - setVisible(false); - setParams(null); - }; + const close = () => { + setVisible(false); + setParams(null); + } - const handleMessage = (event: WebViewMessageEvent) => { - handlePaystackMessage({ - event, - debug, - params, - onGlobalSuccess, - onGlobalCancel, - close, - }); - }; + const handleMessage = (event: WebViewMessageEvent) => { + handlePaystackMessage({ + event, + debug, + params, + onGlobalSuccess, + onGlobalCancel, + close, + }); + }; - const paystackHTML = useMemo(() => { - if (!params) return ''; - return paystackHtmlContent( - generatePaystackParams({ - publicKey, - email: params.email, - amount: params.amount, - reference: params.reference || fallbackRef, - metadata: params.metadata, - ...(currency && { currency }), - channels: defaultChannels, - plan: params.plan, - invoice_limit: params.invoice_limit, - subaccount: params.subaccount, - split: params.split, - split_code: params.split_code, - }), - method, - ); - }, [params, method]); + const paystackHTML = useMemo(() => { + if (!params) return ''; + return paystackHtmlContent( + generatePaystackParams({ + publicKey, + email: params.email, + amount: params.amount, + reference: params.reference || fallbackRef, + metadata: params.metadata, + ...(currency && { currency }), + channels: defaultChannels, + plan: params.plan, + invoice_limit: params.invoice_limit, + subaccount: params.subaccount, + split: params.split, + split_code: params.split_code, + }), + method + ); + }, [params, method]); - if (debug && visible) { - console.log('[Paystack] HTML Injected:', paystackHTML); - } + if (debug && visible) { + console.log('[Paystack] HTML Injected:', paystackHTML); + } - return ( - - {children} - - - debug && console.log('[Paystack] WebView Load Start')} - onLoadEnd={() => debug && console.log('[Paystack] WebView Load End')} - renderLoading={() => } - /> - - - - ); + return ( + + {children} + + + debug && console.log('[Paystack] WebView Load Start')} + onLoadEnd={() => debug && console.log('[Paystack] WebView Load End')} + renderLoading={() => } + /> + + + + ); }; diff --git a/package.json b/package.json index 6059e18..3b68b24 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "dependencies": { "@types/validator": "^13.15.10", "react-native-safe-area-context": "^5.6.2", - "react-native-webview": "^13.16.0", + "react-native-webview": "^13.15.0", "validator": "^13.15.23" }, "files": [