feat: desktop mode falls back to the TUI when no graphical display is available (issue #33)

This commit is contained in:
2026-07-16 17:46:36 +02:00
parent 5801e49dc1
commit 381deb417d
4 changed files with 71 additions and 3 deletions

View File

@@ -57,7 +57,7 @@ defmodule BDS.Application do
{Task.Supervisor, name: BDS.Scripting.TaskSupervisor},
BDS.Scripting.JobSupervisor,
BDS.Embeddings.Index
] ++ embedding_children() ++ mode_children(BDS.Server.mode(), current_env())
] ++ embedding_children() ++ mode_children(boot_mode(), current_env())
opts = [strategy: :one_for_one, name: BDS.Supervisor]
Supervisor.start_link(children, opts)
@@ -77,6 +77,20 @@ defmodule BDS.Application do
Application.get_env(:bds, :current_env_override) || @compiled_env
end
# Desktop mode without a graphical display boots the TUI instead
# (issue #33); the log line explains the surprise mode switch.
defp boot_mode do
resolved = BDS.Server.mode()
effective = BDS.Server.effective_mode(resolved)
if effective != resolved do
require Logger
Logger.info("No graphical display available, starting the terminal UI instead")
end
effective
end
defp desktop_window_children do
if desktop_automation?() do
[]

View File

@@ -28,6 +28,29 @@ defmodule BDS.Server do
def mode(nil), do: :desktop
@doc """
The mode the app actually boots in: the resolved `BDS_MODE`, except that
desktop mode falls back to the TUI when no graphical display is available
(issue #33). Starting the app on a display-less Linux server then still
opens a UI — the terminal one — instead of crashing wx.
Only non-Darwin unix systems fall back: they need `DISPLAY` or
`WAYLAND_DISPLAY` to run wx, while macOS and Windows always have a
graphical session for a launched app.
"""
@spec effective_mode(:desktop | :server | :tui, {atom(), atom()}, %{
optional(String.t()) => String.t()
}) :: :desktop | :server | :tui
def effective_mode(mode \\ mode(), os_type \\ :os.type(), env \\ System.get_env())
def effective_mode(:desktop, {:unix, os}, env) when os != :darwin do
if Enum.any?(["DISPLAY", "WAYLAND_DISPLAY"], &(env[&1] not in [nil, ""])),
do: :desktop,
else: :tui
end
def effective_mode(mode, _os_type, _env), do: mode
@doc """
Whether the HTTP endpoint requires the desktop webview auth token. Only
desktop mode does: in server/tui mode the endpoint stays loopback-only
@@ -35,7 +58,7 @@ defmodule BDS.Server do
per-boot webview token would otherwise lock out.
"""
@spec desktop_auth_required?(:desktop | :server | :tui) :: boolean()
def desktop_auth_required?(mode \\ mode())
def desktop_auth_required?(mode \\ effective_mode())
def desktop_auth_required?(:desktop), do: true
def desktop_auth_required?(_mode), do: false