D1-18: HomeItemProtection — Home menu item cannot be moved, reordered, or deleted

This commit is contained in:
2026-05-30 13:33:40 +02:00
parent e515cfacc6
commit df0ae6a41b
4 changed files with 164 additions and 32 deletions

View File

@@ -180,6 +180,8 @@ defmodule BDS.Desktop.ShellLive.MenuEditor.TreeOps do
end
@spec move_selected(term(), term()) :: term()
def move_selected(%{selected_id: @home_item_id} = state, _direction), do: state
def move_selected(%{selected_id: selected_id} = state, direction)
when direction in [:up, :down] do
case find_path(state.items, selected_id) do
@@ -209,6 +211,8 @@ defmodule BDS.Desktop.ShellLive.MenuEditor.TreeOps do
end
@spec indent_selected(term()) :: term()
def indent_selected(%{selected_id: @home_item_id} = state), do: state
def indent_selected(%{selected_id: selected_id} = state) do
case find_path(state.items, selected_id) do
nil ->
@@ -249,6 +253,8 @@ defmodule BDS.Desktop.ShellLive.MenuEditor.TreeOps do
end
@spec unindent_selected(term()) :: term()
def unindent_selected(%{selected_id: @home_item_id} = state), do: state
def unindent_selected(%{selected_id: selected_id} = state) do
case find_path(state.items, selected_id) do
nil ->
@@ -295,6 +301,8 @@ defmodule BDS.Desktop.ShellLive.MenuEditor.TreeOps do
when drag_item_id == target_item_id,
do: state
def drop_selected(state, @home_item_id, _target_item_id, _position), do: state
@spec drop_selected(term(), term(), term(), term()) :: term()
def drop_selected(state, drag_item_id, target_item_id, position) do
drag_path = find_path(state.items, drag_item_id)

View File

@@ -5,57 +5,73 @@ defmodule BDS.Desktop.ShellLive.MenuEditor.TreePredicates do
@spec can_move_up?(term(), term()) :: term()
def can_move_up?(items, selected_id) do
case TreeOps.find_path(items, selected_id) do
[_parent, index] -> index > 0
[index] -> index > 0
path when is_list(path) -> List.last(path) > 0
_other -> false
if selected_id == TreeOps.home_item_id() do
false
else
case TreeOps.find_path(items, selected_id) do
[_parent, index] -> index > 0
[index] -> index > 0
path when is_list(path) -> List.last(path) > 0
_other -> false
end
end
end
@spec can_move_down?(term(), term()) :: term()
def can_move_down?(items, selected_id) do
case TreeOps.find_path(items, selected_id) do
nil ->
false
if selected_id == TreeOps.home_item_id() do
false
else
case TreeOps.find_path(items, selected_id) do
nil ->
false
path ->
parent_path = Enum.drop(path, -1)
index = List.last(path)
index < length(TreeOps.items_at_path(items, parent_path)) - 1
path ->
parent_path = Enum.drop(path, -1)
index = List.last(path)
index < length(TreeOps.items_at_path(items, parent_path)) - 1
end
end
end
@spec can_indent?(term(), term()) :: term()
def can_indent?(items, selected_id) do
case TreeOps.find_path(items, selected_id) do
nil ->
false
if selected_id == TreeOps.home_item_id() do
false
else
case TreeOps.find_path(items, selected_id) do
nil ->
false
[] ->
false
[] ->
false
[_index] = path ->
index = List.last(path)
index > 0 and match?(%{kind: :submenu}, TreeOps.item_at_path(items, [index - 1]))
[_index] = path ->
index = List.last(path)
index > 0 and match?(%{kind: :submenu}, TreeOps.item_at_path(items, [index - 1]))
path ->
index = List.last(path)
path ->
index = List.last(path)
index > 0 and
match?(
%{kind: :submenu},
TreeOps.item_at_path(items, Enum.drop(path, -1) ++ [index - 1])
)
index > 0 and
match?(
%{kind: :submenu},
TreeOps.item_at_path(items, Enum.drop(path, -1) ++ [index - 1])
)
end
end
end
@spec can_unindent?(term(), term()) :: term()
def can_unindent?(items, selected_id) do
case TreeOps.find_path(items, selected_id) do
[_index] -> false
path when is_list(path) -> length(path) > 1
_other -> false
if selected_id == TreeOps.home_item_id() do
false
else
case TreeOps.find_path(items, selected_id) do
[_index] -> false
path when is_list(path) -> length(path) > 1
_other -> false
end
end
end