defmodule LiveDebuggerWeb.SidebarLive do @moduledoc """ This live view is responsible for displaying the sidebar of the LiveDebugger. It receives events from the `ChannelDashboardLive` live to open the mobile sidebar. """ use LiveDebuggerWeb, :live_view require Logger alias LiveDebugger.Structs.LvProcess alias LiveDebugger.Structs.Trace alias LiveDebugger.Utils.Parsers alias LiveDebuggerWeb.Components.Tree alias LiveDebuggerWeb.Components.Links alias LiveDebugger.Services.ChannelService alias Phoenix.Socket.Message alias LiveDebugger.Utils.URL alias LiveDebuggerWeb.LiveComponents.NestedLiveViewsLinks alias LiveDebugger.Utils.PubSub, as: PubSubUtils attr(:socket, :map, required: true) attr(:id, :string, required: true) attr(:lv_process, :map, required: true) attr(:node_id, :string, required: true) attr(:url, :string, required: true) attr(:class, :string, default: "", doc: "CSS class for the container") def live_render(assigns) do session = %{ "lv_process" => assigns.lv_process, "node_id" => assigns.node_id, "url" => assigns.url, "parent_socket_id" => assigns.socket.id } assigns = assign(assigns, session: session) ~H""" <%= live_render(@socket, __MODULE__, id: @id, session: @session, container: {:aside, class: @class} ) %> """ end @impl true def mount(_params, session, socket) do parent_socket_id = session["parent_socket_id"] lv_process = session["lv_process"] if connected?(socket) do parent_socket_id |> PubSubUtils.node_changed_topic() |> PubSubUtils.subscribe!() lv_process.socket_id |> PubSubUtils.component_deleted_topic(lv_process.transport_pid) |> PubSubUtils.subscribe!() lv_process.socket_id |> PubSubUtils.ts_f_topic(lv_process.transport_pid, :render) |> PubSubUtils.subscribe!() end socket |> assign(:lv_process, lv_process) |> assign(:node_id, session["node_id"]) |> assign(:url, session["url"]) |> assign(:highlight?, false) |> assign(:hidden?, true) |> assign_async_tree() |> assign_async_parent_lv_process() |> assign_async_existing_node_ids() |> ok() end attr(:lv_process, :any, required: true) attr(:node_id, :any, required: true) attr(:url, :any, required: true) @impl true def render(assigns) do ~H"""
""" end @impl true def handle_info({:new_trace, trace}, socket) do existing_node_ids = socket.assigns.existing_node_ids trace_node_id = Trace.node_id(trace) cond do existing_node_ids.ok? && !MapSet.member?(existing_node_ids.result, trace_node_id) -> updated_map_set = MapSet.put(existing_node_ids.result, trace_node_id) socket |> assign_async_tree() |> update_nested_live_views_links() |> assign(:existing_node_ids, Map.put(existing_node_ids, :result, updated_map_set)) Trace.live_component_delete?(trace) -> updated_map_set = MapSet.delete(existing_node_ids.result, trace_node_id) socket |> assign_async_tree() |> update_nested_live_views_links() |> assign(:existing_node_ids, Map.put(existing_node_ids, :result, updated_map_set)) true -> socket end |> noreply() end @impl true def handle_info({:node_changed, node_id}, socket) do socket |> assign(:node_id, node_id) |> noreply() end @impl true def handle_event("open-sidebar", _, socket) do socket |> assign(:hidden?, false) |> noreply() end @impl true def handle_event("select_node", params, socket) do %{"node_id" => node_id, "search-attribute" => attr, "search-value" => val} = params if LiveDebugger.Feature.enabled?(:highlighting) do if !socket.assigns.hidden? && socket.assigns.highlight? do send_event(socket.assigns.lv_process.pid, "highlight", %{attr: attr, val: val}) end send_event(socket.assigns.lv_process.pid, "pulse", %{attr: attr, val: val}) end socket |> push_patch(to: URL.upsert_query_param(socket.assigns.url, "node_id", node_id)) |> assign(:hidden?, true) |> noreply() end @impl true def handle_event("highlight", params, socket) do if socket.assigns.highlight? do %{"search-attribute" => attr, "search-value" => val} = params send_event(socket.assigns.lv_process.pid, "highlight", %{attr: attr, val: val}) end noreply(socket) end @impl true def handle_event("toggle-highlight", _, socket) do if socket.assigns.highlight? do send_event(socket.assigns.lv_process.pid, "highlight") end socket |> update(:highlight?, &(not &1)) |> noreply() end @impl true def handle_event("close_mobile_content", _params, socket) do socket |> assign(:hidden?, true) |> noreply() end attr(:id, :string, required: true) attr(:lv_process, LvProcess, required: true) attr(:tree, :any, required: true) attr(:node_id, :any, required: true) attr(:max_opened_node_level, :any, required: true) attr(:highlight?, :boolean, required: true) attr(:parent_lv_process, :any, required: true) defp sidebar_content(assigns) do ~H"""