Skip to content

modernize UI - #2

Open
BitcoinMechanic wants to merge 8 commits into
innerhat-dev:masterfrom
BitcoinMechanic:modernize-ui
Open

modernize UI#2
BitcoinMechanic wants to merge 8 commits into
innerhat-dev:masterfrom
BitcoinMechanic:modernize-ui

Conversation

@BitcoinMechanic

Copy link
Copy Markdown

Some images from the new design

image image

AI disclosure - all code written by Grok, tested by human on x86_64 Linux only.

@innerhat-dev

innerhat-dev commented Aug 20, 2026

Copy link
Copy Markdown
Owner

After reviewing and testing all commits, just a few small items:

  1. There are redundant Save buttons on the Config page (one at top of page, one at bottom). I would just keep the one at the top (so the user always knows where to look for it / less options) and also make sure all buttons are consistent in style and size across all window sizes. (If I had to pick, I'd choose the rounder nav style buttons, they look nice). Maybe in addition, put the nav buttons in a borderless 'pill container' with no padding that spans the width of the group of nav buttons and has a different shade of the blue for its background than the body color, would look awesome.

  2. The drop down arrows on the right hand side of drop down fields on the Config page should have some margin on the right side so they don't appear to 'crash' into the right edge of the dropdown fields.

  3. The config page 'container' is not consistent in width with the Clients, Threads, and Coinbaser pages 'containers' (though I see what you were going for when comparing to the Status page containers).

  4. There are redundant scrollbars on the Clients page table on narrower layouts that interfere with each other, can be confusing. It is also possible to style scrollbars and I recommend doing so to match the new style.

Screenshot 2026-08-20 at 12 35 12 PM
  1. The Kick button seems to silently fail, no console error and my A3 continues to hash regardless of having clicked it.

@BitcoinMechanic

Copy link
Copy Markdown
Author

Hopefully addresses your feedback. Also added a historical chart of hashrate.

Comment thread src/datum_hashrate_hist.c
return 0;
}

/* downsample if needed */

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stats are computed after this decimation. Seeded a 24h series of 100.0 Th/s with a single 999.0 spike at index 5 (the decimator keeps 0, 12, 24, ...); the dashboard reported Avg: 99.17 - Peak: 100.00. Moving the loop at :295 above this block fixes both figures.

Comment thread src/datum_hashrate_hist.c
if (hr_count < DATUM_HR_HISTORY_SAMPLES) hr_count++;
dirty = 1;

/* persist every sample (60s) — small file, safe */

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Measured 1,507,856 bytes, mtime advancing exactly 60s with the size constant, zero miners connected. That is 2.02 GB/day of writes. Dropping clients[] takes it to 23 KB.

Comment thread src/datum_hashrate_hist.c
static double total_th[DATUM_HR_HISTORY_SAMPLES];
static int hr_head = 0; /* next write index */
static int hr_count = 0;
static hr_client_t clients[DATUM_HR_MAX_CLIENTS];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reachable reader: all three render_svg call sites pass client_key = NULL, and render_sparkline lost its last caller in 11a146e. This is 1.44 MB of the 1.48 MB file.

Comment thread src/datum_hashrate_hist.h
double *out_current, double *out_avg, double *out_peak);

/* Compact sparkline SVG for table cells */
size_t datum_hashrate_hist_render_sparkline(char *out, size_t out_sz,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead since 11a146e removed the per-row chart: no source references, and no call sites in the linked binary.

Comment thread src/datum_hashrate_hist.c
}
}

void datum_hashrate_hist_shutdown(void) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No callers, so dirty (:42, :121, :189) is only ever read here at :241, making it write-only in practice. The save at :192 runs unconditionally every tick regardless.

Comment thread src/datum_hashrate_hist.c
uint32_t magic = HR_MAGIC, ver = HR_VERSION;
int i;
if (!hr_path[0]) return;
f = fopen(hr_path, "wb");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"wb" truncates in place, so a crash mid-write leaves a short file behind a valid magic/version header. Truncated the file inside total_th and restarted: all 1440 samples silently dropped, with no load line, no warning, and no diagnostic of any kind.

Comment thread src/datum_hashrate_hist.c

static void make_client_key(char *key, size_t key_sz, T_DATUM_MINER_DATA *m, int tid, int cid) {
if (m && m->last_auth_username[0]) {
snprintf(key, key_sz, "%s", m->last_auth_username);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-Wformat-truncation on a clean build: 192 bytes into 64, so keys truncate at 63 chars against a 62-char bech32m address.

Comment thread src/datum_hashrate_hist.c
for (i = 0; i < n; i++) {
double x = pad_l + (n == 1 ? plot_w / 2.0 : (double)i * plot_w / (double)(n - 1));
double y = pad_t + plot_h - (vals[i] / vmax) * plot_h;
psz += snprintf(path + psz, sizeof(path) - psz, "%s%.1f,%.1f", i ? " L" : "M", x, y);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With one sample this emits d="M378.0,172.0" against fill="none". Rendered it: 0 pixels differ from blank, versus 244 for a two-point path. Fresh installs show an empty chart for the first two minutes.

Comment thread src/datum_conf.c
.required = false, .ptr = datum_config.mining_pow_algorithm, .default_string[0] = "auto", .max_string_len = sizeof(datum_config.mining_pow_algorithm) },
{ .var_type = DATUM_CONF_STRING, .category = "mining", .name = "hashrate_history_file", .description = "Path to file for persisting hashrate history samples (empty disables disk persistence)",
.example_default = true,
.required = false, .ptr = datum_config.mining_hashrate_history_file, .default_string[0] = "datum_hashrate_history.bin", .max_string_len = sizeof(datum_config.mining_hashrate_history_file) },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-empty default means this is on by default writing to CWD, unlike save_submitblocks_dir which defaults to empty. Pointed it at an unwritable path: cannot write ... No such file or directory repeats every 60s with no suppression.

Comment thread src/datum_api.c
const char *next_dir = (active && dir_mul > 0) ? "desc" : "asc";
const char *cls = active ? (dir_mul > 0 ? "sortable sort-asc" : "sortable sort-desc") : "sortable";
sz += snprintf(&output[sz], max_sz - 1 - sz,
"<TD class=\"%s\"><a href=\"/clients?sort=%s&amp;dir=%s\"><U>%s</U></a></TD>",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sort links drop hr_range (confirmed in the served HTML, all 11 carry only sort/dir), so clicking any column header resets the chart to 24h.

@jasonsopko

Copy link
Copy Markdown

Related, not competing: OCEAN-xyz#230 makes the stylesheet replaceable at runtime (api.custom_css_file) without touching the templates, so it lands on either side of this PR. It applies to this fork's master clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants