How to implement XEP-0333 in iOS Application? - swift

I am developing one chat app in that i need to show message status like WhatsApp app for that i have tried XEP-0333(Chat Marker) but facing issue Like.
1) After getting Received Marker from other end XMPPMessage Archive not updated message with Received Marker (In Core data, message chat marker status not updated).
2) How to implement Displayed Marker logic? (means for each message we need to send displayed marker or for only one dialog at once.)
XEP Link : XEP-0333
Code:
//(Sender Part)
let completeMessage = DDXMLElement.element(withName: "message") as! DDXMLElement //(In that i have set id,body,to and type as chat)
let msgObj = XMPPMessage(from: completeMessage)
msgObj?.addMarkableChatMarker()
xmppStream?.send(msgObj)
//(Receiver Part)
didReceivedMessage - Method
//*Check One condition*
if message.isChatMessageWithBody() && message.isErrorMessage() == false {
if (message.hasChatMarker() == true){
printLog("Message ID\(message.elementID())")
let msgElement = XMPPMessageMng.getChatMessageElement(recipient: message.from().bare(), thread: "")
let threadElement = DDXMLElement.element(withName: "thread") as! DDXMLElement
threadElement.stringValue = "Thread"
msgElement.addChild(threadElement)
let msgReceived = XMPPMessage(from: msgElement)
msgReceived?.addReceivedChatMarker(withID: message.elementID())
xmppStream.send(msgReceived)
}
}
else{
if (message.hasMarkableChatMarker() == true){
printLog("Chat Marker ID\(message.chatMarkerID())")
}else if (message.hasReceivedChatMarker() == true){
printLog("Chat Marker ID\(message.chatMarkerID())")
}
}
//For Display Marker I have done below things.
- When you load message from message archive with JID.
loadArchivedMessagesFromJID - Method
//message as XMPPMessageArchiving_Message_CoreDataObject
let msgReceived = XMPPMessage(from: msgElement)
msgReceived?.addDisplayedChatMarker(withID: message.message.elementID())
xmppStream.send(msgReceived)
Let me know in which right way we can implement Chat marker protocol.
Dev Tools : Xcode 8.3(Swift 3.0) ,
Server : ejabberd

ejabberd still doesn't support xep-0333
here's the link for supported XEP:
Protocols Supported by ejabberd

Related

How to request App Ratings with requestReview() correctly

