fix: fixed CSM-007

This commit is contained in:
2026-05-09 10:41:28 +02:00
parent e5429f7265
commit 88c689ee55
6 changed files with 364 additions and 98 deletions

View File

@@ -82,18 +82,21 @@ defmodule BDS.Desktop.ShellLive do
"load_more_sidebar"
]
@local_menu_actions MapSet.new([
:toggle_sidebar,
:toggle_panel,
:toggle_assistant_sidebar,
:view_posts,
:view_media,
:edit_preferences,
:edit_menu,
:documentation,
:api_documentation,
:close_tab
])
@layout_menu_actions MapSet.new([
:toggle_sidebar,
:toggle_panel,
:toggle_assistant_sidebar,
:close_tab
])
@sidebar_menu_actions MapSet.new([
:view_posts,
:view_media,
:edit_preferences,
:edit_menu,
:documentation,
:api_documentation
])
@local_menu_actions MapSet.union(@layout_menu_actions, @sidebar_menu_actions)
@socket_menu_actions MapSet.new([
:new_post,
:import_media,
@@ -174,15 +177,15 @@ defmodule BDS.Desktop.ShellLive do
@impl true
def handle_event("toggle_sidebar", _params, socket) do
{:noreply, reload_shell(socket, Workbench.toggle_sidebar(socket.assigns.workbench))}
{:noreply, refresh_layout(socket, Workbench.toggle_sidebar(socket.assigns.workbench))}
end
def handle_event("toggle_panel", _params, socket) do
{:noreply, reload_shell(socket, Workbench.toggle_panel(socket.assigns.workbench))}
{:noreply, refresh_layout(socket, Workbench.toggle_panel(socket.assigns.workbench))}
end
def handle_event("toggle_assistant_sidebar", _params, socket) do
{:noreply, reload_shell(socket, Workbench.toggle_assistant_sidebar(socket.assigns.workbench))}
{:noreply, refresh_layout(socket, Workbench.toggle_assistant_sidebar(socket.assigns.workbench))}
end
def handle_event("select_view", %{"view" => view_id}, socket) do
@@ -192,7 +195,7 @@ defmodule BDS.Desktop.ShellLive do
BoundedAtoms.sidebar_view(view_id, :posts)
)
{:noreply, reload_shell(socket, workbench)}
{:noreply, refresh_sidebar(socket, workbench)}
end
def handle_event("select_panel_tab", %{"tab" => tab}, socket) do
@@ -201,7 +204,7 @@ defmodule BDS.Desktop.ShellLive do
|> Workbench.set_panel_visible(true)
|> Workbench.set_panel_tab(BoundedAtoms.panel_tab(tab, :tasks))
{:noreply, reload_shell(socket, workbench)}
{:noreply, refresh_layout(socket, workbench)}
end
def handle_event("open_sidebar_item", %{"route" => _route, "id" => _id} = params, socket) do
@@ -213,15 +216,15 @@ defmodule BDS.Desktop.ShellLive do
end
def handle_event("sync_layout", params, socket) do
{:noreply, reload_shell(socket, Layout.sync(socket.assigns.workbench, params))}
{:noreply, refresh_layout(socket, Layout.sync(socket.assigns.workbench, params))}
end
def handle_event("resize_panel", %{"target" => target, "width" => width}, socket) do
{:noreply, reload_shell(socket, Layout.resize(socket.assigns.workbench, target, width))}
{:noreply, refresh_layout(socket, Layout.resize(socket.assigns.workbench, target, width))}
end
def handle_event(event, params, socket) when event in @sidebar_filter_events do
SidebarEvents.handle(socket, event, params, &reload_shell/2)
SidebarEvents.handle(socket, event, params, &refresh_sidebar/2)
end
def handle_event("create_sidebar_item", %{"kind" => kind}, socket) do
@@ -248,7 +251,12 @@ defmodule BDS.Desktop.ShellLive do
:preview
)
{:noreply, reload_shell(socket, workbench)}
tab_meta = TabHelpers.sync_tab_meta(workbench, socket.assigns[:tab_meta] || %{})
{:noreply,
socket
|> assign(:tab_meta, tab_meta)
|> refresh_layout(workbench)}
end
def handle_event("close_tab", %{"type" => type, "id" => id}, socket) do
@@ -259,7 +267,7 @@ defmodule BDS.Desktop.ShellLive do
{:noreply,
socket
|> assign(:tab_meta, tab_meta)
|> reload_shell(workbench)}
|> refresh_layout(workbench)}
end
def handle_event(
@@ -283,7 +291,7 @@ defmodule BDS.Desktop.ShellLive do
:ok = AI.set_airplane_mode(next_mode)
socket = assign(socket, :offline_mode, next_mode)
{:noreply, reload_shell(socket, socket.assigns.workbench)}
{:noreply, refresh_layout(socket, socket.assigns.workbench)}
end
def handle_event("update_assistant_prompt", %{"assistant" => %{"prompt" => prompt}}, socket) do
@@ -314,7 +322,7 @@ defmodule BDS.Desktop.ShellLive do
|> Workbench.set_panel_visible(true)
|> Workbench.set_panel_tab(:tasks)
{:noreply, reload_shell(socket, workbench)}
{:noreply, refresh_layout(socket, workbench)}
end
def handle_event("settings_shell_command", %{"action" => action}, socket) do
@@ -551,12 +559,57 @@ defmodule BDS.Desktop.ShellLive do
index(assigns)
end
defp reload_shell(socket, workbench) do
defp refresh_layout(socket, workbench) do
git_badge_count = socket.assigns[:git_badge_count] || 0
activity_buttons = Workbench.activity_buttons(workbench, git_badge_count)
task_status = socket.assigns[:task_status] || %{running_task_message: nil, running_task_overflow: nil}
dashboard = socket.assigns[:dashboard] || BDS.UI.Dashboard.empty_snapshot()
page_language = socket.assigns[:page_language] || ShellData.ui_language()
offline_mode = Map.get(socket.assigns, :offline_mode, true)
sidebar_data = socket.assigns[:sidebar_data] || %{}
socket
|> assign(:workbench, workbench)
|> assign(:activity_buttons, activity_buttons)
|> assign(
:sidebar_header,
active_sidebar_label(activity_buttons, workbench.active_view, sidebar_data)
)
|> assign(:panel_tabs, ShellData.panel_tabs(workbench))
|> assign(:current_tab, current_tab(workbench))
|> assign(:editor_meta, ShellData.editor_meta(task_status))
|> assign(
:status,
ShellData.status_bar(workbench, task_status, dashboard,
ui_language: page_language,
offline_mode: offline_mode
)
)
end
defp refresh_sidebar(socket, workbench) do
project_id = (socket.assigns[:projects] || %{})[:active_project_id]
active_view_id = Atom.to_string(workbench.active_view)
sidebar_data =
ShellData.sidebar_view(
project_id,
active_view_id,
ShellSidebarState.current_filters(socket, active_view_id)
)
sidebar_data = ShellSidebarState.merge_ui_state(socket, active_view_id, sidebar_data)
socket
|> assign(:sidebar_data, sidebar_data)
|> refresh_layout(workbench)
end
defp refresh_content(socket, workbench) do
projects = ShellData.project_snapshot()
dashboard = ShellData.dashboard(projects.active_project_id)
git_badge_count = ShellData.git_badge_count(projects.active_project_id)
active_view_id = Atom.to_string(workbench.active_view)
tab_meta = TabHelpers.sync_tab_meta(workbench, socket.assigns[:tab_meta] || %{})
sidebar_data =
ShellData.sidebar_view(
@@ -566,8 +619,26 @@ defmodule BDS.Desktop.ShellLive do
)
sidebar_data = ShellSidebarState.merge_ui_state(socket, active_view_id, sidebar_data)
socket
|> assign(:projects, projects)
|> assign(:current_project, ShellData.current_project(projects))
|> assign(:dashboard, dashboard)
|> assign(:dashboard_timeline_entries, Map.get(dashboard, :timeline_entries, []))
|> assign(:dashboard_category_counts, Map.get(dashboard, :category_counts, []))
|> assign(:dashboard_recent_posts, Map.get(dashboard, :recent_posts, []))
|> assign(
:dashboard_tag_cloud_items,
ShellData.dashboard_tag_cloud_items(Map.get(dashboard, :tag_cloud_items, []))
)
|> assign(:git_badge_count, git_badge_count)
|> assign(:sidebar_data, sidebar_data)
|> refresh_layout(workbench)
end
defp reload_shell(socket, workbench) do
tab_meta = TabHelpers.sync_tab_meta(workbench, socket.assigns[:tab_meta] || %{})
raw_task_status = BDS.Tasks.status_snapshot()
activity_buttons = Workbench.activity_buttons(workbench, git_badge_count)
page_language = socket.assigns[:page_language] || ShellData.ui_language()
offline_mode =
@@ -581,38 +652,13 @@ defmodule BDS.Desktop.ShellLive do
socket
|> assign(:tab_meta, tab_meta)
|> assign(:workbench, workbench)
|> assign(:projects, projects)
|> assign(:current_project, ShellData.current_project(projects))
|> assign(:dashboard, dashboard)
|> assign(:dashboard_timeline_entries, Map.get(dashboard, :timeline_entries, []))
|> assign(:dashboard_category_counts, Map.get(dashboard, :category_counts, []))
|> assign(:dashboard_recent_posts, Map.get(dashboard, :recent_posts, []))
|> assign(
:dashboard_tag_cloud_items,
ShellData.dashboard_tag_cloud_items(Map.get(dashboard, :tag_cloud_items, []))
)
|> assign(:sidebar_data, sidebar_data)
|> assign(
:sidebar_header,
active_sidebar_label(activity_buttons, workbench.active_view, sidebar_data)
)
|> assign(:assistant_cards, ShellData.assistant_cards())
|> assign(:editor_meta, ShellData.editor_meta(task_status))
|> assign(:task_status, task_status)
|> assign(
:status,
ShellData.status_bar(workbench, task_status, dashboard,
ui_language: page_language,
offline_mode: offline_mode
)
)
|> assign(:activity_buttons, activity_buttons)
|> assign(:panel_tabs, ShellData.panel_tabs(workbench))
|> assign(:offline_mode, offline_mode)
|> assign(:assistant_cards, ShellData.assistant_cards())
|> assign(:supported_ui_languages, ShellData.supported_ui_languages())
|> assign(:menu_groups, socket.assigns[:menu_groups] || TitlebarMenu.groups())
|> assign(:titlebar_menu_item_index, socket.assigns[:titlebar_menu_item_index])
|> assign(:current_tab, current_tab(workbench))
|> refresh_content(workbench)
end
defp encoded_shortcuts(shortcuts), do: Jason.encode!(shortcuts)
@@ -657,6 +703,7 @@ defmodule BDS.Desktop.ShellLive do
defp sidebar_create_callbacks do
%{
reload: &reload_shell/2,
refresh_content: &refresh_content/2,
open_sidebar: &open_sidebar_item/3,
append_output: &append_output_entry/5
}
@@ -681,9 +728,11 @@ defmodule BDS.Desktop.ShellLive do
subtitle: Map.get(params, "subtitle", "")
})
tab_meta = TabHelpers.sync_tab_meta(workbench, tab_meta)
socket
|> assign(:tab_meta, tab_meta)
|> reload_shell(workbench)
|> refresh_layout(workbench)
end
defp sidebar_create_action(view), do: SidebarCreate.action(view)
@@ -752,8 +801,16 @@ defmodule BDS.Desktop.ShellLive do
defp handle_menu_action(socket, action) when is_atom(action) do
cond do
MapSet.member?(@local_menu_actions, action) ->
reload_shell(socket, MenuBar.execute(socket.assigns.workbench, action))
MapSet.member?(@layout_menu_actions, action) ->
refresh_layout(socket, MenuBar.execute(socket.assigns.workbench, action))
MapSet.member?(@sidebar_menu_actions, action) ->
workbench = MenuBar.execute(socket.assigns.workbench, action)
tab_meta = TabHelpers.sync_tab_meta(workbench, socket.assigns[:tab_meta] || %{})
socket
|> assign(:tab_meta, tab_meta)
|> refresh_sidebar(workbench)
MapSet.member?(@socket_menu_actions, action) ->
handle_socket_menu_action(socket, action)
@@ -842,14 +899,14 @@ defmodule BDS.Desktop.ShellLive do
socket
end
defp save_current_tab(socket), do: reload_shell(socket, socket.assigns.workbench)
defp save_current_tab(socket), do: refresh_layout(socket, socket.assigns.workbench)
defp publish_current_tab(%{assigns: %{current_tab: %{type: :post, id: post_id}}} = socket) do
send_update(PostEditor, id: "post-editor-#{post_id}", action: :publish)
socket
end
defp publish_current_tab(socket), do: reload_shell(socket, socket.assigns.workbench)
defp publish_current_tab(socket), do: refresh_layout(socket, socket.assigns.workbench)
defp apply_shell_command(socket, action, params \\ %{}),
do: ShellCommandRunner.execute(socket, action, params, shell_command_callbacks())
@@ -860,6 +917,7 @@ defmodule BDS.Desktop.ShellLive do
defp shell_command_callbacks do
%{
reload: &reload_shell/2,
refresh_content: &refresh_content/2,
append_output: &append_output_entry/5
}
end
@@ -876,6 +934,7 @@ defmodule BDS.Desktop.ShellLive do
defp overlay_callbacks,
do: %{
reload: &reload_shell/2,
refresh_content: &refresh_content/2,
append_output: &append_output_entry/5,
execute_sidebar_delete: fn socket, route, id ->
SidebarDelete.execute_delete(socket, route, id, sidebar_delete_callbacks())
@@ -885,12 +944,16 @@ defmodule BDS.Desktop.ShellLive do
defp sidebar_delete_callbacks,
do: %{
reload: &reload_shell/2,
refresh_content: &refresh_content/2,
append_output: &append_output_entry/5
}
defp bridges_callbacks,
do: %{
reload: &reload_shell/2,
refresh_layout: &refresh_layout/2,
refresh_sidebar: &refresh_sidebar/2,
refresh_content: &refresh_content/2,
append_output: &append_output_entry/5,
open_sidebar: &open_sidebar_item/3,
apply_shell_command: &apply_shell_command/3,

View File

@@ -25,7 +25,7 @@ defmodule BDS.Desktop.ShellLive.Bridges do
{:noreply,
socket
|> assign(:tab_meta, tab_meta)
|> callbacks.reload.(socket.assigns.workbench)}
|> callbacks.refresh_sidebar.(socket.assigns.workbench)}
end
def handle_info({:chat_tool_call, conversation_id, tool_call}, socket, _callbacks) do
@@ -82,7 +82,7 @@ defmodule BDS.Desktop.ShellLive.Bridges do
{:noreply,
socket
|> assign(:tab_meta, tab_meta)
|> callbacks.reload.(socket.assigns.workbench)}
|> callbacks.refresh_sidebar.(socket.assigns.workbench)}
end
def handle_info({:open_sidebar_item, params, intent}, socket, callbacks) do
@@ -90,25 +90,30 @@ defmodule BDS.Desktop.ShellLive.Bridges do
end
def handle_info({:chat_editor_toggle_sidebar}, socket, callbacks) do
{:noreply, callbacks.reload.(socket, Workbench.toggle_sidebar(socket.assigns.workbench))}
{:noreply,
callbacks.refresh_layout.(socket, Workbench.toggle_sidebar(socket.assigns.workbench))}
end
def handle_info({:chat_editor_toggle_panel}, socket, callbacks) do
{:noreply, callbacks.reload.(socket, Workbench.toggle_panel(socket.assigns.workbench))}
{:noreply,
callbacks.refresh_layout.(socket, Workbench.toggle_panel(socket.assigns.workbench))}
end
def handle_info({:chat_editor_toggle_assistant_sidebar}, socket, callbacks) do
{:noreply,
callbacks.reload.(socket, Workbench.toggle_assistant_sidebar(socket.assigns.workbench))}
callbacks.refresh_layout.(
socket,
Workbench.toggle_assistant_sidebar(socket.assigns.workbench)
)}
end
def handle_info({:chat_editor_switch_view, view}, socket, callbacks) do
{:noreply,
callbacks.reload.(socket, Workbench.click_activity(socket.assigns.workbench, view))}
callbacks.refresh_sidebar.(socket, Workbench.click_activity(socket.assigns.workbench, view))}
end
def handle_info({:entity_changed, payload}, socket, callbacks) when is_map(payload) do
{:noreply, CliSync.apply_entity_change(socket, payload, callbacks.reload)}
{:noreply, CliSync.apply_entity_change(socket, payload, callbacks.refresh_content)}
end
def handle_info(:refresh_task_status, socket, callbacks) do
@@ -155,7 +160,7 @@ defmodule BDS.Desktop.ShellLive.Bridges do
end
def handle_info(:tags_changed, socket, callbacks) do
{:noreply, callbacks.reload.(socket, socket.assigns.workbench)}
{:noreply, callbacks.refresh_content.(socket, socket.assigns.workbench)}
end
def handle_info({:settings_output, title, message, level}, socket, callbacks) do
@@ -267,7 +272,8 @@ defmodule BDS.Desktop.ShellLive.Bridges do
end
def handle_info({:close_tab, type, id}, socket, callbacks) do
{:noreply, callbacks.reload.(socket, Workbench.close_tab(socket.assigns.workbench, type, id))}
{:noreply,
callbacks.refresh_layout.(socket, Workbench.close_tab(socket.assigns.workbench, type, id))}
end
def handle_info(_message, socket, _callbacks), do: {:noreply, socket}

