Skip to content

v1.32.0

Choose a tag to compare

@SysAdminDoc SysAdminDoc released this 18 Aug 22:06
· 223 commits to main since this release

1.32.0 - 2026-08-18

Added

  • Trust -> Find the feature breaking this page. A binary search over the features that are
    actually running: it turns them all off, then back on in halves, asking after each round whether
    the page is still wrong, and names the one responsible in about five rounds instead of a linear
    hunt through thirty-odd settings. Turning a feature off runs its own destroy rather than
    writing a setting, so reloading restores everything however you stop -- including abandoning
    mid-round. The first round turns everything off, so "this is not Aviary" is a result the search
    can reach rather than a feature named at random. The Control Center and its locale stay on
    throughout and can never be named. The outcome travels in Copy diagnostics as one
    content-free line, and the bug report template has a field for it.

Fixed

  • "Aviary's page script did not load" no longer stands in for "something else answered it".
    A script that wins the very first handshake owns the page agent -- the transferred control port
    stops a later one from displacing it, but nothing can stop the first. The real bridge then sat
    out a three-second timeout and reported agent-absent, which reads as a browser compatibility
    problem when what actually happened is that Aviary's default-on network ad guard is answering to
    somebody else. The agent now refuses a late handshake audibly, and Trust says so. The design note
    on installPageAgent states plainly what the boundary defends and what it does not: it is not
    cryptographic, the refusal itself is forgeable by the page, and it downgrades a diagnostic rather
    than a decision.

  • A browser download is only Saved once the browser says it finished.
    chrome.downloads.download() resolves when the browser accepts the request, so an interrupted
    transfer had already been reported as Saved, marked completed in the queue, and written into the
    duplicate index -- which then refused the retry the user wanted. The extension now reports each
    download's terminal state back to the tab that asked. Started and Saved are distinct
    states on the button; an interrupted transfer reads Retry, marks its queue entry failed, and
    is never recorded as a duplicate; and a transfer still running when the wait gives up stays
    Started rather than claiming either outcome. The tracking is persisted, so the answer still
    arrives after the service worker has been suspended and restarted, and a quality-fallback retry
    reports under the id the page is waiting on. Userscript saves are unchanged: GM_download's own
    callback already is the terminal state.

  • Media inside a quoted post is the quoted account's, not the account that quoted them. The
    extractor walked the whole article subtree and filed every photo and player it found under the
    outer post's handle and id, so saving a photo out of a quote wrote it as if the quoting account
    had published it. Each asset now carries its owner. A quoted post's media is saved under the
    quoted account's handle, its own text, and its own post id where the DOM or a captured record
    supplies one; the post-level Download saves only the post's own media and says so, and every
    excluded asset still has its own Save control. Export records mark quoted and card media with
    whose it is instead of listing it among the account's own.

  • A post with no permalink of its own -- a reply shell still building, or a quote-only post -- no
    longer adopts the quoted post's id, handle, or text. The article's identity is read from outside
    the quote it carries.

  • The exporter's "this is a quoted post" test and the media extractor's are now one definition.
    They disagreed: the exporter looked only for two named test ids while X's current Home renders a
    quote as a focusable div with no test id, so a record could carry a quoted photo with no note
    that a quote existed at all.

Changed

  • The browser floors are declared once, with their reason. They lived in three places that did
    not know about each other -- a number in each manifest and a sentence in docs/INSTALL.md -- and
    the floor is what decides whether a platform feature can be used directly or needs a detection
    branch. src/extension/browser-floors.ts now declares both, records per-feature which of the two
    is true, and preflight fails the build if either manifest disagrees. The decision itself: Firefox
    stays at 128. It is an ESR line, Aviary is sideloaded rather than distributed through a store,
    and raising the floor to pick up URLPattern, @scope or the Navigation API without a branch
    would exclude the users most likely to be running ESR.

  • FeatureRegistry gained suspend/resume, and now runs apply in registration order rather
    than initialization order -- the two differ only once a feature has been suspended and resumed,
    and ad protection is registered first precisely so it runs before anything that reads the
    timeline.