Expo notification click to action - javascript

I can't seem to find a solution when I get a push notification and click on it redirects me to a screen, chat, etc. link to push notification.
I would also like to add a square image to the side and could not find an answer.
The push notifications are sent from a NodeJS server I looked at the docs and search the internet and I did not find anything of interest.
https://docs.expo.dev/versions/latest/sdk/notifications/#managing-notification-categories-interactive-notifications
https://github.com/expo/expo-server-sdk-node
Thank you in advance for your answers ❤️

I'm not quite sure about the square image, but in order to handle redirects you can look at this documentation from expo: https://docs.expo.dev/push-notifications/receiving-notifications/.
You can then pass the data you need for your redirect (i.e. notification_type, relevant id etc) via the data property on your message (this will need to be done wherever the message is created, which from your question is from the node api):
messages.push({
to: pushToken,
body: 'This is a test notification',
data: { notification_type: 'something', id: 'something_else' },
});
It is then up to you to decide how to handle that message based on the extra data you have provided.
For example, taking the code provided in the link above as an example, you could have a handle function as follows:
_handleNotification = response => {
const data = response.notification.request.content;
if (data.type === "new_message") {
// navigate to MessageScreen with data.id as param
} else {
// do something else based on the type or...
}
};

Related

XMPP - How do I delete all messages between two jids, but only for one user?

Problem:
I want to delete all the messages (and thread) from one side of an equation between two users, A and B. I have no idea if this is even possible and if so, how.
I have the:
jid of each user
an XMPP library in JS (custom) that allows me to send IQ or any other type of stanza.
For example, this is how I get my friends (roster) list:
async getFriends() {
const requestId = this.sendStanza(
'iq',
{ type: 'get' },
(stanza) => stanza.c('query', { xmlns: 'jabber:iq:roster' }),
)
const result = await this.once('*', requestId);
const requests = result.children[0].children.map(child => child.attrs.jid);
return requests;
}
Hopefully this is enough for someone to advise me. Thanks.
If you have full access to the client logic, you can implement your own logic, for instance, you can send an IQ stanza with a specific name space (xmlns) along with some elements/attributes, when the receiving side receives that IQ, it will do whatever logic you want (delete messages, thread, etc..)
Check this out:
https://xmpp.org/extensions/xep-0424.html
it is an extension to delete (retract) single message.

Node-Craigslist syntax for details

Hello I am using the package node-craigslist https://github.com/brozeph/node-craigslist, and am hoping that someone can help me with some syntax with the details method.
In his documentation, he gives the example
client
.list()
.then((listings) => client.details(listings[0]))
.then((details) => {
console.log(details);
})
.catch((err) => {
console.error(err);
});
I currently have working the code to get the listings, but not the details. Below is my section of code where I retrieve the listings.
client
.list(options)
.then((listings) => {
listings.forEach((listing) => {
console.log(listing);
searchResults.title[counter] = listing.title;
searchResults.date[counter] = listing.date;
searchResults.location[counter] = listing.location;
searchResults.url[counter] = listing.url;
searchResults.price[counter] = listing.price;
counter++;
if(counter === listings.length) {
socket.emit('redirect'); //change to /results.ejs if done looping
};
});//end of listings foreach
});
I have been trying to incorporate the details into my own code unsuccessfully. Does anybody have any knowledge on how I can do this? Thanks.
You need to pass in a listing object into the method. In his example, he just grabs the most recent listings without any search options, then passes in the first listing from that array of listings. But you could obviously customize the search and the options.
client
.list()
.then((listings) => client.details(listings[0]))
.then((details) => {
console.log(details);
})
.catch((err) => {
console.error(err);
});
Depending on how the rest of your code is structured, you need to determine when to pass a specific listing. In my app that I built with this package, I make the initial search request that returns all the listings, and then when the user clicks on a listing for a search term, I make another request passing along that specific listing OBJECT and then it returns the details.
To be even more specific ...
On the client side the user searches, I emit that to the server then make the search request.
Once the request is finished I emit the results back to the client and then display the information to the user and store each listing object inside a custom data attribute inside each listing for later use.
Once the user clicks on a specific listing, I grab the object from the data-attribute and emit that to the server.
The server listens for that and makes the second DETAILS request using that listing object which is then emitted back to the clients browser.

What is the correct way to listen to nested changes using Firebase?

