defmodule LambentExWeb.MachinesLive.Index do
use LambentExWeb, :live_view
alias LambentExWeb.MachinesLive.Index
import LambentEx.Utils.Color, only: [hex: 1]
@pubsub_name LambentEx.PubSub
@pubsub_topic_fh "machine:"
use Phoenix.LiveEditableView
alias LambentEx.LiveEdit
@speeds %{
# 1 => :THOU,
# 5 => :FTHOU,
10 => :HUNDREDTHS,
50 => :FHUNDREDTHS,
100 => :TENTHS,
500 => :FTENTHS,
1000 => :ONES,
2000 => :TWOS,
5000 => :FIVES,
10_000 => :TENS,
20_000 => :TWENTYS,
30_000 => :THIRTYS,
60_000 => :MINS
}
@impl true
def mount(_params, _session, socket) do
Phoenix.PubSub.subscribe(@pubsub_name, "machines_idx")
Phoenix.PubSub.subscribe(@pubsub_name, LambentEx.Machine.gone_topic())
Phoenix.PubSub.subscribe(@pubsub_name, @pubsub_topic_fh)
{:ok,
socket
|> assign(:machine, nil)
|> assign(:machines, %{})
|> assign(:previews, %{})
|> assign(:nonew, true)
|> assign(:newctrl, [
%{link: ~p"/cfg/machines/new", icon: "plus"},
%{link: ~p"/cfg/machines/library", icon: "book"}
])}
end
@impl true
def handle_params(params, _url, socket) do
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
end
defp apply_action(socket, :index, _params) do
socket
|> assign(:page_link, "Machines")
|> assign(:page_title, "Machine Library")
|> assign(:source, nil)
end
defp apply_action(socket, :new, params) do
# opened from the catalog, the form starts on that entry's configuration
machine =
case LambentEx.Schema.Machines.from_library(params["cls"], params["entry"]) do
nil -> %LambentEx.Schema.Machines{}
prefilled -> prefilled
end
socket
|> assign(:id, :new)
|> assign(:page_link, "Machines")
|> assign(
:page_title,
if(params["entry"], do: "Edit #{params["entry"]}", else: "New Machine")
)
|> assign(:machine, machine)
end
defp apply_action(socket, :library, _params) do
socket
|> assign(:id, :library)
|> assign(:page_link, "Machines")
|> assign(:page_title, "Machine Library")
|> assign(:machine, [])
end
def handle_info({:machines_pub, machine}, socket) do
# IO.inspect(machine)
{:noreply,
socket |> assign(:machines, socket.assigns.machines |> Map.put(machine[:id], machine))}
end
def handle_info({:machines_gone, name}, socket) do
{:noreply, drop_machine(socket, name)}
end
def handle_info({:firehose, {name, data}}, socket) do
{:noreply, socket |> assign(:previews, socket.assigns.previews |> Map.put(name, data))}
end
def handle_event("faster", data, socket) do
LambentEx.Machine.faster(data["id"])
{:noreply, socket}
end
def handle_event("slower", data, socket) do
LambentEx.Machine.slower(data["id"])
{:noreply, socket}
end
def handle_event("dimmer", data, socket) do
LambentEx.Machine.dimmer(data["id"])
{:noreply, socket}
end
def handle_event("brighter", data, socket) do
LambentEx.Machine.brighter(data["id"])
{:noreply, socket}
end
def handle_event("quit", params, socket) do
LambentEx.Machine.quit(params["tgt"])
{:noreply, drop_machine(socket, params["tgt"])}
end
def handle_event("persist", data, socket) do
LambentEx.Machine.persist(data["tgt"])
{:noreply, socket}
end
def handle_event("library-edit", %{"cls" => cls, "entry" => entry}, socket) do
{:noreply, push_patch(socket, to: ~p"/cfg/machines/new?cls=#{cls}&entry=#{entry}")}
end
# the class and entry come from the page, so anything not in the catalog is
# dropped rather than made into atoms
def handle_event("library-add", %{"cls" => cls, "entry" => entry}, socket) do
case LambentEx.Machines.Library.entry(cls, entry) do
nil ->
{:noreply, socket}
spec ->
opts = spec[:mach_opts] || []
LambentEx.MachineSupervisor.start_child(spec[:machine], spec[:args], entry, opts)
{:noreply, socket}
end
end
def handle_info(:update_library, socket) do
send_update(LambentEx.MachinesLive.LibraryFormComponent, id: :library)
{:noreply, socket}
end
defp spd(val) do
@speeds[val]
end
def bgt(val) do
(val / 255 * 100) |> trunc
end
# the listing is keyed by id (step x name), not by the name a quit is sent
# with, so it is matched on the name. the keys of a :full machine are listed
# under their own names, but all carry the machine's in their opts
defp drop_machine(socket, name) do
machines =
socket.assigns.machines
|> Enum.reject(fn {_id, m} -> m[:name] == name or m[:opts][:name] == name end)
|> Map.new()
socket
|> assign(:machines, machines)
|> assign(:previews, socket.assigns.previews |> Map.delete(name))
end
# the machine sends [r, g, b] pixels, but whatever shape turns up is cut back
# into pixels here rather than taking the page down with a FunctionClauseError
defp preview(pile, name) do
pile
|> Map.get(name, [])
|> List.flatten()
|> Enum.chunk_every(3, 3, :discard)
|> Enum.map(fn [r, g, b] -> "##{hex(r)}#{hex(g)}#{hex(b)}" end)
end
end
neiam
/lambent_ex
Lambent Aether 5
public · Issues · Pulls 1 · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
5.1 KiB · text
History
9c0fc16