#ifndef TRANSTUI_UI_H
#define TRANSTUI_UI_H
#include <curses.h>
#include <time.h>
#include "../config.h"
#include "../rpc.h"
#include "../torrent.h"
typedef enum {
VIEW_LIST,
VIEW_DETAIL,
VIEW_SETTINGS,
VIEW_HELP,
} ViewMode;
/* Sidebar categories. Order here is the order shown in the left menu. */
typedef enum {
FILTER_ALL,
FILTER_DOWNLOADING,
FILTER_UPLOADING,
FILTER_PAUSED,
FILTER_COMPLETED,
FILTER_COUNT,
} FilterMode;
typedef enum {
FOCUS_SIDEBAR,
FOCUS_LIST,
} FocusZone;
typedef enum {
SORT_NAME,
SORT_SIZE,
SORT_PROGRESS,
SORT_STATUS,
SORT_DOWN,
SORT_UP,
SORT_RATIO,
SORT_ETA,
SORT_COUNT,
} SortColumn;
typedef enum {
DETAIL_GENERAL,
DETAIL_FILES,
DETAIL_PEERS,
DETAIL_TRACKERS,
DETAIL_TAB_COUNT,
} DetailTab;
/* Color pairs, initialized once in ui_init_colors(). */
enum {
CP_DEFAULT = 1,
CP_HEADER,
CP_SELROW,
CP_SEEDING,
CP_DOWNLOADING,
CP_PAUSED,
CP_ERROR,
CP_CHECK,
CP_BORDER,
CP_ACCENT,
CP_SPLASH_WHITE,
};
/* A single "key -> what it does" entry for the footer hint bar. */
typedef struct {
const char *key;
const char *desc;
} KeyHint;
typedef struct {
RpcClient *rpc;
Config *cfg;
int running;
TorrentList list;
/* indices into list.items after filtering+sorting, rebuilt each frame */
int *order;
size_t order_count;
size_t order_capacity;
int cursor; /* index into order[] */
int top; /* first visible row, index into order[] */
SortColumn sort_col;
int sort_desc;
FilterMode filter;
char search[128];
FocusZone focus;
int sidebar_cursor;
ViewMode view;
int detail_id;
TorrentDetail detail;
int detail_loaded;
DetailTab detail_tab;
int detail_cursor;
char status_msg[256];
time_t status_msg_until;
struct timespec last_poll;
int need_poll_now;
/* set once we've offered (accepted or not) to fix a torrent's download
* directory permissions this session - see check_download_dir_perms() */
int perm_fix_offered;
} AppState;
/* startup_msg, if non-NULL, is shown in the status bar in place of the
* default "Connected to host:port" message once the initial list load
* succeeds - used to report the result of a --add done before the TUI
* started. */
int ui_run(RpcClient *rpc, Config *cfg, const char *startup_msg);
/* Shows the startup splash (block-letter logo) and returns once it's been on
* screen for a bit or the user presses a key, whichever is first. Returns
* that key (so the caller can act on it immediately instead of discarding
* it), or ERR if the splash simply timed out. */
int ui_splash_show(void);
/* Offers to fix a broken *local* connection: "no daemon answering" (offer to
* spawn transmission-daemon) or "daemon answered with 401" (offer to fix its
* RPC auth via sudo), based on rpc->last_http_status. No-op for non-local
* hosts (nothing we can sudo into on someone else's machine). Used both at
* startup and from the settings popup's 'r' retry key. */
void ui_offer_reconnect_help(AppState *st);
/* shared helpers, used across ui_*.c */
void ui_set_status(AppState *st, const char *fmt, ...);
void ui_init_colors(void);
int ui_color_for_status(int status);
void ui_rebuild_order(AppState *st);
int ui_refresh_list(AppState *st);
void ui_open_detail(AppState *st, int torrent_id);
void ui_close_detail(AppState *st);
/* Draws a rounded ╭─╮ box border into win (h x w, starting at 0,0 in win's
* own coordinates). Shared look for panels and popups. */
void ui_box(WINDOW *win, int h, int w);
/* Draws a title left-aligned into a box's top border, e.g. ui_box_title(win, w, "Filter"). */
void ui_box_title(WINDOW *win, int w, const char *title);
/* Renders a wrapping row of "key description" chips at the bottom `nrows`
* lines of the screen (nrows capped to 2). Hints that don't fit are dropped. */
void ui_draw_footer(const KeyHint *hints, size_t n, int nrows);
/* modal dialogs (ui_dialogs.c) - block until answered, then redraw caller's view */
int ui_confirm(const char *title, const char *msg);
int ui_prompt(const char *title, const char *initial, char *out, size_t outsize);
void ui_message(const char *title, const char *msg);
/* Directory picker: navigate with arrows/Enter, `space` selects whichever
* folder is currently open, Backspace goes up, Esc cancels. start_hint (may
* be NULL/empty/nonexistent) is where browsing begins if it's a real
* directory; otherwise falls back to the last folder browsed to, then
* $HOME. Returns 1 with `out` filled on selection, 0 on cancel. */
int ui_folder_browser(const char *start_hint, char *out, size_t outsize);
void ui_dialog_add_torrent(AppState *st);
void ui_dialog_remove(AppState *st, const int *ids, size_t n);
void ui_dialog_speed_limit(AppState *st, const int *ids, size_t n);
/* per-view render+input handlers */
void ui_list_render(AppState *st);
/* Same as ui_list_render() but skips doupdate(), for use as a backdrop
* under a popup that wants a single atomic flush (see ui_settings.c). */
void ui_list_render_content(AppState *st);
void ui_list_handle_key(AppState *st, int ch);
void ui_detail_render(AppState *st);
void ui_detail_handle_key(AppState *st, int ch);
void ui_settings_render(AppState *st);
void ui_settings_handle_key(AppState *st, int ch);
/* Fetches the daemon's current session settings and, if they don't match
* what the user last explicitly set via the settings screen, pushes the
* remembered values back - see reconcile_cache() in ui_settings.c. Called
* once after the initial connection so an unclean daemon restart gets
* fixed up even if the user never reopens settings. */
void ui_settings_reconcile_now(AppState *st);
void ui_help_render(AppState *st);
void ui_help_handle_key(AppState *st, int ch);
#endif