Files
Towards/modules/client/src/app/FileAddressList.cpp
T

111 lines
2.7 KiB
C++
Raw Normal View History

2026-07-22 17:34:44 +02:00
#include "FileAddressList.hpp"
#include <spdlog/spdlog.h>
#include <filesystem>
#include <fstream>
#include <cstdlib>
#include <algorithm>
namespace tw::app {
namespace {
std::string get_config_dir() {
// Try XDG_CONFIG_HOME first
const char* xdg_config_home = std::getenv("XDG_CONFIG_HOME");
if(xdg_config_home && xdg_config_home[0] != '\0') {
return std::string(xdg_config_home) + "/towards";
}
// Fall back to $HOME/.config/towards
const char* home = std::getenv("HOME");
if(home && home[0] != '\0') {
return std::string(home) + "/.config/towards";
}
// Both unset
return "";
}
} // anonymous namespace
FileAddressList::FileAddressList(const std::string& file_name) {
std::string config_dir = get_config_dir();
if(config_dir.empty()) {
spdlog::debug("XDG_CONFIG_HOME and HOME not set; address lists will not be persisted");
m_can_save = false;
return;
}
m_path = config_dir + "/" + file_name;
m_can_save = true;
}
void FileAddressList::load() {
if(m_path.empty()) {
return; // No config path available
}
std::ifstream file(m_path);
if(!file.is_open()) {
// File doesn't exist or can't be read; this is not an error
return;
}
m_entries.clear();
std::string line;
while(std::getline(file, line)) {
// Trim whitespace from the line
size_t start = line.find_first_not_of(" \t\r\n");
size_t end = line.find_last_not_of(" \t\r\n");
if(start != std::string::npos) {
line = line.substr(start, end - start + 1);
if(!line.empty()) {
m_entries.push_back(line);
}
}
}
}
void FileAddressList::save() const {
if(!m_can_save || m_path.empty()) {
return; // Cannot save without config path
}
// Create the directory if needed
std::filesystem::path config_path(m_path);
std::filesystem::path config_dir = config_path.parent_path();
try {
std::filesystem::create_directories(config_dir);
} catch(const std::filesystem::filesystem_error&) {
// If we can't create the directory, silently fail to save
return;
}
// Write entries to file
std::ofstream file(m_path);
if(!file.is_open()) {
return; // Can't open file for writing; silently fail
}
for(const auto& entry : m_entries) {
file << entry << "\n";
}
}
void FileAddressList::remove(const std::string& entry) {
auto it = std::find(m_entries.begin(), m_entries.end(), entry);
if(it != m_entries.end()) {
m_entries.erase(it);
}
}
const std::vector<std::string>& FileAddressList::entries() const {
return m_entries;
}
} // namespace tw::app