feat: git sidebar shows the commit history in its lower half like the GUI (issue #30)
This commit is contained in:
@@ -11,9 +11,9 @@ defmodule BDS.TUI do
|
|||||||
|
|
||||||
Sidebar focus: `↑/↓`/`j/k` navigate, `enter` open, `n` new post,
|
Sidebar focus: `↑/↓`/`j/k` navigate, `enter` open, `n` new post,
|
||||||
`1..5` switch view (posts/media/templates/scripts/tags), `7` git panel
|
`1..5` switch view (posts/media/templates/scripts/tags), `7` git panel
|
||||||
(changed files in the sidebar, scrollable whole-folder diff in the main
|
(changed files plus commit history in the sidebar, scrollable
|
||||||
area; `c` commit all, `u` pull, `s` push, enter jumps the diff to the
|
whole-folder diff in the main area; `c` commit all, `u` pull, `s` push,
|
||||||
selected file), `r` refresh,
|
enter jumps the diff to the selected file), `r` refresh,
|
||||||
`p` projects overlay (switch the active project or open an existing
|
`p` projects overlay (switch the active project or open an existing
|
||||||
blog folder by path, with bash-style tab completion — opening one
|
blog folder by path, with bash-style tab completion — opening one
|
||||||
queues a full database rebuild), `/` vi-style search that live-filters
|
queues a full database rebuild), `/` vi-style search that live-filters
|
||||||
@@ -901,7 +901,27 @@ defmodule BDS.TUI do
|
|||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
defp sidebar_widgets(state, rect) do
|
# The git sidebar mirrors the GUI: changed files on top, commit history
|
||||||
|
# in the lower half (↑ needs push, ↓ remote-only, blank when synced).
|
||||||
|
defp sidebar_widgets(%{view: "git", sidebar: %{git_state: "active"} = sidebar} = state, rect) do
|
||||||
|
[changes_rect, history_rect] =
|
||||||
|
Layout.split(rect, :vertical, [{:percentage, 50}, {:percentage, 50}])
|
||||||
|
|
||||||
|
history_items = Enum.map(sidebar.history_entries, &history_line/1)
|
||||||
|
|
||||||
|
[
|
||||||
|
sidebar_list_widget(state, changes_rect),
|
||||||
|
{%List{
|
||||||
|
items: history_items,
|
||||||
|
selected: nil,
|
||||||
|
block: %Block{title: dgettext("ui", "History"), borders: [:all]}
|
||||||
|
}, history_rect}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
defp sidebar_widgets(state, rect), do: [sidebar_list_widget(state, rect)]
|
||||||
|
|
||||||
|
defp sidebar_list_widget(state, rect) do
|
||||||
items =
|
items =
|
||||||
Enum.map(state.items, fn
|
Enum.map(state.items, fn
|
||||||
{:header, title} -> "── #{title}"
|
{:header, title} -> "── #{title}"
|
||||||
@@ -910,18 +930,27 @@ defmodule BDS.TUI do
|
|||||||
|
|
||||||
focused? = state.focus == :sidebar
|
focused? = state.focus == :sidebar
|
||||||
|
|
||||||
[
|
{%List{
|
||||||
{%List{
|
items: items,
|
||||||
items: items,
|
selected: list_selected(items, state.selected),
|
||||||
selected: list_selected(items, state.selected),
|
highlight_style:
|
||||||
highlight_style:
|
if(focused?,
|
||||||
if(focused?,
|
do: %Style{fg: :black, bg: :cyan},
|
||||||
do: %Style{fg: :black, bg: :cyan},
|
else: %Style{modifiers: [:bold]}
|
||||||
else: %Style{modifiers: [:bold]}
|
),
|
||||||
),
|
block: %Block{title: sidebar_title(state), borders: [:all]}
|
||||||
block: %Block{title: sidebar_title(state), borders: [:all]}
|
}, rect}
|
||||||
}, rect}
|
end
|
||||||
]
|
|
||||||
|
defp history_line(entry) do
|
||||||
|
marker =
|
||||||
|
case entry.sync_status do
|
||||||
|
"local_only" -> "↑ "
|
||||||
|
"remote_only" -> "↓ "
|
||||||
|
_synced -> " "
|
||||||
|
end
|
||||||
|
|
||||||
|
marker <> entry.short_hash <> " " <> to_string(entry.subject || "")
|
||||||
end
|
end
|
||||||
|
|
||||||
defp sidebar_title(%{view: "git", sidebar: %{git_state: "active"} = sidebar}) do
|
defp sidebar_title(%{view: "git", sidebar: %{git_state: "active"} = sidebar}) do
|
||||||
|
|||||||
@@ -114,7 +114,9 @@ rule GitPanel {
|
|||||||
when: TuiKeyPressed(code: "7")
|
when: TuiKeyPressed(code: "7")
|
||||||
-- "7" opens the git panel (issue #30) for content sync: the sidebar
|
-- "7" opens the git panel (issue #30) for content sync: the sidebar
|
||||||
-- lists the changed files from git status (code + path, branch with
|
-- lists the changed files from git status (code + path, branch with
|
||||||
-- ahead/behind counts in the title), the main area shows a
|
-- ahead/behind counts in the title) with the commit history in its
|
||||||
|
-- lower half, like the GUI (short hash + subject; ↑ marks commits
|
||||||
|
-- that still need a push, ↓ remote-only ones), the main area shows a
|
||||||
-- scrollable whole-folder diff (staged + unstaged, capped) paged
|
-- scrollable whole-folder diff (staged + unstaged, capped) paged
|
||||||
-- with pgup/pgdn; enter on a file jumps the diff to it. "c" opens a
|
-- with pgup/pgdn; enter on a file jumps the diff to it. "c" opens a
|
||||||
-- status-line commit prompt (git add -A + commit, empty messages
|
-- status-line commit prompt (git add -A + commit, empty messages
|
||||||
|
|||||||
@@ -800,6 +800,27 @@ defmodule BDS.TUITest do
|
|||||||
assert_receive {:git_result, :push, {:error, _reason}}, 5_000
|
assert_receive {:git_result, :push, {:error, _reason}}, 5_000
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "the sidebar shows the commit history in its lower half", %{project: project} do
|
||||||
|
dir = BDS.Projects.project_data_dir(project)
|
||||||
|
init_repo!(dir)
|
||||||
|
|
||||||
|
state = mount!() |> press("7")
|
||||||
|
|
||||||
|
assert [entry | _] = state.sidebar.history_entries
|
||||||
|
assert entry.subject == "initial"
|
||||||
|
|
||||||
|
text = screen_text(state, 140, 40)
|
||||||
|
assert text =~ "History"
|
||||||
|
# No remote exists, so the commit is local-only and marked for push.
|
||||||
|
assert text =~ "↑ #{entry.short_hash} initial"
|
||||||
|
|
||||||
|
# A commit from the panel shows up in the history immediately.
|
||||||
|
modify!(dir, "tracked.md", "changed\n")
|
||||||
|
state = state |> press("r") |> press("c") |> type("sync commit") |> press("enter")
|
||||||
|
|
||||||
|
assert screen_text(state, 140, 40) =~ "sync commit"
|
||||||
|
end
|
||||||
|
|
||||||
test "git keys in a non-repo project only report", %{project: project} do
|
test "git keys in a non-repo project only report", %{project: project} do
|
||||||
state = mount!() |> press("7")
|
state = mount!() |> press("7")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user