chore: more of the overlay and sidebar stuff
This commit is contained in:
450
lib/bds/desktop/shell_live/overlay_manager.ex
Normal file
450
lib/bds/desktop/shell_live/overlay_manager.ex
Normal file
@@ -0,0 +1,450 @@
|
||||
defmodule BDS.Desktop.ShellLive.OverlayManager do
|
||||
@moduledoc false
|
||||
|
||||
require Logger
|
||||
|
||||
import Phoenix.Component, only: [assign: 3]
|
||||
import Phoenix.LiveView, only: [send_update: 2]
|
||||
|
||||
alias BDS.{AI, Media, Metadata}
|
||||
alias BDS.Desktop.{Overlay, ShellData, UILocale}
|
||||
|
||||
alias BDS.Desktop.ShellLive.{
|
||||
MediaEditor,
|
||||
PostEditor,
|
||||
TabHelpers
|
||||
}
|
||||
|
||||
alias BDS.Desktop.ShellLive.OverlayComponents, as: ShellOverlayComponents
|
||||
|
||||
# ── Event handlers ─────────────────────────────────────────────────────────
|
||||
|
||||
@spec handle_event(String.t(), map(), Phoenix.LiveView.Socket.t(), map()) ::
|
||||
{:noreply, Phoenix.LiveView.Socket.t()}
|
||||
def handle_event("open_overlay", %{"kind" => kind}, socket, callbacks) do
|
||||
socket =
|
||||
case socket.assigns[:current_tab] do
|
||||
%{type: :post, id: post_id}
|
||||
when kind in ["ai_suggestions", "language_picker"] ->
|
||||
send_update(PostEditor,
|
||||
id: "post-editor-#{post_id}",
|
||||
action: :close_quick_actions
|
||||
)
|
||||
|
||||
socket
|
||||
|
||||
%{type: :media, id: media_id}
|
||||
when kind in ["ai_suggestions", "language_picker", "confirm_delete"] ->
|
||||
send_update(MediaEditor,
|
||||
id: "media-editor-#{media_id}",
|
||||
action: :close_quick_actions
|
||||
)
|
||||
|
||||
socket
|
||||
|
||||
_other ->
|
||||
socket
|
||||
end
|
||||
|
||||
overlay =
|
||||
with overlay_kind when not is_nil(overlay_kind) <- ShellOverlayComponents.kind(kind),
|
||||
%{type: route} <- socket.assigns[:current_tab] do
|
||||
tab = socket.assigns.current_tab
|
||||
title = TabHelpers.tab_title(tab, socket.assigns.tab_meta)
|
||||
subtitle = TabHelpers.tab_subtitle(tab, socket.assigns.tab_meta)
|
||||
|
||||
Overlay.open(
|
||||
route,
|
||||
overlay_kind,
|
||||
ShellOverlayComponents.context(socket.assigns, title, subtitle)
|
||||
)
|
||||
end
|
||||
|
||||
socket = assign(socket, :shell_overlay, overlay)
|
||||
|
||||
socket =
|
||||
if kind == "ai_suggestions" and not is_nil(overlay) do
|
||||
if socket.assigns.offline_mode do
|
||||
callbacks.append_output.(
|
||||
socket,
|
||||
translated("AI Suggestions"),
|
||||
translated("Automatic AI actions stay gated by airplane mode."),
|
||||
nil,
|
||||
"info"
|
||||
)
|
||||
|> assign(:shell_overlay, nil)
|
||||
else
|
||||
spawn_ai_suggestions_task(socket)
|
||||
end
|
||||
else
|
||||
socket
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("close_overlay", _params, socket, _callbacks) do
|
||||
{:noreply, assign(socket, :shell_overlay, nil)}
|
||||
end
|
||||
|
||||
def handle_event("overlay_keydown", %{"key" => key}, socket, _callbacks) do
|
||||
socket =
|
||||
case {socket.assigns[:shell_overlay], key} do
|
||||
{nil, _other} ->
|
||||
socket
|
||||
|
||||
{_overlay, "Escape"} ->
|
||||
assign(socket, :shell_overlay, nil)
|
||||
|
||||
{%{kind: :gallery} = overlay, "ArrowLeft"} ->
|
||||
assign(socket, :shell_overlay, Overlay.lightbox_previous(overlay))
|
||||
|
||||
{%{kind: :gallery} = overlay, "ArrowRight"} ->
|
||||
assign(socket, :shell_overlay, Overlay.lightbox_next(overlay))
|
||||
|
||||
_other ->
|
||||
socket
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("overlay_toggle_ai_field", %{"key" => key}, socket, _callbacks) do
|
||||
{:noreply, update_shell_overlay(socket, &Overlay.toggle_ai_field(&1, key))}
|
||||
end
|
||||
|
||||
def handle_event("overlay_set_search", %{"overlay" => %{"query" => query}}, socket, _callbacks) do
|
||||
{:noreply, update_shell_overlay(socket, &Overlay.set_search_query(&1, query))}
|
||||
end
|
||||
|
||||
def handle_event("overlay_set_tab", %{"tab" => tab}, socket, _callbacks) do
|
||||
{:noreply,
|
||||
update_shell_overlay(socket, &Overlay.set_active_tab(&1, ShellOverlayComponents.tab(tab)))}
|
||||
end
|
||||
|
||||
def handle_event("overlay_update_form", %{"overlay" => params}, socket, _callbacks) do
|
||||
socket =
|
||||
socket
|
||||
|> update_shell_overlay(
|
||||
&Overlay.update_form_value(&1, :external_url, Map.get(params, "url", ""))
|
||||
)
|
||||
|> update_shell_overlay(
|
||||
&Overlay.update_form_value(&1, :external_text, Map.get(params, "text", ""))
|
||||
)
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("overlay_select_result", %{"id" => id}, socket, _callbacks) do
|
||||
overlay = socket.assigns[:shell_overlay]
|
||||
current_tab = socket.assigns[:current_tab]
|
||||
|
||||
socket =
|
||||
case {overlay, current_tab} do
|
||||
{%{kind: :insert_link}, %{type: :post, id: post_id}} ->
|
||||
case Overlay.insert_link_result(overlay, id) do
|
||||
nil ->
|
||||
socket
|
||||
|
||||
result ->
|
||||
send(self(), {:post_editor_insert_content, post_id,
|
||||
ShellOverlayComponents.markdown_link(result.title, result.canonical_url)})
|
||||
socket
|
||||
end
|
||||
|
||||
{%{kind: :insert_media}, %{type: :post, id: post_id}} ->
|
||||
case Overlay.insert_media_result(overlay, id) do
|
||||
nil ->
|
||||
socket
|
||||
|
||||
result ->
|
||||
syntax =
|
||||
if result.is_image do
|
||||
""
|
||||
else
|
||||
"[#{result.original_name}](bds-media://#{result.media_id})"
|
||||
end
|
||||
|
||||
send(self(), {:post_editor_insert_content, post_id, syntax})
|
||||
socket
|
||||
end
|
||||
|
||||
_other ->
|
||||
socket
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("overlay_insert_external", _params, socket, _callbacks) do
|
||||
current_tab = socket.assigns[:current_tab]
|
||||
|
||||
socket =
|
||||
case {socket.assigns[:shell_overlay], current_tab} do
|
||||
{%{kind: :insert_link} = overlay, %{type: :post, id: post_id}} ->
|
||||
details =
|
||||
case {overlay.external_url, String.trim(overlay.external_text || "")} do
|
||||
{"", _text} -> nil
|
||||
{url, ""} -> url
|
||||
{url, text} -> ShellOverlayComponents.markdown_link(text, url)
|
||||
end
|
||||
|
||||
if details do
|
||||
send(self(), {:post_editor_insert_content, post_id, details})
|
||||
end
|
||||
|
||||
socket
|
||||
|
||||
_other ->
|
||||
socket
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("overlay_select_language", %{"code" => code}, socket, _callbacks) do
|
||||
current_tab = socket.assigns[:current_tab]
|
||||
|
||||
socket =
|
||||
case {socket.assigns[:shell_overlay], current_tab} do
|
||||
{%{kind: :language_picker}, %{type: :post, id: post_id}} ->
|
||||
send(self(), {:post_editor_translate, post_id, code})
|
||||
socket
|
||||
|
||||
{%{kind: :language_picker}, %{type: :media, id: media_id}} ->
|
||||
send_update(MediaEditor,
|
||||
id: "media-editor-#{media_id}",
|
||||
action: :translate,
|
||||
language: code
|
||||
)
|
||||
|
||||
socket
|
||||
|
||||
_other ->
|
||||
socket
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("overlay_confirm", _params, socket, callbacks) do
|
||||
current_tab = socket.assigns[:current_tab]
|
||||
|
||||
socket =
|
||||
case {socket.assigns[:shell_overlay], current_tab} do
|
||||
{%{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)})
|
||||
socket
|
||||
|
||||
{%{kind: :ai_suggestions} = overlay, %{type: :media, id: media_id}} ->
|
||||
send_update(MediaEditor,
|
||||
id: "media-editor-#{media_id}",
|
||||
action: :apply_ai_suggestions,
|
||||
fields: Overlay.selected_ai_fields(overlay)
|
||||
)
|
||||
|
||||
socket
|
||||
|
||||
{%{kind: :confirm_delete}, %{type: :media, id: media_id}} ->
|
||||
case Media.delete_media(media_id) do
|
||||
{:ok, :deleted} ->
|
||||
workbench = BDS.UI.Workbench.close_tab(socket.assigns.workbench, :media, media_id)
|
||||
|
||||
socket
|
||||
|> assign(:shell_overlay, nil)
|
||||
|> assign(:tab_meta,
|
||||
Map.delete(socket.assigns.tab_meta, {:media, media_id}))
|
||||
|> callbacks.reload.(workbench)
|
||||
|
||||
{:error, reason} ->
|
||||
socket
|
||||
|> assign(:shell_overlay, nil)
|
||||
|> callbacks.append_output.(
|
||||
translated("Delete Media"),
|
||||
inspect(reason),
|
||||
nil,
|
||||
"error"
|
||||
)
|
||||
|> callbacks.reload.(socket.assigns.workbench)
|
||||
end
|
||||
|
||||
{%{kind: :confirm_delete, title: title, entity_name: entity_name}, _tab} ->
|
||||
close_overlay_with_output(socket, callbacks.append_output, title, entity_name)
|
||||
|
||||
{%{kind: :confirm_dialog, title: title, message: message}, _tab} ->
|
||||
close_overlay_with_output(socket, callbacks.append_output, title, message)
|
||||
|
||||
_other ->
|
||||
socket
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("overlay_select_gallery_image", %{"id" => id}, socket, _callbacks) do
|
||||
{:noreply, update_shell_overlay(socket, &Overlay.select_gallery_image(&1, id))}
|
||||
end
|
||||
|
||||
def handle_event("overlay_close_lightbox", _params, socket, _callbacks) do
|
||||
{:noreply, update_shell_overlay(socket, &Overlay.close_lightbox/1)}
|
||||
end
|
||||
|
||||
def handle_event("overlay_lightbox_previous", _params, socket, _callbacks) do
|
||||
{:noreply, update_shell_overlay(socket, &Overlay.lightbox_previous/1)}
|
||||
end
|
||||
|
||||
def handle_event("overlay_lightbox_next", _params, socket, _callbacks) do
|
||||
{:noreply, update_shell_overlay(socket, &Overlay.lightbox_next/1)}
|
||||
end
|
||||
|
||||
# ── handle_info for async AI suggestions ───────────────────────────────────
|
||||
|
||||
@spec handle_info(tuple(), Phoenix.LiveView.Socket.t()) ::
|
||||
{:noreply, Phoenix.LiveView.Socket.t()}
|
||||
def handle_info({:ai_suggestions_result, type, id, result}, socket) do
|
||||
socket =
|
||||
case socket.assigns[:shell_overlay] do
|
||||
%{kind: :ai_suggestions} = overlay ->
|
||||
current_tab = socket.assigns.current_tab
|
||||
|
||||
if current_tab && current_tab.type == type && current_tab.id == id do
|
||||
suggestions =
|
||||
case type do
|
||||
:post ->
|
||||
%{
|
||||
"title" => result.title,
|
||||
"excerpt" => result.excerpt,
|
||||
"slug" => result.slug
|
||||
}
|
||||
|
||||
:media ->
|
||||
%{
|
||||
"title" => result.title,
|
||||
"alt" => result.alt,
|
||||
"caption" => result.caption
|
||||
}
|
||||
end
|
||||
|
||||
assign(socket, :shell_overlay,
|
||||
Overlay.set_ai_suggestions(overlay, suggestions))
|
||||
else
|
||||
socket
|
||||
end
|
||||
|
||||
_other ->
|
||||
socket
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_info({:ai_suggestions_error, type, id, reason}, socket) do
|
||||
Logger.error("AI suggestions error type=#{type} id=#{id} reason=#{inspect(reason)}")
|
||||
|
||||
socket =
|
||||
case socket.assigns[:shell_overlay] do
|
||||
%{kind: :ai_suggestions} = overlay ->
|
||||
current_tab = socket.assigns.current_tab
|
||||
|
||||
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]))}"
|
||||
else
|
||||
inspect(reason)
|
||||
end
|
||||
|
||||
assign(socket, :shell_overlay,
|
||||
Overlay.set_ai_suggestions_error(overlay, message))
|
||||
else
|
||||
socket
|
||||
end
|
||||
|
||||
_other ->
|
||||
socket
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
# ── Private helpers ────────────────────────────────────────────────────────
|
||||
|
||||
@spec update_shell_overlay(Phoenix.LiveView.Socket.t(), (map() -> map())) ::
|
||||
Phoenix.LiveView.Socket.t()
|
||||
defp update_shell_overlay(socket, updater) do
|
||||
case socket.assigns[:shell_overlay] do
|
||||
nil -> socket
|
||||
overlay -> assign(socket, :shell_overlay, updater.(overlay))
|
||||
end
|
||||
end
|
||||
|
||||
@spec close_overlay_with_output(
|
||||
Phoenix.LiveView.Socket.t(),
|
||||
(Phoenix.LiveView.Socket.t(), String.t(), String.t(), any(), String.t() ->
|
||||
Phoenix.LiveView.Socket.t()),
|
||||
String.t(),
|
||||
any()
|
||||
) :: Phoenix.LiveView.Socket.t()
|
||||
defp close_overlay_with_output(socket, append_output, title, details) do
|
||||
socket
|
||||
|> append_output.(title, translated("Command completed"), details, "info")
|
||||
|> assign(:shell_overlay, nil)
|
||||
end
|
||||
|
||||
@spec spawn_ai_suggestions_task(Phoenix.LiveView.Socket.t()) :: Phoenix.LiveView.Socket.t()
|
||||
defp spawn_ai_suggestions_task(socket) do
|
||||
current_tab = socket.assigns.current_tab
|
||||
language = ai_suggestions_language(socket)
|
||||
|
||||
case current_tab do
|
||||
%{type: :post, id: post_id} ->
|
||||
parent = self()
|
||||
|
||||
Task.Supervisor.start_child(BDS.TCP.TaskSupervisor, fn ->
|
||||
case AI.analyze_post(post_id, language: language) do
|
||||
{:ok, result} ->
|
||||
send(parent, {:ai_suggestions_result, :post, post_id, result})
|
||||
|
||||
{:error, reason} ->
|
||||
send(parent, {:ai_suggestions_error, :post, post_id, reason})
|
||||
end
|
||||
end)
|
||||
|
||||
%{type: :media, id: media_id} ->
|
||||
parent = self()
|
||||
|
||||
Task.Supervisor.start_child(BDS.TCP.TaskSupervisor, fn ->
|
||||
case AI.analyze_image(media_id, language: language) do
|
||||
{:ok, result} ->
|
||||
send(parent, {:ai_suggestions_result, :media, media_id, result})
|
||||
|
||||
{:error, reason} ->
|
||||
send(parent, {:ai_suggestions_error, :media, media_id, reason})
|
||||
end
|
||||
end)
|
||||
|
||||
_other ->
|
||||
:ok
|
||||
end
|
||||
|
||||
socket
|
||||
end
|
||||
|
||||
@spec ai_suggestions_language(Phoenix.LiveView.Socket.t()) :: String.t()
|
||||
defp ai_suggestions_language(socket) do
|
||||
active_project_id = socket.assigns.projects.active_project_id
|
||||
{:ok, metadata} = Metadata.get_project_metadata(active_project_id)
|
||||
metadata.main_language || "en"
|
||||
rescue
|
||||
_error -> "en"
|
||||
end
|
||||
|
||||
@spec translated(String.t(), map()) :: String.t()
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, UILocale.current())
|
||||
end
|
||||
176
lib/bds/desktop/shell_live/sidebar_delete.ex
Normal file
176
lib/bds/desktop/shell_live/sidebar_delete.ex
Normal file
@@ -0,0 +1,176 @@
|
||||
defmodule BDS.Desktop.ShellLive.SidebarDelete do
|
||||
@moduledoc false
|
||||
|
||||
import Phoenix.Component, only: [assign: 3]
|
||||
|
||||
alias BDS.{AI, ImportDefinitions, Media, Posts, Scripts, Templates}
|
||||
alias BDS.Desktop.ShellData
|
||||
alias BDS.Desktop.UILocale
|
||||
|
||||
@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
|
||||
{:ok, entity_name} ->
|
||||
assign(socket, :shell_overlay, %{
|
||||
kind: :confirm_delete,
|
||||
title: delete_title(route),
|
||||
entity_name: entity_name,
|
||||
entity_type: route,
|
||||
reference_count: 0,
|
||||
reference_list: [],
|
||||
delete_action: %{source: :sidebar, route: route, id: id}
|
||||
})
|
||||
|
||||
{:error, reason} ->
|
||||
socket
|
||||
|> assign(:shell_overlay, nil)
|
||||
|> callbacks.append_output.(delete_title(route), inspect(reason), nil, "error")
|
||||
|> callbacks.reload.(socket.assigns.workbench)
|
||||
end
|
||||
end
|
||||
|
||||
@spec execute_delete(Phoenix.LiveView.Socket.t(), String.t(), String.t(), map()) ::
|
||||
Phoenix.LiveView.Socket.t()
|
||||
def execute_delete(socket, route, id, callbacks) do
|
||||
case route do
|
||||
"post" ->
|
||||
delete_entity(socket, :post, id, &Posts.delete_post/1, callbacks)
|
||||
|
||||
"media" ->
|
||||
delete_entity(socket, :media, id, &Media.delete_media/1, callbacks)
|
||||
|
||||
"scripts" ->
|
||||
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)
|
||||
|
||||
"chat" ->
|
||||
delete_entity(socket, :chat, id, &AI.delete_chat_conversation/1, callbacks)
|
||||
|
||||
"import" ->
|
||||
delete_entity(socket, :import, id, &ImportDefinitions.delete_definition/1, callbacks)
|
||||
|
||||
_other ->
|
||||
socket
|
||||
|> assign(:shell_overlay, nil)
|
||||
|> callbacks.append_output.(translated("Delete"), inspect(:unsupported_route), nil, "error")
|
||||
|> callbacks.reload.(socket.assigns.workbench)
|
||||
end
|
||||
end
|
||||
|
||||
# ── Private helpers ────────────────────────────────────────────────────────
|
||||
|
||||
defp delete_entity(socket, type, id, delete_fn, callbacks) do
|
||||
case delete_fn.(id) do
|
||||
{:ok, :deleted} ->
|
||||
workbench = BDS.UI.Workbench.close_tab(socket.assigns.workbench, type, id)
|
||||
|
||||
socket
|
||||
|> assign(:shell_overlay, nil)
|
||||
|> assign(:tab_meta, Map.delete(socket.assigns.tab_meta, {type, id}))
|
||||
|> callbacks.reload.(workbench)
|
||||
|
||||
{:error, reason} ->
|
||||
socket
|
||||
|> assign(:shell_overlay, nil)
|
||||
|> callbacks.append_output.(
|
||||
delete_title(Atom.to_string(type)),
|
||||
inspect(reason),
|
||||
nil,
|
||||
"error"
|
||||
)
|
||||
|> callbacks.reload.(socket.assigns.workbench)
|
||||
end
|
||||
end
|
||||
|
||||
@spec delete_target(Phoenix.LiveView.Socket.t(), String.t(), String.t(), String.t() | nil) ::
|
||||
{:ok, String.t()} | {:error, atom()}
|
||||
defp delete_target(socket, route, id, fallback_title) do
|
||||
active_project_id = socket.assigns.projects.active_project_id
|
||||
|
||||
case route 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}
|
||||
|
||||
_other ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
|
||||
"media" ->
|
||||
case Media.get_media(id) do
|
||||
%{project_id: ^active_project_id} = media ->
|
||||
{:ok,
|
||||
present_title(fallback_title) || present_title(media.title) ||
|
||||
present_title(media.original_name) || id}
|
||||
|
||||
_other ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
|
||||
"scripts" ->
|
||||
case Scripts.get_script(id) do
|
||||
%{project_id: ^active_project_id} = script ->
|
||||
{:ok, present_title(fallback_title) || present_title(script.title) || id}
|
||||
|
||||
_other ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
|
||||
"templates" ->
|
||||
case Templates.get_template(id) do
|
||||
%{project_id: ^active_project_id} = template ->
|
||||
{:ok, present_title(fallback_title) || present_title(template.title) || id}
|
||||
|
||||
_other ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
|
||||
"chat" ->
|
||||
case AI.get_chat_conversation(id) do
|
||||
%{title: title} -> {:ok, present_title(fallback_title) || present_title(title) || id}
|
||||
_other -> {:error, :not_found}
|
||||
end
|
||||
|
||||
"import" ->
|
||||
case ImportDefinitions.get_definition(id) do
|
||||
%{project_id: ^active_project_id} = definition ->
|
||||
{:ok, present_title(fallback_title) || present_title(definition.name) || id}
|
||||
|
||||
_other ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
|
||||
_other ->
|
||||
{:error, :unsupported_route}
|
||||
end
|
||||
end
|
||||
|
||||
@spec delete_title(String.t()) :: String.t()
|
||||
defp delete_title("chat"), do: translated("sidebar.chat.deleteConversation")
|
||||
defp delete_title("post"), do: translated("Delete") <> " " <> translated("Post")
|
||||
defp delete_title("media"), do: translated("Delete") <> " " <> translated("Media")
|
||||
defp delete_title("scripts"), do: translated("Delete") <> " " <> translated("Script")
|
||||
defp delete_title("templates"), do: translated("Delete") <> " " <> translated("Template")
|
||||
defp delete_title("import"), do: translated("Delete") <> " " <> translated("Import")
|
||||
defp delete_title(_route), do: translated("Delete")
|
||||
|
||||
@spec present_title(String.t() | nil) :: String.t() | nil
|
||||
defp present_title(value) when is_binary(value) do
|
||||
case String.trim(value) do
|
||||
"" -> nil
|
||||
trimmed -> trimmed
|
||||
end
|
||||
end
|
||||
|
||||
defp present_title(_value), do: nil
|
||||
|
||||
@spec translated(String.t(), map()) :: String.t()
|
||||
defp translated(text, bindings \\ %{}),
|
||||
do: ShellData.translate(text, bindings, UILocale.current())
|
||||
end
|
||||
Reference in New Issue
Block a user