defmodule SlurpeeWeb.BlockchainLive do use SlurpeeWeb, :live_view import SlurpeeWeb.ViewHelpers.SearchQueryHelper, only: [assign_search_query: 2] import SlurpeeWeb.ViewHelpers.ExplorerUrlHelper, only: [explorer_url: 1] @impl true def mount(_params, _session, socket) do Phoenix.PubSub.subscribe(Slurpee.PubSub, "new_head_received") socket = socket |> assign(:query, nil) |> assign(latest_blocks: %{}) {:ok, socket} end @impl true def handle_params(params, _uri, socket) do socket = socket |> assign_search_query(params) |> assign_search() {:noreply, socket} end @impl true def handle_event("search", params, socket) do socket = socket |> assign_search_query(params) |> send_search_after(200) {:noreply, socket} end @impl true def handle_event("start", %{"id" => blockchain_id}, socket) do Slurp.Commander.start_blockchains(where: [id: blockchain_id]) blockchains = Slurp.Commander.blockchains([]) socket = socket |> assign(blockchains: blockchains) {:noreply, socket} end @impl true def handle_event("stop", %{"id" => blockchain_id}, socket) do Slurp.Commander.stop_blockchains(where: [id: blockchain_id]) blockchains = Slurp.Commander.blockchains([]) socket = socket |> assign(blockchains: blockchains) {:noreply, socket} end @impl true def handle_event("start-all", _, socket) do Slurp.Commander.start_blockchains([]) blockchains = Slurp.Commander.blockchains([]) socket = socket |> assign(blockchains: blockchains) {:noreply, socket} end @impl true def handle_event("stop-all", _, socket) do Slurp.Commander.stop_blockchains([]) blockchains = Slurp.Commander.blockchains([]) socket = socket |> assign(blockchains: blockchains) {:noreply, socket} end @impl true def handle_info(:search, socket) do socket = socket |> assign(:search_timer, nil) |> assign_search() {:noreply, socket} end @impl true def handle_info({"new_head_received", blockchain_id, block_number}, socket) do latest_blocks = socket.assigns.latest_blocks |> Map.put(blockchain_id, block_number) {:noreply, assign(socket, latest_blocks: latest_blocks)} end defp send_search_after(socket, after_ms) do if socket.assigns[:search_timer] do socket else timer = Process.send_after(self(), :search, after_ms) assign(socket, :search_timer, timer) end end defp assign_search(socket) do socket |> assign(blockchains: search_blockchains(socket.assigns.query)) end defp search_blockchains(search_term) do [] |> Slurp.Commander.blockchains() |> search_blockchains(search_term) end defp search_blockchains(blockchains, nil) do blockchains end defp search_blockchains(blockchains, search_term) do blockchains |> Enum.filter(fn b -> String.contains?(b.id, search_term) || String.contains?(b.name, search_term) || String.contains?(b.status |> Atom.to_string(), search_term) || String.contains?(b.network_id |> to_string(), search_term) || String.contains?(b.chain_id |> to_string(), search_term) || String.contains?(b.chain, search_term) || String.contains?(b.testnet |> to_string(), search_term) end) end defp running?(%Slurp.Commander.Blockchains.ListItem{status: :running}), do: true defp running?(_), do: false defp none_running?(blockchains), do: running_count(blockchains) == 0 defp all_running?(blockchains), do: running_count(blockchains) == length(blockchains) defp running_count(blockchains) do blockchains |> Enum.filter(&running?/1) |> Enum.count() end end