Thursday, August 3, 2017

Realtime native apps made easy with Fuse tools and Phoenix Channels

Share it Please

Elixir’s Phoenix framework is an ideal choice for building real-time applications and Fuse tools is even easier for building native mobile apps.


In this tutorial i'll show how to build an app using Elixir's Phoenix framework channels and Fuse tools.We won't worry about persistance or authentication.


Installation and Setup


This tutorial will assume the following language and framework versions:


  • Erlang 19.0
  • Elixir 1.4
  • Phoenix 1.2
  • Fuse 1.0

If you need to insall Erlang, Elixir and Fuse tools, i recommend checking out their websites.


To install Phoenix Framework and its dependencies, follow the Phoenix installation docs. Once you are able to install Phoenix withIn the same file, we’ll also need to uncomment line 5, which I’ll explain next:



$ mix archive.install https://github.com/phoenixframework/archives/raw/master/phoenix_new.ez

you should be ready to proceed.


Create New Phoenix App


I'will call it "MessageGram", and create it with



$ mix phoenix.new message_gram

When asked “Fetch and install dependencies?” enter “Y”. Finally, when the new app is generated, you should see the following message:


```
We are all set! Run your Phoenix application:


$ cd message_gram
$ mix phoenix.server

Before moving on, configure your database in config/de.exs and run:


$ mix ecto.create 

```
Next, we’ll need to modify the default MessageGram.UserSocket module. In the same file, we’ll also need to uncomment line 5, which I’ll explain next:


```


Channels


channel "room:*", MessageGram.RoomChannel
```


Of course, our MessageGram.RoomChannel module doesn’t exist yet. Let’s fix that


```
defmodule MessageGram.RoomChannel do
use MessageGram.Web, :channel
def join("room:lobby", payload, socket) do
{:ok, socket}
end


def join("room:" <> _private_room_id, _params, _socket) do
    {:error, %{reason: "Unauthorized"}}
end

def handle_in("new_msg", %{"message" => message, "at" => at}, socket) do
    broadcast! socket, "new_msg", %{message: message, at: at}
    {:noreply,  socket}
end

def handle_out("new_msg", payload, socket) do
    push socket, "new_msg", payload
    {:noreply, socket}
end

end


```


It's finally time to write our Fuse app.


First we'll need the Phoenix Channel javascript client to enable our Fuse app communicate with our Phoenix realtime backend. Since the client that comes with Phoenix by default is written in Es6, we'll need an Es5 version because Fuse tools only support Es5.
Go ahead and download a Phoenix Channel javascript client Es5 version


We are all set! Create our Fuse app:



$ fuse create app MessageGram


Let's add the phoenix-common.js file to the root of our app and modify our MessageGram.unproj file:


```
{
"RootNamespace":"",
"Packages": [
"Fuse",
"FuseJS"
],
"Includes": [
"*",
"phoenix-common.js:Bundle",
]
}


```
This will bundle the phoenix javascript client with our app to enable us use require("phoenix-common") in our ux file.


Lets build our message app in our MainView.ux file:


```


var Observable = require("FuseJS/Observable");
var messages= Observable();
var txt = Observable("");
var Phoenix = require("phoenix-common");
var channel = null;

var socket = new Phoenix.Socket("ws://localhost:4000/socket",{params: {userToken: "123"}})

fetch("http://localhost:4000", {
    method: "get"
}).then(function(resp) {

        socket.connect();

}).catch(function(err) {
    console.log("Error connecting to server")
})


channel = socket.channel("products:lobby", {});
channel.on("new_msg", function(payload) {
    console.log("Main mesage: "+payload.message)

    messages.add(payload)
})
channel.join().receive("ok", function(resp) {
    console.log("Joined successfully")
}).receive("error", function(resp) {
    return console.log("Unable to join", resp)
})

function sendClick() {
    channel.push("new_msg", {message: txt.value, at: new Date().toDateString()})
    txt.value = ""

} 

module.exports = {
    sendClick,
    txt,
    messages
};

</JavaScript>
<Panel Background="#183f">
<Grid Rows="1*,1*">
    <ScrollView>
        <StackPanel ItemSpacing="10">
            <Each Items="{messages}">
                <StackPanel Orientation="Horizontal" ItemSpacing="5">
                    <Text TextColor="White" Value="{message}"/>

                    <Text TextColor="White" Value="{at}"/>
               </StackPanel>
            </Each>
        </StackPanel>
    </ScrollView>
    <StackPanel HitTestMode="LocalBoundsAndChildren">
        <TextInput PlaceholderText="text" PlaceholderColor="#ffffff80" TextColor="White" Width="250" Value="{txt}" />
         <Rectangle Color="#127799" Height="40" Margin="20" Width="100" CornerRadius="80">
          <Text  Value="Send" Alignment="Center" TextColor="White" Clicked="{sendClick}"/>
        </Rectangle>
    </StackPanel>
</Grid>



```
Then run our app with:



$ fuse preview

And that’s it! We can test this by opening our app in multiple browser tabs to simulate multiple users talking to each other in real-time and with our fuse native app.

No comments:

Post a Comment

Powered By Aleme Gabriel