feat(framework): convencion local_files/ — separacion distribuible vs estado

Toda app C++ basada en fn::run_app coloca sus archivos escribibles
bajo <exe_dir>/local_files/. Los distribuibles (.exe, dlls, ttfs,
enrichers/, runtime/) siguen junto al .exe. Esto deja la carpeta
distribuible limpia para zippear y separa con claridad lo que
viaja con la app de lo que el PC genera.

API publica en fn:: (cpp/framework/app_base.h):
  - exe_dir()                    directorio del ejecutable
  - local_dir()                  <exe_dir>/local_files/, creado on-demand
  - local_path(name)             <local_dir>/<name>
  - migrate_to_local_files(...)  mueve archivos viejos desde cwd/exe_dir

Cambios:
- run_app configura io.IniFilename = local_path("imgui.ini") y
  llama migrate_to_local_files(["imgui.ini","app_settings.ini"])
  antes de settings_load(). Migracion idempotente para PCs con
  instalacion previa.
- app_settings.cpp usa local_path("app_settings.ini") en lugar de
  hardcoded "app_settings.ini" relativo al cwd.
- cpp_apps.md §7 documenta la convencion como obligatoria. Las
  apps deben usar fn::local_path() para cualquier archivo
  escribible nuevo.

Beneficios:
- zip distribuible no se "ensucia" con .ini/.db generados al usar.
- reset trivial: borrar local_files/.
- backup/sync per-PC: solo local_files/ es propio del PC.
- elimina la mezcla de paths Linux/Windows que generaba bugs como
  "projects\\default\\operations.db" en builds cross-platform.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 00:32:55 +02:00
parent f0cb5bce24
commit f769928ffd
4 changed files with 262 additions and 5 deletions
+7 -4
View File
@@ -1,6 +1,7 @@
#include "app_settings.h"
#include "imgui.h"
#include "../../framework/app_base.h"
#include <cstdio>
#include <cstdlib>
@@ -16,7 +17,9 @@ AppSettings g_settings;
bool g_font_dirty = false;
bool g_window_open = false;
constexpr const char* kSettingsPath = "app_settings.ini";
// app_settings.ini vive en <exe_dir>/local_files/ (convencion del
// registry — todos los archivos escribibles bajo local_files/).
const char* settings_path() { return fn::local_path("app_settings.ini"); }
const float k_sizes[] = {12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 18.0f, 20.0f};
constexpr int k_size_count = sizeof(k_sizes) / sizeof(k_sizes[0]);
@@ -59,7 +62,7 @@ void parse_line(const char* line) {
AppSettings& settings() { return g_settings; }
void settings_load() {
FILE* f = std::fopen(kSettingsPath, "r");
FILE* f = std::fopen(settings_path(), "r");
if (!f) return;
char line[256];
while (std::fgets(line, sizeof(line), f)) parse_line(line);
@@ -67,9 +70,9 @@ void settings_load() {
}
void settings_save() {
FILE* f = std::fopen(kSettingsPath, "w");
FILE* f = std::fopen(settings_path(), "w");
if (!f) {
std::fprintf(stderr, "[fn_ui] settings_save: no pude abrir %s\n", kSettingsPath);
std::fprintf(stderr, "[fn_ui] settings_save: no pude abrir %s\n", settings_path());
return;
}
std::fprintf(f, "# fn_registry app_settings.ini — autogenerado, editable\n");