From dc35518bad759fd74b7285b67a1c1dc7b22c6a7a Mon Sep 17 00:00:00 2001 From: Chili Palmer Date: Tue, 7 Jul 2026 22:43:05 +0200 Subject: [PATCH] fix: ai preferences crashed and deleted stuff in preferences --- assets/css/app.css | 1 + assets/css/overlays.css | 5 + assets/js/hooks/index.js | 2 + lib/bds/ai.ex | 14 +- lib/bds/desktop/shell_live.ex | 19 + lib/bds/desktop/shell_live/index.html.heex | 1 + lib/bds/desktop/shell_live/notify.ex | 6 + .../overlay_html/shell_overlay.html.heex | 17 + .../shell_live/settings_editor/ai_settings.ex | 56 +- mix.exs | 1 + mix.lock | 1 + priv/gettext/de/LC_MESSAGES/ui.po | 91 +- priv/gettext/en/LC_MESSAGES/ui.po | 91 +- priv/gettext/es/LC_MESSAGES/ui.po | 91 +- priv/gettext/fr/LC_MESSAGES/ui.po | 91 +- priv/gettext/it/LC_MESSAGES/ui.po | 91 +- priv/gettext/ui.pot | 91 +- priv/static/assets/app.css | 455 +++++++++ priv/static/assets/app.js | 954 ++++++++++++++++-- test/bds/ai_test.exs | 22 + test/bds/desktop/shell_live_test.exs | 44 + 21 files changed, 1883 insertions(+), 261 deletions(-) diff --git a/assets/css/app.css b/assets/css/app.css index cec90d7..478bc0b 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -3,6 +3,7 @@ @source "../css"; @source "../js"; @source "../../lib/bds/desktop"; +@source "../../deps/live_toast/lib"; @import "./tokens.css"; @import "./shell.css"; diff --git a/assets/css/overlays.css b/assets/css/overlays.css index 5d27594..f70239b 100644 --- a/assets/css/overlays.css +++ b/assets/css/overlays.css @@ -377,3 +377,8 @@ font: inherit; } + +/* Alert modal (errors) — reuses .confirm-delete-modal with a tone accent. */ +.alert-modal-error { + border-top: 3px solid #ff6b6b; +} diff --git a/assets/js/hooks/index.js b/assets/js/hooks/index.js index 58f52ba..3ebf318 100644 --- a/assets/js/hooks/index.js +++ b/assets/js/hooks/index.js @@ -6,8 +6,10 @@ import { ColourPicker } from "./colour_picker.js"; import { MenuEditorTree } from "./menu_editor_tree.js"; import { MonacoEditor } from "./monaco_editor.js"; import { MonacoDiffEditor } from "./monaco_diff_editor.js"; +import { createLiveToastHook } from "live_toast"; export const Hooks = { + LiveToast: createLiveToastHook(), AppShell, SidebarInteractions, SettingsSectionScroll, diff --git a/lib/bds/ai.ex b/lib/bds/ai.ex index 63a798c..4bf484c 100644 --- a/lib/bds/ai.ex +++ b/lib/bds/ai.ex @@ -54,13 +54,21 @@ defmodule BDS.AI do model = MapUtils.attr(attrs, :model) api_key = MapUtils.attr(attrs, :api_key) - with :ok <- put_setting("ai.#{kind_key}.url", url), - :ok <- put_setting("ai.#{kind_key}.model", model), - :ok <- put_secret("ai.#{kind_key}.api_key", api_key, backend) do + with :ok <- put_or_delete_setting("ai.#{kind_key}.url", url), + :ok <- put_or_delete_setting("ai.#{kind_key}.model", model), + :ok <- put_or_delete_secret("ai.#{kind_key}.api_key", api_key, backend) do {:ok, %{kind: kind, url: url, api_key: api_key, model: model}} end end + # A nil field means "clear it" — writing nil into put_setting/2 would raise a + # FunctionClauseError and crash the caller (the preferences panel). + defp put_or_delete_setting(key, nil), do: delete_setting(key) + defp put_or_delete_setting(key, value) when is_binary(value), do: put_setting(key, value) + + defp put_or_delete_secret(key, nil, _backend), do: delete_setting(encrypted_key(key)) + defp put_or_delete_secret(key, value, backend), do: put_secret(key, value, backend) + @spec get_endpoint(endpoint_kind(), keyword()) :: {:ok, endpoint() | nil} | {:error, term()} def get_endpoint(kind, opts \\ []) when is_atom(kind) and is_list(opts) do diff --git a/lib/bds/desktop/shell_live.ex b/lib/bds/desktop/shell_live.ex index 474d551..f5ba436 100644 --- a/lib/bds/desktop/shell_live.ex +++ b/lib/bds/desktop/shell_live.ex @@ -719,6 +719,11 @@ defmodule BDS.Desktop.ShellLive do {:noreply, refresh_sidebar(socket, socket.assigns.workbench)} end + def handle_info({:shell_alert, title, message}, socket) do + overlay = %{kind: :alert, title: title, message: message, tone: "error"} + {:noreply, assign(socket, :shell_overlay, overlay)} + end + def handle_info(message, socket) do Bridges.handle_info(message, socket, bridges_callbacks()) end @@ -729,6 +734,20 @@ defmodule BDS.Desktop.ShellLive do index(assigns) end + # Dark-themed toast classes for LiveToast (its default is bg-white/text-black). + # Mirrors the library's structural classes but uses the app's dark palette. + @doc false + @spec toast_class_fn(map()) :: [String.t() | false] + def toast_class_fn(assigns) do + [ + "group/toast z-100 pointer-events-auto relative w-full items-center justify-between origin-center overflow-hidden rounded-lg p-4 shadow-lg border col-start-1 col-end-1 row-start-1 row-end-2", + "bg-[#2d2d2d] text-[#f0f0f0] border-[#3c3c3c]", + "[@media(scripting:enabled)]:opacity-0 [@media(scripting:enabled){[data-phx-main]_&}]:opacity-100", + if(assigns[:rest][:hidden] == true, do: "hidden", else: "flex"), + assigns[:kind] == :error && "!bg-[#3a2020] !text-red-300 !border-[#5a2a2a]" + ] + end + defp refresh_layout(socket, workbench), do: SocketState.refresh_layout(socket, workbench) defp refresh_sidebar(socket, workbench), do: SocketState.refresh_sidebar(socket, workbench) diff --git a/lib/bds/desktop/shell_live/index.html.heex b/lib/bds/desktop/shell_live/index.html.heex index f40df65..a470c64 100644 --- a/lib/bds/desktop/shell_live/index.html.heex +++ b/lib/bds/desktop/shell_live/index.html.heex @@ -678,5 +678,6 @@ + diff --git a/lib/bds/desktop/shell_live/notify.ex b/lib/bds/desktop/shell_live/notify.ex index 7fb6797..aef233d 100644 --- a/lib/bds/desktop/shell_live/notify.ex +++ b/lib/bds/desktop/shell_live/notify.ex @@ -20,6 +20,12 @@ defmodule BDS.Desktop.ShellLive.Notify do :ok end + @spec alert(String.t(), String.t()) :: :ok + def alert(title, message) do + send(self(), {:shell_alert, title, message}) + :ok + end + @spec tab_meta(atom(), term(), String.t(), String.t()) :: :ok def tab_meta(type, id, title, subtitle) do send(self(), {:editor_tab_meta, type, id, %{title: title, subtitle: subtitle || ""}}) diff --git a/lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex b/lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex index 83cbc1a..f013e0a 100644 --- a/lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex +++ b/lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex @@ -186,6 +186,23 @@ + <% :alert -> %> +
+ +
+
+

<%= @shell_overlay.title %>

+ +
+
+
<%= @shell_overlay.message %>
+
+ +
+
+ <% :gallery -> %>