Skip to content

Commit

Permalink
Add basic debouncing
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Aug 29, 2021
1 parent ac73922 commit 5928a90
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 7 deletions.
49 changes: 42 additions & 7 deletions lib/phoenix_live_reload/channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,66 @@ defmodule Phoenix.LiveReloader.Channel do

def join("phoenix:live_reload", _msg, socket) do
{:ok, _} = Application.ensure_all_started(:phoenix_live_reload)
patterns = socket.endpoint.config(:live_reload)[:patterns]

if Process.whereis(:phoenix_live_reload_file_monitor) do
FileSystem.subscribe(:phoenix_live_reload_file_monitor)
{:ok, assign(socket, :patterns, patterns)}
config = socket.endpoint.config(:live_reload)

socket =
socket
|> assign(:patterns, config[:patterns] || [])
|> assign(:debounce, config[:debounce] || 0)

{:ok, socket}
else
{:error, %{message: "live reload backend not running"}}
end
end

def handle_info({:file_event, _pid, {path, _event}}, socket) do
if matches_any_pattern?(path, socket.assigns[:patterns]) do
asset_type = remove_leading_dot(Path.extname(path))
Logger.debug("Live reload: #{Path.relative_to_cwd(path)}")
push(socket, "assets_change", %{asset_type: asset_type})
%{patterns: patterns, debounce: debounce} = socket.assigns

if matches_any_pattern?(path, patterns) do
ext = Path.extname(path)

for {path, ext} <- [{path, ext} | debounce(debounce, [ext], patterns)] do
asset_type = remove_leading_dot(ext)
Logger.debug("Live reload: #{Path.relative_to_cwd(path)}")
push(socket, "assets_change", %{asset_type: asset_type})
end
end

{:noreply, socket}
end

defp debounce(0, _exts, _patterns), do: []

defp debounce(time, exts, patterns) when is_integer(time) and time > 0 do
Process.send_after(self(), :debounced, time)
debounce(exts, patterns)
end

defp debounce(exts, patterns) do
receive do
:debounced ->
[]

{:file_event, _pid, {path, _event}} ->
ext = Path.extname(path)

if matches_any_pattern?(path, patterns) and ext not in exts do
[{path, ext} | debounce([ext | exts], patterns)]
else
debounce(exts, patterns)
end
end
end

defp matches_any_pattern?(path, patterns) do
path = to_string(path)

Enum.any?(patterns, fn pattern ->
String.match?(path, pattern) and !String.match?(path, ~r{(^|/)_build/})
String.match?(path, pattern) and not String.match?(path, ~r{(^|/)_build/})
end)
end

Expand Down
3 changes: 3 additions & 0 deletions lib/phoenix_live_reload/live_reloader.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ defmodule Phoenix.LiveReloader do
* `:patterns` - a list of patterns to trigger the live reloading.
This option is required to enable any live reloading.
* `:debounce` - an integer in milliseconds to wait before sending
live reload events to the browser.
* `:iframe_attrs` - attrs to be given to the iframe injected by
live reload. Expects a keyword list of atom keys and string values.
Expand Down

0 comments on commit 5928a90

Please sign in to comment.