@@ -20,7 +20,13 @@ defmodule Phoenix.LiveView.LiveStream do
2020 "stream :dom_id must return a function which accepts each item, got: #{ inspect ( dom_id ) } "
2121 end
2222
23- items_list = for item <- items , do: { dom_id . ( item ) , - 1 , item , opts [ :limit ] }
23+ # We need to go through the items one time to map them into the proper insert tuple format.
24+ # Conveniently, we reverse the list in this pass, which we need to in order to be consistent
25+ # with manually calling stream_insert multiple times, as stream_insert prepends.
26+ items_list =
27+ for item <- items , reduce: [ ] do
28+ items -> [ { dom_id . ( item ) , - 1 , item , opts [ :limit ] } | items ]
29+ end
2430
2531 % LiveStream {
2632 ref: ref ,
@@ -61,16 +67,30 @@ defmodule Phoenix.LiveView.LiveStream do
6167 def insert_item ( % LiveStream { } = stream , item , at , limit ) do
6268 item_id = stream . dom_id . ( item )
6369
64- % { stream | inserts: stream . inserts ++ [ { item_id , at , item , limit } ] }
70+ % { stream | inserts: [ { item_id , at , item , limit } | stream . inserts ] }
6571 end
6672
6773 defimpl Enumerable , for: LiveStream do
6874 def count ( % LiveStream { inserts: inserts } ) , do: { :ok , length ( inserts ) }
6975
7076 def member? ( % LiveStream { } , _item ) , do: raise ( RuntimeError , "not implemented" )
7177
72- def reduce ( % LiveStream { inserts: inserts } = stream , acc , fun ) do
78+ def reduce ( % LiveStream { } = stream , acc , fun ) do
7379 if stream . consumable? do
80+ # the inserts are stored in reverse insert order, so we need to reverse them
81+ # before rendering; we also remove duplicates to only use the most recent
82+ # inserts, which, as the items are reversed, are first
83+ { inserts , _ } =
84+ for { id , _ , _ , _ } = insert <- stream . inserts , reduce: { [ ] , MapSet . new ( ) } do
85+ { inserts , ids } ->
86+ if MapSet . member? ( ids , id ) do
87+ # skip duplicates
88+ { inserts , ids }
89+ else
90+ { [ insert | inserts ] , MapSet . put ( ids , id ) }
91+ end
92+ end
93+
7494 do_reduce ( inserts , acc , fun )
7595 else
7696 raise ArgumentError , """
0 commit comments