From 53233c36f1f1f0271f657f6df0f1bdb9bcce1875 Mon Sep 17 00:00:00 2001 From: Krishna Penukonda Date: Thu, 2 Jul 2026 10:02:14 +0000 Subject: [PATCH] feat: seed /live recently-edited from SQLite history Query SQLite for most recently edited documents on mount, so the recently-edited section includes historical edits (not just real-time). Converts ISO8601 timestamps to Unix epoch for uniform sorting with real-time edit broadcasts. --- lib/unfinal/sqlite_documents.ex | 14 ++++++++++++++ lib/unfinal_web/live/live_live.ex | 24 ++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/unfinal/sqlite_documents.ex b/lib/unfinal/sqlite_documents.ex index 6cb4104..a2b4d1b 100644 --- a/lib/unfinal/sqlite_documents.ex +++ b/lib/unfinal/sqlite_documents.ex @@ -138,6 +138,20 @@ defmodule Unfinal.SqliteDocuments do end end + @doc "List most recently edited documents across all namespaces." + @spec recent_edits(non_neg_integer()) :: [%{path: String.t(), updated_at: String.t()}] + def recent_edits(limit \\ 20) when is_integer(limit) and limit > 0 do + sql = "SELECT path, updated_at FROM documents WHERE updated_at IS NOT NULL ORDER BY updated_at DESC LIMIT ?1" + + case query(sql, [limit]) do + {:ok, %{rows: rows}} -> + Enum.map(rows, fn [path, upd] -> %{path: path, updated_at: upd} end) + + {:error, _} -> + [] + end + end + @doc "Count all document rows." @spec count_documents() :: non_neg_integer() def count_documents do diff --git a/lib/unfinal_web/live/live_live.ex b/lib/unfinal_web/live/live_live.ex index 0b1ca33..0e457d7 100644 --- a/lib/unfinal_web/live/live_live.ex +++ b/lib/unfinal_web/live/live_live.ex @@ -3,6 +3,7 @@ defmodule UnfinalWeb.LiveLive do alias Unfinal.Documents alias Unfinal.NamespaceStore + alias Unfinal.SqliteDocuments alias UnfinalWeb.Layouts alias UnfinalWeb.Presence @@ -21,12 +22,16 @@ defmodule UnfinalWeb.LiveLive do active_paths = active_paths() Enum.each(active_paths, &Phoenix.PubSub.subscribe(Unfinal.PubSub, Documents.topic(&1))) + recent_edits = seed_recent_edits() + recent_paths = Map.keys(recent_edits) -- MapSet.to_list(active_paths) + excerpts = excerpts(MapSet.union(active_paths, MapSet.new(recent_paths)), %{}) + {:ok, assign(socket, active_paths: active_paths, sorted_paths: sorted_paths(), - excerpts: excerpts(active_paths, %{}), - recent_edits: %{}, + excerpts: excerpts, + recent_edits: recent_edits, authenticated: authenticated, user: user, claimed_namespace: claimed_namespace, @@ -103,6 +108,21 @@ defmodule UnfinalWeb.LiveLive do defp claimed_namespace(_session), do: nil + defp seed_recent_edits do + SqliteDocuments.recent_edits(20) + |> Enum.map(fn %{path: path, updated_at: updated_at} -> + {path, parse_timestamp(updated_at)} + end) + |> Map.new() + end + + defp parse_timestamp(iso_string) do + case DateTime.from_iso8601(iso_string) do + {:ok, dt, _} -> DateTime.to_unix(dt) + _ -> 0 + end + end + defp active_paths do @topic |> Presence.list() |> Map.keys() |> MapSet.new() end