diff --git a/web/channels/room_channel.ex b/web/channels/room_channel.ex index 6f20780..f590455 100644 --- a/web/channels/room_channel.ex +++ b/web/channels/room_channel.ex @@ -1,12 +1,14 @@ defmodule KolabChat.RoomChannel do use KolabChat.Web, :channel + @spec join(topic :: binary(), args :: map(), socket :: pid()) :: {:ok, socket :: pid()} def join("room:lobby", _, socket) do {:ok, socket} end + @spec handle_in(topic :: binary, args :: map(), socket :: pid()) :: {:noreply, socket :: pid()} def handle_in("new:message", message, socket) do broadcast! socket, "new:message", %{user: message["user"], body: message["body"]} {:noreply, socket} end end diff --git a/web/channels/system_channel.ex b/web/channels/system_channel.ex index a520a46..6011fd7 100644 --- a/web/channels/system_channel.ex +++ b/web/channels/system_channel.ex @@ -1,105 +1,108 @@ defmodule KolabChat.SystemChannel do use KolabChat.Web, :channel @status [ # user is available for chat :online, :away, # user is connected and visible, but not available :busy, :unavailable, # user is shown as offline :invisible, :offline ] + @spec join(topic :: binary(), args :: map(), socket :: pid()) :: {:ok, socket :: pid()} def join("system", %{"context" => context}, socket) do perform_join(context, socket) end def join("system", _args, socket) do perform_join("default", socket) end + @spec handle_info(:after_join, socket :: pid()) :: {:noreply, socket :: pid()} def handle_info(:after_join, socket) do push socket, "presence_state", Presence.list(socket) push socket, "info", %{user: socket.assigns.user.username} Presence.track(socket, socket.assigns.user.username, %{ status: get_user_status(socket), context: socket.assigns.context }) {:noreply, socket} end + @spec handle_in(topic :: binary, args :: map(), socket :: pid()) :: {:noreply, socket :: pid()} def handle_in("set-status", %{"status" => status}, socket) do status = check_status(status) socket |> update_presence_status(status) |> set_user_status(status) {:noreply, socket} end defp perform_join(context, socket) do socket = assign(socket, :context, context) send self(), :after_join {:ok, socket} end defp update_presence_status(socket, :invalid), do: socket defp update_presence_status(socket, status) do Presence.update(socket, socket.assigns.user.username, %{ status: status, context: socket.assigns.context }) socket end # Makes sure the provided status name is supported # Returns status name as an atom defp check_status(status) do status = String.to_atom(status) if Enum.member?(@status, status) do status else :invalid end end # Get the last user/context status from the database defp get_user_status(socket) do require Amnesia require Amnesia.Helper key = socket.assigns.user.username <> ":" <> socket.assigns.context Amnesia.transaction do case Database.Status.read(key) do # use last status %Database.Status{status: status} -> status # otherwise set status to online _ -> :online end end end # Save the current user/context status to the database defp set_user_status(socket, :invalid), do: socket defp set_user_status(socket, status) do require Amnesia require Amnesia.Helper key = socket.assigns.user.username <> ":" <> socket.assigns.context Amnesia.transaction do Database.Status.write(%Database.Status{key: key, status: status}) end socket end end