Skip to content

Commit

Permalink
Add LiveViewNative.LiveView dispatch_to
Browse files Browse the repository at this point in the history
This allows for finer grain control over which module the rendering
dispatches to
  • Loading branch information
bcardarella committed Dec 19, 2024
1 parent 2a1fb09 commit f388f34
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- `LiveViewNative.Component` no longer imports `Phoenix.Component.to_form/2`
- `LiveViewNative.LiveView` now requires the `dispatch_to` function to determine which module will be used for rendering

### Fixed

Expand Down
29 changes: 24 additions & 5 deletions lib/live_view_native/live_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@ defmodule LiveViewNative.LiveView do
defmodule MyAppWeb.HomeLive do
use MyAppWeb, :live_view
use LiveViewNative,
use LiveViewNative.LiveView,
formats: [:swiftui, :jetpack],
layouts: [
swiftui: {MyAppWeb.Layouts.SwiftUI, :app},
jetpack: {MyAppWeb.Layouts.Jetpack, :app}
]
],
dispatch_to: &Module.concat/2
end
## Options
* `:formats` - the formats this LiveView will delegate to
* `:formats` - the formats this LiveView will delegate to
a render component. For example, specifying `formats: [:swiftui, jetpack]`
for a LiveView named `MyAppWeb.HomeLive` will
invoke `MyAppWeb.HomeLive.SwiftUI` and `MyAppWeb.HomeLivew.Jetpack` when
Expand All @@ -38,19 +39,37 @@ defmodule LiveViewNative.LiveView do
* `:layouts` - which layouts to render for each format,
for example: `[swiftui: {MyAppWeb.Layouts.SwiftUI, :app}]`
* `:dispatch_to` - a function that takes the parent LiveView module
and the format's `plugin.module_suffix` and will determine
which module the `render/1` function will be called on
"""
defmacro __using__(opts) do
quote do
on_mount {LiveViewNative.ContentNegotiator, :call}
@native_opts unquote(opts)
@native_opts unquote(Keyword.take(opts, [:formats, :layouts, :dispatch_to]))
@before_compile LiveViewNative.LiveView
end
end

defp can_dispatch?(nil), do: false
defp can_dispatch?(dispatch_fn) when is_function(dispatch_fn),
do: Function.info(dispatch_fn)[:arity] == 2
defp can_dispatch?(_dispatch_fn), do: false

@doc false
defmacro __before_compile__(%{module: module} = env) do
opts = Module.get_attribute(module, :native_opts)
formats = opts[:formats]
dispatch_fn = opts[:dispatch_to]
if (!can_dispatch?(dispatch_fn)) do
raise """
A function with arity 2 must be passed to `dispatch_to` for `use LiveViewNative.LiveView` on module #{inspect(module)}.
You passed #{inspect(dispatch_fn)}
See docmentation for `LiveViewNative.LiveView.__using__/1`
"""
end
fallback_layouts = normalize_layouts(opts[:layouts])

cond do
Expand All @@ -59,7 +78,7 @@ defmodule LiveViewNative.LiveView do
Enum.reduce(formats, {%{}, %{}}, fn(format, {layouts, render_withs}) ->
case LiveViewNative.fetch_plugin(format) do
{:ok, plugin} ->
render_module = Module.concat(module, plugin.module_suffix)
render_module = dispatch_fn.(module, plugin.module_suffix)
fallback_layout = fallback_layouts[format]
render_with = Function.capture(render_module, :render, 1)

Expand Down
3 changes: 2 additions & 1 deletion priv/templates/lvn.gen/app_name_native.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ defmodule <%= inspect context.native_module %> do
layouts: [<%= if plugins? do %><%= for plugin <- plugins do %>
<%= plugin.format %>: {<%= inspect(Module.concat([context.web_module, Layouts, plugin.module_suffix])) %>, :app}<%= unless last?.(plugins, plugin) do %>,<% end %><% end %><% else %>
# swiftui: {<%= inspect(Module.concat([context.web_module, Layouts, SwiftUI])) %>, :app}<% end %>
]
],
dispatch_to: &Module.concat/2

unquote(verified_routes())
end
Expand Down
3 changes: 2 additions & 1 deletion test/support/live/cids_destroyed_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ defmodule LiveViewNativeTest.CidsDestroyedLive do
use Phoenix.LiveView

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

defmodule GameBoy do
use LiveViewNative.Component,
Expand Down
6 changes: 4 additions & 2 deletions test/support/live/component_and_nested_in_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ defmodule LiveViewNativeTest.ComponentAndNestedInLive do
use Phoenix.LiveView

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

defmodule GameBoy do
use LiveViewNative.Component,
Expand All @@ -13,7 +14,8 @@ defmodule LiveViewNativeTest.ComponentAndNestedInLive do
use Phoenix.LiveView

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

defmodule GameBoy do
use LiveViewNative.Component,
Expand Down
6 changes: 4 additions & 2 deletions test/support/live/component_in_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ defmodule LiveViewNativeTest.ComponentInLive.Root do
use Phoenix.LiveView

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

def mount(_params, _session, socket) do
{:ok, assign(socket, :enabled, true)}
Expand Down Expand Up @@ -30,7 +31,8 @@ defmodule LiveViewNativeTest.ComponentInLive.Live do
use Phoenix.LiveView

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

def render(assigns) do
~H"In HTML 2"
Expand Down
12 changes: 8 additions & 4 deletions test/support/live/components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,8 @@ defmodule LiveViewNativeTest.WithComponentLive do
use Phoenix.LiveView

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

def render(assigns), do: ~H"In HTML"

Expand Down Expand Up @@ -315,7 +316,8 @@ defmodule LiveViewNativeTest.WithMultipleTargets do
use Phoenix.LiveView

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

def render(assigns), do: ~H"In HTML"

Expand Down Expand Up @@ -369,7 +371,8 @@ defmodule LiveViewNativeTest.WithLogOverride do
use Phoenix.LiveView, log: :warning

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

def render(assigns), do: ~H"In HTML"

Expand All @@ -391,7 +394,8 @@ defmodule LiveViewNativeTest.WithLogDisabled do
use Phoenix.LiveView, log: false

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

def render(assigns), do: ~H"In HTML"

Expand Down
15 changes: 10 additions & 5 deletions test/support/live/general.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ defmodule LiveViewNativeTest.ThermostatLive do
use Phoenix.LiveView, container: {:article, class: "thermo"}, namespace: Phoenix.LiveViewTest

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

alias LiveViewNativeTest.ClockLive

Expand Down Expand Up @@ -102,7 +103,8 @@ defmodule LiveViewNativeTest.ClockLive do
use Phoenix.LiveView, container: {:section, class: "clock"}

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

alias LiveViewNativeTest.ClockControlsLive

Expand Down Expand Up @@ -151,7 +153,8 @@ defmodule LiveViewNativeTest.ClockControlsLive do
use Phoenix.LiveView

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

defmodule GameBoy do
use LiveViewNative.Component,
Expand Down Expand Up @@ -179,7 +182,8 @@ end
defmodule LiveViewNativeTest.DashboardLive do
use Phoenix.LiveView, container: {:div, class: inspect(__MODULE__)}
use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

defmodule GameBoy do
use LiveViewNative.Component,
Expand All @@ -204,7 +208,8 @@ end
defmodule LiveViewNativeTest.AssignAsyncLive do
use Phoenix.LiveView
use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

on_mount({__MODULE__, :defaults})

Expand Down
3 changes: 2 additions & 1 deletion test/support/live/inline_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ defmodule LiveViewNativeTest.InlineLive do
formats: [:gameboy, :switch],
layouts: [
gameboy: {LiveViewNativeTest.GameBoyLayouts, :app}
]
],
dispatch_to: &Module.concat/2

def mount(_params, _session, socket) do
{:ok, assign(socket, :count, 100)}
Expand Down
3 changes: 2 additions & 1 deletion test/support/live/params.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ defmodule LiveViewNativeTest.ParamCounterLive do
use Phoenix.LiveView

use LiveViewNative.LiveView,
formats: [:gameboy]
formats: [:gameboy],
dispatch_to: &Module.concat/2

defmodule GameBoy do
use LiveViewNative.Component,
Expand Down
3 changes: 2 additions & 1 deletion test/support/live/template_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ defmodule LiveViewNativeTest.TemplateLive do
formats: [:gameboy, :switch],
layouts: [
gameboy: {LiveViewNativeTest.GameBoyLayouts, :app}
]
],
dispatch_to: &Module.concat/2

def mount(_params, _session, socket) do
{:ok, assign(socket, :count, 200)}
Expand Down

0 comments on commit f388f34

Please sign in to comment.