View File

@@ -19,7 +19,7 @@ defmodule BDS.Desktop.ShellLive.SidebarCreate do
def create(socket, kind, callbacks) do
case socket.assigns.projects.active_project_id do
project_id when is_binary(project_id) -> create(socket, project_id, kind, callbacks)
_other -> callbacks.reload.(socket, socket.assigns.workbench)
_other -> callbacks.refresh_content.(socket, socket.assigns.workbench)
end
end
@@ -32,12 +32,12 @@ defmodule BDS.Desktop.ShellLive.SidebarCreate do
categories: []
}) do
{:ok, _post} ->
callbacks.reload.(socket, socket.assigns.workbench)
callbacks.refresh_content.(socket, socket.assigns.workbench)
{:error, reason} ->
socket
|> callbacks.append_output.(dgettext("ui", "New Post"), inspect(reason), nil, "error")
|> callbacks.reload.(socket.assigns.workbench)
|> callbacks.refresh_content.(socket.assigns.workbench)
end
end
@@ -46,7 +46,7 @@ defmodule BDS.Desktop.ShellLive.SidebarCreate do
{:ok, source_path} ->
case BDS.Media.import_media(%{project_id: project_id, source_path: source_path}) do
{:ok, _media} ->
callbacks.reload.(socket, socket.assigns.workbench)
callbacks.refresh_content.(socket, socket.assigns.workbench)
{:error, reason} ->
socket
@@ -56,16 +56,16 @@ defmodule BDS.Desktop.ShellLive.SidebarCreate do
nil,
"error"
)
|> callbacks.reload.(socket.assigns.workbench)
|> callbacks.refresh_content.(socket.assigns.workbench)
end
:cancel ->
callbacks.reload.(socket, socket.assigns.workbench)
callbacks.refresh_content.(socket, socket.assigns.workbench)
{:error, %{message: message}} ->
socket
|> callbacks.append_output.(dgettext("ui", "Import media"), message, nil, "error")
|> callbacks.reload.(socket.assigns.workbench)
|> callbacks.refresh_content.(socket.assigns.workbench)
end
end
@@ -98,7 +98,7 @@ defmodule BDS.Desktop.ShellLive.SidebarCreate do
nil,
"error"
)
|> callbacks.reload.(socket.assigns.workbench)
|> callbacks.refresh_content.(socket.assigns.workbench)
end
end
@@ -130,7 +130,7 @@ defmodule BDS.Desktop.ShellLive.SidebarCreate do
nil,
"error"
)
|> callbacks.reload.(socket.assigns.workbench)
|> callbacks.refresh_content.(socket.assigns.workbench)
end
end
@@ -151,7 +151,7 @@ defmodule BDS.Desktop.ShellLive.SidebarCreate do
{:error, reason} ->
socket
|> callbacks.append_output.(dgettext("ui", "New Chat"), inspect(reason), nil, "error")
|> callbacks.reload.(socket.assigns.workbench)
|> callbacks.refresh_content.(socket.assigns.workbench)
end
end
@@ -180,12 +180,12 @@ defmodule BDS.Desktop.ShellLive.SidebarCreate do
nil,
"error"
)
|> callbacks.reload.(socket.assigns.workbench)
|> callbacks.refresh_content.(socket.assigns.workbench)
end
end
def create(socket, _project_id, _kind, callbacks),
do: callbacks.reload.(socket, socket.assigns.workbench)
do: callbacks.refresh_content.(socket, socket.assigns.workbench)
def action(:posts), do: %{kind: "post", label: "sidebar.newPost"}
def action(:media), do: %{kind: "media", label: "sidebar.importMedia"}

