mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-09 21:16:26 +08:00
Make frame and text stream updates implicit (#2451)
This commit is contained in:
parent
8431401df1
commit
9bc0832e03
6 changed files with 98 additions and 62 deletions
|
@ -410,11 +410,11 @@ defmodule LivebookWeb.AppSessionLive do
|
||||||
changed_input_ids = Session.Data.changed_input_ids(data)
|
changed_input_ids = Session.Data.changed_input_ids(data)
|
||||||
|
|
||||||
for {{idx, frame}, cell} <- Notebook.find_frame_outputs(data.notebook, ref) do
|
for {{idx, frame}, cell} <- Notebook.find_frame_outputs(data.notebook, ref) do
|
||||||
|
input_views = input_views_for_cell(cell, data, changed_input_ids)
|
||||||
|
|
||||||
send_update(LivebookWeb.Output.FrameComponent,
|
send_update(LivebookWeb.Output.FrameComponent,
|
||||||
id: "outputs-#{idx}-output",
|
id: "outputs-#{idx}-output",
|
||||||
outputs: frame.outputs,
|
event: {:update, update_type, frame.outputs, input_views}
|
||||||
update_type: update_type,
|
|
||||||
input_views: input_views_for_cell(cell, data, changed_input_ids)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -432,7 +432,7 @@ defmodule LivebookWeb.AppSessionLive do
|
||||||
:markdown -> LivebookWeb.Output.MarkdownComponent
|
:markdown -> LivebookWeb.Output.MarkdownComponent
|
||||||
end
|
end
|
||||||
|
|
||||||
send_update(module, id: "outputs-#{idx}-output", text: output.text)
|
send_update(module, id: "outputs-#{idx}-output", event: {:append, output.text})
|
||||||
data_view
|
data_view
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
|
|
|
@ -7,19 +7,11 @@ defmodule LivebookWeb.Output.FrameComponent do
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def update(assigns, socket) do
|
def update(%{event: {:update, update_type, outputs, input_views}}, socket) do
|
||||||
{update_type, assigns} = Map.pop(assigns, :update_type, nil)
|
socket = assign(socket, input_views: input_views)
|
||||||
{outputs, assigns} = Map.pop!(assigns, :outputs)
|
|
||||||
|
|
||||||
socket = assign(socket, assigns)
|
|
||||||
|
|
||||||
socket = assign_new(socket, :num_outputs, fn -> length(outputs) end)
|
|
||||||
|
|
||||||
socket =
|
socket =
|
||||||
case update_type do
|
case update_type do
|
||||||
nil ->
|
|
||||||
stream(socket, :outputs, stream_items(outputs))
|
|
||||||
|
|
||||||
:replace ->
|
:replace ->
|
||||||
socket
|
socket
|
||||||
|> assign(num_outputs: length(outputs))
|
|> assign(num_outputs: length(outputs))
|
||||||
|
@ -34,6 +26,17 @@ defmodule LivebookWeb.Output.FrameComponent do
|
||||||
{:ok, socket}
|
{:ok, socket}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update(assigns, socket) do
|
||||||
|
{outputs, assigns} = Map.pop!(assigns, :outputs)
|
||||||
|
|
||||||
|
socket = assign(socket, assigns)
|
||||||
|
|
||||||
|
socket = assign_new(socket, :num_outputs, fn -> length(outputs) end)
|
||||||
|
socket = stream(socket, :outputs, stream_items(outputs))
|
||||||
|
|
||||||
|
{:ok, socket}
|
||||||
|
end
|
||||||
|
|
||||||
defp stream_items(outputs) do
|
defp stream_items(outputs) do
|
||||||
for {idx, output} <- Enum.reverse(outputs) do
|
for {idx, output} <- Enum.reverse(outputs) do
|
||||||
%{id: Integer.to_string(idx), idx: idx, output: output}
|
%{id: Integer.to_string(idx), idx: idx, output: output}
|
||||||
|
|
|
@ -5,24 +5,34 @@ defmodule LivebookWeb.Output.MarkdownComponent do
|
||||||
def mount(socket) do
|
def mount(socket) do
|
||||||
{:ok,
|
{:ok,
|
||||||
socket
|
socket
|
||||||
|> assign(allowed_uri_schemes: Livebook.Config.allowed_uri_schemes())
|
|> assign(allowed_uri_schemes: Livebook.Config.allowed_uri_schemes(), initialized: false)
|
||||||
|> stream(:chunks, [])}
|
|> stream(:chunks, [])}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
def update(%{event: {:append, text}}, socket) do
|
||||||
|
{:ok, append_text(socket, text)}
|
||||||
|
end
|
||||||
|
|
||||||
def update(assigns, socket) do
|
def update(assigns, socket) do
|
||||||
{text, assigns} = Map.pop(assigns, :text)
|
{text, assigns} = Map.pop(assigns, :text)
|
||||||
|
|
||||||
socket = assign(socket, assigns)
|
socket = assign(socket, assigns)
|
||||||
|
|
||||||
if text do
|
if socket.assigns.initialized do
|
||||||
chunk = %{id: Livebook.Utils.random_long_id(), text: text}
|
|
||||||
{:ok, stream_insert(socket, :chunks, chunk)}
|
|
||||||
else
|
|
||||||
{:ok, socket}
|
{:ok, socket}
|
||||||
|
else
|
||||||
|
{:ok,
|
||||||
|
socket
|
||||||
|
|> append_text(text)
|
||||||
|
|> assign(:initialized, true)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp append_text(socket, text) do
|
||||||
|
chunk = %{id: Livebook.Utils.random_long_id(), text: text}
|
||||||
|
stream_insert(socket, :chunks, chunk)
|
||||||
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
|
|
|
@ -3,23 +3,36 @@ defmodule LivebookWeb.Output.PlainTextComponent do
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(socket) do
|
def mount(socket) do
|
||||||
{:ok, stream(socket, :chunks, [])}
|
{:ok,
|
||||||
|
socket
|
||||||
|
|> assign(initialized: false)
|
||||||
|
|> stream(:chunks, [])}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
def update(%{event: {:append, text}}, socket) do
|
||||||
|
{:ok, append_text(socket, text)}
|
||||||
|
end
|
||||||
|
|
||||||
def update(assigns, socket) do
|
def update(assigns, socket) do
|
||||||
{text, assigns} = Map.pop(assigns, :text)
|
{text, assigns} = Map.pop(assigns, :text)
|
||||||
|
|
||||||
socket = assign(socket, assigns)
|
socket = assign(socket, assigns)
|
||||||
|
|
||||||
if text do
|
if socket.assigns.initialized do
|
||||||
chunk = %{id: Livebook.Utils.random_long_id(), text: text}
|
|
||||||
{:ok, stream_insert(socket, :chunks, chunk)}
|
|
||||||
else
|
|
||||||
{:ok, socket}
|
{:ok, socket}
|
||||||
|
else
|
||||||
|
{:ok,
|
||||||
|
socket
|
||||||
|
|> append_text(text)
|
||||||
|
|> assign(:initialized, true)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp append_text(socket, text) do
|
||||||
|
chunk = %{id: Livebook.Utils.random_long_id(), text: text}
|
||||||
|
stream_insert(socket, :chunks, chunk)
|
||||||
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
|
|
|
@ -5,16 +5,30 @@ defmodule LivebookWeb.Output.TerminalTextComponent do
|
||||||
def mount(socket) do
|
def mount(socket) do
|
||||||
{:ok,
|
{:ok,
|
||||||
socket
|
socket
|
||||||
|> assign(modifiers: [], last_line: nil, last_html_line: nil)
|
|> assign(modifiers: [], last_line: nil, last_html_line: nil, initialized: false)
|
||||||
|> stream(:html_lines, [])}
|
|> stream(:html_lines, [])}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
def update(%{event: {:append, text}}, socket) do
|
||||||
|
{:ok, append_text(socket, text)}
|
||||||
|
end
|
||||||
|
|
||||||
def update(assigns, socket) do
|
def update(assigns, socket) do
|
||||||
{text, assigns} = Map.pop(assigns, :text)
|
{text, assigns} = Map.pop(assigns, :text)
|
||||||
socket = assign(socket, assigns)
|
socket = assign(socket, assigns)
|
||||||
|
|
||||||
if text do
|
if socket.assigns.initialized do
|
||||||
|
{:ok, socket}
|
||||||
|
else
|
||||||
|
{:ok,
|
||||||
|
socket
|
||||||
|
|> append_text(text)
|
||||||
|
|> assign(:initialized, true)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp append_text(socket, text) do
|
||||||
text = (socket.assigns.last_line || "") <> text
|
text = (socket.assigns.last_line || "") <> text
|
||||||
|
|
||||||
text = Livebook.Notebook.normalize_terminal_text(text)
|
text = Livebook.Notebook.normalize_terminal_text(text)
|
||||||
|
@ -35,15 +49,11 @@ defmodule LivebookWeb.Output.TerminalTextComponent do
|
||||||
|
|
||||||
socket = stream(socket, :html_lines, stream_items)
|
socket = stream(socket, :html_lines, stream_items)
|
||||||
|
|
||||||
{:ok,
|
|
||||||
assign(socket,
|
assign(socket,
|
||||||
last_html_line: last_html_line,
|
last_html_line: last_html_line,
|
||||||
last_line: last_line,
|
last_line: last_line,
|
||||||
modifiers: modifiers
|
modifiers: modifiers
|
||||||
)}
|
)
|
||||||
else
|
|
||||||
{:ok, socket}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
|
|
@ -2923,14 +2923,14 @@ defmodule LivebookWeb.SessionLive do
|
||||||
changed_input_ids = Session.Data.changed_input_ids(data)
|
changed_input_ids = Session.Data.changed_input_ids(data)
|
||||||
|
|
||||||
for {{idx, frame}, cell} <- Notebook.find_frame_outputs(data.notebook, ref) do
|
for {{idx, frame}, cell} <- Notebook.find_frame_outputs(data.notebook, ref) do
|
||||||
send_update(LivebookWeb.Output.FrameComponent,
|
|
||||||
id: "outputs-#{idx}-output",
|
|
||||||
outputs: frame.outputs,
|
|
||||||
update_type: update_type,
|
|
||||||
# Note that we are not updating data_view to avoid re-render,
|
# Note that we are not updating data_view to avoid re-render,
|
||||||
# but any change that causes frame to re-render will update
|
# but any change that causes frame to re-render will update
|
||||||
# data_view first
|
# data_view first
|
||||||
input_views: input_views_for_cell(cell, data, changed_input_ids)
|
input_views = input_views_for_cell(cell, data, changed_input_ids)
|
||||||
|
|
||||||
|
send_update(LivebookWeb.Output.FrameComponent,
|
||||||
|
id: "outputs-#{idx}-output",
|
||||||
|
event: {:update, update_type, frame.outputs, input_views}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2948,7 +2948,7 @@ defmodule LivebookWeb.SessionLive do
|
||||||
:markdown -> LivebookWeb.Output.MarkdownComponent
|
:markdown -> LivebookWeb.Output.MarkdownComponent
|
||||||
end
|
end
|
||||||
|
|
||||||
send_update(module, id: "outputs-#{idx}-output", text: output.text)
|
send_update(module, id: "outputs-#{idx}-output", event: {:append, output.text})
|
||||||
data_view
|
data_view
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
|
|
Loading…
Add table
Reference in a new issue