feat: add calendar visibility picker

Derive session calendars from event metadata and apply one visibility contract to month rendering, appointment focus, and search without filtering persistence writes.

Add keyboard picker coverage, full-model save regression tests, documentation, warning-clean builds, sanitizer verification, and live PTY terminal restoration checks.
This commit is contained in:
2026-07-18 09:01:27 +01:00
parent 2774087d14
commit 88d370bf99
14 changed files with 416 additions and 12 deletions

View File

@@ -97,6 +97,40 @@ void test_compact_and_input()
check(nocal::tui::decode_key("\x1b[6~") == nocal::tui::Action::next_month,
"PageDown is decoded");
check(nocal::tui::decode_key("k") == nocal::tui::Action::up, "Vim movement is decoded");
check(nocal::tui::decode_key("c") == nocal::tui::Action::calendars,
"c opens the calendar picker");
}
void test_calendar_picker_frame()
{
using namespace std::chrono;
auto state = nocal::tui::ScreenState{};
state.visible_month = year{2026} / July;
state.selected_day = year{2026} / July / day{17};
state.today = state.selected_day;
state.width = 52;
state.height = 10;
state.ansi = false;
state.show_calendar_picker = true;
state.calendar_index = 1;
const std::vector<nocal::Calendar> calendars{
{.id = "", .name = "Default", .color = {}, .visible = true,
.read_only = false},
{.id = "work", .name = "Work", .color = {}, .visible = false,
.read_only = false},
};
const auto frame = nocal::tui::render_month(
std::span<const nocal::Event>{}, calendars, state);
check(frame.find("CALENDARS") != std::string::npos &&
frame.find("1 of 2 visible") != std::string::npos &&
frame.find("[x] Default") != std::string::npos &&
frame.find("[ ] Work") != std::string::npos,
"calendar picker renders visibility and selection context");
check(std::count(frame.begin(), frame.end(), '\n') == 9,
"calendar picker fills the requested height");
check(frame.find("\x1b[") == std::string::npos,
"calendar picker remains readable without ANSI styling");
}
void test_navigation()
@@ -164,6 +198,7 @@ int main()
test_compact_and_input();
test_navigation();
test_search_frames();
test_calendar_picker_frame();
if (failures != 0) {
std::cerr << failures << " TUI test(s) failed\n";
return EXIT_FAILURE;