Custom UI Implementation for Web Search and RSS actions in SUSI iOS Using Kingfisher for Image Caching

The SUSI Server is an AI powered server which is capable of responding to intelligent answers based on user’s queries. The queries to the susi server are obtained either as a websearch using the application or as an RSS feed. Two of the actions are websearch and RSS. These actions as the name suggests respond to queries based on search results from the web which are rendered in the clients. In order to use use these action types and display them in the SUSI iOS client, we need to first parse the actions looking for these action types and then creating a custom UI for them to display them. To start with, we need to make send the query to the server to receive an intelligent response from the server. This response is parsed into different action types supported by the server and saved into relevant objects. Here, we check the action types by looping through the answers array containing the actions and based on that, we save the data for that action. if type == ActionType.rss.rawValue {    message.actionType = ActionType.rss.rawValue    message.rssData = RSSAction(data: data, actionObject: action) } else if type == ActionType.websearch.rawValue {    message.actionType = ActionType.websearch.rawValue    message.message = action[Client.ChatKeys.Query] as? String ?? "" } Here, we parsed the data response from the server and looked for the rss and websearch action type followed by which we saved the data we received from the server for each of the action types in their own objects. Next, when a message object is created, we insert it into the dataSource item by appending it and use the `insertItems(at: [IndexPath])` method of collection view to insert them into the views at a particular index. Before adding them, we need to create a Custom UI for them. This UI will consist of a Collection View which is scrollable in the horizontal direction inside a CollectionView Cell. To start with this, we create a new class called `WebsearchCollectionView` which will be a `UIView` consisting of a `UICollectionView`. We start by adding a collection view into the UIView inside the `init` method by overriding it. Declare a collection view using flow layout and scroll direction set to `horizontal`. Also, hide the scroll indicators and assign the delegate and datasource to `self`. Now to populate this collection view, we need to specify the number of items that will show up. For this, we make use of the `message` variable declared. We use the `websearchData` in case of websearch action and `rssData` otherwise. Now to specify the number of cells, we use the below method which returns the number of rss or websearch action objects and defaults to 0 such cells. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {     if let rssData = message?.rssData {         return rssData.count     } else if let webData = message?.websearchData {         return webData.count     }     return 0 } We display the title, description and image for each object for which we need to create a UI for the cells. Let’s start by creating…

Continue ReadingCustom UI Implementation for Web Search and RSS actions in SUSI iOS Using Kingfisher for Image Caching

Websearch and Link Preview support in SUSI iOS

The SUSI.AI server responds to API calls with answers to the queries made. These answers might contain an action, for example a web search, where the client needs to make a web search request to fetch different web pages based on the query. Thus, we need to add a link preview in the iOS Client for each such page extracting and displaying the title, description and a main image of the webpage. At first we make the API call adding the query to the query parameter and get the result from it. API Call: http://api.susi.ai/susi/chat.json?timezoneOffset=-330&q=amazon And get the following result: { "query": "amazon", "count": 1, "client_id": "aG9zdF8xMDguMTYyLjI0Ni43OQ==", "query_date": "2017-06-02T14:34:15.675Z", "answers": [ { "data": [{ "0": "amazon", "1": "amazon", "timezoneOffset": "-330" }], "metadata": { "count": 1 }, "actions": [{ "type": "answer", "expression": "I don't know how to answer this. Here is a web search result:" }, { "type": "websearch", "query": "amazon" }] }], "answer_date": "2017-06-02T14:34:15.773Z", "answer_time": 98, "language": "en", "session": { "identity": { "type": "host", "name": "108.162.246.79", "anonymous": true } } } After parsing this response, we first recognise the type of action that needs to be performed, here we get `websearch` which means we need to make a web search for the query. Here, we use `DuckDuckGo’s` API to get the result. API Call to DuckDuckGo: http://api.duckduckgo.com/?q=amazon&format=json I am adding just the first object of the required data since the API response is too long. Path: $.RelatedTopics[0] {  "Result": "<a href=\"https://duckduckgo.com/Amazon.com\">Amazon.com</a>Amazon.com, also called Amazon, is an American electronic commerce and cloud computing company...",  "Icon": { "URL": "https://duckduckgo.com/i/d404ba24.png", "Height": "", "Width": "" },  "FirstURL": "https://duckduckgo.com/Amazon.com",  "Text": "Amazon.com Amazon.com, also called Amazon, is an American electronic commerce and cloud computing company..." } For the link preview, we need an image logo, URL and a description for the same so, here we will use the `Icon.URL` and `Text` key. We have our own class to parse this data into an object. class WebsearchResult: NSObject {        var image: String = "no-image"    var info: String = "No data found"    var url: String = "https://duckduckgo.com/"    var query: String = ""        init(dictionary: [String:AnyObject]) {                if let relatedTopics = dictionary[Client.WebsearchKeys.RelatedTopics] as? [[String : AnyObject]] {                        if let icon = relatedTopics[0][Client.WebsearchKeys.Icon] as? [String : String] {                if let image = icon[Client.WebsearchKeys.Icon] {                    self.image = image                }            }                        if let url = relatedTopics[0][Client.WebsearchKeys.FirstURL] as? String {                self.url = url            }                        if let info = relatedTopics[0][Client.WebsearchKeys.Text] as? String {                self.info = info            }                        if let query = dictionary[Client.WebsearchKeys.Heading] as? String {                let string = query.lowercased().replacingOccurrences(of: " ", with: "+")                self.query = string            }           }       }    } We now have the data and only thing left is to display it in the UI. Within the Chat Bubble, we need to add a container view which will contain the image, and the text description.  let websearchContentView = UIView()        let searchImageView: UIImageView = {        let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))        imageView.contentMode = .scaleAspectFit        // Placeholder image assigned…

Continue ReadingWebsearch and Link Preview support in SUSI iOS