Closed sangamivivek closed 1 year ago
@mohanenm
@sangamivivek by inconsistent, do you mean it sometimes throws this error and sometimes does not?
yes @mohanenm ,while closing and opening the app it sometimes throws this error and sometimes does not
@sangamivivek can you try moving the configure outside component?
Maybe on your index.js
file
Not sure if this is helpful, but The example in the bildit repo calls configure within a React.useEffect block. According to this SO post, passing an empty array in useEffect makes sure it is called only once. I think the combination of useEffect with the array ensures it is called only once when the app starts and synchronously so it happens before any other flybuy method calls.
@addingama What would moving it out of the component do?
We are still running into this error when force closing and reopening the app.
The weird thing is that this problem is solved by removing the call to FlyBuy.Pickup.onPermissionChanged();
...however, when they remove that call we stop getting location updates.
Can you share the index.js
and App.tsx
content?
@sangamivivek ^
@addingama Index.js
import React from 'react'; import { AppRegistry } from 'react-native'; import App from './src/App'; import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => App);
Below is the FlyBuy Config snippet in App.tsx
useAsyncEffect(async () => {
await fetchRemoteConfig();
const remotevalue = await getAllRemoteValues();
QuantumMetric.QuantumMetricLibrary.sendEvent(79, JSON.stringify(remotevalue));
const iosToken = await RemoteConfig.getRemoteValue('flybuy_token_ios')
const androidToken = await RemoteConfig.getRemoteValue('flybuy_token_android')
let versionConfig = await RemoteConfig.getRemoteValue('version_check');
let flags = await RemoteConfig.getRemoteValue('feature_flags');
if ('force_update' in flags && flags.force_update) {
checkVersion(versionConfig)
}
await notifee.createChannel({
id: 'default',
name: 'TSC Notifications',
lights: false,
vibration: true,
importance: AndroidImportance.HIGH,
});
if (Platform.OS === 'ios') {
FlyBuy.Core.configure(iosToken);
} else {
FlyBuy.Core.configure(androidToken);
}
FlyBuy.Pickup.configure();
let basketIdStore = await getItemFromPersistance(BASKET_ID_PERSISTANT_KEY);
if(basketIdStore==null){
persistItem(GROUP_ORDER_PERSISTANT_KEY, false);
}
if (Platform.OS === 'ios') {
if (!Settings.get('hasRunBefore')) {
Settings.set({ hasRunBefore: true });
clearData();
persistItem(ALREADY_LAUNCHED, false);
}else{
persistItem(ALREADY_LAUNCHED, true);
}
}
}, []);
useEffect(() => { AppState.addEventListener("change",handleStateChange); let unsub = messaging().onMessage(async (remoteMessage) => { if (remoteMessage?.message_source === 'flybuy') { FlyBuy.Core.handleRemoteNotification(remoteMessage.data); } else if (remoteMessage?.data?.message_source === 'flybuy') { FlyBuy.Core.handleRemoteNotification(remoteMessage.data); } else { let now: Date = new Date(); const {actiontype, action, payload} = remoteMessage.data ?? {}; let notificationData: NotifeeNotification = { title: remoteMessage.notification?.title ?? '', body: remoteMessage.notification?.body ?? payload ?? '', android: { channelId: 'default', pressAction: {id: 'default', mainComponent: 'TSC'}, }, data:remoteMessage.data }; if (actiontype && action) { notificationData['data'] = {actiontype, action}; } notifee.displayNotification(notificationData); }
if((remoteMessage.notification?.title || remoteMessage.notification?.body) && AppState.currentState === "active"){
let notificationData: NotifeeNotification = {
title: remoteMessage.notification?.title,
body: remoteMessage.notification?.body,
android: {
channelId: 'default',
pressAction: {id: 'default', mainComponent: 'TSC'},
},
data:remoteMessage.data
};
notifee.displayNotification(notificationData);
}
});
return () => {
unsub();
AppState.removeEventListener("change", handleStateChange)
};
}, []);
@addingama @mohanenm code snippet that calls the FlyBuy.Pickup.onPermissionChanged() method during order confirmation.
const createOrder = async (sitId, mode, pid, timeplaced, readytime,cafeData) => { const vehicleDetails: any = await getItemFromPersistance( VEHICLE_DATA_PERSISTANT_KEY, ); const CUSTOMER_INFO = { name: user && Object.keys(user).length ? user?.firstName ?? '' : cartStore?.guestUser?.firstName ?? '', carType: vehicleDetails?.model ?? '', carColor: vehicleDetails?.color ?? '', licensePlate: '', phone: user && Object.keys(user).length ? user?.phone ?? '' : cartStore?.guestUser?.phone ?? '', }; const format = timeplaced?.split(' '); const timePlaced = format[0].slice(0, 4) + '/' + format[0].slice(4, 6) + '/' + format[0].slice(6); const formatReady = readytime?.split(' '); const readyTime = formatReady[0].slice(0, 4) + '-' + formatReady[0].slice(4, 6) + '-' + formatReady[0].slice(6); const cafeutc = cafeData; let offsetformat = "'" + cafeutc?.utcoffset + "'"; const offset = offsetformat.split(''); let dateOffset; let endTimeOffset; const endTimeformat = readyTime + 'T' + formatReady[1] + ':11.000Z'; if (cafeutc?.utcoffset < 0) { if (isNaN(offset[4])) { dateOffset = moment(new Date()) .add(offset[2], 'hours') .format('YYYY-MM-DD HH:mm'); endTimeOffset = moment(endTimeformat,'YYYY-MM-DD HH:mm') .add(offset[2], 'hours') .format('YYYY-MM-DD HH:mm'); } else { if (isNaN(offset[5])) { dateOffset = moment(new Date()) .add(offset[2], 'hours') .add(offset[4] + 0, 'minutes') .format('YYYY-MM-DD HH:mm'); endTimeOffset = moment(endTimeformat,'YYYY-MM-DD HH:mm') .add(offset[2], 'hours') .add(offset[4] + 0, 'minutes') .format('YYYY-MM-DD HH:mm'); } else { dateOffset = moment(new Date()) .add(offset[2], 'hours') .add(offset[4] + offset[5], 'minutes') .format('YYYY-MM-DD HH:mm'); endTimeOffset = moment(endTimeformat,'YYYY-MM-DD HH:mm') .add(offset[2], 'hours') .add(offset[4] + offset[5], 'minutes') .format('YYYY-MM-DD HH:mm'); } } // dateOffset = // dateOffset.split('-').join('/').replace(' ', 'T') + '.000Z'; // endTimeOffset = // endTimeOffset.split('-').join('/').replace(' ', 'T') + '.000Z'; dateOffset = dateOffset.replace(' ', 'T') + ':00.000Z'; endTimeOffset = endTimeOffset.replace(' ', 'T') + ':00.000Z'; } else { if (isNaN(offset[4])) { dateOffset = moment(new Date()) .subtract(offset[2], 'hours') .format('YYYY-MM-DD HH:mm'); endTimeOffset = moment(endTimeformat,'YYYY-MM-DD HH:mm') .subtract(offset[2], 'hours') .format('YYYY-MM-DD HH:mm'); } else { if (isNaN(offset[5])) { dateOffset = moment(new Date()) .subtract(offset[2], 'hours') .subtract(offset[4] + 0, 'minutes') .format('YYYY-MM-DD HH:mm'); endTimeOffset = moment(endTimeformat,'YYYY-MM-DD HH:mm') .subtract(offset[2], 'hours') .subtract(offset[4] + 0, 'minutes') .format('YYYY-MM-DD HH:mm'); } else { dateOffset = moment(new Date()) .subtract(offset[2], 'hours') .subtract(offset[4] + offset[5], 'minutes') .format('YYYY-MM-DD HH:mm'); endTimeOffset = moment(endTimeformat,'YYYY-MM-DD HH:mm') .subtract(offset[2], 'hours') .subtract(offset[4] + offset[5], 'minutes') .format('YYYY-MM-DD HH:mm'); } } dateOffset = dateOffset.replace(' ', 'T') + ':00.000Z'; endTimeOffset = endTimeOffset.replace(' ', 'T') + ':00.000Z'; } let pickupWindow:any; pickupWindow = { start: endTimeOffset, end: endTimeOffset, }; setLoading(true); FlyBuy.Core.Customer.getCurrentCustomer() .then((customerResult) => { FlyBuy.Core.Orders.createOrder({ siteId: sitId, pid: pid, customerInfo: CUSTOMER_INFO, pickupWindow: pickupWindow, orderState: OrderStateType.CREATED, pickupType: mode }).then((order) => { setLoading(false); setOrders(order); if(Platform.OS === "android") FlyBuy.Pickup.onPermissionChanged(); }).catch((e)=>{ // logError(EVENTNAME.SDK_ERROR,e,"getCurrentCustomer_createorder") setLoading(false); }); }) .catch((e) => { FlyBuy.Core.Customer.createCustomer(CUSTOMER_INFO).then( (customer) => { FlyBuy.Core.Orders.createOrder({ siteId: sitId, pid: pid, customerInfo: CUSTOMER_INFO, pickupWindow: pickupWindow, orderState: OrderStateType.CREATED, pickupType: mode }).then((order) => { setLoading(false); setOrders(order); if(Platform.OS === "android") FlyBuy.Pickup.onPermissionChanged(); }).catch((e)=>{ // logError(EVENTNAME.SDK_ERROR,e,"createCustomer_createorder") setLoading(false); }); }, ); }); fetchOrders(); }; const fetchOrders = async () => { FlyBuy.Core.Orders.fetchOrders() .then((orders) => { const filter = orders.find( (o) => o.partnerIdentifier === route?.params?.oloid, ); setOrders(filter); }) .catch((err) => { // logError(EVENTNAME.SDK_ERROR,err,"fetchOrders") setLoading(false); }); };
@addingama any thoughts?
@addingama Just following up on this once more, not quite sure what is happening here, but think it might be related to the wrapper.
Hi, @sangamivivek I can't do much with minimum reproduction repository.
If it's not happening on the sample app, then it's likely not the wrapper issue.
I don't see any updated status related to the changes that I requested.
Call the configure outside any react component
If this is happening on dev and it's not always reproduced, then there is a high chance the App.js is re-mounted and calling the configure again.
Please try create a release build and see if it's crashing or not.
Thanks @addingama We will try and let you know if any issues.
Hi @addingama and @mohanenm,
We have tested both approaches, testing in release build and calling the configure in index.js outside the react component. Unfortunately the error still persists.
To provide a clear overview of the issue. Initially the same codebase works perfectly with react-native-bildit-flybuy version 1.0.4 , however when upgrading to latest version 2.1.1 iOS works fine but android is throwing an error.
Here are the only Changes made in codebase to update the wrapper:
Added in android/app/build.gradle
implementation ("androidx.appcompat:appcompat:1.3.1") { version { strictly '1.3.1' } }
Added In Android Manifest.xml
android:fullBackupContent="false" tools:replace="android:allowBackup, android:usesCleartextTraffic, android:fullBackupContent"
Added Kotlin version in android /build.gradle
kotlinVersion = "1.6.0"
Please let me know if you require any additional information or if there are other steps we should consider to resolve this issue.
@addingama I recreated it in the development app. It is only happening to me when I select always authorized permissions though.
cc: @sangamivivek
I am only able to recreate it when android location permissions are set to “Allow all the time” and FlyBuy.Pickup.onPermissionChanged(); is called.
FlyBuy.Pickup.onPermissionChanged()
can be implemented when denying location permissions or allowing while-in-use permissions just fine, but breaks with “Allow all the time”. If I removeFlyBuy.Pickup.onPermissionChanged()
, allow all the time permissions work fine. Similar to @sangamivivek, I console.logged core.configure and confirmed it only gets called once.
Code snippet:
const createOrder = () => {
console.log(Platform.OS)
FlyBuy.Pickup.onPermissionChanged();
FlyBuy.Core.Orders.createOrder({
siteId: SITE_ID,
pid: NEW_PID.toString(),
customerInfo: CUSTOMER_INFO,
pickupType: PickupType.CURBSIDE
})
.then((order) => console.log('order', order))
.catch((err) => console.log(err));
};
@sangamivivek please try version 2.1.3
I've added small changes to prevent crashes
@addingama Thank you for the update. I've installed version 2.1.3, and so far, it's been working well without any crashes. We'll continue to monitor and conduct thorough QA testing. If we happen to come across any issues, we'll let you know. Thanks again! cc: @mohanenm
Describe the bug
Getting 'FlyBuyCore.configure called more than once' error on app start, eventhough we are calling it only once and also this error is inconsistent. versions: "react-native": "0.64.2", "react-native-bildit-flybuy": "2.1.1",
Screenshots
Config code snippet on App.tsx
useAsyncEffect(async () => { if (Platform.OS === 'ios') { FlyBuy.Core.configure(iosToken); } else { FlyBuy.Core.configure(androidToken); } FlyBuy.Pickup.configure(); }, []);