braverhealth / phoenix-socket-dart

Cross-platform and stream-based implementation of Phoenix Sockets
https://pub.dev/packages/phoenix_socket
BSD 3-Clause "New" or "Revised" License
74 stars 37 forks source link

Can't join the channel? #9

Closed freewebwithme closed 3 years ago

freewebwithme commented 3 years ago

Hi I am experimenting this package to connect socket and join a channel

    var _socket = PhoenixSocket(
      wsEndpoint, // "ws://localhost:4000/socket/websocket"
      socketOptions: PhoenixSocketOptions(
        params: {"token": token},
      ),
    );
    _socket.connect().then((socket) {
      print("Connect _socket success? ${_socket.isConnected}");
      var topic = "cart:$userId";
      var channel = socket.addChannel(topic: topic);
      print("Join Channel success? ${channel.isJoined}");
    });

I can see that socket is connected. but I can't join my channel. I tried using wscat

> ["1","1","cart:1","phx_join", {}]
< ["1","1","cart:1","phx_reply",{"response":{},"status":"ok"}]

Am I missing something?

matehat commented 3 years ago

Yes, you need to add that step before the print statement (assuming you make the enclosing function async):

await channel.join().future

Until you call .join(), nothing is sent to the backend with regards to joining the channel.

freewebwithme commented 3 years ago

Oh I see. then

var pushResponse = await channel.join().future;
print("Channel payload: ${pushResponse.response}");

that prints empty {} I send message from server like this

broadcast(socket, "cart", %{carts: carts, total_items: total_items, total_price: total_price})
matehat commented 3 years ago

You probably need to

broadcast(socket, "cart:1", %{carts: carts, total_items: total_items, total_price: total_price})
freewebwithme commented 3 years ago

Thanks and Sorry for bothering But I did exactly what you told me. But response map is still empty.

  def join("cart:" <> user_id, _params, %{assigns: %{current_user: user}} = socket) do
    # check if current user match client user
    IO.puts("Printing user_id #{user_id}")

    if String.to_integer(user_id) == user.id do
      # If authorized, return cart information
      {carts, total_items, total_price} = CartResolver.get_updated_carts(user.id)
      IO.puts("Cart channel join successful")

      socket =
        assign(socket, :carts, carts)
        |> assign(:total_items, total_items)
        |> assign(:total_price, total_price)
        |> assign(:user_id, user_id)

      send(self(), :send_cart)

      # {:ok, %{carts: carts, total_items: total_items, total_price: total_price}, socket}
      {:ok, socket}
    else
      {:error, %{reason: "unauthenticated"}}
    end
  end

  def join("cart:" <> _user_id, _params, _socket) do
    IO.puts("Can't join a channel")
    {:error, %{reason: "unauthenticated"}}
  end

  def handle_info(
        :send_cart,
        socket = %{
          assigns: %{
            carts: carts,
            total_items: total_items,
            total_price: total_price,
            user_id: user_id
          }
        }
      ) do

    broadcast!(socket, "cart:" <> user_id, %{
      carts: carts,
      total_items: total_items,
      total_price: total_price
    })

    {:noreply, socket}
  end

This is elixir code. If I broadcast! there is no response. It is {} But in the web client. It receives response from channel

this is flutter code

    var _socket = PhoenixSocket(
      wsEndpoint,
      socketOptions: PhoenixSocketOptions(
        params: {"token": token},
      ),
    );
    _socket.connect().then((socket) async {
      print("Connect _socket success? ${socket.isConnected}");
      var topic = "cart:$userId";
      print("Topic: $topic");

      var channel = socket.addChannel(topic: topic);
      channel.join().future.then((pushResponse) {
        print("Join Channel success? ${channel.isJoined}");
        print("Join response: ${pushResponse.response}");
      });

if I send reply like this {:ok, %{carts: carts, total_items: total_items, total_price: total_price}, socket} from join/3 I get a response in pushResponse.response What am I missing again?

matehat commented 3 years ago

The response you get when you wait for the response of join() is the reply given to the join callback in Phoenix.

Subsequent messages you broadcast on a channel from within your Phoenix server arrive as distinct messages on the channel.messages stream on the Dart channel (that have successfully joined).