Skip to content

v1.1.0

Choose a tag to compare

@trendvidia trendvidia released this 16 Oct 13:40
· 834 commits to main since this release

Android's Storage Access Framework becomes usable, two long-standing cgo
memory bugs in the Android bridge are fixed, and the test helpers stop
shipping in production binaries. The minor bump is for the new
storage.CreateChild API. Apps that use auth should read Changed:
sign-in tokens are now kept per app, so users sign in once more after
upgrading. Everything else is additive or a fix. This is also the first
release made with the repository public.

Added

  • storage.CreateChild, for stores that name their own children
    (#303). storage.Child
    does path arithmetic — it names a resource whether or not anything is
    there — and that does not work where the store assigns identity. Under
    Android's SAF a document ID is opaque and DocumentsContract hands the URI
    back only on creation, so a folder the user picked could not be scaffolded
    into at all. CreateChild(parent, name, listable) asks the store to make
    the resource and returns what it called it, and
    repository.ChildCreatingRepository is the optional capability a repository
    implements to answer it. Repositories that can name a child by path
    arithmetic implement nothing: for them CreateChild is Child plus
    CreateListable or an empty Writer, and it verifies the resource exists
    before returning rather than handing back a URI pointing at nothing.
  • driver/software.WindowlessCanvas, so the software driver's constructors
    return a nameable type without reaching into bellui/test
    (#304).

Changed

  • Sign-in tokens are stored per app
    (#335). Every bellui app
    on a machine shared one bellui-auth/<provider>.enc, so one app could read
    another's sign-in. Tokens now live under bellui-auth/<app ID>/, and the
    app ID is part of the encryption key. Behaviour change: tokens saved by
    an earlier version are not read, so users sign in once more after
    upgrading; and SaveToken, LoadToken and ClearToken now need an app ID,
    returning the new auth.ErrNoAppID without one (Preferences already need
    it).

Fixed

  • Ctrl+Tab moves focus out of a widget that keeps Tab
    (#340). A multi-line
    Entry and the x/dag canvas keep Tab and Shift+Tab for themselves, and every
    Tab with a modifier went to the shortcut path, so a keyboard-only user who
    tabbed into one could not leave it (WCAG 2.1.2). Ctrl+Tab and Ctrl+Shift+Tab
    now move focus to the next and previous widget from any such widget, on the
    desktop, embedded and mobile drivers. Behaviour change: while a widget
    that keeps Tab is focused, Ctrl+Tab no longer reaches the app's main-menu or
    widget shortcuts; on every other widget it still does. The web build is not
    covered yet: browsers keep Ctrl+Tab for themselves
    (#357).
  • GitHub sign-in asks for GitHub's scopes
    (#335). The OpenID
    default (openid email profile) was applied before the GitHub branch, so
    GitHub never got its own default of user:email read:user.
  • desktop.App is implemented on every desktop platform
    (#338). It gained
    SetSystemTrayTooltip and SetSystemTrayOnTapped, but the app did not
    forward them on macOS, Windows or Linux/BSD, so the documented
    if desk, ok := a.(desktop.App); ok { … } check was always false and an
    app following it silently got no system tray.
  • The test helpers no longer ship in production binaries
    (#304). driver/software
    imported bellui/test for one interface and two constructors, and
    bellui/test imports testify — so every desktop and web binary linked
    testify, gopkg.in/yaml.v3, spew, difflib and testing. In the js/wasm
    build of cmd/bellui_settings that was 988,505 bytes, 2.09% of the
    artifact, and 208 yaml symbols. The canvas moved to internal/memcanvas;
    the public API is unchanged, since test.WindowlessCanvas and
    test.SoftwarePainter are now aliases of the moved types. A CI gate keeps
    it that way.
  • Android: every write to a file was a double free
    (#315). writeStream
    freed the buffer the Go caller had allocated with C.CBytes and frees
    itself, which Scudo catches and turns into an abort — "invalid chunk state
    when deallocating"
    . Pre-existing; found by the first complete
    hack/safprobe run.
  • Android: contentURIGetFileName corrupted the heap and answered the wrong
    name
    (#315). It returned
    a string literal on its error path, which the Go caller frees — free() on
    static storage. It also queried the raw URI, but _display_name is a column
    of the document, so a tree URI had no row to find and Name() fell back to
    the percent-encoded document ID: primary%3ADocuments where a user expects
    Documents. The same literal-return shape was in listContentURI and
    listURI.
  • Android: a picked SAF folder can be scaffolded into
    (#303). CreateChild for
    content:// goes through DocumentsContract.createDocument, and refuses a
    duplicate name rather than letting the provider silently invent
    "name (1)". Child resolves an existing child by display name, and
    reports storage.ErrNotExists for one that is not there instead of a URI
    that looks real. Exists and Delete work for content://. Parent
    remains unsupported, and now says why: SAF exposes no upward link.
  • Android: listing a subdirectory listed the picked folder instead
    (#303). List and
    CanList took their document ID from getTreeDocumentId, which returns the
    root's ID for any URI under the tree — so a scaffolded tree looked flat.
  • Android: folder grants survive a restart
    (#303). Nothing called
    takePersistableUriPermission, so every pick was single-use and an app
    could not store a folder URI and reopen it later.
  • Android: listContentURI leaked a JNI local reference per row
    (#303) — a directory of
    any size overruns the 512-entry table, which aborts the process.
  • A pending double-tap no longer outlives its widget
    (#310). A single tap on a
    DoubleTappable leaves a timer waiting TapDoubleDelay for a second one,
    and nothing cancelled it when the canvas went away — only a second tap did.
    It then dispatched into widgets whose renderers had been destroyed. Tap a
    widget, close the dialog holding it inside the double-tap window, and that
    was a nil dereference.
  • URI.Path() now says what it is: the RFC3986 path component, and a
    filesystem path only under file://. On Android a content:// URI gives
    /tree/primary%3ADocuments, which looks like a path, is not one, and
    resolves under / if handed to os.MkdirAll
    (#303).

Note

The SAF behaviour above is verified on a device — 21 assertions against the
external-storage provider on an API 34 emulator, including the duplicate-name
refusal and a grant surviving a force-stop — using the new hack/safprobe
harness. The remaining gap is that the run was driven by hand rather than by
the harness's own script
(#314).

Dependencies

  • github.com/belluikit/systray v1.12.1: an app's exit callback could run
    twice when Quit raced with the platform's own close handling; it is now
    guarded so it runs once.
  • github.com/belluikit/fsnotify v1.10.2: synced with upstream fsnotify
    (v1.10.1 plus later fixes), keeping the fork's Windows fixes.
  • x/mmedia requires github.com/belluikit/goffmpeg v0.4.1, whose prebuilt
    purego bridges were rebuilt and now expose the device-modes API
    (#330).

Licensing

  • The EmojiOne Color font ships with its license file again, and
    THIRD_PARTY_NOTICES.md now covers the fyne-x code and test assets, the
    vendored packages, every bundled font, the Material Design icons and the
    sign-in logos (#325).
    Attributions the rebrand had rewritten to "bellui-x" name fyne-x again.

CI

  • CI runs on GitHub-hosted runners with stock Go instead of self-hosted
    machines and the go-plus toolchain, and installs the system packages those
    images lack (#325,
    #329).
  • apt-get install needs -y: five Linux legs died the moment apt had an
    upgrade to do (#307).
  • chromium is launched without snap-confine, which had refused to start it
    from the runner service and took every wasm package down with it
    (#311).
  • TestRender asserts the rendered image rather than an exact PNG byte
    string, which go1.27's compress/flate changed
    (#318).
  • The PowerShell go-plus assertions accept (plus <version>), which go1.27's
    fork build reports (#320).

The x/* modules (charts, dag, editor, mmedia, tables) are released as v1.1.0 alongside.