Skip to content

nitro-input v0.4.0

Choose a tag to compare

@ronickg ronickg released this 13 Oct 01:18
· 2 commits to main since this release
  • Android: NitroNumber's numeric transition no longer blocks the UI
    thread (ANRs).
    A glyph mask the warm thread had not made yet was blurred
    in onDraw, and the shared mask cache made every mask inside its lock. Two
    ANRs on low-end phones followed: the UI thread Blocked in the cache's
    get behind the warm thread (which runs at MIN_PRIORITY), and the UI
    thread waiting for a GC while the blur allocated two float copies of a large
    glyph. Now masks are made outside the lock, the UI thread never blurs (a
    mask not warmed yet is drawn sharp for a frame while the warm thread makes
    it), and the blur reuses per-thread buffers instead of allocating per mask.
    A mask the screen is waiting on is made ahead of the warm-up's queue (it
    waited behind every digit at every blur level, ~50 ms), the warm thread runs
    at background priority rather than the lowest, and a mask that cannot be
    made is skipped rather than crashing the app.
  • iOS: the numeric transition no longer blurs on the main thread. Its
    digits were blurred and rasterized ahead of the first swap, but on the main
    queue: opening a screen of numeric figures spent ~1 s of the main thread on
    it (Release, simulator), in blocks of up to ~180 ms, and a prefix or suffix
    that changed text was blurred on demand mid-frame. The warm-up now runs on
    a background queue, a blur the screen is waiting on on a second one ahead
    of it (drawn sharp until it lands), and the shared glyph caches are
    thread-safe.
  • NitroInput lays out at its real size in the commit that mounts it.
    Its size came from the view, through onSizeChange and a React commit, so
    the first layout had none: an autoWidth field took its parent's width (or
    none) for a commit, and every field without a fixed height moved by a pixel
    or two as its line box arrived. Now a single-line field is measured on the JS
    thread before its view exists (a new NitroInputMeasure), with the code the
    view sizes itself with - fonts, affixes and their seams, number and mask
    formatting, the placeholder and keepPlaceholder's tail - as React
    Native's TextInput measures in its shadow node. About 0.1 ms per field;
    the view's own report then matches and no longer costs a commit. A wrapping
    field, a transform worklet and a style that sets both sides keep the old
    path.
  • A framed field sizes itself. With no width or height from its style,
    an outlined or filled field took the size of its text line alone: the
    frame's side insets and the label were left out, so a resting label was
    drawn outside the field and a filled one cut its text off. Its size now
    includes the frame: the side insets either side of the text or the resting
    label, whichever is wider, and above and below it the same 16 of padding
    (and a filled field's label line) a wrapping field already had. A field
    given a height in its style is unchanged.
  • A secure field fits its bullets. Android set the password input type
    after the typeface, which switches the field to monospace, so its bullets
    were wider than the field measured them; the typeface is now put back, as
    React Native's TextInput does. On iOS the field measured its text as
    bullets in its own font, but UIKit draws U+2219 in the system font; it now
    measures those. An autoWidth secure field showed ●●●●… for 8 characters
    on iOS and 5 bullets on Android.
  • No size jump on mount, and no amount sliding in on a reused field. A
    size the view reported before its props were applied (the defaults', or a
    recycled view's last element's) reached JS and made the field jump to it and
    back. And on iOS a recycled view took the empty text its props reset fed the
    engine for its first, so a reflowing amount on a reused view slid in instead
    of showing as it is.
  • Android: keepPlaceholder's greyed tail stays inside the field. The
    rest of the placeholder, drawn after what was typed, was not clipped to the
    text area as the field's own text and hint are: in a padded field narrower
    than its placeholder (or once the typed text filled it), the tail ran over
    the padding to the field's edge. iOS already clipped it.
  • A TextInput style no longer crashes a field, and NitroInput reads
    its typography from it.
    Fabric hands a view its style's keys as props,
    and six to eight of each view's native props shared a name with a text
    style key: style={{ fontWeight: '700' }} threw ("Value is a string,
    expected a number") on NitroInput, NitroNumber and NitroText, and a
    numeric fontSize or color there was fought over by the style and the
    prop. The native props are renamed (textSize, textWeight,
    textFamily, textColor, textLetterSpacing, textLineHeight,
    textAlignment, textVerticalAlignment); the components' own props keep
    their names. A test now fails if any native prop shares a name with a React
    Native style key or view prop. NitroInput also takes fontSize,
    fontWeight, fontFamily, color, letterSpacing, lineHeight,
    textAlign and textAlignVertical from style, as TextInput does (its
    style is typed as TextInput's); the props of the same name win.
  • NitroInput matches TextInput in three more places, found by a
    visual comparison of the two side by side:
    • Android: textAlign center / right on a plain field did nothing; the
      alignment set when the field became plain (before textAlign arrived in
      the same commit) overrode it.
    • A style padding or border insets the text and adds to the size the
      field works out for itself, as TextInput's does. An autoWidth field
      with paddingHorizontal: 8 squeezed its text to "…" on iOS; on Android
      the padding did not inset the text at all (React Native never hands a
      Nitro view its padding there, so the view now insets its text, overlay and
      frame itself).
    • iOS: lineHeight sets a single line's height, as on Android; it was the
      font's own line box whatever the prop said.