Skip to content

fix(v2): make hashes recoverable without HTTPS and show all firmware hashes - #4083

Merged
gantoine merged 3 commits into
rommapp:masterfrom
Spinnich:fix/v2-hash-copy-and-firmware-hashes
Aug 4, 2026
Merged

fix(v2): make hashes recoverable without HTTPS and show all firmware hashes#4083
gantoine merged 3 commits into
rommapp:masterfrom
Spinnich:fix/v2-hash-copy-and-firmware-hashes

Conversation

@Spinnich

@Spinnich Spinnich commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Description
Explain the changes or enhancements you are proposing with this pull request.

Fixes #4082

RomM served over plain HTTP has no way to get a full file hash out of the UI.
Hashes are displayed abbreviated (012345…234567), and the only way to get the
full value was the copy button, which fails with "Couldn't copy to clipboard.
This requires a secure (HTTPS) connection."
The browser's Clipboard API is
gated behind a secure context, so on HTTP it does not exist at all. Because the
abbreviation is generated in JavaScript, the rest of the hash was never in the
page to begin with, so selecting it by hand was not an option either. The data
was genuinely unreachable.

This affects anyone running RomM on a LAN address or a bare hostname without a
reverse proxy terminating TLS. The shipped Docker image has no HTTPS listener,
so this is the default experience for a plain docker compose up install.

What changed

Clicking a hash chip now reveals the full value as selectable text whenever a
copy cannot land, so Ctrl+C works as a fallback:

  • On HTTP the click no longer attempts a copy that is guaranteed to fail, so
    the confusing error toast is gone. It reveals the value instead.
  • On HTTPS nothing changes: the click copies as before. Reveal only kicks in if
    the copy itself throws.
  • The trailing icon reflects the state (copy / eye / eye-off) so the affordance
    is clear without adding any new translated strings.
  • Clicking again collapses the chip back to the abbreviation.

Separately, the platform Firmware tab only ever displayed the MD5, as a
plain chip with user-select: none and no copy button, while CRC and SHA-1 were
never shown at all despite being stored and returned by the API. Firmware hashes
are exactly what you need when verifying a BIOS against a known-good database,
so all three now render as copyable chips, matching the ROM Files tab.

Files changed

File Change
frontend/src/v2/components/shared/HashChip.vue Reveal-on-click fallback. Adds revealed state, a displayed computed, a state-driven trailing icon, and CSS that re-enables text selection and wrapping when revealed. Used by the ROM Metadata tab, Files tab summary, and per-file rows, so all of them are fixed by this one change.
frontend/src/v2/components/Gallery/FirmwareTab.vue Replaces the unselectable MD5 chip with HashChip for SHA-1, MD5 and CRC, each rendered only when present. Drops the now-unused .r-v2-fw__row-hash style.
frontend/src/v2/components/shared/HashChip.test.ts New. Covers abbreviation, copying the full value rather than the abbreviation, revealing when the clipboard is unavailable, revealing when a copy fails, and collapsing again.
frontend/src/v2/components/Gallery/FirmwareTab.test.ts New. Asserts a copyable chip per stored hash and that absent hashes are skipped.

Testing

  • npm run test — 627 passing across 49 files, no regressions.
  • npm run typecheck — no errors under src/.
  • trunk fmt && trunk check — clean.
  • All changes are under src/v2/; no v1 files are touched.

Notes for reviewers

  • The title attribute changed. It was LABEL: value (click to copy) and is
    now just LABEL: value. The old suffix would be wrong once the chip is
    revealed, and it was hardcoded English in a repo with strict i18n parity, so
    dropping it keeps this PR at zero locale changes.
  • The click handler ignores a click that ends a drag-select inside the chip.
    Without that guard, highlighting a revealed hash and releasing the mouse would
    fire click and collapse the value out from under the selection, defeating
    the whole point. The guard is deliberately scoped to the chip's own subtree so
    a selection elsewhere on the page doesn't leave the collapse click dead.
  • Reveal was chosen over always showing the full hash to keep rows compact.
    Worth a second opinion: a revealed 40-character SHA-1 wraps to a second line,
    which nudges the row height. All the containers involved already use
    flex-wrap: wrap, so nothing overflows, but it is a visible layout shift.
  • No ARIA state on the toggle. The icon communicates the state visually but
    there is no aria-expanded or equivalent. Happy to add it if you'd like it in
    this PR rather than a follow-up.
  • The firmware hash order (SHA-1, MD5, CRC) intentionally matches FileRow and
    FilesSummary.

