Mix . install (
[
{ :plug_cowboy , "~> 2.5" } ,
{ :jason , "~> 1.0" } ,
{ :phoenix , "~> 1.7.2" , override: true } ,
{ :phoenix_live_view , "~> 0.18.2" } ,
{ :phoenix_live_reload , "~> 1.4.1" , override: true } ,
{ :live_view_native , "~> 0.0.7" } ,
{ :live_view_native_swift_ui , "~> 0.0.7" }
] ,
config: [
live_view_native: [
{ :platforms , [ LiveViewNativeSwiftUi.Platform ] } ,
{ LiveViewNativeSwiftUi.Platform , [ app_name: "LiveView Native" ] }
] ,
live_view_native_livebook: [
{ LiveViewNativeLivebook.Endpoint ,
[
http: [ ip: { 127 , 0 , 0 , 1 } , port: 5001 ] ,
server: true ,
pubsub_server: LiveViewNativeLivebook.PubSub ,
live_view: [ signing_salt: "aaaaaaaa" ] ,
secret_key_base: String . duplicate ( "a" , 64 ) ,
live_reload: [
patterns: [
~r/ #{ __ENV__ . file |> String . split ( "#" ) |> hd ( ) } $/
]
]
] }
]
]
)
defmodule Router do
use Phoenix.Router
import Phoenix.LiveView.Router
pipeline :browser do
plug ( :accepts , [ "html" ] )
plug ( :put_root_layout , html: { LiveViewNativeLivebook.Layouts , :root_layout } )
end
scope "/" , LiveViewNativeLivebook do
pipe_through ( :browser )
live ( "/" , HomeLive , :index )
end
end
defmodule LiveViewNativeLivebook.LiveReloader.Socket do
use Phoenix.Socket , log: false
channel ( "phoenix:live_reload" , LiveViewNativeLivebook.LiveReloader.Channel )
def connect ( _params , socket ) , do: { :ok , socket }
def id ( _socket ) , do: nil
end
defmodule LiveViewNativeLivebook.LiveReloader.Channel do
use Phoenix.Channel
def join ( "phoenix:live_reload" , _msg , socket ) do
{ :ok , _ } = Application . ensure_all_started ( :phoenix_live_reload )
Phoenix.PubSub . subscribe ( LiveViewNativeLivebook.PubSub , "reloader" )
{ :ok , socket }
end
def handle_info ( :trigger , socket ) do
push ( socket , "assets_change" , % { asset_type: "" } )
{ :noreply , socket }
end
end
defmodule LiveViewNativeLivebook.Endpoint do
use Phoenix.Endpoint , otp_app: :live_view_native_livebook
socket ( "/live" , Phoenix.LiveView.Socket )
socket ( "/phoenix/live_reload/socket" , LiveViewNativeLivebook.LiveReloader.Socket )
plug ( Phoenix.LiveReloader )
plug ( Router )
end
defmodule LiveViewNativeLivebook.ErrorView do
def render ( template , _ ) , do: Phoenix.Controller . status_message_from_template ( template )
end
defmodule LiveViewNativeLivebook.Layouts do
import Phoenix.Component , only: [ sigil_H: 2 ]
import Phoenix.HTML.Tag
def root_layout ( assigns ) do
~H"""
< html >
< head >
< meta name = "csrf-token " content = { csrf_token_value ( ) } >
</ head >
< body >
<%= @ inner_content %>
</ body >
</ html >
"""
end
end
Run the application Supervisor
{ :ok , pid } =
Supervisor . start_link (
[
{ Phoenix.PubSub , name: LiveViewNativeLivebook.PubSub } ,
LiveViewNativeLivebook.Endpoint
] ,
strategy: :one_for_one
)
Modify the templates for each platform
defmodule LiveViewNativeLivebook.HomeLive do
use Phoenix.LiveView , layout: { __MODULE__ , :layout }
use LiveViewNative.LiveView
def layout ( assigns ) do
~H"""
<%= @ inner_content %>
"""
end
@ impl true
def render ( % { platform_id: :swiftui } = assigns ) do
~Z"""
<Text modifiers={@native |> foreground_style(primary: {:color, :mint})}>
Hello from LiveView Native!
</Text>
""" swiftui
end
def render ( assigns ) do
~H"""
< div > Hello from LiveView!!</ div >
"""
end
end
Trigger the reloader after each template update
Phoenix.PubSub . broadcast! ( LiveViewNativeLivebook.PubSub , "reloader" , :trigger )