fix(ui, backend): optimize run.bat cache, fix push hanging, normalize path history, redesign New Tab
Some checks failed
Build Releases / Build Linux x64 DEB (push) Failing after 1m33s
Build Releases / Build Windows x64 (push) Successful in 6m31s
Build Releases / Create Release (push) Has been skipped

This commit is contained in:
2026-06-19 15:37:56 -05:00
parent cb145fe722
commit d338023e59
4 changed files with 80 additions and 27 deletions

View File

@@ -14,7 +14,9 @@ if %errorlevel%==0 (
set "GENERATOR="
)
if not exist build\CMakeCache.txt (
cmake -S . -B build %GENERATOR% -DCMAKE_BUILD_TYPE=Release || exit /b 1
)
cmake --build build --config Release --parallel || exit /b 1
if exist build\bin\gitree.exe (

View File

@@ -148,12 +148,14 @@ namespace
std::vector<std::string> withAuthOverrideArguments(std::vector<std::string> arguments,
const std::optional<GitAuthOverride> &auth)
{
arguments.insert(arguments.begin(), {
"-c", "credential.interactive=never",
});
if (!auth || auth->username.empty())
return arguments;
const std::string header = "http.extraHeader=Authorization: Basic " +
encodeBase64(auth->username + ":" + auth->password);
arguments.insert(arguments.begin(), {
"-c", "credential.interactive=never",
arguments.insert(arguments.begin() + 2, {
"-c", header,
});
return arguments;

View File

@@ -118,6 +118,24 @@ namespace
return plain;
}
#endif
std::string normalizePath(const std::string &path)
{
if (path.empty())
return {};
try
{
std::filesystem::path p(path);
std::string result = p.lexically_normal().generic_string();
if (result.size() > 1 && result.back() == '/')
result.pop_back();
return result;
}
catch (...)
{
return path;
}
}
}
UserData::UserData()
@@ -200,7 +218,11 @@ void UserData::load()
{
const char *path = ikv_as_string(ikv_array_get(history, index));
if (path && *path)
recently_closed_.emplace_back(path);
{
std::string normalized = normalizePath(path);
if (std::find(recently_closed_.begin(), recently_closed_.end(), normalized) == recently_closed_.end())
recently_closed_.emplace_back(std::move(normalized));
}
}
}
if (const ikv_node_t *recent = object_value(root, "recent_repositories", IKV_ARRAY))
@@ -210,7 +232,11 @@ void UserData::load()
{
const char *path = ikv_as_string(ikv_array_get(recent, index));
if (path && *path)
recent_repositories_.emplace_back(path);
{
std::string normalized = normalizePath(path);
if (std::find(recent_repositories_.begin(), recent_repositories_.end(), normalized) == recent_repositories_.end())
recent_repositories_.emplace_back(std::move(normalized));
}
}
}
if (const ikv_node_t *session = object_value(root, "session", IKV_OBJECT))
@@ -304,7 +330,11 @@ void UserData::load()
{
const char *path = ikv_as_string(ikv_array_get(history, index));
if (path && *path)
recently_closed_.emplace_back(path);
{
std::string normalized = normalizePath(path);
if (std::find(recently_closed_.begin(), recently_closed_.end(), normalized) == recently_closed_.end())
recently_closed_.emplace_back(std::move(normalized));
}
}
}
if (const ikv_node_t *recent = object_value(root, "recent_repositories", IKV_ARRAY))
@@ -314,7 +344,11 @@ void UserData::load()
{
const char *path = ikv_as_string(ikv_array_get(recent, index));
if (path && *path)
recent_repositories_.emplace_back(path);
{
std::string normalized = normalizePath(path);
if (std::find(recent_repositories_.begin(), recent_repositories_.end(), normalized) == recent_repositories_.end())
recent_repositories_.emplace_back(std::move(normalized));
}
}
}
if (const ikv_node_t *session = object_value(root, "session", IKV_OBJECT))
@@ -399,7 +433,11 @@ void UserData::load()
while (history >> std::quoted(path))
{
if (!path.empty())
recently_closed_.push_back(path);
{
std::string normalized = normalizePath(path);
if (std::find(recently_closed_.begin(), recently_closed_.end(), normalized) == recently_closed_.end())
recently_closed_.push_back(std::move(normalized));
}
if (recently_closed_.size() == 100)
break;
}
@@ -408,7 +446,10 @@ void UserData::load()
std::ifstream session(directory_ / "session.txt");
session >> active_repository_;
while (session >> std::quoted(path))
open_repositories_.push_back(path);
{
if (!path.empty())
open_repositories_.push_back(normalizePath(path));
}
if (open_repositories_.empty())
active_repository_ = 0;
else
@@ -438,8 +479,9 @@ void UserData::addRecentRepository(const std::string &path)
{
if (path.empty())
return;
std::erase(recent_repositories_, path);
recent_repositories_.insert(recent_repositories_.begin(), path);
const std::string normalized = normalizePath(path);
std::erase(recent_repositories_, normalized);
recent_repositories_.insert(recent_repositories_.begin(), normalized);
if (recent_repositories_.size() > 100)
recent_repositories_.resize(100);
save();
@@ -449,12 +491,13 @@ void UserData::addRecentlyClosed(const std::string &path)
{
if (path.empty())
return;
std::erase(recent_repositories_, path);
recent_repositories_.insert(recent_repositories_.begin(), path);
const std::string normalized = normalizePath(path);
std::erase(recent_repositories_, normalized);
recent_repositories_.insert(recent_repositories_.begin(), normalized);
if (recent_repositories_.size() > 100)
recent_repositories_.resize(100);
std::erase(recently_closed_, path);
recently_closed_.insert(recently_closed_.begin(), path);
std::erase(recently_closed_, normalized);
recently_closed_.insert(recently_closed_.begin(), normalized);
if (recently_closed_.size() > 100)
recently_closed_.resize(100);
save();
@@ -472,6 +515,8 @@ std::string UserData::takeRecentlyClosed()
void UserData::setRepositorySession(std::vector<std::string> paths, size_t active_repository)
{
for (auto &path : paths)
path = normalizePath(path);
open_repositories_ = std::move(paths);
active_repository_ = open_repositories_.empty()
? 0

View File

@@ -3759,7 +3759,9 @@ void draw_footer() {
void draw_new_tab() {
ImGui::BeginChild("new_tab", {-1, -ui(28.0f)}, ImGuiChildFlags_None);
const float margin = ui(84.0f);
const float margin = ui(48.0f);
const float content_width = std::min(ui(850.0f), ImGui::GetContentRegionAvail().x - margin * 2.0f);
ImGui::SetCursorPos({margin, ui(28.0f)});
ImGui::PushFont(g_bold_font, 0.0f);
ImGui::SetWindowFontScale(1.25f);
@@ -3767,20 +3769,20 @@ void draw_new_tab() {
ImGui::SetWindowFontScale(1.0f);
ImGui::PopFont();
ImGui::SetCursorPosX(margin);
if (ImGui::Button(ICON_TB_FOLDER_OPEN " Open", {ui(92.0f), ui(36.0f)}))
if (ImGui::Button(ICON_TB_FOLDER_OPEN " Open", {ui(112.0f), ui(40.0f)}))
pick_and_open_repository();
ImGui::SameLine();
if (ImGui::Button(ICON_TB_DOWNLOAD " Clone", {ui(96.0f), ui(36.0f)}))
ImGui::SameLine(0, ui(8.0f));
if (ImGui::Button(ICON_TB_DOWNLOAD " Clone", {ui(116.0f), ui(40.0f)}))
g_clone_popup = true;
ImGui::SameLine();
if (ImGui::Button(ICON_TB_PLUS " Create", {ui(100.0f), ui(36.0f)}))
ImGui::SameLine(0, ui(8.0f));
if (ImGui::Button(ICON_TB_PLUS " Create", {ui(120.0f), ui(40.0f)}))
g_init_popup = true;
ImGui::SetCursorPosX(margin);
ImGui::SetNextItemWidth(std::max(ui(280.0f), ImGui::GetContentRegionAvail().x - margin));
ImGui::SetNextItemWidth(content_width);
ImGui::InputTextWithHint("##repository_filter", ICON_TB_MAGNIFYING_GLASS " Search repositories",
g_repository_filter.data(), g_repository_filter.size());
ImGui::Dummy({0, ui(7.0f)});
ImGui::Dummy({0, ui(10.0f)});
ImGui::SetCursorPosX(margin);
ImGui::PushFont(g_bold_font, 0.0f);
ImGui::TextUnformatted("Recent");
@@ -3816,7 +3818,7 @@ void draw_new_tab() {
for (const std::string& path : discovered_repositories) add_repository(path);
ImGui::SetCursorPosX(margin);
ImGui::BeginChild("repository_list", {-margin, -ui(8.0f)}, ImGuiChildFlags_None);
ImGui::BeginChild("repository_list", {content_width, -ui(8.0f)}, ImGuiChildFlags_None);
int visible_index = 0;
for (const std::string& repository_path : repositories) {
const std::filesystem::path path(repository_path);
@@ -3828,16 +3830,17 @@ void draw_new_tab() {
continue;
ImGui::PushID(visible_index++);
const bool clicked = ImGui::Selectable("##repository", false,
ImGuiSelectableFlags_None, {0, ui(22.0f)});
ImGuiSelectableFlags_None, {0, ui(28.0f)});
const ImVec2 minimum = ImGui::GetItemRectMin();
ImDrawList* draw = ImGui::GetWindowDrawList();
const float row_font_size = ImGui::GetFontSize();
const float text_y_offset = (ui(28.0f) - row_font_size) * 0.5f;
draw->AddText(g_bold_font, row_font_size,
{minimum.x + ui(3.0f), minimum.y + ui(2.0f)},
{minimum.x + ui(8.0f), minimum.y + text_y_offset},
IM_COL32(45, 192, 238, 255), name.c_str());
const float name_width = g_bold_font->CalcTextSizeA(
row_font_size, std::numeric_limits<float>::max(), 0.0f, name.c_str()).x;
draw->AddText({minimum.x + name_width + ui(14.0f), minimum.y + ui(2.0f)},
draw->AddText({minimum.x + ui(8.0f) + name_width + ui(14.0f), minimum.y + text_y_offset},
IM_COL32(137, 143, 154, 255), repository_path.c_str());
if (clicked) open_repository(repository_path.c_str());
if (ImGui::BeginPopupContextItem()) {
@@ -3858,6 +3861,7 @@ void draw_new_tab() {
ImGui::EndChild();
}
void draw_app() {
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);