Background:
I'm trying to send SMS messages via the browser using Firebase, Twilio, and Node.js. My current data structure in Firebase looks like this:
{ messages :
{ +15553485 :
{ FB-GENERATED-KEY-1 :
{ body: "hello world"
timestamp: 1461758765472 }
},
{ FB-GENERATED-KEY-3 :
{ body: "I love dogs"
timestamp: 1461758765475 }
}
}
},
{ +15550000 :
{ FB-GENERATED-KEY-2 :
{ body: "goodbye world"
timestamp: 1461758765473 }
},
{ FB-GENERATED-KEY-4 :
{ body: "I love cats"
timestamp: 1461758765476 }
}
}
}
}
When a message is added to Firebase via the frontend the backend needs to get notified in order to send an SMS via Twilio. When the backend gets a reply from the phone (via Twilio), it adds it to Firebase.
Problems:
When I listen for changes to a thread I receive all messages sent/recieved for that phone number. Obviously the backend doesn't want to send all the messages again, so I'm only interested in the most recent message added to the thread.
Also I can't seem to easily get the phone number (the key) that has messages underneath it.
What I've tried:
ref.child('messages').on('child_added', ...) — this works for new phone numbers that are added at /messages, however Firebase doesn't send through the new phone number (key), only everything from FB-GENERATED-KEY-2 down.
ref.child('messages').on('child_changed', ...) — this returns all of the messages in a thread, not only the new ones. I can sort on the server and find the most recent message, but that seems like it'll get heavy quite quickly – what if you've sent thousands of messages?
Storing messages at the root level (aka. flattening the tree) and storing the number as an attribute instead could work, but I'm going to need to use the phone number as a sort of index to connect with other data later (like a foreign key).
Questions:
How can I only get the most recent message when listening to activity on the parent /messages and not a particular phone number?
How can I get the key (phone number) when using a child_ event?
Does this data structure make sense?
You can get the Firebase key by calling key() on the snapshot returned by your child_added listener.
Then you can add another nested listener like this:
ref.child('messages').on('child_added', function (snapshot) {
var phone = snapshot.key();
ref.child('messages').child(phone).on('child_added', function (message) {
//send SMS
}, function (error) {
});
}, function (error) {
});
The Firebase API allows you to listen for changes in value or for operations on children. It does not have a way to listen for changes in grandchildren.
In NoSQL databases you often need to model the data for the way your application uses it. If I look at your specific use-case:
When a message is added to Firebase via the frontend the backend needs to get notified in order to send an SMS via Twilio.
I see a queue here:
smsQueue: {
pushId1: {
number: "+15553485",
body: "hello world",
timestamp: 1461758765472
},
pushId2: {
number: "+15550000",
body: "goodbye world",
timestamp: 1461758765473
},
pushId3: {
number: "+15553485",
body: "I love dogs",
timestamp: 1461758765475
},
pushId4: {
number: "+15550000",
body: "I love cats",
timestamp: 1461758765476
}
}
With this structure your back-end (which hopefully uses firebase-queue) can take each task from the queue, call twilio and delete the item from the queue.

Can I relabel the person.noun for Profile object type in Facebook Open Graph?

I have created a Story using Open Graph and the object I want to use is called Service, which is really just a Profile but I want the text in the post to say 'service' rather than 'person' (which it does now). I have tried creating a custom object but it seems overly complicated for what I need so I have 2 questions:
Can I create a custom type that simply inherits from Profile that can be created in the same way (using the FB.api javascript method)? I don't want to have to use self-hosted types..
Can I simply re-label person.noun from 'person' to 'service' somehow? I can't see a way to do that..
My code to post the story is:
FB.login(function (response) {
if (response.authResponse) {
var strmessage = 'Some message';
var profileid = 'xxxxxxxxx;
var opts = {
profile: profileid,
message: strmessage,
no_feed_story: false,
'fb:explicitly_shared': true
};
FB.api('https://graph.facebook.com/me/mynamespace:myaction', 'post', opts, function (response) {
if (!response || response.error) {
Result("Your message has not been posted");
}
else {
//Message has been posted
Result("Your message has been posted");
}
});
You're going to have to do the custom object if you want a custom name. And, you're going to have to do it on the FB Developer site and go through the whole approval process and all that. And no, there is no way to do any sort of inherence on this.
FB's Open Graph is pretty simple if you use the built in actions and objects, but as soon as you go down the road of wanting custom names for stuff, you are going to have to go all in with it.
I finally put the time aside to implement a custom action and type. It wasn't the most intuitive process but I got there in the end and my app is now approved and doing exactly what I wanted it to do. I'm actually glad I put myself through this learning process as custom stories have great potential and I'm sure I'll find other applications for them in the future.

Ember.js: Save record to Ember.Data, wait for response before displaying

I'm building an app which allows users to post to Twitter. When they click the submit button we close the posting form. We create a Message object which is saved to the data store and sent to the server. The server creates a Post object, then submits a request to Twitter. The server then updates the Post object, replies back to the UI with the updated information.
That part is already working. But I need to know if it's NOT working so that I can alert the user that their message did not go through and keep the posting form open. Here's some pertinent information about my app.
Social.Message = DS.Model.extend({
text: DS.attr("string"),
created: DS.attr("date"),
isPending: DS.attr("boolean"),
posts: DS.hasMany("Social.Post")
});
Social.Post = DS.Model.extend({
text: DS.attr("string"),
status: DS.attr("string"),
created: DS.attr("date"),
message: DS.belongsTo("Social.Message"),
msgStatus: function() {
return ((this.get('status') === 'S') ? true : false);
}.property('status')
});
The lifecycle of a post (status) goes from P (pending) to Q (queued) to S (sent), E (error) is also a possibility, and the status that I'm really looking for. Here's the saveMessage method:
saveMessage: function(text){
var acct = Social.Account.find(this.get("id")),
msg = Social.store.createRecord(
Social.Message,
{
text: text,
created: new Date()
}
);
acct.get("messages").addObject(msg);
Social.store.commit();
Ember.run.later(this, function() {
msg.get('posts').forEach(function(p){
p.reload();
});
}, 1000);
}
You can see that I pause for a second to let the server process, then attempt to reload the Post object with the response from Twitter. Those last few lines are where I think this new code would go, but I'm not sure how to listen to something that might not come back. I'd rather not "wait" for a second, instead it would be nice if the message could just update. Not sure how to accomplish that though.
Thoughts?
You need to run your code as a callback after the record is created. This is how:
msg.one('didCreate', function() {
// transition to new route showing data just created
});
Social.store.commit();
This will add a one time call on the record for when it is created. There are also 'didUpdate' and 'didDelete' hooks as well. You need to add these callbacks before the create is called (obviously).
I'm not sure how to handle the error condition as I haven't looked into that yet.
Edit: this is actually broken, per https://github.com/emberjs/data/issues/405, so waiting may be the only option currently.
It sounds like you don't want the two-way data binding here and you might benefit from one-way instead. Here is a great full length blog post that explains it a bit more in depth
http://www.solitr.com/blog/2012/06/ember-input-field-with-save-button/

Categories