Skip to content

Commit

Permalink
added broadcast_poke; close #60
Browse files Browse the repository at this point in the history
  • Loading branch information
grych committed Apr 13, 2018
1 parent acaf03b commit 63182d9
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 33 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
The performance of `poke` and `peek` operations increases significantly, as the event handler
does not have to get the assigns from the browser each time.

#### `broadcast_poke`
You now may broadcast the assign, in exactly the same way you're doing `poke`.

## v0.7.5
### New Features
#### Living assigns inside the shared comamander
Expand Down
14 changes: 8 additions & 6 deletions lib/drab/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ defmodule Drab.Client do
if enables_drab?(controller) do
commander = commander_for(controller)
view = view_for(controller)
action = Phoenix.Controller.action_name(conn)

controller_and_action =
Phoenix.Token.sign(
Expand All @@ -146,11 +147,11 @@ defmodule Drab.Client do
__controller: controller,
__commander: commander,
__view: view,
__action: Phoenix.Controller.action_name(conn),
__action: action,
__assigns: assigns
)

broadcast_topic = topic(commander.__drab__().broadcasting, controller, conn.request_path)
broadcast_topic = topic(commander.__drab__().broadcasting, controller, conn.request_path, action)

templates = DrabModule.all_templates_for(commander.__drab__().modules)

Expand Down Expand Up @@ -214,8 +215,9 @@ defmodule Drab.Client do
end

# defp topic(:all, _, _), do: "all"
@spec topic(atom | String.t(), atom | String.t(), String.t()) :: String.t()
defp topic(:same_path, _, path), do: Drab.Core.same_path(path)
defp topic(:same_controller, controller, _), do: Drab.Core.same_controller(controller)
defp topic(topic, _, _) when is_binary(topic), do: Drab.Core.same_topic(topic)
@spec topic(atom | String.t(), atom | String.t(), atom | String.t(), atom | String.t()) :: String.t()
defp topic(:same_path, _, path, _), do: Drab.Core.same_path(path)
defp topic(:same_controller, controller, _, _), do: Drab.Core.same_controller(controller)
defp topic(:same_action, controller, _, action), do: Drab.Core.same_action(controller, action)
defp topic(topic, _, _, _) when is_binary(topic), do: Drab.Core.same_topic(topic)
end
8 changes: 5 additions & 3 deletions lib/drab/commander.ex
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ defmodule Drab.Commander do
end
end)

