I used cordova-sms-plugin 0.1.11 "Cordova SMS Plugin" for my ionic2 app to send text message. I just wanted to simply open the default SMS app on user's device. Below is my code:
public sendSMS(phoneNumber){
var option = {
replaceLineBreaks: false,
android: {
intent: 'INTENT'
},
ios: {
intent: 'INTENT'
}
};
SMS.send(phoneNumber, "", option)
.then(()=>{
//this.showAlert("Message sent!", "");
alert("Message sent");
}, (err)=>{
console.log("sms fail:"+err);
})
}
The code works as expected to open the SMS app on user's device. However, on the opened SMS, my users need to tap on the recipient to make the "soft keyboard" to show up and users can no longer use the functions the sms provided (like attaching photos).
Plus, users could only send one message, and the sms app closed itself and "redirect" back to my app.
If users quit my app and open their SMS app independently, the SMS app works fine again.
I don't know what I did wrong on my code. Or is there any better cordova plugin I can use that fulfills my purpose?
Thank you for your help in advance :-)
This cordova plugin (cordova-sms-plugin) is better to be used if you want to send text messages from the "backend". e.g. Design your own text message box, send button...
If you just want to open the default SMS app use the code below:
import { DomSanitizer } from '#angular/platform-browser';
then add the service to constructor:
constructor(private sanitizer:DomSanitizer)
Then the method to call:
public sanitize(url: string):any {
return this.sanitizer.bypassSecurityTrustUrl(url);
}
the method: return type use any. Some said use SafeUrl, but somehow the new service doesn't have that.
Html view:
<a [href]="sanitize('sms:' + item.sms)">
Related
I'm developing a personal trading card DB in Ember.JS with a Laravel 8 REST API... for fun? Currently working on a page to add cards to my DB in bulk. The user will select what deck they want to add cards to and the respective deck's card checklist will be displayed, where I can select what cards will be added. I'm stuck on displaying the appropriate card's for their respective deck.
I'm using the ember package Service
import { inject as service } from '#ember/service';
...
#service store;
Inside my controller, I'm calling an action that will update the variable/displayed cards.
#action updateModel() {
let x = this.store.query('card', {
year: {
eq : yearVar
}
});
...
}
This is the error info:
Uncaught (in promise)
Object { message: "Aborted",
name: "AbortError",
stack: "exports.DOMException#http://10.0.0.0:4200/assets/vendor.js:49690:28\nfetch/WHATWGFetch</xhr.onabort/<#http://10.0.0.0:4200/assets/vendor.js:49730:22\nsetTimeout handler*fetch/WHATWGFetch</xhr.onabort#http://10.0.0.0:4200/assets/vendor.js:49729:23\nEventHandlerNonNull*fetch/WHATWGFetch<#http://10.0.0.0:4200/assets/vendor.js:49728:11\ninitializePromise#http://10.0.0.0:4200/assets/vendor.js:47175:15\nPromise#http://10.0.0.0:4200/assets/vendor.js:47631:35\nfetch#http://10.0.0.0:4200/assets/vendor.js:49697:16\nexports.default#http://10.0.0.0:4200/assets/vendor.js:49801:30\n_fetchRequest#http://10.0.0.0:4200/assets/vendor.js:52788:16\najax#http://10.0.0.0:4200/assets/vendor.js:52753:35\nquery#http://10.0.0.0:4200/assets/vendor.js:52361:19\n_query/promise<#http://10.0.0.0:4200/assets/vendor.js:71800:61\ninvokeCallback#http://10.0.0.0:4200/assets/vendor.js:47150:17\nthen/<#http://10.0.0.0:4200/assets/vendor.js:47207:40\n#http://10.0.0.0:4200/assets/vendor.js:42711:62\ninvoke#http://10.0.0.0:4200/assets/vendor.js:41296:16\nflush#http://10.0.0.0:4200/assets/vendor.js:41211:19\nflush#http://10.0.0.0:4200/assets/vendor.js:41374:21\n_end#http://10.0.0.0:4200/assets/vendor.js:41815:34\nBackburner/this._boundAutorunEnd#http://10.0.0.0:4200/assets/vendor.js:41539:14\npromise callback*buildNext/<#http://10.0.0.0:4200/assets/vendor.js:41040:35\nflush#http://10.0.0.0:4200/assets/vendor.js:26782:5\n_scheduleAutorun#http://10.0.0.0:4200/assets/vendor.js:41981:14\n_ensureInstance#http://10.0.0.0:4200/assets/vendor.js:41972:14\nschedule#http://10.0.0.0:4200/assets/vendor.js:41665:19\n#http://10.0.0.0:4200/assets/vendor.js:42711:28\nthen#http://10.0.0.0:4200/assets/vendor.js:47207:14\n_query#http://10.0.0.0:4200/assets/vendor.js:71800:42\nquery#http://10.0.0.0:4200/assets/vendor.js:72905:32\nupdateModel#http://10.0.0.0:4200/assets/cam-card-comp.js:607:18\nEventListener.handleEvent*addEventListener#http://10.0.0.0:4200/assets/vendor.js:39057:15\ninstall#http://10.0.0.0:4200/assets/vendor.js:39194:23\ncommit/tag<#http://10.0.0.0:4200/assets/vendor.js:36926:25\ntrack#http://10.0.0.0:4200/assets/vendor.js:40488:7\ncommit#http://10.0.0.0:4200/assets/vendor.js:36924:42\ncommit#http://10.0.0.0:4200/assets/vendor.js:36999:19\ninTransaction#http://10.0.0.0:4200/assets/vendor.js:37019:13\n_renderRoots#http://10.0.0.0:4200/assets/vendor.js:6446:36\n_renderRootsTransaction#http://10.0.0.0:4200/assets/vendor.js:6490:14\n_renderRoot#http://10.0.0.0:4200/assets/vendor.js:6435:12\n_appendDefinition#http://10.0.0.0:4200/assets/vendor.js:6360:12\nappendOutletView#http://10.0.0.0:4200/assets/vendor.js:6350:12\ninvoke#http://10.0.0.0:4200/assets/vendor.js:41298:16\nflush#http://10.0.0.0:4200/assets/vendor.js:41211:19\nflush#http://10.0.0.0:4200/assets/vendor.js:41374:21\n_end#http://10.0.0.0:4200/assets/vendor.js:41815:34\nBackburner/this._boundAutorunEnd#http://10.0.0.0:4200/assets/vendor.js:41539:14\npromise callback*buildNext/<#http://10.0.0.0:4200/assets/vendor.js:41040:35\nflush#http://10.0.0.0:4200/assets/vendor.js:26782:5\n_scheduleAutorun#http://10.0.0.0:4200/assets/vendor.js:41981:14\n_end#http://10.0.0.0:4200/assets/vendor.js:41821:18\nBackburner/this._boundAutorunEnd#http://10.0.0.0:4200/assets/vendor.js:41539:14\npromise callback*buildNext/<#http://10.0.0.0:4200/assets/vendor.js:41040:35\nflush#http://10.0.0.0:4200/assets/vendor.js:26782:5\n_scheduleAutorun#http://10.0.0.0:4200/assets/vendor.js:41981:14\n_end#http://10.0.0.0:4200/assets/vendor.js:41821:18\nBackburner/this._boundAutorunEnd#http://10.0.0.0:4200/assets/vendor.js:41539:14\npromise callback*buildNext/<#http://10.0.0.0:4200/assets/vendor.js:41040:35\nflush#http://10.0.0.0:4200/assets/vendor.js:26782:5\n_scheduleAutorun#http://10.0.0.0:4200/assets/vendor.js:41981:14\n" }
vendor.js:41829:18
I checked the URL the ember app was sending to the API, it is as follows, and it's correct:
http:10.0.0.0:4000/cards?year[eq]=2022
Took this URL and pasted it into my browser, it successfully returned the appropriate checklist. This tells me I'm creating the query correctly and sending it correctly. Mozilla Firefox's inspector shows the network GET request was BLOCKED, and I'm given the EmberJS error.
if request is blocked it could be CORS problem (by default it accept only same origin but in you case fornt-end served on 4200 and api on 4000), in laravel 8 check config/cors.php and allow all origines * something like this <?phpreturn['paths'=>['api/*'],'allowed_methods'=>['*'],'allowed_origins'=>['*'],'allowed_origins_patterns'=>[],'allowed_headers'=>['*'],'exposed_headers'=>false,'max_age'=>false,'supports_credentials'=>false,];
I am trying to get a very simple Unity application (Unity Version 2019.4.20f1 Personal) to authenticate with Facebook's SDK for unity. I have set up a local HTTPS server (with self-signed certificates) using Django & Gunicorn (Yes, not ideal, but just trying this out first), which serves the build products of Unity's WebGL.
Here is my one and only script in unity:
public class FacebookHelper : MonoBehaviour
{
// Awake function from Unity's MonoBehavior
void Awake ()
{
if (!FB.IsInitialized) {
// Initialize the Facebook SDK
FB.Init(InitCallback, OnHideUnity);
} else {
// Already initialized, signal an app activation App Event
FB.ActivateApp();
}
}
private void InitCallback ()
{
if (FB.IsInitialized) {
// Signal an app activation App Event
FB.ActivateApp();
// Continue with Facebook SDK
// ...
} else {
Debug.Log("Failed to Initialize the Facebook SDK");
}
}
private void OnHideUnity (bool isGameShown)
{
if (!isGameShown) {
// Pause the game - we will need to hide
Time.timeScale = 0;
} else {
// Resume the game - we're getting focus again
Time.timeScale = 1;
}
}
public void Login() {
var perms = new List<string>(){"public_profile", "email"};
FB.LogInWithReadPermissions(perms, this.AuthCallback);
}
public void Logout() {
FB.LogOut();
Debug.Log("User logged out.");
}
public void AuthCallback (ILoginResult result) {
if (FB.IsLoggedIn) {
// AccessToken class will have session details
var aToken = Facebook.Unity.AccessToken.CurrentAccessToken;
// Print current access token's User ID
Debug.Log("UserID: " + aToken.UserId);
// Print current access token's granted permissions
foreach (string perm in aToken.Permissions) {
Debug.Log("Permission: " + perm);
}
} else {
Debug.Log("User cancelled login");
}
}
}
where the Login() and Logout functions are called respectively when the two buttons below are pressed:
In Chrome, I have two issues:
I am getting CORS and CORB errors, notably only on the Logout() action, and not on the Login action.
For the Login() action, the Login Dialog is problematic because it opens a new tab as per usual, but it never allows me to input my login details before immediately closing this new tab. For some reason, my logging statements still say that FacebookSDK has successfully logged in.
In an attempt to solve this, I have
Enabled CORS on my Django application, according to instructions here. Sadly, this didn't work.
On the Facebook platform, I have done all these, to no avail as well:
Added localhost to the App Domain
Enabled Allow Cross Domain Share Redirects
Added https://localhost:8080 as the Website
Added https://localhost:8080 as a valid OAuth redirect uri to the 'Facebook Login for Gaming' Product
However, in Safari, I met with none of the aforementioned problems. The login flow works fine.
EDIT:
However, something I encountered on both Chrome and Safari is that for some reason, when the SDK is initialized, it always automatically signs in a default user. For now, I will just add some code to sign out at initialize time to remedy this.
As usual, spent quite a while on this but wasn't able to figure out how I can solve this. According to my understanding, I have to make sure the responses to my server have the Access-Control-Allow-Origin header, and these may be some ways I think I can do it:
Somehow make FacebookSDK set the Access-Control-Allow-Origin header on the response? Maybe their GraphQL API will be more helpful?
Use Nginx to reverse proxy and serve the static files instead, and then I should be able to do something like adding the Access-Control-Allow-Origin header as well. I have thought of doing this but it'll take a bit of investigation, so I haven't tried this yet.
For the CORB issues, I don't really have any ideas though.
I really appreciate it if anyone has taken the time to read up till here, but anyways, thank you to anyone who can help at all! :)
EDIT 1:
Here is the request/response for Safari:
And here are the request/response for Chrome:
The observations I can make is that for some reason Facebook is not returning the Access-Control-Allow-Origin in the response for the Chrome request. Maybe it is due to the additional headers in the Chrome request?
You need to use a third library or do that in Chrome itself but it's prerence dependent
pip install django-cors-headers
So in Settings:
INSTALLED_APPS = (
...
'corsheaders',
...
)
MIDDLEWARE_CLASSES = (
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
)
Or check out his docs for more details https://github.com/adamchainz/django-cors-headers#setup
Based on the online example I wanted to try to add Rich Response Buttons and Basic cards using Dialogflow Fulfillment and Inline editor, but I'm not getting anything rendered in the Dialogflow Messenger client. Are rich responses not fully supported?
According to the readme file, the Dialogflow Fulfillment library is no longer being maintained; therefore, it seems that you can't use rich response in Dialogflow messenger directly with this library.
Based on this, if you want to use rich responses with Dialogflow messenger, you can create a webhook service. To start testing this, I recommend you do the following:
1- Use Cloud Functions to create an HTTP function. This documentation mentions the process to create one from the Cloud Console. Please take in account this considerations in the second step:
Runtime: Python 3.8
Entry point: entry_function
Inside the inline editor, copy and paste the following code:
from flask import jsonify
def entry_function(request):
response_json = jsonify(
fulfillment_text="This message is from Dialogflow's testing!",
fulfillment_messages=[
{
"payload": {
"richContent": [[{
"actionLink": "https://assistant.google.com/",
"subtitle": "This is the body text of a card. You can even use line\n breaks and emoji! 💁",
"title": "Title: this is a card title",
"type": "info"
}]]
}
}
]
)
return response_json
Deploy the function. Afther that, enter to your function and in the 'TRIGGER' section copy the Trigger URL
2- Enable and manage fulfillment in Dialogflow
3- Test your Dialogflow messenger.
We have an Outlook Add-In which runs in OWA.
The Manifest sits on https://company.ourdomain.com
The Javascript sits on https://company.ourdomain.com
The Custom Web Service we wrote in-house sits on https://company.ourdomain.com
When I make a call from within JavaScript in response to an Add-In Command, I use the format https://company.ourdomain.com/api/Controller/Action in the ajax call.
I end up getting one of those CORS errors (sometimes it's pre-flight, other times CORB). Why am I getting this if the Javascript is literally sitting on the same domain as the web service?
I'm assuming I'm authenticated since I've logged into my Outlook account.
What gives?
NOTE:
As an experiment I attempted a RESTful call by directly typing in the URL (No OWA involved). This caused the code to Authenticate against Azure AD. Then afterward I logged into OWA in the same browser session and everything worked fine. Do I actually need to authenticate within the Javascript even if the webservice I'm calling is in the same domain?
AJAX CALL WHICH GENERATES ERROR
Remember, it will work just fine after I've made a RESTful call by making a call to my web service directly from the Browser
var apiUri = '/api/People/ShowRecord';
$.ajax({
url: apiUri,
type: 'POST',
data: JSON.stringify(serviceRequest),
contentType: 'application/json; charset=utf-8',
dataType: 'json'
}).done(function (response) {
if (!response.isError) {
// response to successful call
}
else {
// ...
}
}).fail(function (status) {
// some other response
}).always(function () {
console.log("Completed");
});
OBSERVATION
When I call the api from the Address Bar the code below is run. This code never gets invoked by Javascript
[assembly: OwinStartup(typeof(EEWService.AuthStartup))]
namespace EEWService
{
public partial class AuthStartup
{
public void Configuration(IAppBuilder app)
{ app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Notifications = new WsFederationAuthenticationNotifications
{
RedirectToIdentityProvider = (context) =>
{
context.ProtocolMessage.Whr = "ourdomain.com";
return Task.FromResult(0);
}
},
MetadataAddress = ConfigurationManager.AppSettings["ida:MetadataAddress"],
Wtrealm = ConfigurationManager.AppSettings["ida:Audience"],
TokenValidationParameters = new TokenValidationParameters
{
ValidAudiences = new string[] { $"spn:{ConfigurationManager.AppSettings["ida:Audience"]}" }
}
});
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
},
MetadataAddress = ConfigurationManager.AppSettings["ida:MetadataAddress"],
});
}
}
}
There are a few problems with this I think.
The first one is you are trying to serve your static content off the same server you are serving your code from. This is in general considered a bad-practice, purely because no point in wasting those precious server resources for static content. Ideally you should upload your static content to a CDN - and let the users' browser make a request to some super-cached file server. However - I understand this option might not be available to you as of now. This also isn't the root cause.
The second and the real problem is, (you think you are but) you are not authenticated. Authentication in Outlook web-addins doesn't come by default, it's something you need to handle. When Outlook loads your web add-in into the side panel it makes certain methods available to you which you can use and kind-of create a pseudo-identity (as an example Office.context.mailbox.userProfile.emailAddress ) - but if you want real authentication, you will need to do that yourself.
There are three ways of doing that as far as I can tell.
The first one is through the Exchange Identity Token
Second one is through the Single Sign On feature
The third one - which I think is the most convenient and the simplest in logic to implement is using WebSockets. (SignalR might be what you need).
When the user loads your first page, make sure a JS value like window.Unique_ID available to them. This will come in handy.
Have a button in your UI - which reads "Authenticate"
When the user clicks to this button, you pop them out to a url which will redirect to your authentication URL. (Something like https://company.ourdomain.com/redirToAuth). This would save you the trouble of getting blocked in the side-panel, because you are using window.open with a url that's on your domain. Pass that Unique_ID to redirection which then redirects you to OAuth login URL. That should look like https://login.microsoftonline.com/......&state=Unique_ID
Right after popping the user to sign in window, in your main JS (which is client-side), you open a web-socket to your server, again with that Unique_ID and start listening.
When the user completes authentication, the OAuth flow should post back either an access token, or the code. If you get the access token, you can send it through the sockets to front-end (using the Unique_ID which is in the parameters of post-back) or if you had the code, you finish authenticating the user with a server-to-server call and pass the access token the same way afterwards. So you use that unique Id to track the socket that user connected from and relay access token to only that user.
I am making a real-time webapp using Django. Django does all the heavy lifting. To make the app real-time, when a change is made in Django, it is published to redis. I then set up a node.js app that marshals the data from redis to socket.io.
So right now things look like this.
Django -> Redis -> Node.js -> Socket.IO -> Browser
I'm OK with using redis and think it is great. I looked into gevent-socketio but it is not what I am looking for. Is there a way to do:
Django -> Redis -> Socket.IO -> Browser?
Redis and socket.io don't communicate directly.. you need server in between, especially if You use websockets, long-polling etc.
You can use django-socketio.
What you have done is similar to Trello:
http://blog.fogcreek.com/the-trello-tech-stack/
We started a project called bus.io on npm. It should help you. It simplifies connecting sockets to a pub sub and distributing messages to them.
On the server.
var express = require('express')
var app = express();
app.use(express.static(__dirname+'/public'));
var server = require('http').Server(app).listen(3000);
var bus = require('bus.io')(server);
On the client.
<script type="text/javascript src="/bus.io/bus.io.js">
var sock = io.connect();
sock.on('connect', function () {
sock.message().action('say').content('hello').deliver();
});
sock.on('say', function (msg) {
console.log(msg.content());
});
</script>
This example demonstrates building a message and delivering it to the server. By default the message will loop back to the sender. A "sender" is an actor and by default a sender will send a message to itself. You can customize the actor and target. So for instance you wanted to send a message to everyone.
On the server you could add this to force all your messages to go to everyone.
sock.in(function (msg, sock, next) {
msg.target('everyone').deliver();
});
Or on the client.
sock.message().target('everyone').action('say').content('hello').deliver();
There is a shorthand too.
sock.message({target:'everyone', action:'say', content:'hello'}).deliver();
You can also change how the actor is assigned, by default it is the socket.id.
bus.actor(function (sock, cb) {
//so if you had a session you could get the user name from the session
cb(null, sock.handshake.session.user);
});
Messages are automatically propagated from the client to other clients through the bus. The bus is built ontop of redis and socket.io.
If you have any questions or would like some help contact checkout our http://turbonetix.io or the project on github https://github.com/turbonetix/bus.io.git