chore(deps): bump @opentui/core from 0.7.0 to 0.8.1
Bumps @opentui/core from 0.7.0 to 0.8.1.
Release notes
Sourced from @opentui/core's releases.
Release v0.8.1
OpenTUI 0.8.1 can play video.
VideoRenderable, and<video>in React and Solid, plays an MP4 file with H.264 video and AAC audio. Native code does the decoding, the media clock, the audio, and the drawing. Frames draw like anImageRenderable, with Kitty, Sixel, or Unicode blocks:const video = new VideoRenderable(renderer, { source: "./clip.mp4", width: 60, height: 20, autoplay: true, loop: true, onError: console.error, }) renderer.root.add(video)To show only part of a clip, you could make a node the size of the whole board and let its parent clip it. That gets expensive quickly. Nine such tiles of one 1080p clip used 2.3 cores and sent 58 MB of Kitty data per frame, which is far over the output limit. The new
cropoption selects a region in source pixels, and the decoder scales and copies only that region. The same nine tiles use 0.93 cores and 5.1 MB per frame. There is a second cost: each player of a clip with audio opens its own audio device, even when it ismuted. Setaudio: falseon every tile except the one that plays sound:// The top-left quarter of a 1920x1080 clip, with no audio device. const tile = new VideoRenderable(renderer, { source: "./clip.mp4", crop: { left: 0, top: 0, width: 960, height: 540 }, audio: false, width: 30, height: 10, })
ImageRenderabletakes the samecrop. To decode video, the native library now statically links a decode-only LGPL build of FFmpeg 9.0.2. This makes each stripped library 2.6 to 3.5 MB larger. On linux-x64 it grows from 5.20 MB to 8.40 MB.Over a slow link such as ssh, the terminal reads frames more slowly than OpenTUI writes them. Once the pty and the link filled up, the JavaScript thread waited inside write(2), and keys and timers waited behind it. On a 48 KB/s link it spent 79% of its time there, and the median key wait was 123.7 ms. In 0.8.1, on Linux and macOS when stdout is a terminal, a native thread owned by the Session does the write. On the same link, the JavaScript thread spends no time in write(2), and the median key wait is 0.1 ms. The screen still lags by the size of the link's buffers. The app also uses more CPU per run, because it now does the updates that it used to skip while it waited. Set
OTUI_STDOUT_THREAD=0to write on the JavaScript thread as before.A slow link also made exit unreliable. In 0.8.0, the close gave up after one second and cancelled the session before it wrote the restore sequence. A 40-row quit at 16 KB/s left the terminal in the alternate screen with mouse reporting on. Now the close waits as long as output keeps moving. If nothing is written for one second, or if the close has run for ten seconds, the renderer stops waiting. It lets the write in progress finish, drops the queued output, writes the restore, and rejects
closedas late.The Session writes at most 8 MiB in one frame. In 0.8.0, a larger frame failed, and the repaint after it was just as large. The screen froze, but input still worked. Three 1000x700 Kitty images were enough to cause it. Now a frame sends its cells and the images that fit, and later frames send the rest. If one image is too large for a frame on its own, OpenTUI sends a copy at the size it is shown. A 1272x2015 photo shown at 880x1400 pixels sends 6.6 MB instead of 13.7 MB. The image draws as blocks only if that copy is too large as well. If a frame's cells alone are too large, the new
frame:droppedevent reports it once for each content. In 0.8.0,console.errorreported it on every frame:renderer.on(CliRenderEvents.FRAME_DROPPED, ({ bytes, limit }) => { console.warn(`dropped a frame of ${bytes} bytes (limit ${limit})`) })One layout change can show in existing apps. When Yoga gives a node zero width or height, OpenTUI used to paint and hit-test it as one cell, on top of its siblings. A common case is a one-row header above a ScrollBox with
flexGrow. Once the list is taller than the screen, Yoga shrinks the header to zero rows. The header and the first list row then mixed into one line. Now the header is not drawn at all. To keep it, give the headerflexShrink: 0, or give the ScrollBoxflexBasis: 0:const column = new BoxRenderable(renderer, { flexDirection: "column", height: "100%" }) column.add(new TextRenderable(renderer, { content: "filter: (type)", flexShrink: 0 })) column.add(new ScrollBoxRenderable(renderer, { flexGrow: 1, minHeight: 0 }))
... (truncated)
Commits
9a09079Release v0.8.17303776core: bound the whole close and restore at the limit (#1893)4b10d91core: make the TypeScript tests faster and fix two test-order flakes (#1895)85b015dnative: draw frames that are larger than the output limit (#1890)269db3ebuild: migrate to Zig 0.17 (#1586)9b7d5fbnative: show a source region on video and image nodes (#1888)6a1264enative: pad video RGBA rows for swscale's SIMD stores (#1889)1823930native: add an audio option to play video without a device (#1884)3091d20native: enable the stdout writer on macOS (#1881)75e0d0acore: accept program status until the terminal closes (#1871)- Additional commits viewable in compare view
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Summary by cubic
Updates @opentui/core to 0.8.1, which adds video rendering and a background stdout writer for slow terminals. Frames larger than 8 MiB now degrade gracefully instead of freezing the screen.
Migration
- Nodes with zero width or height are no longer painted as one cell on top of siblings. Add
flexShrink: 0to the node (orflexBasis: 0to its sibling) to keep it visible.
Ask Polylane for an impact assessment of this pull request: