defmodule LivebookWeb.HomeLive do use LivebookWeb, :live_view import LivebookWeb.SessionHelpers alias LivebookWeb.{LearnHelpers, LayoutHelpers} alias Livebook.{Sessions, Notebook} on_mount LivebookWeb.SidebarHook @impl true def mount(_params, _session, socket) do if connected?(socket) do Livebook.Sessions.subscribe() Livebook.SystemResources.subscribe() Livebook.NotebookManager.subscribe_starred_notebooks() end sessions = Sessions.list_sessions() |> Enum.filter(&(&1.mode == :default)) notebook_infos = Notebook.Learn.visible_notebook_infos() |> Enum.take(3) starred_notebooks = Livebook.NotebookManager.starred_notebooks() {:ok, assign(socket, self_path: ~p"/", sessions: sessions, starred_notebooks: starred_notebooks, starred_expanded?: false, notebook_infos: notebook_infos, page_title: "Livebook", new_version: Livebook.UpdateCheck.new_version(), update_instructions_url: Livebook.Config.update_instructions_url(), app_service_url: Livebook.Config.app_service_url(), memory: Livebook.SystemResources.memory() )} end @impl true def render(assigns) do ~H""" <:topbar_action>
<.link navigate={~p"/open/file"} class="button-base button-outlined-gray whitespace-nowrap"> Open <.link class="button-base button-blue" patch={~p"/new"}> <.remix_icon icon="add-line" class="align-middle mr-1" /> New notebook
<.update_notification version={@new_version} instructions_url={@update_instructions_url} /> <.memory_notification memory={@memory} app_service_url={@app_service_url} />

Starred notebooks

<%= if @starred_notebooks == [] do %> <.no_entries> Your starred notebooks will appear here.
First time around? Check out the notebooks below to get started. <:actions> <.link navigate={~p"/learn"} class="flex items-center text-blue-600 pl-5"> Learn more <.remix_icon icon="arrow-right-line" class="align-middle ml-1" />
<% # Note: it's fine to use stateless components in this comprehension, # because @notebook_infos never change %>
<% else %> <.live_component module={LivebookWeb.NotebookCardsComponent} id="starred-notebook-list" notebook_infos={visible_starred_notebooks(@starred_notebooks, @starred_expanded?)} sessions={@sessions} added_at_label="Starred" > <:card_icon :let={{_info, idx}}> <% end %>
<.live_component module={LivebookWeb.HomeLive.SessionListComponent} id="session-list" sessions={@sessions} starred_notebooks={@starred_notebooks} memory={@memory} />
<.modal :if={@live_action == :import} id="import-modal" show width={:big} patch={@self_path}> <.live_component module={LivebookWeb.HomeLive.ImportComponent} id="import" tab={@tab} import_opts={@import_opts} /> """ end defp update_notification(%{version: nil} = assigns), do: ~H"" defp update_notification(assigns) do ~H"""
Livebook v<%= @version %> available! <%= if @instructions_url do %> Check out the news on livebook.dev and follow the update instructions <% else %> Check out the news and installation steps on livebook.dev <% end %> 🚀
""" end defp memory_notification(assigns) do ~H"""
<.remix_icon icon="alarm-warning-line" class="align-text-bottom mr-0.5" /> Less than 30 MB of memory left, consider adding more resources to the instance or closing running sessions
""" end @impl true def handle_params(%{"session_id" => session_id}, _url, socket) do session = Enum.find(socket.assigns.sessions, &(&1.id == session_id)) {:noreply, assign(socket, session: session)} end def handle_params(%{}, _url, socket) when socket.assigns.live_action == :public_new_notebook do {:noreply, create_session(socket, queue_setup: true)} end def handle_params(_params, _url, socket), do: {:noreply, socket} @impl true def handle_event("unstar_notebook", %{"idx" => idx}, socket) do on_confirm = fn socket -> %{file: file} = Enum.fetch!(socket.assigns.starred_notebooks, idx) Livebook.NotebookManager.remove_starred_notebook(file) socket end {:noreply, confirm(socket, on_confirm, title: "Unstar notebook", description: "Once you unstar this notebook, you can always star it again.", confirm_text: "Unstar", opt_out_id: "unstar-notebook" )} end def handle_event("toggle_starred_expanded", %{}, socket) do {:noreply, update(socket, :starred_expanded?, ¬/1)} end @impl true def handle_info({type, session} = event, socket) when type in [:session_created, :session_updated, :session_closed] and session.mode == :default do {:noreply, update(socket, :sessions, &update_session_list(&1, event))} end def handle_info({:memory_update, memory}, socket) do {:noreply, assign(socket, memory: memory)} end def handle_info({:starred_notebooks_updated, starred_notebooks}, socket) do {:noreply, assign(socket, starred_notebooks: starred_notebooks)} end def handle_info({:fork, file}, socket) do {:noreply, fork_notebook(socket, file)} end def handle_info({:open, file}, socket) do {:noreply, open_notebook(socket, file)} end def handle_info(_message, socket), do: {:noreply, socket} defp visible_starred_notebooks(notebooks, starred_expanded?) defp visible_starred_notebooks(notebooks, true), do: notebooks defp visible_starred_notebooks(notebooks, false), do: Enum.take(notebooks, 6) end