In this post we will discuss the message model of SUSI.AI webclient and how youtube autoplay features selectively autoplays only the last played song from youtube. The answer or response to any query to susi is send by server in json format, which is just a raw form of data which is then used by webclient to create the message in desired form in different action types. Every response to a query is given in an array of action types with each element in the array is a snippet of HTML codes. This array is called the messageListItem. This messageListItem array is further, a part of a bigger array which contains all the codes for the query, answer and date elements. This array is called the messageListItems. This contains the final code block of all the messages displayed on the web client. All this is handled by two files MessageListItem.js and MessageSection.js and we will discuss their working below in detail.
MessageSection.js
The MessageSection.js file creates the final array which contains the code of the complete section with the date, queries and responses. this section slices the raw data from the server into smaller snippets which contain either a single query or response. This snippet is then send to MessageListItem.js which takes this raw data and creates the corresponding in HTML codes which are then send back to MessageSection.js which finally push this codeblock into the MessageListItems array.
let messageListItems = []; if (this.state.search) { let markID = this.state.searchState.scrollID; let markedMessages = this.state.searchState.markedMsgs; messageListItems = getMessageListItem(markedMessages, false, markID); } else { messageListItems = getMessageListItem( this.state.messages, this.state.showLoading, ); }
From the code block above, the messageListItems array is initialised by an empty array and then getMessageListItem is called which creates and return the new array with all necessary code.
The getMessageListItem() function maps the raw data and sends one array element at a time to the MessageListItem.js to create the corresponding message and then push back the data into the final array. From below code we can see that it also slice the Latest message from the list and verifies each time whether the message is the last on in the array or not. Whenever the message is not the lastest one, it sends false as a parameter and sends true otherwise.
let latestMessage = messages[messages.length - 1]; // return the list of messages return messages.map(message => { if (message !== latestMessage) { return ( < MessageListItem key = { message.id } message = { message } latestUserMsgID = { latestUserMsgID } latestMessage = { false } /> ); } return ( < MessageListItem key = { message.id } message = { message } latestUserMsgID = { latestUserMsgID } latestMessage = { true } /> ); });
MessageListItem.js
The MessageListItem components which basically creates every message takes in four parameters as argument. These are
- message
- markID
- latestMessage
- LatestUserMsgID
The message parameter contains the raw message data object and the markID is the Id assigned to every message used during the search message feature. The parameter latestUserMsgID assigns a unique id which is provided by the server itself which helps in giving selective feedback for the answers. The latestMessage parameter is a boolean type parameter used to identify the last message and is used in autoplay feature discussed below.
The message object has a key named action which is an array of the action types required for our message. For example, for the response to a video play query the message aoject has two action types, answer and video_play. The first action type displays the text message and the later type plays the video. Every element of the MessageListItem is governed by the rules of different action types.
Youtube autoplay
The autoplay feature for youtube videos is implemented such that only the last played video is autoplayed whenever we open chat.susi.ai and other just simply loads and wait for user action to play them. Whenever the action type video_play is called, an iframe is created using the react-youtube library using the following code
case 'video_play': { let identifier = data.answers[0].actions[index].identifier; < section className = { messageContainerClasses } > < YouTube videoId = { identifier } opts = { opts } onReady = { this._onReady } />
The code contains the Youtube tag from react-youtube library with three paramters.
- VideoId contains the unique id given to every youtube video.
- opts which contains the options which youtube provides us including autoplay.
- onReady is the function called when the video loads completely in our brower and is ready to be played.
The opts variable whose value remains constant for a particular message is defined using const type and uses a unary statement to check whether the message is latest or not.
const opts = { height: this.state.height, width: this.state.width, playerVars: { autoplay: this.props.latestMessage ? 1 : 0, }, };
Whenever the prop latestMessage is true, the autoplay variable in player variables has value 1 which corresponds to yes and is 0 otherwise. This regulates when a video will play automatically or not.
Resources
- react-youtube – https://www.npmjs.com/package/react-youtube
- prop types – https://www.npmjs.com/package/prop-types
- MessageSection – https://github.com/fossasia/chat.susi.ai/blob/master/src/components/ChatApp/MessageSection/MessageSection.react.js
- MessageListItem – https://github.com/fossasia/chat.susi.ai/blob/master/src/components/ChatApp/MessageListItem/MessageListItem.react.js