From 500de62841a3cc51516ddadbc4a024c10c1fdc7e Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Jul 2026 14:15:56 +0000 Subject: [PATCH] fix(ui): explain pending OTS on tap, render the stamp glyph and pill icons larger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tapping the pending OTS pill now shows a toast explaining that the attestation is waiting to be stamped into the Bitcoin blockchain (new ots_info_pending_description). The OpenTimestamps glyph gets a near-full-em content box — its fine outline read much lighter than Material's solid shapes at the standard 80..880 bounds — and HeaderPill icons go from 11dp to 13dp. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01AgEpNtwnetPhETXQSdq4b5 --- .../amethyst/ui/note/elements/DisplayOts.kt | 9 +++++- amethyst/src/main/res/values/strings.xml | 1 + .../font/material_symbols_outlined.ttf | Bin 469812 -> 469856 bytes .../amethyst/commons/ui/note/HeaderPill.kt | 2 +- .../add_custom_glyphs.py | 29 +++++++++--------- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/elements/DisplayOts.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/elements/DisplayOts.kt index 43ffee19e3..22c3720962 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/elements/DisplayOts.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/elements/DisplayOts.kt @@ -75,11 +75,18 @@ fun DisplayOts( }, whenPending = { // The stamp icon plus an ellipsis: attestation requested, not yet - // anchored. The content description carries the words. + // anchored. The content description carries the words; tapping + // explains what is being waited on. HeaderPill( symbol = MaterialSymbols.OpenTimestamps, text = "…", contentDescription = stringRes(R.string.timestamp_pending_short), + onClick = { + accountViewModel.toastManager.toast( + R.string.ots_info_title, + R.string.ots_info_pending_description, + ) + }, ) }, ) diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index 9005e9f7e7..a9ed842bdd 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -3021,6 +3021,7 @@ Timestamp Proof There\'s proof this post was signed sometime before %1$s. The proof was stamped in the Bitcoin blockchain at that date and time. + A timestamp proof for this post has been requested and is waiting to be stamped in the Bitcoin blockchain. It usually completes within a few hours. Edit Article Edit Post diff --git a/commons/src/commonMain/composeResources/font/material_symbols_outlined.ttf b/commons/src/commonMain/composeResources/font/material_symbols_outlined.ttf index d75ba235aab931c0844fa28d9529614b88afa8b8..aed61e63f444fc798feb320f8b9ba482543dd9d4 100644 GIT binary patch delta 2369 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 (glyph name, traced SVG). Keep codepoints at the very end of -# the BMP private-use area (U+F8xx tail) to stay clear of the range Material -# Symbols actually allocates. +# codepoint -> (glyph name, traced SVG, content-box fractions). Keep +# codepoints at the very end of the BMP private-use area (U+F8xx tail) to +# stay clear of the range Material Symbols actually allocates. +# +# Material's own solid shapes draw inside 80..880 of a 960 upm em; a glyph +# with fine outlines (like the OpenTimestamps stamp) reads much lighter at +# the same bounds, so it gets a near-full-em box to appear the same size. CUSTOM = { - 0xF8F0: ("opentimestamps", os.path.join(HERE, "custom", "opentimestamps.svg")), + 0xF8F0: ("opentimestamps", os.path.join(HERE, "custom", "opentimestamps.svg"), 20 / 960, 940 / 960), } -# Fit content into the same square Material Symbols draw in (its check_circle -# glyph spans 80..880 in a 960 upm font). Scaled to the font's real upm. -BOX_MIN_FRAC = 80 / 960 -BOX_MAX_FRAC = 880 / 960 - def svg_path_data(svg_file): with open(svg_file, "r", encoding="utf-8") as f: @@ -54,15 +53,15 @@ def draw_svg(paths, pen): parse_path(d, pen) -def build_glyph(paths, upm): +def build_glyph(paths, upm, box_min_frac, box_max_frac): # First pass: raw outline bounds. bounds = BoundsPen(None) draw_svg(paths, bounds) x_min, y_min, x_max, y_max = bounds.bounds - # Uniform scale into the Material content box, centered on both axes. - box_min = BOX_MIN_FRAC * upm - box_max = BOX_MAX_FRAC * upm + # Uniform scale into the content box, centered on both axes. + box_min = box_min_frac * upm + box_max = box_max_frac * upm box = box_max - box_min scale = box / max(x_max - x_min, y_max - y_min) tx = box_min + (box - (x_max - x_min) * scale) / 2 - x_min * scale @@ -79,8 +78,8 @@ def main(font_path): upm = font["head"].unitsPerEm order = font.getGlyphOrder() - for codepoint, (name, svg_file) in sorted(CUSTOM.items()): - glyph = build_glyph(svg_path_data(svg_file), upm) + for codepoint, (name, svg_file, box_min_frac, box_max_frac) in sorted(CUSTOM.items()): + glyph = build_glyph(svg_path_data(svg_file), upm, box_min_frac, box_max_frac) if name not in order: order.append(name)