Unable to run media capabilities API in mobile devices - microsoft-teams

I am working with microsoftTeams.media.selectMedia(... API on clicking button getting
9000
OLD_PLATFORM
Platform code is outdated and does not implement this API.
Here I am iPhone Xr with Microsoft Version 3.20.0
TypeScript Code:
onFileSelected() {
microsoftTeams.initialize();
microsoftTeams.media.selectMedia(
this.mediaInput,
(
error: microsoftTeams.SdkError,
attachments: microsoftTeams.media.Media[]
) => {
if (error) {
if (error.message) {
alert(' ErrorCode: ' + error.errorCode + error.message);
} else {
alert(' ErrorCode: ' + error.errorCode);
}
}
if (attachments) {
this.y = attachments[0];
}
}
);
}
HTML Code:
<button
(click)="onFileSelected()"
class="btn-cm"
style="
color: #58ef47;
margin-top: 15px;
width: 150px;
height: 40px;
font-size: medium;
"
>
Select File
</button>
{{ "data:" + y?.mimeType + ";base64," + y?.preview }}
Note: I am running thins code in Angular App as a Task Module in Extension
But after several refreshes it shows the camera options that means it works
How I can improve this or there is some fix required from MS?

Please try moving microsoftTeams.initialize() when the page loaded and see if it works? You can also try setting up this sample and confirm if facing same in it - tab-device-permissions
The same question is answered here - https://github.com/OfficeDev/microsoft-teams-library-js/issues/799

Related

Reconnect issue when hiding and showing React WebChat using CSS

Currently, I'm using the React version of WebChat on my site. (https://github.com/Microsoft/BotFramework-WebChat)
I'm building a feature to hide and show the WebChat element on a page. When the page first loads, the WebChat shows. When clicking on top of the WebChat (.chatbot-top-pane), the WebChat minimizes (.chat-window hides). When clicking on the div again to maximize the window (show .chat-window), the WebChat shows then tries to reconnect to the server, but fails. Why does it try to reconnect? Did the session somehow end in the background and it's trying to resume using the same token?
I tried using display: none, visibility: hidden on .chat-window.
<div className="chatbot-container">
<div className="chatbot-top-pane" onClick={handleToggleStatus.bind(this)}>
<p className="chatbot-pane-label-text">Chatbot Disco</p>
</div>
<ReactWebChat className="chat-window" directLine={createDirectLine({ token })} />
</div>
Also, I tried wrapping the .chat-window with a div and tried hiding .chat-window-container, instead:
<div className="chatbot-container">
<div className="chatbot-top-pane" onClick={handleToggleStatus.bind(this)}>
<p className="chatbot-pane-label-text">Chatbot Disco</p>
</div>
<div className="chat-window-container">
<ReactWebChat className="chat-window" directLine={createDirectLine({ token })} />
</div>
</div>
Below is a screenshot of the error message displayed on the WebChat
Error message on WebChat
I tried the same thing on the iframe version of the WebChat and had no issue at all.
When Web Chat dismounts, it triggers the DIRECT_LINE/DISCONNECT action to fire which causes DirectLine to disconnect. However, looking over your code, I'm not sure why you would have an issue with that especially since your implementation looks similar to the Minimizable WebChat Sample and you are not dismounting the Web Chat component.
I put together a simplified version of the sample that seems to work fine.
Web Chat v4
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import ReactWebChat, { createDirectLine, createStore } from 'botframework-webchat';
import classNames from 'classnames';
const WebChat = () => {
const [token, setToken] = useState('');
const [minimized, setMinimized] = useState(false);
const directLine = useMemo(() => createDirectLine({ token }), [token]);
const store = useMemo(() => createStore(), []);
const toggleChatVisivility = useCallback(() => setMinimized(minimized => !minimized), [setMinimized]);
useEffect(() => {
(async function () {
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();
setToken(token);
})();
}, []);
return (
<React.Fragment>
<button onClick={toggleChatVisivility}>{minimized ? 'Show Chat' : 'Hide Chat'}</button>
<ReactWebChat className={classNames('webchat__chat-container', minimized ? 'webchat__hidden': 'webchat__visivle')} directLine={directLine} store={store} />
</React.Fragment>);
}
export default WebChat;
css
.webchat__chat-container {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.webchat__hidden {
visibility: hidden;
}
Screen capture
Hopefully the code snippets above help you figure out what's missing from your implementation. Sorry, I couldn't be more helpful. Let me know if you run into anymore questions. I'm happy to help answer them.

How to implement AutoComplete Text view in an adaptive card

I have a use case in which i have to show responses from an API to the user, as he types in the text view in the adaptive card, I have a Bot using Microsoft Bot Framework, my chat bot is currently working in a web client, but i want this functionality to also work on Microsoft Teams and other platforms (in which adaptive card is supported). Adaptive Card doesn't support AutoComplete view, its in there roadmap for now.
So here i am looking for a workaround to implement this functionality in my Bot.
If your main use case is Teams, then you have another option, but it will work only in Teams - it is to use a Task Module. Basically, Task Modules are a special kind of popup window in Teams. You have two options for what gets shown in a Task Module:
An Adaptive Card
Any custom web page, that is basically just being IFramed into the popup
So, you could look at using option 2 above, building anything you want into the web page, including "autocomplete". Later, if / when Adaptive Cards offers what you need, you could simply change out what gets shown to the user, from being your custom web page, to being the Adaptive Card.
You can read more about Task Modules, and how to get started, at What are Task Modules.
Of course, as I said, Task Modules only work in Teams, so it won't help your other scenarios, but perhaps you can use the regular Adaptive Cards there, and do the Task Module if you detect the client is using Microsoft Teams.
Although Adaptive Cards do not support autocomplete view as of now, instead of using Adaptive Cards, you can build our own component and use attachmentMiddleware to intercept those cards. You can add an input field with your autocomplete logic in your custom renderer.
Refer to this sample for the implementation of the above logic.
Code Sample:
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Custom attachment with GitHub Stargazers</title>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<script src="https://unpkg.com/react#16.8.6/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16.8.6/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-redux#7.1.0/dist/react-redux.min.js"></script>
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
<style>
html, body { height: 100% }
body { margin: 0 }
#webchat {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat" role="main"></div>
<script type="text/babel">
const GitHubRepositoryAttachment = props =>
<div style={{ fontFamily: '\'Calibri\', \'Helvetica Neue\', Arial, sans-serif', margin: 20, textAlign: 'center' }}>
<svg height="64" viewBox="0 0 16 16" version="1.1" width="64" aria-hidden="true"><path fillRule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg>
<p>
{ props.owner }/<br />{ props.repo }
</p>
</div>;
(async function () {
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();
const { ReactWebChat } = window.WebChat;
const attachmentMiddleware = () => next => card => {
switch (card.attachment.contentType) {
case 'application/vnd.microsoft.botframework.samples.github-repository':
return <GitHubRepositoryAttachment owner={ card.attachment.content.owner } repo={ card.attachment.content.repo } />;
default:
return next(card);
}
};
window.ReactDOM.render(
<ReactWebChat
attachmentMiddleware={ attachmentMiddleware }
directLine={ window.WebChat.createDirectLine({ token }) }
/>,
document.getElementById('webchat')
);
store.dispatch({
type: 'WEB_CHAT/SET_SEND_BOX',
payload: { text: 'sample:github-repository' }
});
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
</body>
</html>
Also, refer to this SO answer on Autocompletion with Botframework's Web Chat where you can add flexdatalist to WebChat's input field, but you also have to dispatch actions to WebChat's store to notify it of changes.
Hope this helps.

How to show the bot icon in the webchat?

I have an image for my bot, but it's not showing up in the webchat.
Is there any way to make it happen like the image in this link (https://cloud.githubusercontent.com/assets/979837/19395693/cbdf6ac2-91f3-11e6-8a48-ba533bf91dca.png) ?
My script for the bot is:
<script>
//Scrip for the webchat window
(function () {
var div = document.createElement("div");
document.getElementsByTagName('body')[0].appendChild(div);
div.outerHTML = "<div id='botDiv' style='height: 38px; position: fixed; bottom: 0; right: 1%; z-index: 1000; background-color: #fff'><div id='botTitleBar' style='height: 38px; width: 350px; position:fixed; cursor: pointer;'></div><iframe width='400px' height='600px' src='https://webchat.botframework.com/embed/xxx'></iframe></div>";
document.querySelector('body').addEventListener('click', function (e) {
e.target.matches = e.target.matches || e.target.msMatchesSelector;
if (e.target.matches('#botTitleBar')) {
var botDiv = document.querySelector('#botDiv');
botDiv.style.height = botDiv.style.height == '600px' ? '38px' : '600px';
};
});
}());
</script>
I would recommend you step away from the webchat channel iFrame option and utilize the BotFramework-WebChat tool, instead. The webchat channel is fine for simple deployments, but it isn't overly robust out-of-the-bot.
If you look over sample 04.b.display-user-bot-images-styling from the BotFramework-WebChat repo, you will see precisely how you can effect the bot/user avatars.
In short, you will include the web chat CDN into you html file, assign some basic styling for the web chat div, followed by the script that connects to and generates that actual web chat experience.
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Avatar with images and initials</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--
For demonstration purposes, we are using the development branch of Web Chat at "/master/webchat.js".
When you are using Web Chat for production, you should use the latest stable release at "/latest/webchat.js",
or lock down on a specific version with the following format: "/4.1.0/webchat.js".
-->
<script src="https://cdn.botframework.com/botframework-webchat/master/webchat.js"></script>
<style>
html, body { height: 100% }
body { margin: 0 }
#webchat {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat" role="main"></div>
<script>
(async function () {
// In this demo, we are using Direct Line token from MockBot.
// To talk to your bot, you should use the token exchanged using your Direct Line secret.
// You should never put the Direct Line secret in the browser or client app.
// https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();
const styleOptions = {
botAvatarImage: 'https://learn.microsoft.com/en-us/azure/bot-service/v4sdk/media/logo_bot.svg?view=azure-bot-service-4.0',
botAvatarInitials: 'BF',
userAvatarImage: 'https://github.com/compulim.png?size=64',
userAvatarInitials: 'WC'
};
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
styleOptions
}, document.getElementById('webchat'));
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
</body>
</html>
This option does require generating a direct line token. This is accomplished by passing your direct line secret to the direct line /tokens/generate api and receiving a token back. The generated token is tied to the particular session so, as such, provides a certain level of security. Please don't use your secret in this setting.
The below is a node.js example and can be run as an independent app or incorporated into your existing bot as a separate api call made while the html page / web chat is loading. It wouldn't be hard to recreate an equivalent dotnet version.
server.post('/directline/token', (req, res) => {
// userId must start with `dl_`
const userId = (req.body && req.body.id) ? req.body.id : `dl_${Date.now() + Math.random().toString(36) }`;
const options = {
method: 'POST',
uri: 'https://directline.botframework.com/v3/directline/tokens/generate',
headers: {
'Authorization': `Bearer ${process.env.directLineSecret}`
},
json: {
User: {
Id: userId
}
}
};
request.post(options, (error, response, body) => {
if (!error && response.statusCode < 300) {
res.send({
token: body.token
});
} else {
res.status(500).send('Call to retrieve token from DirectLine failed');
}
});
});
Hope of help!

React render image from prop

I am trying to pass an image url to the children and then require it as follows:
import React, {Component} from 'react';
let color = require('../../css/colors.js');
let defaultStyle = {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexBasis: 'calc(50% - 40px)',
flexDirection: 'column',
margin: '20px',
backgroundColor: color.blueCard
}
class Card extends Component {
render() {
const imgUrl = require(this.props.background);
return (<div style={{
...defaultStyle
}}>
<img src={imgUrl} alt="img"/>
</div>);
}
}
export default Card;
this.props.background looks something like this: "../../img/album1.jpg"
When im starting the React App i get the following error message on const imgUrl = require(this.props.background);:
Error: Cannot find module "."
webpackMissingModule
The React App was created using create-react-app. My guess is that webpack cant parse the resource file.
**Parent Component**
<InputSection ref="inputS" ImD={this.getData} imageUri={require(this.state.imageurl)} />
**Child Component**
<img ref="image" src={this.props.imageUri} />
try this, I think it will work.
Does not need the require in this case, You can simply get the props which you're passing from the Parent component.
for ex :
<Card background={your_value}/>
then in Card component
const imgUrl = this.props.background;

Inline support Chat implementation

We are creating a live chat support system. Currently if the visitor clicks on live chat button, a new window opens up and user can talk their. What I am trying to accomplish is to open the chat window inline like this link:
http://anantgarg.com/chat/sampleb.php
Please note that we are building support chat system not peer chat system as the above link intends.
The problem we are facing here is that how we'll be able to access the database which is located on different server (our server) and not on the server where our client's website is located. The above solution can work fine if we are on the same server.
So, please suggest on how to overcome this hurdle.
Thanks.
I think, for solve your task you may use WebSockets, it support cross-domain connections.
In your case, you may write chat client side and place it on cliet's website, but request from it weill processed by your server with DB access.
Extend
Of course you can use JSON with WebSockets just as JSON with AJAX. WebSockets is transport - JSON is content passed with this transport.
I write this code when reserarch WebSockets (chat lietn side):
function connect(){
var socket;
var host = window.location.host;
var wsUrl = "ws://" + host + "/connect";
try{
var socket = new WebSocket(wsUrl);
message('<p class="event">Socket Status: '+socket.readyState);
socket.onopen = function(){
message('<p class="event">Socket Status: '+socket.readyState+' (open)');
//Run "Ping-Pong" for support connection
setTimeout(pingPong, 5000);
}
socket.onmessage = function(msg){
//Parse server answer from string to JSON object
var answer = JSON.parse(msg.data);
if (answer.type == 'message') {
message('<p class="message">'+answer.user+': '+answer.message);
}
}
socket.onclose = function(){
message('<p class="event">Socket Status: '+socket.readyState+' (Closed)');
}
} catch(exception){
message('<p>Error'+exception);
}
function send(){
var text = $('#text').val();
if(text==""){
message('<p class="warning">Please enter a message');
return ;
}
try{
//Send data via JSON
socket.send('{"type": "message", "message":'+JSON.stringify(text)+'}');
} catch(exception){
message('<p class="warning">');
}
$('#text').val("");
}
var token = 0;
function pingPong()
{
token++;
try{
var msg = {'type': 'ping', 'token': token};
socket.send(JSON.stringify(msg));
setTimeout(pingPong, 5000);
} catch(exception){
message('<p class="warning">');
}
}
function message(msg){
$('#chatLog').append(msg+'</p>');
}//End message()
$('#text').keypress(function(event) {
if (event.keyCode == '13') {
send();
}
});
$('#disconnect').click(function(){
socket.close();
});
}
$(document).ready(function() {
if(!("WebSocket" in window)){
$('#chatLog, input, button, #examples').fadeOut("fast");
$('<p>Oh no, you need a browser that supports WebSockets. How about Google Chrome?</p>').appendTo('#container');
}else{
//The user has WebSockets
connect();
}
});
</script>
<meta charset=utf-8 />
<style type="text/css">
body{font-family:Arial, Helvetica, sans-serif;}
#container{
border:5px solid grey;
width:800px;
margin:0 auto;
padding:10px;
}
#chatLog{
padding:5px;
border:1px solid black;
}
#chatLog p{margin:0;}
.event{color:#999;}
.warning{
font-weight:bold;
color:#CCC;
}
</style>
<title>WebSockets Client</title>
</head>
<body>
<div id="wrapper">
<div id="container">
<h1>WebSockets Client</h1>
<div id="chatLog">
</div>
<p id="examples">e.g. try 'hi', 'name', 'age', 'today'</p>
<input id="text" type="text" />
<button id="disconnect">Disconnect</button>
</div>
</div>
</body>
</html>​
Also you can use SocketIO library for it, but I dont sure for it cross-domain work.

Resources