I am currently learning how to ask the user for an AppStore rating in the app. I have read through numerous documentations and reports from Apple and other bloggers, but I still have questions:
I thought that I want to display my request after the user has completed a sequence of actions 3 times. But if the user doesn't want to rate my app right now, can I ask him to rate my app again later? I also read that Apple controls when and how often the review request is displayed (up to 3x / year)
My app has different functions. Therefore it is not guaranteed that the user accesses exactly this function, where I want to show the rating view. Is it therefore possible to call up the rating request at different points in the app and simply leave it up to Apple whether the rating request is also displayed?
Best regards
Edit for #K bakalov :
enum AppReviewRequest {
#AppStorage("runCountSinceLastRequest") static var runCountSinceLastRequest = 0
#AppStorage("lastVersion") static var lastVersion = ""
static let threshold = 4
static let currentVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String
static func countUpRequestReview() {
if currentVersion != lastVersion {
if runCountSinceLastRequest < threshold - 1 {
runCountSinceLastRequest += 1
print(runCountSinceLastRequest)
}
}
}
static func requestReviewIfNeeded() {
if currentVersion != lastVersion {
if runCountSinceLastRequest == threshold {
if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
SKStoreReviewController.requestReview(in: scene)
lastVersion = currentVersion
runCountSinceLastRequest = 0
}
}
}
}
}
I assume you already read that but if you haven't I am leaving a link for you to check it out: https://developer.apple.com/documentation/storekit/requesting_app_store_reviews
It contains helpful information and guides when and how to prompt the user to leave a review.
Back to your questions.
Yes, you can ask again for review but there is no guarantee that the Review pop-up (alert) will be presented again. It is usually delayed in time and sometimes requires a new update of the app to trigger a new review prompt; That is correct, Apple has control over it but I don't know if its limited to only 3 times a year.
Yes, you can call it as many times as you want and wherever you find it suitable. Although, I highly encourage you to read (if still haven't) the link above. You need to think of a non-intrusive way to ask for review, otherwise you risk the user to dismiss the prompt, even if they like the app.
Just an advice, many apps use an approach with a custom popup "Do you like the app? Yes/No", if "Yes" then request a review using requestReview() call. And/or as mentioned in the article above, you can always use a manual review by redirecting to the AppStore, if you need it as a result of a CTA (tap on a button for example).

How capture the facebook fbclid and forward it to the client with a button click

We're testing a new tracking method and want to pass the Facebook fbclid on to the client.
Just to be clear...
The user clicks the Facebook ad,
They land on our page
They click a button and are taken to the client
How can we capture the fbclid and forward it on to the client when the user clicks the button on our page?
I added the following code. Which included adding a class to the link. Will check to see if it works.
let anchors = document.getElementsByClassName("marketingAnchor")
Array.from(anchors).forEach(element => {
let currentURL = new URL(window.location.href)
let AnchorHref = element.getAttribute('href')
let tmpURLObj = new URL(AnchorHref)
let fbclidParam = currentURL.searchParams.get("fbclid")
if (AnchorHref == null || fbclidParam == null) return;
tmpURLObj.searchParams.set('fbclid', fbclidParam);
element.setAttribute('href', tmpURLObj.href)
});</script>

How to set local notification content to be the same as the content presented in the home screen when opened? [SWIFT]

I am trying to recreate an existing motivational quote app as practice.
On this app, you get a notification which displays the contents, and if you click it the home page provides you with the rest of the quote (screenshots below). I have seen this type of app a lot – they all use collection views and the notification and homepage content always match.
I have tried mimicking this by setting up local notifications for the next 7 days to provide the user with a random quote from my array:
func configureNotifications() {
let shuffled = quotes.shuffled()
for i in 1...7 {
let content = UNMutableNotificationContent()
content.title = “Daily quotes”
content.body = shuffled[i].text
let alertDate = Date().byAdding(days: i) // scheduled for next 7 days added
var alertComponents = Calendar.current.dateComponents([.day, .month, .year], from: alertDate)
alertComponents.hour = 10
Etc
}
func updateQuoteHome() {
guard let selectedQuote = quotes.randomElement() else {
fatalError("Unable to read a quote.")
}
updateLabels(with: selectedQuote)
}
However, once the notification is clicked, or if the user just randomly opens the app, the content displayed is obviously completely different.
What is the method to link these two together – is it even possible with local notification or are these apps utilising push notifications?
Is there something about this in the documentation?
Thank you ~
You should use Push Notifications for this feature. If you have little or no backend experience you can use Firebase Functions and Firebase Messaging to achieve this.

How to get the closest beaon in Ionic 3

currently I’m working with iBeacons and by far have managed to scan and display them on screen. But then I was told to scan and display for ONLY the nearest one ( the closest one), and ignore all the others. Can someone give me a rough idea how to get the closest beacon among a bunch of beacons that I have?
I believe that I can’t use the Proximity and Accuracy in this case since they often fluctuate.
Basically I haven't figured out how to work with the logic:
onBeaconsDiscovered() {
this.delegate.didRangeBeaconsInRegion().subscribe( data => {
if (data.beacons !== null) {
let nearestBeacon = // { code for detecting the nearest beacon }
// then show up a notification / alert / toast ...
}
});
}
Please help! I appreciate every idea.
You can see my answer on how to do this in native Swift code here : Swift find closest Beacon by rssi
Here is a direct translation of that Swift code into JavaScript:
var closestBeacon = null;
for (var beacon in data.beacons) {
if (beacon.rssi < 0 && closestBeacon != null && beacon.rssi > closestBeacon.rssi) {
closestBeacon = beacon;
}
}
Keep in mind that the this.delegate.didRangeBeaconsInRegion().subscribe( data => { callback will happen once per second. So if you want to issue an alert based upon the closest beacon, you also need to take care not to to pop up new alerts every single second.
If you want to keep track of beacons you have already handled, you can declare a new object in some global-like scope outside the callback:
var triggeredBeacons = {};
Then before you do any processing on a beacon, construct a string key based on your beacon identifiers, and make sure it has not triggered before:
var beaconIdentifiers = beacon.uuid + " " + beacon.major + " " + beacon.minor;
if (triggeredBeacons[beaconIdentifiers] == true) {
// beacon has already triggered. Ignore it
}
else {
triggeredBeacons[beaconIdentifiers] = true;
// Put your beacon processing here
}

Soundcloud API Get current track name without widget

Is it possible via the SoundCloud API to get the current playing trackname ? Via the widget it's ok but it will be better (UX point of view) if I could without.
I found nobody mention it, if you have an idea, you're welcome !
Thx
I'm currently looking to do the same thing. Seems that the only way to do it via the API is to use what they call "activities" : https://developers.soundcloud.com/docs/api/reference#activities
So you can have a list of all activities made by a user, which includes the listening of a track. But I assume the activity will appear in the list only once the music has been played, not while the music plays.
Has anyone already used that functionnality ?
Regards,
Seb
I coded this litlle script that bind DOM's updates but it's very tricky.
// Bind new song on the soundcloud player
$('.playbackSoundBadge').bind('DOMSubtreeModified', function(e){
track_info = e.target;
if(track_info.className.indexOf('sc-media-image') > -1){
thumb = track_info.querySelector('span');
if(thumb != null){
splitted_url = track_info.href.split(/\//);
playing.artist = splitted_url[3];
playing.trackname = splitted_url[4];
thumb = track_info.querySelector('span');
playing.thumbnail = standardizeThumb(thumb.style.backgroundImage);
toaster(playing);
}
}
});
// Toast factory
function toaster(playing){
// Is there already a toast ?
toast = document.getElementById('sc-toast');
if(toast == null){
toast = document.createElement('div');
toast.id = 'sc-toast';
document.body.appendChild(toast);
}else{
toast.innerHTML = '';
}
// Build our toast
thumb = document.createElement('img');
thumb.src = playing.thumbnail;
toast.appendChild(thumb);
wrapper = document.createElement('div');
wrapper.className = 'wrapper-text';
playing.artist = standardizeString(playing.artist);
playing.trackname = standardizeString(playing.trackname);
artist = document.createElement('h1');
artist.innerHTML = playing.artist;
trackname = document.createElement('h2');
trackname.innerHTML = playing.trackname;
wrapper.appendChild(artist);
wrapper.appendChild(trackname);
toast.appendChild(wrapper);
}