Skip to content

Instantly share code, notes, and snippets.

@bcardarella
Last active May 7, 2023 22:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bcardarella/753a24a728e3f2f3449c3dd683d4e6c6 to your computer and use it in GitHub Desktop.
Save bcardarella/753a24a728e3f2f3449c3dd683d4e6c6 to your computer and use it in GitHub Desktop.

LiveView Native Livebook

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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment