chore: noise in tests
This commit is contained in:
@@ -16,17 +16,38 @@ defmodule BDS.Desktop.ShellData do
|
||||
|
||||
def activity_icon(id) do
|
||||
case to_string(id) do
|
||||
"posts" -> ~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6zM6 20V4h7v5h5v11H6z"></path><path d="M8 12h8v2H8zm0 4h8v2H8z"></path></svg>)
|
||||
"pages" -> ~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M4 4h10v4h6v12H4V4zm10 1.5V9h4.5L14 5.5zM7 12h10v1.5H7V12zm0 3h10v1.5H7V15z"></path></svg>)
|
||||
"media" -> ~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"></path></svg>)
|
||||
"scripts" -> ~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M20 3H4a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h7v2H8v2h8v-2h-3v-2h7a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1zM5 14V5h14v9H5zm2-7.5L9.5 9 7 11.5l1.4 1.4L12.3 9 8.4 5.1 7 6.5zm6.5 5.5h4v-2h-4v2z"></path></svg>)
|
||||
"templates" -> ~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M4 4h7v7H4V4zm9 0h7v7h-7V4zM4 13h7v7H4v-7zm9 0h7v7h-7v-7zM5.5 5.5v4h4v-4h-4zm9 0v4h4v-4h-4zm-9 9v4h4v-4h-4zm9 0v4h4v-4h-4z"></path></svg>)
|
||||
"tags" -> ~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58s1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41s-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"></path></svg>)
|
||||
"chat" -> ~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z"></path><circle cx="8" cy="10" r="1.5"></circle><circle cx="12" cy="10" r="1.5"></circle><circle cx="16" cy="10" r="1.5"></circle></svg>)
|
||||
"import" -> ~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></svg>)
|
||||
"git" -> ~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M22 11.73L12.27 2a1 1 0 0 0-1.41 0L8.84 4.02l2.56 2.56a1.2 1.2 0 0 1 1.52 1.53l2.47 2.47a1.2 1.2 0 1 1-.72.67l-2.3-2.3v6.06a1.2 1.2 0 1 1-.85 0V8.9a1.2 1.2 0 0 1-.66-1.59L8.35 4.8 2 11.16a1 1 0 0 0 0 1.41L11.73 22a1 1 0 0 0 1.41 0L22 13.14a1 1 0 0 0 0-1.41z"></path></svg>)
|
||||
"settings" -> ~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M19.14 12.94c.04-.31.06-.63.06-.94 0-.31-.02-.63-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"></path></svg>)
|
||||
_other -> activity_icon("posts")
|
||||
"posts" ->
|
||||
~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6zM6 20V4h7v5h5v11H6z"></path><path d="M8 12h8v2H8zm0 4h8v2H8z"></path></svg>)
|
||||
|
||||
"pages" ->
|
||||
~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M4 4h10v4h6v12H4V4zm10 1.5V9h4.5L14 5.5zM7 12h10v1.5H7V12zm0 3h10v1.5H7V15z"></path></svg>)
|
||||
|
||||
"media" ->
|
||||
~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"></path></svg>)
|
||||
|
||||
"scripts" ->
|
||||
~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M20 3H4a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h7v2H8v2h8v-2h-3v-2h7a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1zM5 14V5h14v9H5zm2-7.5L9.5 9 7 11.5l1.4 1.4L12.3 9 8.4 5.1 7 6.5zm6.5 5.5h4v-2h-4v2z"></path></svg>)
|
||||
|
||||
"templates" ->
|
||||
~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M4 4h7v7H4V4zm9 0h7v7h-7V4zM4 13h7v7H4v-7zm9 0h7v7h-7v-7zM5.5 5.5v4h4v-4h-4zm9 0v4h4v-4h-4zm-9 9v4h4v-4h-4zm9 0v4h4v-4h-4z"></path></svg>)
|
||||
|
||||
"tags" ->
|
||||
~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58s1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41s-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"></path></svg>)
|
||||
|
||||
"chat" ->
|
||||
~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z"></path><circle cx="8" cy="10" r="1.5"></circle><circle cx="12" cy="10" r="1.5"></circle><circle cx="16" cy="10" r="1.5"></circle></svg>)
|
||||
|
||||
"import" ->
|
||||
~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></svg>)
|
||||
|
||||
"git" ->
|
||||
~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M22 11.73L12.27 2a1 1 0 0 0-1.41 0L8.84 4.02l2.56 2.56a1.2 1.2 0 0 1 1.52 1.53l2.47 2.47a1.2 1.2 0 1 1-.72.67l-2.3-2.3v6.06a1.2 1.2 0 1 1-.85 0V8.9a1.2 1.2 0 0 1-.66-1.59L8.35 4.8 2 11.16a1 1 0 0 0 0 1.41L11.73 22a1 1 0 0 0 1.41 0L22 13.14a1 1 0 0 0 0-1.41z"></path></svg>)
|
||||
|
||||
"settings" ->
|
||||
~s(<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M19.14 12.94c.04-.31.06-.63.06-.94 0-.31-.02-.63-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"></path></svg>)
|
||||
|
||||
_other ->
|
||||
activity_icon("posts")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -83,18 +104,28 @@ defmodule BDS.Desktop.ShellData do
|
||||
|
||||
def assistant_cards do
|
||||
[
|
||||
%{label: dgettext("ui", "Offline Gate"), text: dgettext("ui", "Automatic AI actions stay gated by airplane mode.")},
|
||||
%{
|
||||
label: dgettext("ui", "Offline Gate"),
|
||||
text: dgettext("ui", "Automatic AI actions stay gated by airplane mode.")
|
||||
},
|
||||
%{
|
||||
label: dgettext("ui", "Filesystem Sync"),
|
||||
text: dgettext("ui", "Metadata flush, diffing, and rebuild hooks still need editor wiring.")
|
||||
text:
|
||||
dgettext("ui", "Metadata flush, diffing, and rebuild hooks still need editor wiring.")
|
||||
},
|
||||
%{label: dgettext("ui", "Desktop Runtime"), text: dgettext("ui", "The app window is now served from LiveView state.")}
|
||||
%{
|
||||
label: dgettext("ui", "Desktop Runtime"),
|
||||
text: dgettext("ui", "The app window is now served from LiveView state.")
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
def editor_meta(task_status) do
|
||||
[
|
||||
%{label: dgettext("ui", "Status"), value: task_status.running_task_message || dgettext("ui", "Idle")},
|
||||
%{
|
||||
label: dgettext("ui", "Status"),
|
||||
value: task_status.running_task_message || dgettext("ui", "Idle")
|
||||
},
|
||||
%{label: dgettext("ui", "Mode"), value: dgettext("ui", "Offline")},
|
||||
%{label: dgettext("ui", "Main Language"), value: ui_language()}
|
||||
]
|
||||
@@ -120,12 +151,24 @@ defmodule BDS.Desktop.ShellData do
|
||||
|
||||
def git_badge_count(project_id, opts) when is_binary(project_id) do
|
||||
provider = Keyword.get(opts, :provider, git_remote_state_provider())
|
||||
custom_provider? = provider != (&BDS.Git.remote_state/2)
|
||||
|
||||
try do
|
||||
case provider.(project_id, []) do
|
||||
{:ok, %{behind: behind}} when is_integer(behind) and behind > 0 -> behind
|
||||
{:ok, %{behind: behind}} when is_binary(behind) -> parse_positive_count(behind)
|
||||
_other -> 0
|
||||
has_git =
|
||||
custom_provider? ||
|
||||
case BDS.Projects.get_project(project_id) do
|
||||
nil -> false
|
||||
project -> File.dir?(Path.join(BDS.Projects.project_data_dir(project), ".git"))
|
||||
end
|
||||
|
||||
if has_git do
|
||||
case provider.(project_id, []) do
|
||||
{:ok, %{behind: behind}} when is_integer(behind) and behind > 0 -> behind
|
||||
{:ok, %{behind: behind}} when is_binary(behind) -> parse_positive_count(behind)
|
||||
_other -> 0
|
||||
end
|
||||
else
|
||||
0
|
||||
end
|
||||
rescue
|
||||
error in [DBConnection.OwnershipError, Exqlite.Error] ->
|
||||
|
||||
@@ -60,6 +60,9 @@ defmodule BDS.Desktop.ShellLive do
|
||||
use Gettext, backend: BDS.Gettext
|
||||
|
||||
@refresh_interval 1_500
|
||||
|
||||
def refresh_interval, do: @refresh_interval
|
||||
|
||||
@output_entry_limit 20
|
||||
@sidebar_filter_events [
|
||||
"toggle_sidebar_filters",
|
||||
@@ -126,7 +129,9 @@ defmodule BDS.Desktop.ShellLive do
|
||||
|> MapSet.union(MapSet.new([:open_in_browser, :open_data_folder]))
|
||||
|> MapSet.union(MapSet.new([:preview_post, :rebuild_database, :reindex_text]))
|
||||
|> MapSet.union(MapSet.new([:rebuild_embedding_index, :metadata_diff, :regenerate_calendar]))
|
||||
|> MapSet.union(MapSet.new([:validate_translations, :fill_missing_translations, :find_duplicates]))
|
||||
|> MapSet.union(
|
||||
MapSet.new([:validate_translations, :fill_missing_translations, :find_duplicates])
|
||||
)
|
||||
|> MapSet.union(MapSet.new([:generate_sitemap, :validate_site, :upload_site]))
|
||||
end
|
||||
|
||||
@@ -138,7 +143,7 @@ defmodule BDS.Desktop.ShellLive do
|
||||
|
||||
if connected do
|
||||
Phoenix.PubSub.subscribe(BDS.PubSub, Watcher.topic())
|
||||
:timer.send_interval(@refresh_interval, :refresh_task_status)
|
||||
Process.send_after(self(), :refresh_task_status, @refresh_interval)
|
||||
end
|
||||
|
||||
workbench = Workbench.new()
|
||||
@@ -158,13 +163,13 @@ defmodule BDS.Desktop.ShellLive do
|
||||
|> assign(:titlebar_menu_item_index, nil)
|
||||
|> assign(:tab_meta, %{})
|
||||
|> assign(:project_menu_open, false)
|
||||
|> assign(:sidebar_filters_by_view, %{})
|
||||
|> assign(:sidebar_filter_panels, %{})
|
||||
|> assign(:chat_editor_request_refs, %{})
|
||||
|> assign(:shell_overlay, nil)
|
||||
|> assign(:output_entries, [])
|
||||
|> reload_shell(workbench)
|
||||
|> tap(&sync_menu_bar_locale/1)}
|
||||
|> assign(:sidebar_filters_by_view, %{})
|
||||
|> assign(:sidebar_filter_panels, %{})
|
||||
|> assign(:chat_editor_request_refs, %{})
|
||||
|> assign(:shell_overlay, nil)
|
||||
|> assign(:output_entries, [])
|
||||
|> reload_shell(workbench)
|
||||
|> tap(&sync_menu_bar_locale/1)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
@@ -262,7 +267,14 @@ defmodule BDS.Desktop.ShellLive do
|
||||
%{"route" => route, "id" => id} = params,
|
||||
socket
|
||||
) do
|
||||
{:noreply, SidebarDelete.request_delete(socket, route, id, Map.get(params, "title"), sidebar_delete_callbacks())}
|
||||
{:noreply,
|
||||
SidebarDelete.request_delete(
|
||||
socket,
|
||||
route,
|
||||
id,
|
||||
Map.get(params, "title"),
|
||||
sidebar_delete_callbacks()
|
||||
)}
|
||||
end
|
||||
|
||||
def handle_event("toggle_offline_mode", _params, socket) do
|
||||
@@ -319,7 +331,8 @@ defmodule BDS.Desktop.ShellLive do
|
||||
do: OverlayManager.handle_event("overlay_keydown", params, socket, overlay_callbacks())
|
||||
|
||||
def handle_event("overlay_toggle_ai_field", params, socket),
|
||||
do: OverlayManager.handle_event("overlay_toggle_ai_field", params, socket, overlay_callbacks())
|
||||
do:
|
||||
OverlayManager.handle_event("overlay_toggle_ai_field", params, socket, overlay_callbacks())
|
||||
|
||||
def handle_event("overlay_set_search", params, socket),
|
||||
do: OverlayManager.handle_event("overlay_set_search", params, socket, overlay_callbacks())
|
||||
@@ -334,22 +347,36 @@ defmodule BDS.Desktop.ShellLive do
|
||||
do: OverlayManager.handle_event("overlay_select_result", params, socket, overlay_callbacks())
|
||||
|
||||
def handle_event("overlay_insert_external", params, socket),
|
||||
do: OverlayManager.handle_event("overlay_insert_external", params, socket, overlay_callbacks())
|
||||
do:
|
||||
OverlayManager.handle_event("overlay_insert_external", params, socket, overlay_callbacks())
|
||||
|
||||
def handle_event("overlay_select_language", params, socket),
|
||||
do: OverlayManager.handle_event("overlay_select_language", params, socket, overlay_callbacks())
|
||||
do:
|
||||
OverlayManager.handle_event("overlay_select_language", params, socket, overlay_callbacks())
|
||||
|
||||
def handle_event("overlay_confirm", params, socket),
|
||||
do: OverlayManager.handle_event("overlay_confirm", params, socket, overlay_callbacks())
|
||||
|
||||
def handle_event("overlay_select_gallery_image", params, socket),
|
||||
do: OverlayManager.handle_event("overlay_select_gallery_image", params, socket, overlay_callbacks())
|
||||
do:
|
||||
OverlayManager.handle_event(
|
||||
"overlay_select_gallery_image",
|
||||
params,
|
||||
socket,
|
||||
overlay_callbacks()
|
||||
)
|
||||
|
||||
def handle_event("overlay_close_lightbox", params, socket),
|
||||
do: OverlayManager.handle_event("overlay_close_lightbox", params, socket, overlay_callbacks())
|
||||
|
||||
def handle_event("overlay_lightbox_previous", params, socket),
|
||||
do: OverlayManager.handle_event("overlay_lightbox_previous", params, socket, overlay_callbacks())
|
||||
do:
|
||||
OverlayManager.handle_event(
|
||||
"overlay_lightbox_previous",
|
||||
params,
|
||||
socket,
|
||||
overlay_callbacks()
|
||||
)
|
||||
|
||||
def handle_event("overlay_lightbox_next", params, socket),
|
||||
do: OverlayManager.handle_event("overlay_lightbox_next", params, socket, overlay_callbacks())
|
||||
@@ -484,7 +511,8 @@ defmodule BDS.Desktop.ShellLive do
|
||||
next_socket =
|
||||
cond do
|
||||
Map.has_key?(socket.assigns.chat_editor_request_refs, ref) ->
|
||||
{conversation_id, remaining_refs} = Map.pop(socket.assigns.chat_editor_request_refs, ref)
|
||||
{conversation_id, remaining_refs} =
|
||||
Map.pop(socket.assigns.chat_editor_request_refs, ref)
|
||||
|
||||
if reason == :normal do
|
||||
assign(socket, :chat_editor_request_refs, remaining_refs)
|
||||
@@ -552,7 +580,7 @@ defmodule BDS.Desktop.ShellLive do
|
||||
task_status = localize_task_status(raw_task_status, page_language)
|
||||
|
||||
socket
|
||||
|> assign(:tab_meta, tab_meta)
|
||||
|> assign(:tab_meta, tab_meta)
|
||||
|> assign(:workbench, workbench)
|
||||
|> assign(:projects, projects)
|
||||
|> assign(:current_project, ShellData.current_project(projects))
|
||||
@@ -737,7 +765,13 @@ defmodule BDS.Desktop.ShellLive do
|
||||
apply_shell_command(socket, Atom.to_string(action))
|
||||
|
||||
true ->
|
||||
append_output_entry(socket, "Menu", "Unsupported shell command", Atom.to_string(action), "error")
|
||||
append_output_entry(
|
||||
socket,
|
||||
"Menu",
|
||||
"Unsupported shell command",
|
||||
Atom.to_string(action),
|
||||
"error"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -871,5 +905,4 @@ defmodule BDS.Desktop.ShellLive do
|
||||
pid -> send(pid, {:set_ui_locale, locale})
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ defmodule BDS.Desktop.ShellLive.Bridges do
|
||||
@moduledoc false
|
||||
|
||||
import Phoenix.Component, only: [assign: 3]
|
||||
import Phoenix.LiveView, only: [send_update: 2]
|
||||
import Phoenix.LiveView, only: [connected?: 1, send_update: 2]
|
||||
|
||||
alias BDS.Desktop.ShellData
|
||||
alias BDS.Desktop.ShellLive.{ChatEditor, PostEditor}
|
||||
@@ -103,7 +103,8 @@ defmodule BDS.Desktop.ShellLive.Bridges do
|
||||
end
|
||||
|
||||
def handle_info({:chat_editor_switch_view, view}, socket, callbacks) do
|
||||
{:noreply, callbacks.reload.(socket, Workbench.click_activity(socket.assigns.workbench, view))}
|
||||
{:noreply,
|
||||
callbacks.reload.(socket, Workbench.click_activity(socket.assigns.workbench, view))}
|
||||
end
|
||||
|
||||
def handle_info({:entity_changed, payload}, socket, callbacks) when is_map(payload) do
|
||||
@@ -113,35 +114,40 @@ defmodule BDS.Desktop.ShellLive.Bridges do
|
||||
def handle_info(:refresh_task_status, socket, callbacks) do
|
||||
raw_task_status = BDS.Tasks.status_snapshot()
|
||||
|
||||
case SessionUtil.next_completed_task_result(socket, raw_task_status) do
|
||||
nil ->
|
||||
task_status =
|
||||
BDS.Desktop.ShellLive.TaskLocalization.localize_task_status(
|
||||
raw_task_status,
|
||||
socket.assigns.page_language
|
||||
socket =
|
||||
case SessionUtil.next_completed_task_result(socket, raw_task_status) do
|
||||
nil ->
|
||||
task_status =
|
||||
BDS.Desktop.ShellLive.TaskLocalization.localize_task_status(
|
||||
raw_task_status,
|
||||
socket.assigns.page_language
|
||||
)
|
||||
|
||||
socket
|
||||
|> assign(:task_status, task_status)
|
||||
|> assign(:editor_meta, ShellData.editor_meta(task_status))
|
||||
|> assign(
|
||||
:status,
|
||||
ShellData.status_bar(
|
||||
socket.assigns.workbench,
|
||||
task_status,
|
||||
socket.assigns.dashboard,
|
||||
ui_language: socket.assigns.page_language,
|
||||
offline_mode: socket.assigns.offline_mode
|
||||
)
|
||||
)
|
||||
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign(:task_status, task_status)
|
||||
|> assign(:editor_meta, ShellData.editor_meta(task_status))
|
||||
|> assign(
|
||||
:status,
|
||||
ShellData.status_bar(
|
||||
socket.assigns.workbench,
|
||||
task_status,
|
||||
socket.assigns.dashboard,
|
||||
ui_language: socket.assigns.page_language,
|
||||
offline_mode: socket.assigns.offline_mode
|
||||
)
|
||||
)}
|
||||
task ->
|
||||
socket
|
||||
|> SessionUtil.mark_task_result_handled(task.id)
|
||||
|> callbacks.apply_shell_command_result.(task.result)
|
||||
end
|
||||
|
||||
task ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> SessionUtil.mark_task_result_handled(task.id)
|
||||
|> callbacks.apply_shell_command_result.(task.result)}
|
||||
if connected?(socket) do
|
||||
Process.send_after(self(), :refresh_task_status, BDS.Desktop.ShellLive.refresh_interval())
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_info({:tags_editor_output, title, message, level}, socket, callbacks) do
|
||||
@@ -210,7 +216,12 @@ defmodule BDS.Desktop.ShellLive.Bridges do
|
||||
end
|
||||
|
||||
def handle_info({:post_editor_insert_content, post_id, content}, socket, _callbacks) do
|
||||
send_update(PostEditor, id: "post-editor-#{post_id}", action: :insert_content, content: content)
|
||||
send_update(PostEditor,
|
||||
id: "post-editor-#{post_id}",
|
||||
action: :insert_content,
|
||||
content: content
|
||||
)
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
@@ -220,7 +231,8 @@ defmodule BDS.Desktop.ShellLive.Bridges do
|
||||
end
|
||||
|
||||
def handle_info({:post_editor_apply_ai_suggestions, post_id, fields}, socket, _callbacks) do
|
||||
send_update(PostEditor, id: "post-editor-#{post_id}",
|
||||
send_update(PostEditor,
|
||||
id: "post-editor-#{post_id}",
|
||||
action: :apply_ai_suggestions,
|
||||
fields: fields
|
||||
)
|
||||
|
||||
@@ -61,7 +61,8 @@ defmodule BDS.Desktop.ShellLive.ChatEditor do
|
||||
|
||||
def handle_event("toggle_chat_model_selector", _params, socket) do
|
||||
{:noreply,
|
||||
assign(socket, :model_selector_open?, not socket.assigns.model_selector_open?) |> build_data()}
|
||||
assign(socket, :model_selector_open?, not socket.assigns.model_selector_open?)
|
||||
|> build_data()}
|
||||
end
|
||||
|
||||
def handle_event("select_chat_model", %{"model" => model_id}, socket) do
|
||||
@@ -101,7 +102,10 @@ defmodule BDS.Desktop.ShellLive.ChatEditor do
|
||||
) do
|
||||
socket =
|
||||
socket
|
||||
|> assign(:surface_tabs, Map.put(socket.assigns.surface_tabs, surface_id, parse_integer(index)))
|
||||
|> assign(
|
||||
:surface_tabs,
|
||||
Map.put(socket.assigns.surface_tabs, surface_id, parse_integer(index))
|
||||
)
|
||||
|> build_data()
|
||||
|
||||
{:noreply, socket}
|
||||
@@ -272,7 +276,10 @@ defmodule BDS.Desktop.ShellLive.ChatEditor do
|
||||
assign(socket, :request, nil) |> build_data()
|
||||
|
||||
{:error, reason} ->
|
||||
notify_parent({:chat_editor_output, dgettext("ui", "Chat"), format_error(reason), "error"})
|
||||
notify_parent(
|
||||
{:chat_editor_output, dgettext("ui", "Chat"), format_error(reason), "error"}
|
||||
)
|
||||
|
||||
assign(socket, :request, nil) |> build_data()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -215,7 +215,8 @@ defmodule BDS.Desktop.ShellLive.ChatEditor.MessageBuild do
|
||||
persisted_markers = persisted_tool_markers_for_request(messages, request)
|
||||
|
||||
{remaining, _persisted_markers} =
|
||||
Enum.reduce(tool_markers, {[], persisted_markers}, fn marker, {remaining, persisted_markers} ->
|
||||
Enum.reduce(tool_markers, {[], persisted_markers}, fn marker,
|
||||
{remaining, persisted_markers} ->
|
||||
case pop_matching_tool_marker(persisted_markers, marker) do
|
||||
{nil, persisted_markers} -> {remaining ++ [marker], persisted_markers}
|
||||
{_matched, persisted_markers} -> {remaining, persisted_markers}
|
||||
|
||||
@@ -30,9 +30,17 @@ defmodule BDS.Desktop.ShellLive.ChatSurface do
|
||||
|
||||
defp assistant_reply(socket) do
|
||||
if socket.assigns.offline_mode do
|
||||
BDS.Gettext.lgettext(socket.assigns.page_language, "ui", "Automatic AI actions stay gated by airplane mode.")
|
||||
BDS.Gettext.lgettext(
|
||||
socket.assigns.page_language,
|
||||
"ui",
|
||||
"Automatic AI actions stay gated by airplane mode."
|
||||
)
|
||||
else
|
||||
BDS.Gettext.lgettext(socket.assigns.page_language, "ui", "The assistant sidebar chat surface is ready, but model execution is not connected yet.")
|
||||
BDS.Gettext.lgettext(
|
||||
socket.assigns.page_language,
|
||||
"ui",
|
||||
"The assistant sidebar chat surface is ready, but model execution is not connected yet."
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,6 +31,7 @@ defmodule BDS.Desktop.ShellLive.ImportEditor do
|
||||
]
|
||||
|
||||
use Gettext, backend: BDS.Gettext
|
||||
|
||||
import TaxonomyEditing,
|
||||
only: [
|
||||
existing_taxonomy_terms: 1,
|
||||
@@ -344,7 +345,8 @@ defmodule BDS.Desktop.ShellLive.ImportEditor do
|
||||
mapped_to <- Map.get(params, "mapped_to"),
|
||||
normalized_value <-
|
||||
TaxonomyEditing.normalize_taxonomy_mapping_value(project_id, type, mapped_to),
|
||||
updated_report <- TaxonomyEditing.update_taxonomy_mapping(report, type, name, normalized_value),
|
||||
updated_report <-
|
||||
TaxonomyEditing.update_taxonomy_mapping(report, type, name, normalized_value),
|
||||
{:ok, _definition} <-
|
||||
ImportDefinitions.update_definition(definition_id, %{
|
||||
last_analysis_result: updated_report
|
||||
@@ -375,7 +377,8 @@ defmodule BDS.Desktop.ShellLive.ImportEditor do
|
||||
%{} = report <- ImportDefinitions.decode_analysis_result(definition),
|
||||
normalized_value <-
|
||||
TaxonomyEditing.normalize_taxonomy_mapping_value(project_id, type, ""),
|
||||
updated_report <- TaxonomyEditing.update_taxonomy_mapping(report, type, name, normalized_value),
|
||||
updated_report <-
|
||||
TaxonomyEditing.update_taxonomy_mapping(report, type, name, normalized_value),
|
||||
{:ok, _definition} <-
|
||||
ImportDefinitions.update_definition(definition_id, %{
|
||||
last_analysis_result: updated_report
|
||||
@@ -409,7 +412,8 @@ defmodule BDS.Desktop.ShellLive.ImportEditor do
|
||||
|
||||
def handle_event("toggle_import_ai_model_selector", _params, socket) do
|
||||
{:noreply,
|
||||
assign(socket, :model_selector_open?, not socket.assigns.model_selector_open?) |> build_data()}
|
||||
assign(socket, :model_selector_open?, not socket.assigns.model_selector_open?)
|
||||
|> build_data()}
|
||||
end
|
||||
|
||||
def handle_event("select_import_ai_model", %{"model" => model_id}, socket) do
|
||||
@@ -432,7 +436,11 @@ defmodule BDS.Desktop.ShellLive.ImportEditor do
|
||||
if socket.assigns.offline_mode? do
|
||||
notify_output(
|
||||
dgettext("ui", "Import"),
|
||||
BDS.Gettext.lgettext(socket.assigns[:page_language] || ShellData.ui_language(), "ui", "Automatic AI actions stay gated by airplane mode."),
|
||||
BDS.Gettext.lgettext(
|
||||
socket.assigns[:page_language] || ShellData.ui_language(),
|
||||
"ui",
|
||||
"Automatic AI actions stay gated by airplane mode."
|
||||
),
|
||||
"info"
|
||||
)
|
||||
|
||||
@@ -485,7 +493,10 @@ defmodule BDS.Desktop.ShellLive.ImportEditor do
|
||||
|
||||
# ── handle_info for async tasks ────────────────────────────────────────────
|
||||
|
||||
@spec handle_info({:import_analysis_progress, atom() | String.t(), String.t()}, Phoenix.LiveView.Socket.t()) ::
|
||||
@spec handle_info(
|
||||
{:import_analysis_progress, atom() | String.t(), String.t()},
|
||||
Phoenix.LiveView.Socket.t()
|
||||
) ::
|
||||
{:noreply, Phoenix.LiveView.Socket.t()}
|
||||
def handle_info({:import_analysis_progress, step, detail}, socket) do
|
||||
socket =
|
||||
@@ -551,7 +562,8 @@ defmodule BDS.Desktop.ShellLive.ImportEditor do
|
||||
|> assign(:analysis_state, default_analysis_state())
|
||||
|> notify_output(dgettext("ui", "Import"), message, "error")
|
||||
|
||||
match?(%{ref: ^ref}, socket.assigns.execution_state) and reason not in [:normal, :shutdown] ->
|
||||
match?(%{ref: ^ref}, socket.assigns.execution_state) and
|
||||
reason not in [:normal, :shutdown] ->
|
||||
message = if is_binary(reason), do: reason, else: inspect(reason)
|
||||
|
||||
socket
|
||||
@@ -631,7 +643,10 @@ defmodule BDS.Desktop.ShellLive.ImportEditor do
|
||||
|
||||
notify_parent(
|
||||
{:import_editor_tab_meta, socket.assigns.definition_id, title,
|
||||
dgettext("ui", "Select a WordPress export file (WXR) and an uploads folder to analyze what would be imported.")}
|
||||
dgettext(
|
||||
"ui",
|
||||
"Select a WordPress export file (WXR) and an uploads folder to analyze what would be imported."
|
||||
)}
|
||||
)
|
||||
|
||||
socket
|
||||
|
||||
@@ -130,7 +130,7 @@ defmodule BDS.Desktop.ShellLive.ImportEditor.ProgressTracking do
|
||||
)
|
||||
|> append_output.(
|
||||
dgettext("ui", "Import"),
|
||||
dgettext("ui", "Import completed successfully!", count: previous_state.count),
|
||||
dgettext("ui", "Import completed successfully!", count: previous_state.count),
|
||||
nil,
|
||||
"info"
|
||||
)
|
||||
@@ -265,9 +265,7 @@ defmodule BDS.Desktop.ShellLive.ImportEditor.ProgressTracking do
|
||||
seconds = div(ms, 1000)
|
||||
|
||||
if seconds < 60 do
|
||||
dgettext("ui", "ETA: %{value}",
|
||||
value: dgettext("ui", "%{count}s", count: seconds)
|
||||
)
|
||||
dgettext("ui", "ETA: %{value}", value: dgettext("ui", "%{count}s", count: seconds))
|
||||
else
|
||||
m = div(seconds, 60)
|
||||
s = rem(seconds, 60)
|
||||
|
||||
@@ -86,7 +86,11 @@ defmodule BDS.Desktop.ShellLive.ImportEditor.TaxonomyEditing do
|
||||
socket
|
||||
|> append_output.(
|
||||
dgettext("ui", "Import"),
|
||||
BDS.Gettext.lgettext(socket.assigns.page_language, "ui", "Automatic AI actions stay gated by airplane mode."),
|
||||
BDS.Gettext.lgettext(
|
||||
socket.assigns.page_language,
|
||||
"ui",
|
||||
"Automatic AI actions stay gated by airplane mode."
|
||||
),
|
||||
nil,
|
||||
"info"
|
||||
)
|
||||
|
||||
@@ -124,7 +124,12 @@ defmodule BDS.Desktop.ShellLive.MediaEditor do
|
||||
|> build_data()
|
||||
|
||||
notify_parent({:media_editor_dirty, media.id, false})
|
||||
notify_parent({:media_editor_tab_meta, media.id, display_title(updated_media), updated_media.original_name || updated_media.mime_type || ""})
|
||||
|
||||
notify_parent(
|
||||
{:media_editor_tab_meta, media.id, display_title(updated_media),
|
||||
updated_media.original_name || updated_media.mime_type || ""}
|
||||
)
|
||||
|
||||
{:noreply, socket}
|
||||
|
||||
{:ok, nil} ->
|
||||
@@ -218,7 +223,11 @@ defmodule BDS.Desktop.ShellLive.MediaEditor do
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("change_media_post_picker", %{"media_post_picker" => %{"query" => query}}, socket) do
|
||||
def handle_event(
|
||||
"change_media_post_picker",
|
||||
%{"media_post_picker" => %{"query" => query}},
|
||||
socket
|
||||
) do
|
||||
socket =
|
||||
socket
|
||||
|> assign(:post_picker_query, to_string(query || ""))
|
||||
@@ -351,7 +360,13 @@ defmodule BDS.Desktop.ShellLive.MediaEditor do
|
||||
{:noreply, build_data(socket)}
|
||||
|
||||
{:error, reason} ->
|
||||
notify_output(socket, dgettext("ui", "Refresh Translation"), inspect(reason), "error")
|
||||
notify_output(
|
||||
socket,
|
||||
dgettext("ui", "Refresh Translation"),
|
||||
inspect(reason),
|
||||
"error"
|
||||
)
|
||||
|
||||
{:noreply, build_data(socket)}
|
||||
end
|
||||
|
||||
@@ -469,7 +484,12 @@ defmodule BDS.Desktop.ShellLive.MediaEditor do
|
||||
|> build_data()
|
||||
|
||||
notify_parent({:media_editor_dirty, media.id, false})
|
||||
notify_parent({:media_editor_tab_meta, media.id, display_title(updated_media), updated_media.original_name || updated_media.mime_type || ""})
|
||||
|
||||
notify_parent(
|
||||
{:media_editor_tab_meta, media.id, display_title(updated_media),
|
||||
updated_media.original_name || updated_media.mime_type || ""}
|
||||
)
|
||||
|
||||
notify_output(socket, dgettext("ui", "Media"), dgettext("ui", "Media saved"))
|
||||
socket
|
||||
|
||||
@@ -684,7 +704,6 @@ defmodule BDS.Desktop.ShellLive.MediaEditor do
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@spec media_editor_save_state_label(term()) :: term()
|
||||
def media_editor_save_state_label(:dirty), do: dgettext("ui", "Unsaved")
|
||||
def media_editor_save_state_label(:saved), do: dgettext("ui", "Saved")
|
||||
|
||||
@@ -3,7 +3,6 @@ defmodule BDS.Desktop.ShellLive.MenuEditor do
|
||||
|
||||
use Phoenix.LiveComponent
|
||||
|
||||
|
||||
use Gettext, backend: BDS.Gettext
|
||||
|
||||
alias BDS.Desktop.ShellLive.MenuEditor.{
|
||||
@@ -238,7 +237,11 @@ defmodule BDS.Desktop.ShellLive.MenuEditor do
|
||||
tab_meta =
|
||||
Map.put(socket.assigns.tab_meta, {:menu_editor, tab_id}, %{
|
||||
title: dgettext("ui", "Blog Menu"),
|
||||
subtitle: dgettext("ui", "Manage the central blog navigation outline and save it to meta/menu.opml.")
|
||||
subtitle:
|
||||
dgettext(
|
||||
"ui",
|
||||
"Manage the central blog navigation outline and save it to meta/menu.opml."
|
||||
)
|
||||
})
|
||||
|
||||
socket
|
||||
@@ -407,7 +410,6 @@ defmodule BDS.Desktop.ShellLive.MenuEditor do
|
||||
"""
|
||||
end
|
||||
|
||||
|
||||
@spec row_label(term(), term()) :: term()
|
||||
def row_label(item, category_titles) do
|
||||
if item.kind == :category_archive do
|
||||
@@ -430,8 +432,11 @@ defmodule BDS.Desktop.ShellLive.MenuEditor do
|
||||
def editing_title(_menu_editor), do: dgettext("ui", "Select Page")
|
||||
|
||||
@spec editing_hint(term()) :: term()
|
||||
def editing_hint(%{draft: %{type: :category}}), do: dgettext("ui", "Select an existing category or press Enter to create a new archive entry")
|
||||
def editing_hint(_menu_editor), do: dgettext("ui", "Select a page below or press Enter to create a submenu")
|
||||
def editing_hint(%{draft: %{type: :category}}),
|
||||
do: dgettext("ui", "Select an existing category or press Enter to create a new archive entry")
|
||||
|
||||
def editing_hint(_menu_editor),
|
||||
do: dgettext("ui", "Select a page below or press Enter to create a submenu")
|
||||
|
||||
@spec editing_placeholder(term()) :: term()
|
||||
def editing_placeholder(%{draft: %{type: :category}}),
|
||||
|
||||
@@ -31,7 +31,11 @@ defmodule BDS.Desktop.ShellLive.MenuEditor.State do
|
||||
|
||||
%{
|
||||
title: dgettext("ui", "Blog Menu Editor"),
|
||||
description: dgettext("ui", "Manage the central blog navigation outline and save it to meta/menu.opml."),
|
||||
description:
|
||||
dgettext(
|
||||
"ui",
|
||||
"Manage the central blog navigation outline and save it to meta/menu.opml."
|
||||
),
|
||||
items: state.items,
|
||||
selected_id: state.selected_id,
|
||||
draft: draft,
|
||||
|
||||
@@ -87,7 +87,12 @@ defmodule BDS.Desktop.ShellLive.MiscEditor do
|
||||
|
||||
case Generation.apply_validation(project_id, report) do
|
||||
{:ok, result} ->
|
||||
notify_output(dgettext("ui", "Site Validation"), dgettext("ui", "Validation changes applied"), inspect(result))
|
||||
notify_output(
|
||||
dgettext("ui", "Site Validation"),
|
||||
dgettext("ui", "Validation changes applied"),
|
||||
inspect(result)
|
||||
)
|
||||
|
||||
notify_command("validate_site")
|
||||
{:noreply, socket}
|
||||
end
|
||||
@@ -108,7 +113,9 @@ defmodule BDS.Desktop.ShellLive.MiscEditor do
|
||||
|
||||
notify_output(
|
||||
dgettext("ui", "Translation Validation"),
|
||||
dgettext("ui", "Deleted %{dbRows} DB rows and %{files} files, flushed %{flushed} translations to disk",
|
||||
dgettext(
|
||||
"ui",
|
||||
"Deleted %{dbRows} DB rows and %{files} files, flushed %{flushed} translations to disk",
|
||||
dbRows: result.deleted_database_rows,
|
||||
files: result.deleted_files,
|
||||
flushed: result.flushed_translations
|
||||
@@ -193,7 +200,11 @@ defmodule BDS.Desktop.ShellLive.MiscEditor do
|
||||
|
||||
next_payload = Map.put(payload, :pairs, next_pairs)
|
||||
notify_tab_meta(tab_type, tab_id, %{payload: next_payload})
|
||||
notify_output(dgettext("ui", "Find Duplicates"), dgettext("ui", "Selected pairs dismissed"))
|
||||
|
||||
notify_output(
|
||||
dgettext("ui", "Find Duplicates"),
|
||||
dgettext("ui", "Selected pairs dismissed")
|
||||
)
|
||||
|
||||
{:noreply, assign(socket, :selected_pairs, MapSet.new()) |> build_data()}
|
||||
|
||||
@@ -242,13 +253,16 @@ defmodule BDS.Desktop.ShellLive.MiscEditor do
|
||||
end
|
||||
|
||||
def handle_event("open_duplicate_post", %{"id" => id, "title" => title}, socket) do
|
||||
notify_open_sidebar_item(%{"route" => "post", "id" => id, "title" => title, "subtitle" => "draft"}, :preview)
|
||||
notify_open_sidebar_item(
|
||||
%{"route" => "post", "id" => id, "title" => title, "subtitle" => "draft"},
|
||||
:preview
|
||||
)
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
# ── Public helper functions (used by template) ─────────────────────────────
|
||||
|
||||
|
||||
@spec misc_class(atom()) :: String.t()
|
||||
def misc_class(:site_validation), do: "site-validation-view"
|
||||
def misc_class(:metadata_diff), do: "metadata-diff-view"
|
||||
@@ -430,7 +444,9 @@ defmodule BDS.Desktop.ShellLive.MiscEditor do
|
||||
subtitle: Map.get(meta, :subtitle, ""),
|
||||
summary: %{},
|
||||
summary_text:
|
||||
dgettext("ui", "Checked DB rows: %{dbRows} · Checked files: %{files} · Invalid DB rows: %{invalidDb} · Invalid files: %{invalidFiles}",
|
||||
dgettext(
|
||||
"ui",
|
||||
"Checked DB rows: %{dbRows} · Checked files: %{files} · Invalid DB rows: %{invalidDb} · Invalid files: %{invalidFiles}",
|
||||
dbRows: report.checked_database_row_count,
|
||||
files: report.checked_filesystem_file_count,
|
||||
invalidDb: length(report.invalid_database_rows),
|
||||
|
||||
@@ -64,8 +64,6 @@ defmodule BDS.Desktop.ShellLive.OverlayComponents do
|
||||
|
||||
def markdown_link(text, url), do: "[#{text}](#{url})"
|
||||
|
||||
|
||||
|
||||
def project_metadata(nil), do: %{main_language: "en", blog_languages: []}
|
||||
|
||||
def project_metadata(project_id) do
|
||||
|
||||
@@ -148,8 +148,12 @@ defmodule BDS.Desktop.ShellLive.OverlayManager do
|
||||
socket
|
||||
|
||||
result ->
|
||||
send(self(), {:post_editor_insert_content, post_id,
|
||||
ShellOverlayComponents.markdown_link(result.title, result.canonical_url)})
|
||||
send(
|
||||
self(),
|
||||
{:post_editor_insert_content, post_id,
|
||||
ShellOverlayComponents.markdown_link(result.title, result.canonical_url)}
|
||||
)
|
||||
|
||||
socket
|
||||
end
|
||||
|
||||
@@ -233,13 +237,15 @@ defmodule BDS.Desktop.ShellLive.OverlayManager do
|
||||
|
||||
socket =
|
||||
case {socket.assigns[:shell_overlay], current_tab} do
|
||||
{%{kind: :confirm_delete, delete_action: %{source: :sidebar, route: route, id: id}},
|
||||
_tab} ->
|
||||
{%{kind: :confirm_delete, delete_action: %{source: :sidebar, route: route, id: id}}, _tab} ->
|
||||
callbacks.execute_sidebar_delete.(socket, route, id)
|
||||
|
||||
{%{kind: :ai_suggestions} = overlay, %{type: :post, id: post_id}} ->
|
||||
send(self(), {:post_editor_apply_ai_suggestions, post_id,
|
||||
Overlay.selected_ai_fields(overlay)})
|
||||
send(
|
||||
self(),
|
||||
{:post_editor_apply_ai_suggestions, post_id, Overlay.selected_ai_fields(overlay)}
|
||||
)
|
||||
|
||||
socket
|
||||
|
||||
{%{kind: :ai_suggestions} = overlay, %{type: :media, id: media_id}} ->
|
||||
@@ -258,8 +264,10 @@ defmodule BDS.Desktop.ShellLive.OverlayManager do
|
||||
|
||||
socket
|
||||
|> assign(:shell_overlay, nil)
|
||||
|> assign(:tab_meta,
|
||||
Map.delete(socket.assigns.tab_meta, {:media, media_id}))
|
||||
|> assign(
|
||||
:tab_meta,
|
||||
Map.delete(socket.assigns.tab_meta, {:media, media_id})
|
||||
)
|
||||
|> callbacks.reload.(workbench)
|
||||
|
||||
{:error, reason} ->
|
||||
@@ -331,8 +339,7 @@ defmodule BDS.Desktop.ShellLive.OverlayManager do
|
||||
}
|
||||
end
|
||||
|
||||
assign(socket, :shell_overlay,
|
||||
Overlay.set_ai_suggestions(overlay, suggestions))
|
||||
assign(socket, :shell_overlay, Overlay.set_ai_suggestions(overlay, suggestions))
|
||||
else
|
||||
socket
|
||||
end
|
||||
@@ -355,13 +362,12 @@ defmodule BDS.Desktop.ShellLive.OverlayManager do
|
||||
if current_tab && current_tab.type == type && current_tab.id == id do
|
||||
message =
|
||||
if is_map(reason) and Map.has_key?(reason, :kind) do
|
||||
"#{reason.kind}: #{inspect(Map.drop(reason, [:kind]))}"
|
||||
"#{reason.kind}: #{inspect(Map.drop(reason, [:kind]))}"
|
||||
else
|
||||
inspect(reason)
|
||||
end
|
||||
|
||||
assign(socket, :shell_overlay,
|
||||
Overlay.set_ai_suggestions_error(overlay, message))
|
||||
assign(socket, :shell_overlay, Overlay.set_ai_suggestions_error(overlay, message))
|
||||
else
|
||||
socket
|
||||
end
|
||||
@@ -444,5 +450,4 @@ defmodule BDS.Desktop.ShellLive.OverlayManager do
|
||||
rescue
|
||||
_error -> "en"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -47,6 +47,7 @@ defmodule BDS.Desktop.ShellLive.PostEditor do
|
||||
]
|
||||
|
||||
use Gettext, backend: BDS.Gettext
|
||||
|
||||
import PostMetadata,
|
||||
only: [
|
||||
blank?: 1,
|
||||
@@ -589,7 +590,10 @@ defmodule BDS.Desktop.ShellLive.PostEditor do
|
||||
{:ok, %{language_code: language_code}}
|
||||
when is_binary(language_code) and language_code != "" ->
|
||||
socket
|
||||
|> put_component_draft_field("language", normalize_language(language_code, socket.assigns.canonical_language))
|
||||
|> put_component_draft_field(
|
||||
"language",
|
||||
normalize_language(language_code, socket.assigns.canonical_language)
|
||||
)
|
||||
|> build_data()
|
||||
|
||||
{:error, reason} ->
|
||||
@@ -685,7 +689,10 @@ defmodule BDS.Desktop.ShellLive.PostEditor do
|
||||
socket
|
||||
|> assign(:post, updated_post)
|
||||
|> assign(:project_metadata, metadata)
|
||||
|> assign(:drafts, Map.put(socket.assigns.drafts, active_language, refreshed_form))
|
||||
|> assign(
|
||||
:drafts,
|
||||
Map.put(socket.assigns.drafts, active_language, refreshed_form)
|
||||
)
|
||||
|> assign(:save_state, :dirty)
|
||||
|> assign(:dirty?, true)
|
||||
|> assign(:shell_overlay, nil)
|
||||
@@ -822,5 +829,4 @@ defmodule BDS.Desktop.ShellLive.PostEditor do
|
||||
@spec post_editor_mode_label(term()) :: term()
|
||||
def post_editor_mode_label(:markdown), do: dgettext("ui", "Markdown")
|
||||
def post_editor_mode_label(:preview), do: dgettext("ui", "Preview")
|
||||
|
||||
end
|
||||
|
||||
@@ -151,7 +151,10 @@ defmodule BDS.Desktop.ShellLive.ScriptEditor do
|
||||
socket
|
||||
|> assign(:draft, nil)
|
||||
|> build_data()
|
||||
|> notify_output(dgettext("ui", "Scripts"), dgettext("ui", "Script published"))
|
||||
|> notify_output(
|
||||
dgettext("ui", "Scripts"),
|
||||
dgettext("ui", "Script published")
|
||||
)
|
||||
|> notify_reload()
|
||||
|
||||
{:error, reason} ->
|
||||
@@ -273,8 +276,8 @@ defmodule BDS.Desktop.ShellLive.ScriptEditor do
|
||||
| Regex.scan(~r/function\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/, content || "",
|
||||
capture: :all_but_first
|
||||
)
|
||||
|> List.flatten()
|
||||
|> Enum.reject(&(&1 == "main"))
|
||||
|> List.flatten()
|
||||
|> Enum.reject(&(&1 == "main"))
|
||||
]
|
||||
end
|
||||
|
||||
@@ -287,4 +290,4 @@ defmodule BDS.Desktop.ShellLive.ScriptEditor do
|
||||
send(self(), :reload_shell)
|
||||
socket
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -118,13 +118,16 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor do
|
||||
end
|
||||
|
||||
def handle_event("save_settings_publishing", _params, socket) do
|
||||
socket = PublishingSettings.save_publishing(socket, reload_callback(), append_output_callback())
|
||||
socket =
|
||||
PublishingSettings.save_publishing(socket, reload_callback(), append_output_callback())
|
||||
|
||||
notify_parent(:settings_changed)
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("clear_settings_publishing", _params, socket) do
|
||||
{:noreply, PublishingSettings.clear_publishing(socket, reload_callback(), append_output_callback())}
|
||||
{:noreply,
|
||||
PublishingSettings.clear_publishing(socket, reload_callback(), append_output_callback())}
|
||||
end
|
||||
|
||||
def handle_event("change_settings_new_category", %{"name" => name}, socket) do
|
||||
@@ -138,25 +141,38 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor do
|
||||
end
|
||||
|
||||
def handle_event("reset_settings_categories", _params, socket) do
|
||||
socket = ManagedCategories.reset_categories(socket, reload_callback(), append_output_callback())
|
||||
socket =
|
||||
ManagedCategories.reset_categories(socket, reload_callback(), append_output_callback())
|
||||
|
||||
notify_parent(:settings_changed)
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("save_settings_category", %{"category_settings" => params}, socket) do
|
||||
socket = ManagedCategories.save_category(socket, params, reload_callback(), append_output_callback())
|
||||
socket =
|
||||
ManagedCategories.save_category(socket, params, reload_callback(), append_output_callback())
|
||||
|
||||
notify_parent(:settings_changed)
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("remove_settings_category", %{"category" => category}, socket) do
|
||||
socket = ManagedCategories.remove_category(socket, category, reload_callback(), append_output_callback())
|
||||
socket =
|
||||
ManagedCategories.remove_category(
|
||||
socket,
|
||||
category,
|
||||
reload_callback(),
|
||||
append_output_callback()
|
||||
)
|
||||
|
||||
notify_parent(:settings_changed)
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("toggle_settings_mcp_agent", %{"agent" => agent}, socket) do
|
||||
socket = MCPConfig.toggle_mcp_agent(socket, agent, reload_callback(), append_output_callback())
|
||||
socket =
|
||||
MCPConfig.toggle_mcp_agent(socket, agent, reload_callback(), append_output_callback())
|
||||
|
||||
notify_parent(:settings_changed)
|
||||
{:noreply, socket}
|
||||
end
|
||||
@@ -385,5 +401,4 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor do
|
||||
|
||||
defp section_matches?(query, keywords),
|
||||
do: Enum.any?(keywords, &String.contains?(&1, String.downcase(query)))
|
||||
|
||||
end
|
||||
|
||||
@@ -27,10 +27,7 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.AISettings do
|
||||
),
|
||||
"online_title_model" => get_model_preference(:title),
|
||||
"online_image_analysis_model" => get_model_preference(:image_analysis),
|
||||
"online_chat_images" =>
|
||||
model_supports_images?(
|
||||
get_model_preference(:image_analysis)
|
||||
),
|
||||
"online_chat_images" => model_supports_images?(get_model_preference(:image_analysis)),
|
||||
"offline_url" => Map.get(airplane_endpoint || %{}, :url, ""),
|
||||
"offline_api_key" => Map.get(airplane_endpoint || %{}, :api_key, ""),
|
||||
"offline_mode" => Map.get(assigns, :offline_mode, AI.airplane_mode?(true)),
|
||||
@@ -48,9 +45,7 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.AISettings do
|
||||
"offline_title_model" => get_model_preference(:airplane_title),
|
||||
"offline_image_analysis_model" => get_model_preference(:airplane_image_analysis),
|
||||
"offline_chat_images" =>
|
||||
model_supports_images?(
|
||||
get_model_preference(:airplane_image_analysis)
|
||||
),
|
||||
model_supports_images?(get_model_preference(:airplane_image_analysis)),
|
||||
"system_prompt" => EditorSettings.get_global_setting("ai.system_prompt") || ""
|
||||
}
|
||||
end
|
||||
@@ -120,14 +115,14 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.AISettings do
|
||||
attrs.online_chat_tools,
|
||||
attrs.online_chat_disable_reasoning
|
||||
),
|
||||
:ok <- maybe_put_model_preference(:title, attrs.online_title_model),
|
||||
:ok <- maybe_put_model_preference(:image_analysis, attrs.online_image_analysis_model),
|
||||
:ok <-
|
||||
maybe_put_image_model_capabilities(
|
||||
attrs.online_image_analysis_model,
|
||||
attrs.online_chat_images
|
||||
),
|
||||
:ok <- maybe_put_model_preference(:airplane_chat, attrs.offline_chat_model),
|
||||
:ok <- maybe_put_model_preference(:title, attrs.online_title_model),
|
||||
:ok <- maybe_put_model_preference(:image_analysis, attrs.online_image_analysis_model),
|
||||
:ok <-
|
||||
maybe_put_image_model_capabilities(
|
||||
attrs.online_image_analysis_model,
|
||||
attrs.online_chat_images
|
||||
),
|
||||
:ok <- maybe_put_model_preference(:airplane_chat, attrs.offline_chat_model),
|
||||
:ok <-
|
||||
maybe_put_chat_model_capabilities(
|
||||
attrs.offline_chat_model,
|
||||
@@ -135,17 +130,17 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.AISettings do
|
||||
attrs.offline_chat_disable_reasoning
|
||||
),
|
||||
:ok <- maybe_put_model_preference(:airplane_title, attrs.offline_title_model),
|
||||
:ok <-
|
||||
maybe_put_model_preference(
|
||||
:airplane_image_analysis,
|
||||
attrs.offline_image_analysis_model
|
||||
),
|
||||
:ok <-
|
||||
maybe_put_image_model_capabilities(
|
||||
attrs.offline_image_analysis_model,
|
||||
attrs.offline_chat_images
|
||||
),
|
||||
:ok <- EditorSettings.put_global_setting("ai.system_prompt", attrs.system_prompt) do
|
||||
:ok <-
|
||||
maybe_put_model_preference(
|
||||
:airplane_image_analysis,
|
||||
attrs.offline_image_analysis_model
|
||||
),
|
||||
:ok <-
|
||||
maybe_put_image_model_capabilities(
|
||||
attrs.offline_image_analysis_model,
|
||||
attrs.offline_chat_images
|
||||
),
|
||||
:ok <- EditorSettings.put_global_setting("ai.system_prompt", attrs.system_prompt) do
|
||||
socket
|
||||
|> assign(:settings_editor_ai_draft, %{})
|
||||
|> assign(:offline_mode, attrs.offline_mode)
|
||||
|
||||
@@ -500,8 +500,8 @@ defmodule BDS.Desktop.ShellLive.SidebarComponents do
|
||||
"""
|
||||
end
|
||||
|
||||
|
||||
defp sidebar_deletable?(route), do: route in ["post", "media", "scripts", "templates", "chat", "import"]
|
||||
defp sidebar_deletable?(route),
|
||||
do: route in ["post", "media", "scripts", "templates", "chat", "import"]
|
||||
|
||||
defp sidebar_delete_testid("post"), do: "sidebar-delete-post"
|
||||
defp sidebar_delete_testid("media"), do: "sidebar-delete-media"
|
||||
@@ -513,10 +513,19 @@ defmodule BDS.Desktop.ShellLive.SidebarComponents do
|
||||
|
||||
defp sidebar_delete_title("chat"), do: dgettext("ui", "Delete conversation")
|
||||
defp sidebar_delete_title("post"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Post")
|
||||
defp sidebar_delete_title("media"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Media")
|
||||
defp sidebar_delete_title("scripts"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Script")
|
||||
defp sidebar_delete_title("templates"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Template")
|
||||
defp sidebar_delete_title("import"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Import")
|
||||
|
||||
defp sidebar_delete_title("media"),
|
||||
do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Media")
|
||||
|
||||
defp sidebar_delete_title("scripts"),
|
||||
do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Script")
|
||||
|
||||
defp sidebar_delete_title("templates"),
|
||||
do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Template")
|
||||
|
||||
defp sidebar_delete_title("import"),
|
||||
do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Import")
|
||||
|
||||
defp sidebar_delete_title(_route), do: dgettext("ui", "Delete")
|
||||
|
||||
defp template_sidebar?(sidebar_data), do: Map.get(sidebar_data, :title) == "Templates"
|
||||
|
||||
@@ -6,7 +6,13 @@ defmodule BDS.Desktop.ShellLive.SidebarDelete do
|
||||
alias BDS.{AI, ImportDefinitions, Media, Posts, Scripts, Templates}
|
||||
use Gettext, backend: BDS.Gettext
|
||||
|
||||
@spec request_delete(Phoenix.LiveView.Socket.t(), String.t(), String.t(), String.t() | nil, map()) ::
|
||||
@spec request_delete(
|
||||
Phoenix.LiveView.Socket.t(),
|
||||
String.t(),
|
||||
String.t(),
|
||||
String.t() | nil,
|
||||
map()
|
||||
) ::
|
||||
Phoenix.LiveView.Socket.t()
|
||||
def request_delete(socket, route, id, fallback_title, callbacks) do
|
||||
case delete_target(socket, route, id, fallback_title) do
|
||||
@@ -43,9 +49,15 @@ defmodule BDS.Desktop.ShellLive.SidebarDelete do
|
||||
delete_entity(socket, :scripts, id, &Scripts.delete_script/1, callbacks)
|
||||
|
||||
"templates" ->
|
||||
delete_entity(socket, :templates, id, fn tid ->
|
||||
Templates.delete_template(tid, force: true)
|
||||
end, callbacks)
|
||||
delete_entity(
|
||||
socket,
|
||||
:templates,
|
||||
id,
|
||||
fn tid ->
|
||||
Templates.delete_template(tid, force: true)
|
||||
end,
|
||||
callbacks
|
||||
)
|
||||
|
||||
"chat" ->
|
||||
delete_entity(socket, :chat, id, &AI.delete_chat_conversation/1, callbacks)
|
||||
@@ -56,7 +68,12 @@ defmodule BDS.Desktop.ShellLive.SidebarDelete do
|
||||
_other ->
|
||||
socket
|
||||
|> assign(:shell_overlay, nil)
|
||||
|> callbacks.append_output.(dgettext("ui", "Delete"), inspect(:unsupported_route), nil, "error")
|
||||
|> callbacks.append_output.(
|
||||
dgettext("ui", "Delete"),
|
||||
inspect(:unsupported_route),
|
||||
nil,
|
||||
"error"
|
||||
)
|
||||
|> callbacks.reload.(socket.assigns.workbench)
|
||||
end
|
||||
end
|
||||
@@ -95,7 +112,9 @@ defmodule BDS.Desktop.ShellLive.SidebarDelete do
|
||||
"post" ->
|
||||
case Posts.get_post(id) do
|
||||
%{project_id: ^active_project_id} = post ->
|
||||
{:ok, present_title(fallback_title) || present_title(post.title) || present_title(post.slug) || id}
|
||||
{:ok,
|
||||
present_title(fallback_title) || present_title(post.title) ||
|
||||
present_title(post.slug) || id}
|
||||
|
||||
_other ->
|
||||
{:error, :not_found}
|
||||
@@ -155,7 +174,10 @@ defmodule BDS.Desktop.ShellLive.SidebarDelete do
|
||||
defp delete_title("post"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Post")
|
||||
defp delete_title("media"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Media")
|
||||
defp delete_title("scripts"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Script")
|
||||
defp delete_title("templates"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Template")
|
||||
|
||||
defp delete_title("templates"),
|
||||
do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Template")
|
||||
|
||||
defp delete_title("import"), do: dgettext("ui", "Delete") <> " " <> dgettext("ui", "Import")
|
||||
defp delete_title(_route), do: dgettext("ui", "Delete")
|
||||
|
||||
@@ -168,5 +190,4 @@ defmodule BDS.Desktop.ShellLive.SidebarDelete do
|
||||
end
|
||||
|
||||
defp present_title(_value), do: nil
|
||||
|
||||
end
|
||||
|
||||
@@ -3,7 +3,9 @@ defmodule BDS.Desktop.ShellLive.SidebarEvents do
|
||||
|
||||
alias BDS.Desktop.ShellLive.SidebarState, as: ShellSidebarState
|
||||
|
||||
@spec handle(Phoenix.LiveView.Socket.t(), String.t(), map(), (Phoenix.LiveView.Socket.t(), term() -> Phoenix.LiveView.Socket.t())) ::
|
||||
@spec handle(Phoenix.LiveView.Socket.t(), String.t(), map(), (Phoenix.LiveView.Socket.t(),
|
||||
term() ->
|
||||
Phoenix.LiveView.Socket.t())) ::
|
||||
{:noreply, Phoenix.LiveView.Socket.t()}
|
||||
def handle(socket, event, params, reload)
|
||||
|
||||
|
||||
@@ -49,7 +49,8 @@ defmodule BDS.Desktop.ShellLive.TabHelpers do
|
||||
end
|
||||
end
|
||||
|
||||
defp default_tab_subtitle(_tab), do: "Desktop workbench content routed through the Elixir shell."
|
||||
defp default_tab_subtitle(_tab),
|
||||
do: "Desktop workbench content routed through the Elixir shell."
|
||||
|
||||
def tab_route_label(nil), do: dgettext("ui", "Dashboard")
|
||||
def tab_route_label(%{type: type}), do: ShellData.route_label(type)
|
||||
@@ -168,7 +169,11 @@ defmodule BDS.Desktop.ShellLive.TabHelpers do
|
||||
%{name: name} ->
|
||||
%{
|
||||
title: blank_to_nil(name) || dgettext("ui", "Untitled Import"),
|
||||
subtitle: dgettext("ui", "Select a WordPress export file (WXR) and an uploads folder to analyze what would be imported.")
|
||||
subtitle:
|
||||
dgettext(
|
||||
"ui",
|
||||
"Select a WordPress export file (WXR) and an uploads folder to analyze what would be imported."
|
||||
)
|
||||
}
|
||||
|
||||
_other ->
|
||||
@@ -183,7 +188,11 @@ defmodule BDS.Desktop.ShellLive.TabHelpers do
|
||||
defp derived_tab_meta(%{type: :menu_editor}) do
|
||||
%{
|
||||
title: dgettext("ui", "Blog Menu"),
|
||||
subtitle: dgettext("ui", "Manage the central blog navigation outline and save it to meta/menu.opml.")
|
||||
subtitle:
|
||||
dgettext(
|
||||
"ui",
|
||||
"Manage the central blog navigation outline and save it to meta/menu.opml."
|
||||
)
|
||||
}
|
||||
end
|
||||
|
||||
@@ -212,7 +221,8 @@ defmodule BDS.Desktop.ShellLive.TabHelpers do
|
||||
if is_binary(value), do: String.trim(value) != "", else: false
|
||||
end
|
||||
|
||||
defp post_record_title(%Post{} = post), do: blank_to_nil(post.title) || blank_to_nil(post.slug) || post.id
|
||||
defp post_record_title(%Post{} = post),
|
||||
do: blank_to_nil(post.title) || blank_to_nil(post.slug) || post.id
|
||||
|
||||
defp post_record_subtitle(%Post{} = post), do: Atom.to_string(post.status)
|
||||
|
||||
|
||||
@@ -272,11 +272,13 @@ defmodule BDS.Desktop.ShellLive.TagsEditor do
|
||||
end),
|
||||
selected: selected,
|
||||
new_tag:
|
||||
Map.get(socket.assigns, :tags_editor, %{}) |> Map.get(:new_tag, %{"name" => "", "color" => ""}),
|
||||
Map.get(socket.assigns, :tags_editor, %{})
|
||||
|> Map.get(:new_tag, %{"name" => "", "color" => ""}),
|
||||
edit_draft: edit_draft,
|
||||
templates: templates,
|
||||
merge_target:
|
||||
Map.get(socket.assigns, :tags_editor, %{}) |> Map.get(:merge_target, List.first(selected) || ""),
|
||||
Map.get(socket.assigns, :tags_editor, %{})
|
||||
|> Map.get(:merge_target, List.first(selected) || ""),
|
||||
selected_section: selected_section
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
defmodule BDS.Desktop.ShellLive.TaskLocalization do
|
||||
@moduledoc false
|
||||
|
||||
|
||||
def localize_task_status(task_status, locale) do
|
||||
tasks = Enum.map(Map.get(task_status, :tasks, []), &localize_task(&1, locale))
|
||||
active = Enum.filter(tasks, &(&1.status in [:running, :pending]))
|
||||
|
||||
@@ -165,7 +165,11 @@ defmodule BDS.Desktop.ShellLive.TemplateEditor do
|
||||
%Template{} = template ->
|
||||
case MCP.validate_template(current_draft(socket.assigns, template)["content"] || "") do
|
||||
{:ok, %{valid: true}} ->
|
||||
notify_output(socket, dgettext("ui", "Templates"), dgettext("ui", "Template syntax is valid"))
|
||||
notify_output(
|
||||
socket,
|
||||
dgettext("ui", "Templates"),
|
||||
dgettext("ui", "Template syntax is valid")
|
||||
)
|
||||
|
||||
{:ok, %{valid: false, errors: errors}} ->
|
||||
notify_output(socket, dgettext("ui", "Templates"), Enum.join(errors, "; "), "error")
|
||||
@@ -235,4 +239,4 @@ defmodule BDS.Desktop.ShellLive.TemplateEditor do
|
||||
send(self(), :reload_shell)
|
||||
socket
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,9 +21,7 @@ defmodule BDS.Desktop.Shutdown do
|
||||
userData: self()
|
||||
)
|
||||
|
||||
:wxFrame.connect(frame, :command_menu_selected,
|
||||
callback: &__MODULE__.command_menu_selected/2
|
||||
)
|
||||
:wxFrame.connect(frame, :command_menu_selected, callback: &__MODULE__.command_menu_selected/2)
|
||||
|
||||
:ok
|
||||
rescue
|
||||
|
||||
Reference in New Issue
Block a user