diff --git a/lib/unfinal/document_server.ex b/lib/unfinal/document_server.ex index b95f004..530d8ca 100644 --- a/lib/unfinal/document_server.ex +++ b/lib/unfinal/document_server.ex @@ -215,5 +215,11 @@ defmodule Unfinal.DocumentServer do path, %{content: doc.content, etag: doc.etag, revision: doc.revision} }) + + Phoenix.PubSub.broadcast(Unfinal.PubSub, Documents.edit_topic(), { + :edit, + path, + System.system_time(:second) + }) end end diff --git a/lib/unfinal/documents.ex b/lib/unfinal/documents.ex index 378e5f4..99f1b06 100644 --- a/lib/unfinal/documents.ex +++ b/lib/unfinal/documents.ex @@ -19,6 +19,9 @@ defmodule Unfinal.Documents do def topic(path), do: @topic_prefix <> Base.url_encode64(ContentStore.normalize_path(path), padding: false) + @spec edit_topic() :: String.t() + def edit_topic, do: "edits" + @spec get(path()) :: Document.t() def get(path), do: path |> ContentStore.normalize_path() |> server_call(:get) diff --git a/lib/unfinal_web/live/live_live.ex b/lib/unfinal_web/live/live_live.ex index 34a5459..0b1ca33 100644 --- a/lib/unfinal_web/live/live_live.ex +++ b/lib/unfinal_web/live/live_live.ex @@ -17,6 +17,7 @@ defmodule UnfinalWeb.LiveLive do if connected?(socket) do Phoenix.PubSub.subscribe(Unfinal.PubSub, @topic) + Phoenix.PubSub.subscribe(Unfinal.PubSub, Documents.edit_topic()) active_paths = active_paths() Enum.each(active_paths, &Phoenix.PubSub.subscribe(Unfinal.PubSub, Documents.topic(&1))) @@ -25,6 +26,7 @@ defmodule UnfinalWeb.LiveLive do active_paths: active_paths, sorted_paths: sorted_paths(), excerpts: excerpts(active_paths, %{}), + recent_edits: %{}, authenticated: authenticated, user: user, claimed_namespace: claimed_namespace, @@ -37,6 +39,7 @@ defmodule UnfinalWeb.LiveLive do active_paths: MapSet.new(), sorted_paths: [], excerpts: %{}, + recent_edits: %{}, authenticated: authenticated, user: user, claimed_namespace: claimed_namespace, @@ -72,6 +75,20 @@ defmodule UnfinalWeb.LiveLive do end end + def handle_info({:edit, path, timestamp}, socket) do + socket = update(socket, :recent_edits, &Map.put(&1, path, timestamp)) + + socket = + if not MapSet.member?(socket.assigns.active_paths, path) and + not Map.has_key?(socket.assigns.excerpts, path) do + update(socket, :excerpts, &Map.put(&1, path, Documents.get(path).content)) + else + socket + end + + {:noreply, socket} + end + @impl true def handle_event("toggle_mobile_menu", _params, socket) do {:noreply, assign(socket, mobile_menu_open: !socket.assigns.mobile_menu_open)} @@ -120,6 +137,14 @@ defmodule UnfinalWeb.LiveLive do defp document_href("/" <> path), do: "/n/" <> path defp document_href(_path), do: "/n" + defp visible_recent(recent_edits, active_paths, limit \\ 10) do + recent_edits + |> Enum.reject(fn {path, _ts} -> MapSet.member?(active_paths, path) end) + |> Enum.sort_by(fn {_, ts} -> -ts end) + |> Enum.take(limit) + |> Enum.map(fn {path, _ts} -> path end) + end + @impl true def render(assigns) do ~H""" @@ -160,6 +185,25 @@ defmodule UnfinalWeb.LiveLive do
+ + <% visible_recent = visible_recent(@recent_edits, @active_paths) %> + +