AI assistance disclosure

This PR was written with AI assistance (Claude). The root-cause analysis, the
audit of every clipboard call site in v2, the implementation and the tests were
AI-generated, then reviewed and verified by me.

Checklist
Please check all that apply.

  • I've tested the changes locally
  • I've updated relevant comments
  • I've assigned reviewers for this PR
  • I've added unit tests that cover the changes

Screenshots (if applicable)

New hash reveal on rom file that can be copied when accessing via HTTP (accessing via HTTPS, behavior not modified)
image

image

New hash reveal on firmware file that can be copied when when accessing via HTTP (accessing via HTTPS, firmware now gets existing rom behavior)
image

image

…hashes

The Clipboard API only exists in a secure context, so over plain HTTP the
copy button on a hash chip always failed. Because the displayed value is
abbreviated in JavaScript, the rest of the hash was never in the DOM
either, leaving the full value unreachable on any HTTP install.

Clicking a chip now reveals the full value as selectable text whenever a
copy cannot land, so Ctrl+C works as a fallback. On HTTP the click no
longer attempts the doomed copy, so the misleading error toast is gone.
Behaviour over HTTPS is unchanged apart from revealing when a copy throws.

The firmware tab only ever showed the MD5, as an unselectable chip with no
copy affordance, while the stored CRC and SHA-1 were never displayed. All
three now render as copyable chips, matching the ROM files tab.

Fixes rommapp#4082

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR makes abbreviated hashes recoverable when clipboard copying is unavailable and expands firmware rows to display SHA-1, MD5, and CRC hashes.

  • Adds selectable reveal/collapse behavior and state-specific icons to the shared HashChip.
  • Reuses HashChip for every available firmware hash.
  • Adds focused tests for clipboard fallback, reveal behavior, and conditional firmware hash rendering.

Confidence Score: 5/5

The PR appears safe to merge with no concrete blocking or independently actionable non-blocking issues identified.

The clipboard composable’s boolean return contract matches the new fallback logic, and the firmware integration follows established HashChip markup and wrapping conventions without introducing conflicting row behavior.

Important Files Changed

Filename Overview
frontend/src/v2/components/shared/HashChip.vue Adds a clipboard-aware reveal fallback while preserving successful secure-context copy behavior.
frontend/src/v2/components/shared/HashChip.test.ts Covers abbreviation, full-value copying, unavailable and failed clipboard fallbacks, selection state, and collapse behavior.
frontend/src/v2/components/Gallery/FirmwareTab.vue Replaces the plain MD5 display with compact shared chips for every available firmware hash.
frontend/src/v2/components/Gallery/FirmwareTab.test.ts Verifies hash ordering, values, and omission of absent firmware hashes.

Reviews (1): Last reviewed commit: "fix(v2): make hashes recoverable without..." | Re-trigger Greptile

Spinnich and others added 2 commits August 3, 2026 16:05
…urface

MetadataTab was the only place labelling the row SHA1, while FileRow,
FilesSummary and the firmware list all use SHA-1. It was also inconsistent
within its own list, sitting directly beside a CHD SHA-1 row.

The label is hardcoded rather than translated, so no locale changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The files list and the firmware list both read SHA-1, CHD SHA-1, MD5, CRC,
RA. The metadata tab led with CRC instead, so the same hashes appeared in a
different order depending on which tab the user was on.

Covers the ordering with a unit test, including the CHD SHA-1 position: the
mock library holds no CHD, so that branch cannot be reached in a browser.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Spinnich
Spinnich requested a review from gantoine August 3, 2026 16:24
@gantoine
gantoine merged commit 071e82a into rommapp:master Aug 4, 2026
7 checks passed
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.

[Bug] Hash values in the v2 UI cannot be copied or read in full

2 participants