feat(refresh): add timed background repository reloads
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <git2.h>
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
@@ -85,6 +86,8 @@ struct RepositoryView {
|
||||
std::vector<WorkingFile> working_files;
|
||||
int selected_commit = 0;
|
||||
int scroll_to_commit = -1;
|
||||
std::chrono::steady_clock::time_point last_background_refresh{};
|
||||
bool pending_background_refresh = false;
|
||||
ToolbarHistoryAction undo_action;
|
||||
ToolbarHistoryAction redo_action;
|
||||
|
||||
|
||||
@@ -116,6 +116,9 @@ float g_outline_icon_size = 15.0f;
|
||||
enum class ToolbarActionRequest { none, pull, push };
|
||||
ToolbarActionRequest g_pending_toolbar_action = ToolbarActionRequest::none;
|
||||
ToolbarActionRequest g_running_toolbar_action = ToolbarActionRequest::none;
|
||||
using RefreshClock = std::chrono::steady_clock;
|
||||
constexpr auto active_refresh_interval = std::chrono::seconds(2);
|
||||
constexpr auto background_refresh_interval = std::chrono::seconds(5);
|
||||
|
||||
|
||||
float ui(float value) { return value * g_ui_scale; }
|
||||
@@ -175,11 +178,45 @@ bool copy_to_clipboard(std::string_view text, const char* description) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void mark_repository_refreshed(RepositoryView& repository) {
|
||||
repository.last_background_refresh = RefreshClock::now();
|
||||
repository.pending_background_refresh = false;
|
||||
}
|
||||
|
||||
bool reload_repository_background(RepositoryView& repository, bool surface_errors = false) {
|
||||
if (!g_git_manager || !repository.repo || repository.path.empty()) return false;
|
||||
std::string error;
|
||||
repository.pending_background_refresh = false;
|
||||
repository.last_background_refresh = RefreshClock::now();
|
||||
if (!g_git_manager->reload(repository, error)) {
|
||||
if (surface_errors && !error.empty()) g_notice = error;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void process_repository_background_refreshes() {
|
||||
if (!g_git_manager || g_tabs.empty()) return;
|
||||
if (g_running_toolbar_action != ToolbarActionRequest::none) return;
|
||||
if (!g_running_branch_checkout.empty() || !g_requested_branch_checkout.empty()) return;
|
||||
const RefreshClock::time_point now = RefreshClock::now();
|
||||
for (size_t index = 0; index < g_tabs.size(); ++index) {
|
||||
RepositoryView& repository = *g_tabs[index];
|
||||
if (!repository.repo || repository.path.empty()) continue;
|
||||
const auto interval = index == g_active_tab ? active_refresh_interval : background_refresh_interval;
|
||||
const bool due = repository.pending_background_refresh ||
|
||||
repository.last_background_refresh.time_since_epoch().count() == 0 ||
|
||||
now - repository.last_background_refresh >= interval;
|
||||
if (due) reload_repository_background(repository, index == g_active_tab);
|
||||
}
|
||||
}
|
||||
|
||||
bool run_repository_action(const std::vector<std::string>& arguments, const std::string& success_notice,
|
||||
const std::string& focus_commit = {}) {
|
||||
std::string output;
|
||||
if (!g_git_manager->captureGit(repo(), arguments, output, g_notice)) return false;
|
||||
if (!g_git_manager->reload(repo(), g_notice)) return false;
|
||||
mark_repository_refreshed(repo());
|
||||
if (!focus_commit.empty()) g_pending_commit_jump = focus_commit;
|
||||
g_notice = success_notice;
|
||||
return true;
|
||||
@@ -295,6 +332,7 @@ void activate_repository_tab(size_t index) {
|
||||
g_active_tab = index;
|
||||
g_tab_to_select = g_tabs[index].get();
|
||||
reset_repository_view();
|
||||
g_tabs[index]->pending_background_refresh = true;
|
||||
persist_repository_session();
|
||||
}
|
||||
|
||||
@@ -322,6 +360,7 @@ void close_tab(size_t index) {
|
||||
bool open_repository(const char* path) {
|
||||
const bool opened = g_git_manager->openRepository(repo(), path, g_notice);
|
||||
if (opened) {
|
||||
mark_repository_refreshed(repo());
|
||||
if (g_user_data && path && *path) g_user_data->addRecentRepository(path);
|
||||
reset_repository_view();
|
||||
persist_repository_session();
|
||||
@@ -2844,7 +2883,7 @@ void draw_popups() {
|
||||
std::string output;
|
||||
g_git_manager->captureGit(repo(), {"lfs", "install", "--local"}, output, g_notice);
|
||||
}
|
||||
g_git_manager->reload(repo(), g_notice);
|
||||
if (g_git_manager->reload(repo(), g_notice)) mark_repository_refreshed(repo());
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
@@ -3086,7 +3125,8 @@ void draw_app() {
|
||||
}
|
||||
if (ImGui::BeginMenu("Edit")) { ImGui::MenuItem("Preferences", nullptr, false, false); ImGui::EndMenu(); }
|
||||
if (ImGui::BeginMenu("View")) {
|
||||
if (ImGui::MenuItem("Refresh", "F5")) g_git_manager->reload(repo(), g_notice);
|
||||
if (ImGui::MenuItem("Refresh", "F5") && g_git_manager->reload(repo(), g_notice))
|
||||
mark_repository_refreshed(repo());
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Help")) {
|
||||
@@ -3431,7 +3471,8 @@ int runGitree(int argc, char** argv) {
|
||||
} else if (!user_data.openRepositories().empty()) {
|
||||
for (const std::string& path : user_data.openRepositories()) {
|
||||
g_tabs.push_back(std::make_unique<RepositoryView>());
|
||||
if (!path.empty()) git_manager.openRepository(*g_tabs.back(), path, g_notice);
|
||||
if (!path.empty() && git_manager.openRepository(*g_tabs.back(), path, g_notice))
|
||||
mark_repository_refreshed(*g_tabs.back());
|
||||
}
|
||||
g_active_tab = std::min(user_data.activeRepository(), g_tabs.size() - 1);
|
||||
g_tab_to_select = g_tabs[g_active_tab].get();
|
||||
@@ -3457,6 +3498,7 @@ int runGitree(int argc, char** argv) {
|
||||
|
||||
while (!window_manager.shouldClose()) {
|
||||
window_manager.pollEvents();
|
||||
process_repository_background_refreshes();
|
||||
const bool dpi_changed = window_manager.consumeDpiChange();
|
||||
if (dpi_changed || g_zoom_reload_requested) {
|
||||
load_fonts(combined_ui_scale(window_manager.dpiScale(), g_zoom_percent));
|
||||
|
||||
Reference in New Issue
Block a user