I am trying to use Phoenix LiveView to create a desktop application. Now, the only way to do this in a somewhat user friendly way (at least the only one I know off) is to launch my Phoenix app/server in and then open browser window in the client's machine.
And this is the trick. Opening a browser's window in the client's machine.
By looking into some github repositories of other formidable Elixir programmers, I was able to fetch a piece of code that somewhat does the job.
demo/lib/demo/application.ex
defmodule Demo.Application do
@moduledoc false
use Application
def start(_type, _args) do
children = [
DemoWeb.Telemetry,
{Phoenix.PubSub, name: Demo.PubSub},
DemoWeb.Endpoint
]
opts = [strategy: :one_for_one, name: Demo.Supervisor]
result = Supervisor.start_link(children, opts)
start_browser_command =
case :os.type do
{:win32, _} ->
"start"
{:unix, :darwin} ->
"open"
{:unix, _} ->
"xdg-open"
end
if System.find_executable(start_browser_command) do
System.cmd(start_browser_command, ["http://localhost:4000"])
else
Mix.raise "Command not found: #{start_browser_command}"
end
result
end
def config_change(changed, _new, removed) do
DemoWeb.Endpoint.config_change(changed, removed)
:ok
end
end
This is supposed to first start the Phoenix App and then open the window.
So, this code makes me feel a little uncomfortable for a specific reason: I was under the impression that the start
function should be only for starting my phoenix server and not for anything else.
But then the question arises:
start
function's job is only to launch the app, then what is the correct/best place to do other tasks, like opening a browser's window or performing some preparation after the app is launched?Typically, we use Application.start_phase/3
invented exactly for that purpose.
If you want to run it asynchronously, just spawn another supervised GenServer
that would implement handle_continue/2
and {:stop, :normal, _}
gracefully from there after having its job done.