Cancel one day of a regularly scheduled notification in Expo - react-native

I have a notification that users receive daily. It's supposed to be a reminder. However, users need to skip notifications ocasionally,
I am triggering these expo notifications using
Notifications.scheduleNotificationAsync({
content: {
title,
body,
data,
categoryIdentifier,
},
trigger: {
channelId,
hour: reminderTime.getHours(),
minute: reminderTime.getMinutes(),
repeats: true,
}
})
Is there a way to disable the notification temporarily say for a day? Right Now I am just deleting the channel and resetting it after that day. But I am assuming there is a better way?

maybe if you create an exception list and validate before sending the notification.
exception = "01/07/2022"
if (new Date() == new Date(exception)){
return console.log("[NOTIFICATIONS] - exception found")
}
// normal post

Related

How to remove a specific notification forever using react-native-push-notification

I am currently using the react-native-push-notification library to schedule and receive notifications in my React Native app. I am able to cancel a scheduled notification using the cancelLocalNotification method, but this only cancels the notification for 24 hours. I want to find a way to remove a specific notification forever, so it will not be rescheduled.
I have tried using the following code to cancel a notification by its ID, but it only cancels it for 24 hours:
const onCancelNotification = async (id: string) => {
// Get a list of all scheduled notifications
PushNotification.getScheduledLocalNotifications((notifications) => {
// Iterate through the list of notifications
notifications.forEach((notification) => {
// Check if the notification is the one you want to cancel
if (notification.id.indexOf(id) === 0) {
// Cancel the notification
PushNotification.cancelLocalNotification(notification.id);
}
});
});
};
I would greatly appreciate any help or suggestions on how to achieve this.
This code snippet demonstrates a workaround for removing a specific scheduled local notification in React Native. The function onRemoveNotification takes in an id parameter, which is used to identify the specific notification that needs to be removed.
It's important to note that there is no direct method for removing a specific scheduled local notification in React Native. This code provides a workaround that can be used, but it's important to be aware that it relies on scheduling a notification with an earlier date and setting the repeatType to undefined.
Please note that this code is not a perfect solution and could have side effects on the app.
const onRemoveNotification = async (id: string) => {
// Get a list of all scheduled notifications
PushNotification.getScheduledLocalNotifications((notifications) => {
// Iterate through the list of notifications
notifications.forEach((notification) => {
// Check if the notification is the one you want to cancel
if (notification.data.notificationId?.indexOf(id) === 0) {
// Create a new date one day earlier than the current scheduled date
const earlyDate = moment(notification.date).add(-1, "day").toDate();
// remove the notification
// schedule the notification with an earlier date and repeat type undefined
// this will effectively "remove" the notification
// since it will not be displayed
PushNotification.localNotificationSchedule({
id: notification.id,
title: notification.title,
message: notification.message,
repeatType: undefined,
date: earlyDate,
});
// cancel the previous scheduled notification
PushNotification.cancelLocalNotification(notification.id);
}
});
});
};

Expo Calendar Creating and Tracking Events

I am having a seriously tough time figuring out how to effectively manage events created with .createEventAsync() method in expo-calendar API. Docs found here. This is the structure of the parameter I am entering into .createEventAsync().
testEvent = {
calendarId: calendarId,
title: event.position,
startDate: shiftStart,
endDate: shiftEnd,
location: event.store.name,
alarms: [],
id: event.id,
}
The idea is to have the event id on the app calendar be the same as the id on the OS calendar, but it seems like that is not possible. I am trying to build a system that requests permissions, if permissions granted then sync all events on the app with the os calendar. If the event already exists, do not create another event.
The function runs a check with:
async function checkEventExists(eventId: any) {
try {
const event = await Calendar.getEventAsync(eventId)
console.log(console.log(event))
if (event) {
return true
}
} catch {
return false
}
}
If false, event is not created. If true then .createEventAsync() is called.
Currently, new instances of the same event are created every time the app polls data from the server and this is unrelated, but also creates 7 instances of 1 event each time data is polled. How do people usually manage and track calendar events after creation? I thought event id would be a good way to tell if the event is one and the same, but I was wrong.

Expo Notifications repeats after a specified date

Im trying to schedule a daily notification with expo notifications. I need to fire this notification from a specified date in the future. So it will be for example: schedule the notification on 20 days in the future and from there fire it daily until cancelled. How can't find anything in the documentation on how to do this. Does anyone have an idea?
You can set a starting date like this:
await Notifications.scheduleNotificationAsync({
content: {
title,
body,
sound: true,
vibrate: [0, 255, 255, 255],
},
trigger: {
date: "your-date"
},
});
Later on you can switch on repeats like this:
trigger: {
repeats: true //or false
},
I'm not sure what you mean by fire until cancelled. Should the user specifically cancel the notification or is som state variable changing? Either way, I think you can add repeats: true or false depending on any variable.
Hope this helps!

Expo in app purchases for React Native — how to tell if subscription is current / active?

Current app is Expo for React Native which is ejected to the bare workflow.
Using expo-in-app-purchases for IAP.
How can you tell if a subscription is active or not?
When I grab the purchase history via:
const { results } = InAppPurchases.connectAsync();
if you look at the results, a result returns the following fields:
purchaseTime
transactionReceipt
orderId
productId
acknowledged
originalPurchaseTime
originalOrderId
purchaseState
Now purchaseState is always an integer. I'm mostly seeing 3 (I think I've seen a 1 one time...) Not sure this actually tells me anything valuable as they are all 3s
Short of manually taking the most recent purchase and adding 30 days (this is a monthly subscription) then seeing if this date is in the past, I'm not sure how to find if current user has active subscription. Help!
Thanks in advance!
Apple gives you the receipt as a signed and base64-encoded string. In order to see the contents of the receipt (including the 'expires at' date), you need to send this receipt to Apple's receipt verification endpoint along with your app-specific password.
More info here: https://developer.apple.com/documentation/storekit/in-app_purchase/validating_receipts_with_the_app_store
A function similar to this worked for me. This retrieves the receipt info as a JSON object and inside there is expires_at_ms, which can be compared to today's date to see if the subscription has expired.
async validateAppleReceipt(receipt) {
const prodURL = 'https://buy.itunes.apple.com/verifyReceipt'
const stagingURL = 'https://sandbox.itunes.apple.com/verifyReceipt'
const appSecret = '1234...'
const payload = {
"receipt-data": receipt,
"password": appSecret,
"exclude-old-transactions": true,
}
// First, try to validate against production
const prodRes = await axios.post(prodURL, payload)
// If status is 21007, fall back to sandbox
if (prodRes.data && prodRes.data.status === 21007) {
const sandboxRes = await axios.post(stagingURL, payload)
return sandboxRes.data.latest_receipt_info[0]
}
// Otherwise, return the prod data!
return prodRes.data.latest_receipt_info[0]
}
Have you tried to use
const { responseCode, results } = await getPurchaseHistoryAsync(true);

Push Notifications. How to know if the app was in foreground or background

When a notification arrives the app executes the callback configured for receiving the notifications.
In case the notification arrives with the app in background I want the application to move to a specific view. But if the notification arrives with the app in foreground I just want to print an alert.
How can I know in the callback function the status of the application when the notification arrived?
Thank you.
I don't know how dependable this is, but it seems to work when the app is running, but just in the background:
var sleeping = false;
document.addEventListener("pause", function() {sleeping = true;}, false);
document.addEventListener("resume", function() {sleeping = false;}, false);
and then:
function pushNotificationReceived(props, payload) {
if (sleeping) {
alert("caught me napping");
} else {
alert("I've been waiting for you.");
}
}
The tricky case is when the application is completely stopped. You need to log in before the notification callback gets called, and the resume event is fired long before this. If you want to handle that case, you will probably need something like the following in your WL.Client.Push.onReadyToSubscribe function:
sleeping = true;
setTimeout(function(){sleeping = false;}, 1000);
(anything that arrives within 1 second of being ready to subscribe, probably arrived when we were asleep, and is just getting delivered now)
It is a bit of a haCk, and I'm sure there are all sorts of odd timing cases but it seems to cover many of the cases.