137 lines
3.8 KiB
Elixir
137 lines
3.8 KiB
Elixir
defmodule Phoenix.LiveView.Socket.AssignsNotInSocket do
|
|
@moduledoc false
|
|
|
|
defimpl Inspect do
|
|
def inspect(_, _) do
|
|
"#Phoenix.LiveView.Socket.AssignsNotInSocket<>"
|
|
end
|
|
end
|
|
|
|
defstruct [:__assigns__]
|
|
@type t :: %__MODULE__{}
|
|
end
|
|
|
|
defmodule Phoenix.LiveView.Socket do
|
|
@moduledoc """
|
|
The LiveView socket for Phoenix Endpoints.
|
|
|
|
This is typically mounted directly in your endpoint.
|
|
|
|
socket "/live", Phoenix.LiveView.Socket,
|
|
websocket: [connect_info: [session: @session_options]]
|
|
|
|
To share an underlying transport connection between regular
|
|
Phoenix channels and LiveView processes, `use Phoenix.LiveView.Socket`
|
|
from your own `MyAppWeb.UserSocket` module.
|
|
|
|
Next, declare your `channel` definitions and optional `connect/3`, and
|
|
`id/1` callbacks to handle your channel specific needs, then mount
|
|
your own socket in your endpoint:
|
|
|
|
socket "/live", MyAppWeb.UserSocket,
|
|
websocket: [connect_info: [session: @session_options]]
|
|
|
|
If you require session options to be set at runtime, you can use
|
|
an MFA tuple. The function it designates must return a keyword list.
|
|
|
|
socket "/live", MyAppWeb.UserSocket,
|
|
websocket: [connect_info: [session: {__MODULE__, :runtime_opts, []}]]
|
|
|
|
# ...
|
|
|
|
def runtime_opts() do
|
|
Keyword.put(@session_options, :domain, host())
|
|
end
|
|
"""
|
|
use Phoenix.Socket
|
|
|
|
require Logger
|
|
|
|
@derive {Inspect,
|
|
only: [
|
|
:id,
|
|
:endpoint,
|
|
:router,
|
|
:view,
|
|
:parent_pid,
|
|
:root_pid,
|
|
:assigns,
|
|
:transport_pid
|
|
]}
|
|
|
|
defstruct id: nil,
|
|
endpoint: nil,
|
|
view: nil,
|
|
parent_pid: nil,
|
|
root_pid: nil,
|
|
router: nil,
|
|
assigns: %{__changed__: %{}},
|
|
private: %{live_temp: %{}},
|
|
fingerprints: Phoenix.LiveView.Diff.new_fingerprints(),
|
|
redirected: nil,
|
|
host_uri: nil,
|
|
transport_pid: nil
|
|
|
|
@typedoc "Struct returned when `assigns` is not in the socket."
|
|
@opaque assigns_not_in_socket :: Phoenix.LiveView.Socket.AssignsNotInSocket.t()
|
|
|
|
@typedoc "The data in a LiveView as stored in the socket."
|
|
@type assigns :: map | assigns_not_in_socket()
|
|
|
|
@type fingerprints :: {nil, map} | {binary, map}
|
|
|
|
@type t :: %__MODULE__{
|
|
id: binary(),
|
|
endpoint: module(),
|
|
view: module(),
|
|
parent_pid: nil | pid(),
|
|
root_pid: pid(),
|
|
router: module(),
|
|
assigns: assigns,
|
|
private: map(),
|
|
fingerprints: fingerprints,
|
|
redirected: nil | tuple(),
|
|
host_uri: URI.t() | :not_mounted_at_router,
|
|
transport_pid: pid() | nil
|
|
}
|
|
|
|
channel "lvu:*", Phoenix.LiveView.UploadChannel
|
|
channel "lv:*", Phoenix.LiveView.Channel
|
|
|
|
@impl Phoenix.Socket
|
|
def connect(_params, %Phoenix.Socket{} = socket, connect_info) do
|
|
{:ok, put_in(socket.private[:connect_info], connect_info)}
|
|
end
|
|
|
|
@impl Phoenix.Socket
|
|
def id(socket), do: socket.private.connect_info[:session]["live_socket_id"]
|
|
|
|
defmacro __using__(_opts) do
|
|
quote do
|
|
use Phoenix.Socket
|
|
|
|
channel "lvu:*", Phoenix.LiveView.UploadChannel
|
|
channel "lv:*", Phoenix.LiveView.Channel
|
|
|
|
def connect(params, socket, info), do: {:ok, socket}
|
|
defdelegate id(socket), to: unquote(__MODULE__)
|
|
|
|
defoverridable connect: 3, id: 1
|
|
|
|
@before_compile unquote(__MODULE__)
|
|
end
|
|
end
|
|
|
|
defmacro __before_compile__(_env) do
|
|
quote do
|
|
defoverridable connect: 3, id: 1
|
|
|
|
def connect(params, %Phoenix.Socket{} = socket, connect_info) do
|
|
with {:ok, %Phoenix.Socket{} = new_socket} <- super(params, socket, connect_info) do
|
|
Phoenix.LiveView.Socket.connect(params, new_socket, connect_info)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|