View File

@@ -31,7 +31,7 @@ defmodule BDS.Desktop.ShellLive.SidebarDelete do
socket
|> assign(:shell_overlay, nil)
|> callbacks.append_output.(delete_title(route), inspect(reason), nil, "error")
|> callbacks.reload.(socket.assigns.workbench)
|> callbacks.refresh_content.(socket.assigns.workbench)
end
end
@@ -74,7 +74,7 @@ defmodule BDS.Desktop.ShellLive.SidebarDelete do
nil,
"error"
)
|> callbacks.reload.(socket.assigns.workbench)
|> callbacks.refresh_content.(socket.assigns.workbench)
end
end
@@ -88,7 +88,7 @@ defmodule BDS.Desktop.ShellLive.SidebarDelete do
socket
|> assign(:shell_overlay, nil)
|> assign(:tab_meta, Map.delete(socket.assigns.tab_meta, {type, id}))
|> callbacks.reload.(workbench)
|> callbacks.refresh_content.(workbench)
{:error, reason} ->
socket
@@ -99,7 +99,7 @@ defmodule BDS.Desktop.ShellLive.SidebarDelete do
nil,
"error"
)
|> callbacks.reload.(socket.assigns.workbench)
|> callbacks.refresh_content.(socket.assigns.workbench)
end
end