From ea2a1b6f5ea4e116edbd0bb26cd87c2b53396e70 Mon Sep 17 00:00:00 2001 From: SimpleTest Date: Mon, 3 Aug 2026 02:31:04 +0300 Subject: [PATCH] Stabilize realtime discovery pagination --- .../live/activity_live/index.ex | 23 ++++--------------- .../live/mutual_aid_live_test.exs | 15 ++++++++---- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/lib/who_need_help_web/live/activity_live/index.ex b/lib/who_need_help_web/live/activity_live/index.ex index 242460c..2703293 100644 --- a/lib/who_need_help_web/live/activity_live/index.ex +++ b/lib/who_need_help_web/live/activity_live/index.ex @@ -68,21 +68,6 @@ defmodule WhoNeedHelpWeb.ActivityLive.Index do user_id = socket.assigns.current_scope.user.id already_mine? = Enum.any?(socket.assigns.my_activities, &(&1.id == activity.id)) - {activities, activities_cursor} = - update_entry( - socket.assigns.activities, - activity, - not is_nil(socket.assigns.viewport) and - Activities.visible_open_activity?( - socket.assigns.current_scope, - activity, - socket.assigns.filters, - socket.assigns.viewport - ), - :asc, - socket.assigns.activities_cursor - ) - {my_activities, my_activities_cursor} = update_entry( socket.assigns.my_activities, @@ -94,12 +79,14 @@ defmodule WhoNeedHelpWeb.ActivityLive.Index do socket = socket - |> assign(:activities, activities) - |> assign(:activities_cursor, activities_cursor) |> assign(:my_activities, my_activities) |> assign(:my_activities_cursor, my_activities_cursor) - if socket.assigns.refresh_timer || socket.assigns.view_mode == "list" do + # A single authoritative page reload keeps the list, cursor, result count, + # and map clusters on the same database snapshot. Applying the PubSub item + # locally and then accepting an in-flight async page allowed an older page + # to overwrite a newer bounded window during bursts. + if socket.assigns.refresh_timer do {:noreply, socket} else timer = Process.send_after(self(), :refresh_discovery, 100) diff --git a/test/who_need_help_web/live/mutual_aid_live_test.exs b/test/who_need_help_web/live/mutual_aid_live_test.exs index d63df16..ed0e4a4 100644 --- a/test/who_need_help_web/live/mutual_aid_live_test.exs +++ b/test/who_need_help_web/live/mutual_aid_live_test.exs @@ -665,7 +665,11 @@ defmodule WhoNeedHelpWeb.MutualAidLiveTest do first = List.first(requests) overflow = List.last(requests) - assert_eventually(fn -> has_element?(view, "#open-request-#{first.id}") end) + assert_eventually(fn -> + has_element?(view, "#open-request-#{first.id}") and + has_element?(view, "button", "Load more in this area") + end) + refute has_element?(view, "#open-request-#{overflow.id}") view |> element("button", "Load more in this area") |> render_click() @@ -704,7 +708,7 @@ defmodule WhoNeedHelpWeb.MutualAidLiveTest do "safety_confirmed" => true }) - assert render(view) =~ "Realtime coffee meetup" + assert_eventually(fn -> render(view) =~ "Realtime coffee meetup" end) end test "activity realtime updates keep a bounded window without skipping pagination" do @@ -738,11 +742,14 @@ defmodule WhoNeedHelpWeb.MutualAidLiveTest do activity end - render(view) first = List.first(activities) overflow = List.last(activities) - assert has_element?(view, "#open-activity-#{first.id}") + assert_eventually(fn -> + has_element?(view, "#open-activity-#{first.id}") and + has_element?(view, "button", "Load more") + end) + refute has_element?(view, "#open-activity-#{overflow.id}") view |> element("button", "Load more") |> render_click()