commit 39f7911506b8e593009c0fff0d43675987354a86
parent f141b42063953c528fcaa8dd191d793583922b9b
Author: citbl <citbl@citbl.org>
Date: Wed, 8 Oct 2025 22:43:49 +1000
UI improvements
Diffstat:
4 files changed, 64 insertions(+), 21 deletions(-)
diff --git a/config.h b/config.h
@@ -1,15 +1,24 @@
#pragma once
+#define VERSION "v1.1"
+
#define FEEDS "~/.config/readr/feeds"
-#define FEED_CAP 20
+// the width of the left column:
+#define FEED_CAP 26
+
+// allocation caps
#define POSTS_CAP 128
#define FEEDS_CAP 32
#define TITLE_CAP 128
#define URL_CAP 8192
-#define TEXT_COLOR TB_WHITE
+// for colour details see termbox2.h
+
+#define LOGO_COLOR (TB_WHITE | TB_BRIGHT)
+#define TEXT_COLOR (TB_WHITE | TB_DIM)
#define BACK_COLOR TB_DEFAULT
-#define LINE_COLOR (TB_BLACK | TB_BRIGHT)
+#define LINE_COLOR (TB_WHITE | TB_DIM)
#define FEED_COLOR TB_CYAN
-#define POST_COLOR TB_YELLOW
+#define POST_COLOR (TB_YELLOW)
+#define SEEN_COLOR (TB_YELLOW | TB_DIM)
diff --git a/feeds.c b/feeds.c
@@ -50,9 +50,9 @@ fetch_feed(feed_t* feed, char* url)
mrss_error_t rc = mrss_parse_url(url, &rss);
if (rc != MRSS_OK || rss == NULL) {
- char short_url[19];
- strncpy(short_url, url, 18);
- short_url[18] = '\0';
+ char short_url[FEEDS_CAP - 1];
+ strncpy(short_url, url, FEEDS_CAP - 2);
+ short_url[FEEDS_CAP - 2] = '\0';
asprintf(&feed->title, "%s%s", "(bad) ", short_url);
return;
}
diff --git a/render.c b/render.c
@@ -4,28 +4,55 @@
#include "tui.h"
#include "config.h"
+#define HORIZ_LINE 0x2500
+#define VERT_LINE 0x2502
+
static void
-draw_top_bar(void)
+draw_bars(void)
{
+ int i;
const int width = tb_width();
- for (int i = 0; i < width; i++) {
- tb_set_cell(i, 0, ' ', LINE_COLOR, LINE_COLOR);
+ const int height = tb_height();
+
+ // verticals first
+
+ for (i = 2; i < height - 2; i++) {
+ tb_set_cell(0, i, VERT_LINE, LINE_COLOR, BACK_COLOR);
+ tb_set_cell(FEED_CAP + 5, i, VERT_LINE, LINE_COLOR, BACK_COLOR); /* separator line */
+ tb_set_cell(width - 1, i, VERT_LINE, LINE_COLOR, BACK_COLOR);
+ }
+
+ for (i = 0; i < width; i++) {
+ tb_set_cell(i, 2, HORIZ_LINE, LINE_COLOR, BACK_COLOR);
+ tb_set_cell(i, height - 2, HORIZ_LINE, LINE_COLOR, BACK_COLOR);
}
- tb_print(1, 0, TEXT_COLOR, LINE_COLOR, "readr");
- tb_print(width - 51, 0, TEXT_COLOR, LINE_COLOR, "[enter] open link [space] open comments [q] quit");
+ tb_print(1, 1, LOGO_COLOR, BACK_COLOR, "readr");
+ tb_print(width - 5, 1, TEXT_COLOR, BACK_COLOR, VERSION);
+ tb_print(width - 66,
+ height - 1,
+ TEXT_COLOR,
+ BACK_COLOR,
+ "[arrows] move [enter] open link [space] open comments [q] quit");
+
+ // corners top
+
+ tb_set_cell(0, 2, 0x250C, LINE_COLOR, BACK_COLOR);
+ tb_set_cell(FEED_CAP + 5, 2, 0x252C, LINE_COLOR, BACK_COLOR);
+ tb_set_cell(width - 1, 2, 0x2510, LINE_COLOR, BACK_COLOR);
+
+ // corners bottom
+
+ tb_set_cell(0, height - 2, 0x2514, LINE_COLOR, BACK_COLOR);
+ tb_set_cell(FEED_CAP + 5, height - 2, 0x2534, LINE_COLOR, BACK_COLOR);
+ tb_set_cell(width - 1, height - 2, 0x2518, LINE_COLOR, BACK_COLOR);
}
static void
draw_background(void)
{
- const int height = tb_height();
tb_set_clear_attrs(TEXT_COLOR, BACK_COLOR);
tb_clear();
-
- for (int i = 0; i < height; i++) {
- tb_set_cell(FEED_CAP + 5, i, 0x2595, LINE_COLOR, BACK_COLOR); /* vert line */
- }
}
void
@@ -35,14 +62,14 @@ render(app_t* app)
draw_background();
- draw_top_bar();
+ draw_bars();
int i;
for (i = 0; i < app->feeds_len; i++) {
const feed_t* feed = app->feeds[i];
color = (app->selected_panel == 0 && i == app->selected_feed) ? (FEED_COLOR | TB_REVERSE)
: (FEED_COLOR);
- tb_print(1, 4 + i, color, TB_DEFAULT, feed->title ? feed->title : "N/A");
+ tb_print(2, 4 + i, color, BACK_COLOR, feed->title ? feed->title : "N/A");
}
char title[TITLE_CAP] = { 0 };
@@ -55,7 +82,7 @@ render(app_t* app)
title[len] = '\0';
color = (app->selected_panel == 1 && i == app->selected_post) ? (POST_COLOR | TB_REVERSE)
: (POST_COLOR);
- tb_print(FEED_CAP + 10, 4 + i, color, TB_DEFAULT, title);
+ tb_print(FEED_CAP + 10, 4 + i, color, BACK_COLOR, title);
}
tb_present();
diff --git a/tui.c b/tui.c
@@ -25,8 +25,15 @@ present(app_t* app)
if (can_poll == TB_OK) {
switch (ev.type) {
case (TB_EVENT_KEY):
- if (ev.key == TB_KEY_CTRL_Q || ev.key == TB_KEY_ESC || ev.ch == 'q') goto RIP;
+
+ if (ev.key == TB_KEY_CTRL_Q //
+ || ev.key == TB_KEY_ESC //
+ || ev.key == TB_KEY_CTRL_C //
+ || ev.ch == 'q')
+ goto RIP;
+
handle_key(app, ev);
+
break;
case (TB_EVENT_MOUSE):
break;