@broadcasts ~w(same_path same_controller)a
@broadcasts ~w(same_path same_controller same_action)a
@doc """
Set up broadcasting listen subject for the current commander.
Expand All @@ -467,8 +467,10 @@ defmodule Drab.Commander do
Options:
* `:same_path` (default) - broadcasts will go to the browsers rendering the same url
* `:same_controller` - broadcasted message will be received by all browsers, which renders the page generated
by the same controller
* `:same_controller` - broadcasted message will be received by all browsers, which
renders the page generated by the same controller
* `:same_action` - the message will be received by the browsers, rendered with the
same controller and action
* `"topic"` - any topic you want to set, messages will go to the clients sharing this topic
See `Drab.Core.broadcast_js/2` for more.
Expand Down
9 changes: 9 additions & 0 deletions lib/drab/core.ex
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,15 @@ defmodule Drab.Core do
@spec same_controller(String.t() | atom) :: String.t()
def same_controller(controller), do: "controller:#{controller}"

@doc """
Helper for broadcasting functions, returns topic for a given controller and action.
iex> same_action(DrabTestApp.LiveController, :index)
"controller:Elixir.DrabTestApp.LiveController#index"
"""
@spec same_action(String.t() | atom, String.t() | atom) :: String.t()
def same_action(controller, action), do: "action:#{controller}##{action}"

@doc """
Helper for broadcasting functions, returns topic for a given topic string.
iex> same_topic("mytopic")
Expand Down
58 changes: 55 additions & 3 deletions lib/drab/live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,8 @@ defmodule Drab.Live do
"""
@spec poke(Phoenix.Socket.t(), Keyword.t()) :: result
def poke(socket, assigns) do
do_poke(socket, nil, nil, assigns, &Drab.Core.exec_js/2)
# do_poke(socket, nil, nil, assigns, &Drab.Core.exec_js/2)
poke(socket, nil, nil, assigns)
end

@doc """
Expand All @@ -323,7 +324,8 @@ defmodule Drab.Live do
"""
@spec poke(Phoenix.Socket.t(), String.t(), Keyword.t()) :: result
def poke(socket, partial, assigns) do
do_poke(socket, nil, partial, assigns, &Drab.Core.exec_js/2)
# do_poke(socket, nil, partial, assigns, &Drab.Core.exec_js/2)
poke(socket, nil, partial, assigns)
end

@doc """
Expand All @@ -332,11 +334,61 @@ defmodule Drab.Live do
iex> poke(socket, MyApp.UserView, "user.html", name: "Bożywój")
%Phoenix.Socket{ ...
"""
@spec poke(Phoenix.Socket.t(), atom, String.t(), Keyword.t()) :: result
@spec poke(Phoenix.Socket.t(), atom | nil, String.t() | nil, Keyword.t()) :: result
def poke(socket, view, partial, assigns) do
do_poke(socket, view, partial, assigns, &Drab.Core.exec_js/2)
end

@doc """
Broadcasting version of `poke/2`.
Please notice that broadcasting living assigns makes sense only for the pages, which was rendered
with the same templates.
Always returns socket.
iex> broadcast_poke(socket, count: 42)
%Phoenix.Socket{ ...
"""
@spec broadcast_poke(Phoenix.Socket.t(), Keyword.t()) :: result
def broadcast_poke(socket, assigns) do
# do_poke(socket, nil, nil, assigns, &Drab.Core.broadcast_js/2)
broadcast_poke(socket, nil, nil, assigns)
end

@doc """
Like `broadcast_poke/2`, but limited only to the given partial name.
iex> broadcast_poke(socket, "user.html", name: "Bożywój")
%Phoenix.Socket{ ...
"""
@spec broadcast_poke(Phoenix.Socket.t(), String.t(), Keyword.t()) :: result
def broadcast_poke(socket, partial, assigns) do
# do_poke(socket, nil, partial, assigns, &Drab.Core.broadcast_js/2)
broadcast_poke(socket, nil, partial, assigns)
end

@doc """
Like `broadcast_poke/3`, but searches for the partial within the given view.
iex> broadcast_poke(socket, MyApp.UserView, "user.html", name: "Bożywój")
%Phoenix.Socket{ ...
"""
@spec broadcast_poke(Phoenix.Socket.t(), atom | nil, String.t() | nil, Keyword.t()) :: result
def broadcast_poke(socket, view, partial, assigns) do
# if socket.assigns.__broadcast_topic =~ "same_path:" ||
# socket.assigns.__broadcast_topic =~ "action:" do
do_poke(socket, view, partial, assigns, &Drab.Core.broadcast_js/2)
# else
# raise ArgumentError,
# message: """
# Broadcasting `poke` makes sense only with `:same_path` or `:same_action` options.

# You tried: `#{socket.assigns.__broadcast_topic}`
# """
# end
end

@spec do_poke(Phoenix.Socket.t(), atom | nil, String.t() | nil, Keyword.t(), function) :: result
defp do_poke(socket, view, partial_name, assigns, function) do
if Enum.member?(Keyword.keys(assigns), :conn) do
Expand Down
31 changes: 31 additions & 0 deletions test/integration/live_broadcasting_text.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule DrabTestApp.LiveBroadcastingTest do
use DrabTestApp.IntegrationCase

defp broadcasting_index do
broadcasting_url(DrabTestApp.Endpoint, :broadcasting)
end

defp wait_for_drab() do
broadcasting_index() |> navigate_to()
find_element(:id, "page_loaded_indicator")
end

setup do
wait_for_drab()
[socket: drab_socket()]
end

test "poke should be broadcasted" do
change_to_secondary_session()
wait_for_drab()

change_to_default_session()
click_and_wait("broadcast_button")
assert visible_text(find_element(:id, "broadcast_out")) == "broadcasted"

change_to_secondary_session()
assert visible_text(find_element(:id, "broadcast_out")) == "broadcasted"

end

end
1 change: 1 addition & 0 deletions test/support/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ defmodule DrabTestApp.Router do
get("/tests/live/query", LiveQueryController, :index, as: :live_query)
get("/tests/live/table", LiveController, :table, as: :table)
get("/tests/live/advanced", LiveController, :advanced, as: :advanced)
get("/tests/live/broadcasting", LiveController, :broadcasting, as: :broadcasting)

get("/tests/element", ElementController, :index, as: :element)
end
Expand Down
25 changes: 4 additions & 21 deletions test/support/web/commanders/live_commander.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ defmodule DrabTestApp.LiveCommander do

use Drab.Commander, modules: [Drab.Live, Drab.Element]
onload(:page_loaded)
broadcasting(:same_action)

def page_loaded(socket) do
DrabTestApp.IntegrationCase.add_page_loaded_indicator(socket)
Expand Down Expand Up @@ -79,22 +80,7 @@ defmodule DrabTestApp.LiveCommander do
end

defhandler update_mini(socket, _sender) do
# IO.inspect(sender)
# poke socket, class1: "btn", class2: "btn-warning",
# hidden: !peek(socket, :hidden), list: [1,2,3], color: "red"
# poke socket, "users.html", color: "color"
# poke socket, color: "blue", count: 13
# poke socket, "user.html", user: "Bravo"
# poke socket, "partial1.html", in_partial: "updated partial 1", color: "#66FFFF", link: "https://tg.pl/drab"
# poke socket, users: ["a", "b"] #, link: "aaaa"
# poke socket, link: "a"
# partial4 = render_to_string(DrabTestApp.LiveView, "partial4.html", in_partial: "in partial4",
# color: "#aaaabb", link: "http://tg.pl")
# set_prop(socket, "#partial4_placeholder", innerHTML: partial4)
# , user: "Hendryk")
poke(socket, users: ["Mirmił", "Hegemon", "Kokosz", "Kajko"])
# poke(socket, in_partial: "in_partial after") |> IO.inspect()
# peek(socket, :in_partial) |> IO.inspect()
end

defhandler update_users(socket, _sender) do
Expand All @@ -109,10 +95,7 @@ defmodule DrabTestApp.LiveCommander do
poke(socket, excluded: "Hegemon")
end

# defp loop(socket) do
# IO.inspect self()
# IO.inspect socket
# Process.sleep 5000
# loop(socket)
# end
defhandler broadcast(socket, _sender) do
broadcast_poke(socket, text: "broadcasted")
end
end
4 changes: 4 additions & 0 deletions test/support/web/controllers/live_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,8 @@ defmodule DrabTestApp.LiveController do
in_partial: "in partial before"
)
end

def broadcasting(conn, _param) do
render(conn, text: "set in the controller")
end
end
8 changes: 8 additions & 0 deletions test/support/web/templates/live/broadcasting.html.drab
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div id="begin"></div>
<div id="drab_pid"></div>

<div>
<button id="broadcast_button" drab-click="broadcast">Broadcast</button>
</div>
<br>
<div id="broadcast_out"><%= @text %></div>
1 change: 1 addition & 0 deletions test/support/web/templates/page/index.html.eex
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Pages for Integration Tests: <br>
<a href="/tests/live/query">Drab.Live + Drab.Query</a><br>
<a href="/tests/live/table">Drab.Live and html table</a><br>
<a href="/tests/live/advanced">Drab.Live advanced tests</a><br>
<a href="/tests/live/broadcasting">Drab.Live broadcasting tests</a><br>
<a href="/tests/element">Drab.Element</a><br>
<a href="/tests/share">Shared Controllers</a><br>
<br>
Expand Down

0 comments on commit 63182d9

Please sign in to comment.