# config counter = :counters.new(1, []) Application.put_env(:sfe, Sfe.Endpoint, http: [ip: {127, 0, 0, 1}, port: 5001], pubsub_server: Sfe.PubSub, adapter: Bandit.PhoenixAdapter, debug_errors: true, code_reloader: true, server: true, live_view: [signing_salt: "aaaaaaaa"], secret_key_base: String.duplicate("a", 64) ) Application.put_env(:sfe, Sfe.HomeLive, counter_ref: counter) # application defmodule Sfe do defmodule Application do use Elixir.Application require Logger def start(_type, _args) do Logger.debug("Sfe starting...") children = [ Sfe.Endpoint, {Phoenix.PubSub, name: Sfe.PubSub} ] opts = [strategy: :one_for_one, name: Sfe.Supervisor] Supervisor.start_link(children, opts) end end defmodule ErrorView do def render(template, _), do: Phoenix.Controller.status_message_from_template(template) end defmodule Router do use Phoenix.Router import Phoenix.LiveView.Router pipeline :browser do plug(:accepts, ["html"]) end scope "/", Sfe do pipe_through(:browser) live("/", HomeLive, :index) end end defmodule Endpoint do use Phoenix.Endpoint, otp_app: :sfe if code_reloading? do socket("/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket) plug(Phoenix.LiveReloader) plug(Phoenix.CodeReloader) end socket("/live", Phoenix.LiveView.Socket) plug(Sfe.Router) end end defmodule Sfe.HomeLive do use Phoenix.LiveView, layout: {__MODULE__, :live} @topic "counter" defp counter_ref(), do: Application.get_env(:sfe, __MODULE__)[:counter_ref] defp counter_value(), do: :counters.get(counter_ref(), 1) def mount(_params, _session, socket) do Sfe.Endpoint.subscribe(@topic) {:ok, assign(socket, :count, counter_value())} end defp phx_vsn, do: Application.spec(:phoenix, :vsn) defp lv_vsn, do: Application.spec(:phoenix_live_view, :vsn) def render("live.html", assigns) do ~H""" <%= @inner_content %> """ end def render(assigns) do ~H""" Multiplayer Counter <%= @count %> """ end def handle_event("inc", _params, socket) do dbg(:counters.add(counter_ref(), 1, 1)) counter_value(socket) end def handle_event("dec", _params, socket) do dbg(:counters.sub(counter_ref(), 1, 1)) counter_value(socket) end def handle_info(%{topic: "counter", event: "counter", payload: cval}, socket) do {:noreply, assign(socket, :count, cval)} end defp counter_value(socket) do Sfe.Endpoint.broadcast_from(self(), @topic, "counter", counter_value()) {:noreply, assign(socket, :count, counter_value())} end end