refactor(settings): consolidate appdata state into ikv2b

This commit is contained in:
2026-06-18 23:23:48 -05:00
parent e3b6c34e88
commit e1107756f9
3 changed files with 89 additions and 7 deletions

View File

@@ -34,7 +34,6 @@ UserData::UserData()
{
directory_ = roaming_directory() / "Identity" / "Gitree";
std::filesystem::create_directories(directory_);
imgui_ini_path_ = (directory_ / "imgui.ini").string();
load();
}
@@ -43,10 +42,22 @@ UserData::~UserData()
save();
}
std::filesystem::path UserData::dataPath() const
{
return directory_ / "user_data.ikv2b";
}
void UserData::removeLegacyFiles() const
{
std::error_code error;
for (const char *name : {"imgui.ini", "settings.ini", "history.txt", "session.txt", "user_data.ikv"})
std::filesystem::remove(directory_ / name, error);
}
void UserData::load()
{
const std::filesystem::path data_path = directory_ / "user_data.ikv";
if (ikv_node_t *root = ikv_parse_file(data_path.string().c_str()))
const std::filesystem::path binary_path = dataPath();
if (ikv_node_t *root = ikvb_parse_file(binary_path.string().c_str()))
{
if (const ikv_node_t *settings = object_value(root, "settings", IKV_OBJECT))
{
@@ -113,6 +124,75 @@ void UserData::load()
return;
}
const std::filesystem::path text_data_path = directory_ / "user_data.ikv";
if (ikv_node_t *root = ikv_parse_file(text_data_path.string().c_str()))
{
if (const ikv_node_t *settings = object_value(root, "settings", IKV_OBJECT))
{
if (const ikv_node_t *value = object_value(settings, "sidebar_width", IKV_FLOAT))
sidebar_width_ = static_cast<float>(ikv_as_float(value));
if (const ikv_node_t *value = object_value(settings, "details_width", IKV_FLOAT))
details_width_ = static_cast<float>(ikv_as_float(value));
if (const ikv_node_t *value = object_value(settings, "pull_mode", IKV_INT))
pull_mode_ = static_cast<int>(ikv_as_int(value));
if (const ikv_node_t *value = object_value(settings, "zoom_percent", IKV_INT))
zoom_percent_ = static_cast<int>(ikv_as_int(value));
if (const ikv_node_t *heights = object_value(settings, "sidebar_sections", IKV_ARRAY))
{
const uint32_t count = std::min<uint32_t>(
ikv_array_size(heights), static_cast<uint32_t>(sidebar_section_heights_.size()));
for (uint32_t index = 0; index < count; ++index)
sidebar_section_heights_[index] = static_cast<float>(ikv_as_float(ikv_array_get(heights, index)));
}
}
if (const ikv_node_t *history = object_value(root, "recently_closed", IKV_ARRAY))
{
const uint32_t count = std::min<uint32_t>(ikv_array_size(history), 100);
for (uint32_t index = 0; index < count; ++index)
{
const char *path = ikv_as_string(ikv_array_get(history, index));
if (path && *path)
recently_closed_.emplace_back(path);
}
}
if (const ikv_node_t *recent = object_value(root, "recent_repositories", IKV_ARRAY))
{
const uint32_t count = std::min<uint32_t>(ikv_array_size(recent), 100);
for (uint32_t index = 0; index < count; ++index)
{
const char *path = ikv_as_string(ikv_array_get(recent, index));
if (path && *path)
recent_repositories_.emplace_back(path);
}
}
if (const ikv_node_t *session = object_value(root, "session", IKV_OBJECT))
{
if (const ikv_node_t *active = object_value(session, "active_tab", IKV_INT))
active_repository_ = static_cast<size_t>(std::max<int64_t>(0, ikv_as_int(active)));
if (const ikv_node_t *tabs = object_value(session, "tabs", IKV_ARRAY))
{
for (uint32_t index = 0; index < ikv_array_size(tabs); ++index)
{
const char *path = ikv_as_string(ikv_array_get(tabs, index));
open_repositories_.emplace_back(path ? path : "");
}
}
}
ikv_free(root);
sidebar_width_ = std::clamp(sidebar_width_, 180.0f, 520.0f);
details_width_ = std::clamp(details_width_, 280.0f, 650.0f);
pull_mode_ = std::clamp(pull_mode_, 0, 3);
zoom_percent_ = std::clamp(zoom_percent_, 80, 200);
for (float &height : sidebar_section_heights_)
height = std::clamp(height, 42.0f, 500.0f);
if (open_repositories_.empty())
active_repository_ = 0;
else
active_repository_ = std::min(active_repository_, open_repositories_.size() - 1);
save();
return;
}
// Import the original files once when upgrading an existing installation.
std::ifstream settings(directory_ / "settings.ini");
std::string key;
@@ -161,6 +241,7 @@ void UserData::load()
active_repository_ = 0;
else
active_repository_ = std::min(active_repository_, open_repositories_.size() - 1);
save();
}
void UserData::addRecentRepository(const std::string &path)
@@ -238,6 +319,7 @@ void UserData::save() const
for (const auto &path : open_repositories_)
ikv_array_add_string(tabs, path.c_str());
ikv_write_file((directory_ / "user_data.ikv").string().c_str(), root);
ikvb_write_file_version(dataPath().string().c_str(), root, IKV_VERSION_2);
ikv_free(root);
removeLegacyFiles();
}

View File

@@ -12,7 +12,6 @@ public:
~UserData();
[[nodiscard]] const std::filesystem::path &directory() const { return directory_; }
[[nodiscard]] const std::string &imguiIniPath() const { return imgui_ini_path_; }
[[nodiscard]] const std::vector<std::string> &recentRepositories() const { return recent_repositories_; }
[[nodiscard]] const std::vector<std::string> &recentlyClosed() const { return recently_closed_; }
[[nodiscard]] const std::vector<std::string> &openRepositories() const { return open_repositories_; }
@@ -44,9 +43,10 @@ public:
private:
void load();
[[nodiscard]] std::filesystem::path dataPath() const;
void removeLegacyFiles() const;
std::filesystem::path directory_;
std::string imgui_ini_path_;
std::vector<std::string> recent_repositories_;
std::vector<std::string> recently_closed_;
std::vector<std::string> open_repositories_;

View File

@@ -3294,7 +3294,7 @@ int runGitree(int argc, char** argv) {
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
ImGui::GetIO().IniFilename = user_data.imguiIniPath().c_str();
ImGui::GetIO().IniFilename = nullptr;
load_fonts(combined_ui_scale(window_manager.dpiScale(), g_zoom_percent));
ImGui_ImplGlfw_InitForOpenGL(window_manager.nativeWindow(), true);
ImGui_ImplOpenGL3_Init("#version 330");