v0.0.23 - Add ncurses idle callback polling to auto-refresh footer log updates

This commit is contained in:
Laan Tungir
2026-05-21 08:54:47 -04:00
parent 502a632a83
commit 50eafbe022
5 changed files with 124 additions and 29 deletions

View File

@@ -11,8 +11,8 @@
*/
#define NT_VERSION_MAJOR 0
#define NT_VERSION_MINOR 0
#define NT_VERSION_PATCH 22
#define NT_VERSION "v0.0.22"
#define NT_VERSION_PATCH 23
#define NT_VERSION "v0.0.23"
#include <ncurses.h>
#include <stdio.h>

View File

@@ -314,10 +314,8 @@ void menu_login(void) {
nt_log("Signed in via n_signer URL (%s) npub: %s", endpoint_url, g_state.npub_bech32);
if (state_load_user_info_async() != 0) {
nt_log("Failed to start background user-info load.");
} else {
nt_log("Loading profile/relay data in background...");
if (state_load_user_info() != 0) {
nt_log("Failed to load profile/relay data after login.");
}
return;
@@ -393,10 +391,8 @@ void menu_login(void) {
nt_log("Signed in via qrexec n_signer (%s:%s) npub: %s", target_qube, service_name, g_state.npub_bech32);
if (state_load_user_info_async() != 0) {
nt_log("Failed to start background user-info load.");
} else {
nt_log("Loading profile/relay data in background...");
if (state_load_user_info() != 0) {
nt_log("Failed to load profile/relay data after login.");
}
return;

View File

@@ -727,6 +727,9 @@ int nt_query_sync_verbose(const char *filter_json,
char **events = NULL;
int events_n = 0;
int events_cap = 0;
char **seen_ids = NULL;
int seen_n = 0;
int seen_cap = 0;
int i;
if (!events_out || !event_count || !filter_json || !relay_urls || relay_count <= 0) {
@@ -743,6 +746,73 @@ int nt_query_sync_verbose(const char *filter_json,
return -1;
}
if (verbose && phase_label) {
nt_log("%s: querying %d relays with per-relay diagnostics",
phase_label,
relay_count);
for (i = 0; i < relay_count; i++) {
nt_log("%s: relay %d/%d target: %s",
phase_label,
i + 1,
relay_count,
relay_urls[i] ? relay_urls[i] : "(null)");
}
for (i = 0; i < relay_count; i++) {
const char *reason = "unknown";
int before_count = events_n;
int relay_ok = nt_query_one_relay(relay_urls[i],
filter,
timeout_ms,
verbose,
phase_label,
&events,
&events_n,
&events_cap,
&seen_ids,
&seen_n,
&seen_cap,
&reason);
int added = events_n - before_count;
if (relay_ok < 0) {
nt_log("%s: relay %d/%d %s -> error (%s)",
phase_label,
i + 1,
relay_count,
relay_urls[i] ? relay_urls[i] : "(null)",
reason ? reason : "unknown");
nt_free_string_array(events, events_n);
nt_free_string_array(seen_ids, seen_n);
cJSON_Delete(filter);
return -1;
}
nt_log("%s: relay %d/%d %s -> %s (reason=%s, new_events=%d, total=%d)",
phase_label,
i + 1,
relay_count,
relay_urls[i] ? relay_urls[i] : "(null)",
relay_ok ? "connected" : "no_data_or_error",
reason ? reason : "unknown",
added,
events_n);
}
nt_free_string_array(seen_ids, seen_n);
cJSON_Delete(filter);
if (events_n <= 0) {
return -1;
}
nt_log("%s: collected %d unique events total", phase_label, events_n);
*events_out = events;
*event_count = events_n;
return 0;
}
pool = nostr_relay_pool_create(NULL);
if (!pool) {
cJSON_Delete(filter);
@@ -750,12 +820,6 @@ int nt_query_sync_verbose(const char *filter_json,
return -1;
}
if (verbose && phase_label) {
nt_log("%s: querying %d relays via nostr_core relay pool",
phase_label,
relay_count);
}
pool_events = nostr_relay_pool_query_sync(pool,
relay_urls,
relay_count,
@@ -790,12 +854,6 @@ int nt_query_sync_verbose(const char *filter_json,
}
free(pool_events);
if (verbose && phase_label) {
nt_log("%s: relay pool collected %d unique events",
phase_label,
events_n);
}
nostr_relay_pool_destroy(pool);
*events_out = events;
*event_count = events_n;

View File

@@ -17,16 +17,46 @@ static int g_body_row = 0;
static char g_app_name[128] = "NOSTR TERMINAL";
static char g_app_version[64] = "";
static char g_user[256] = "";
static char g_composed_title[512] = "NOSTR TERMINAL";
static char g_status_line[512] = "";
static NtLogEntry g_log_entries[NT_LOG_MAX];
static int g_log_head = 0;
static int g_log_count = 0;
static pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;
static unsigned long g_log_version = 0;
static unsigned long g_rendered_status_version = 0;
static int g_idle_callback_registered = 0;
static WINDOW *nt_body_window(void) {
return (WINDOW *)tuin_body_window();
}
static void nt_tui_idle_callback(void) {
unsigned long log_version_snapshot;
unsigned long rendered_snapshot;
TuiStatus status;
pthread_mutex_lock(&g_log_mutex);
log_version_snapshot = g_log_version;
rendered_snapshot = g_rendered_status_version;
pthread_mutex_unlock(&g_log_mutex);
if (log_version_snapshot == rendered_snapshot) {
return;
}
status = nt_status();
tuin_render_footer(&status);
doupdate();
}
static void nt_register_idle_callback_once(void) {
if (!g_idle_callback_registered) {
tuin_set_idle_callback(nt_tui_idle_callback);
g_idle_callback_registered = 1;
}
}
void nt_print(const char *fmt, ...) {
WINDOW *body = nt_body_window();
char line[8192];
@@ -89,17 +119,20 @@ int nt_run_external_editor(int (*spawn)(void *user), void *user) {
return result;
}
static void nt_refresh_composed_title(void) {
if (g_user[0] != '\0') {
snprintf(g_composed_title, sizeof(g_composed_title), "%s - %s - %s", g_app_name, g_app_version, g_user);
} else {
snprintf(g_composed_title, sizeof(g_composed_title), "%s - %s", g_app_name, g_app_version);
}
}
TuiFrame nt_frame(const char *breadcrumb) {
static char composed_title[512];
TuiFrame frame;
if (g_user[0] != '\0') {
snprintf(composed_title, sizeof(composed_title), "%s - %s - %s", g_app_name, g_app_version, g_user);
} else {
snprintf(composed_title, sizeof(composed_title), "%s - %s", g_app_name, g_app_version);
}
nt_refresh_composed_title();
frame.app_name = composed_title;
frame.app_name = g_composed_title;
frame.app_version = "";
frame.breadcrumb = breadcrumb;
return frame;
@@ -114,6 +147,7 @@ TuiStatus nt_status(void) {
snprintf(g_status_line, sizeof(g_status_line), "%s", g_log_entries[idx].text);
}
status.text = g_status_line;
g_rendered_status_version = g_log_version;
pthread_mutex_unlock(&g_log_mutex);
return status;
@@ -122,6 +156,8 @@ TuiStatus nt_status(void) {
void nt_set_app_info(const char *name, const char *version) {
snprintf(g_app_name, sizeof(g_app_name), "%s", (name && name[0] != '\0') ? name : "NOSTR TERMINAL");
snprintf(g_app_version, sizeof(g_app_version), "%s", (version && version[0] != '\0') ? version : "");
nt_refresh_composed_title();
nt_register_idle_callback_once();
}
void nt_set_window_title(const char *title) {
@@ -134,6 +170,7 @@ void nt_set_window_title(const char *title) {
void nt_set_user(const char *user) {
snprintf(g_user, sizeof(g_user), "%s", (user && user[0] != '\0') ? user : "");
nt_refresh_composed_title();
}
void nt_log(const char *fmt, ...) {
@@ -170,6 +207,7 @@ void nt_log(const char *fmt, ...) {
if (g_log_count < NT_LOG_MAX) {
g_log_count++;
}
g_log_version++;
pthread_mutex_unlock(&g_log_mutex);
}
@@ -207,6 +245,7 @@ void nt_log_clear(void) {
g_log_head = 0;
g_log_count = 0;
g_status_line[0] = '\0';
g_log_version++;
pthread_mutex_unlock(&g_log_mutex);
}

View File

@@ -483,6 +483,8 @@ int state_load_user_info(void) {
snprintf(g_state.user_name, sizeof(g_state.user_name), "%s", g_state.npub_bech32);
}
nt_set_user(g_state.user_name);
return 0;
}