Skip to content

fix(ui): follow toolkit's MVVM-only widgets, unblocking the upgrade to Android - #223

Merged
tannevaled merged 1 commit into
mainfrom
fix/toolkit-mvvm-only
Aug 18, 2026
Merged

fix(ui): follow toolkit's MVVM-only widgets, unblocking the upgrade to Android#223
tannevaled merged 1 commit into
mainfrom
fix/toolkit-mvvm-only

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

go-widgets/toolkit converted 20+ widgets in one sweep (v0.189 → v0.204) from "settable field plus an OnChange slot" to "state is an mvvm.Observable, reached through an accessor". reader pinned toolkit v0.188.0, so nothing was broken for its users — but it could not move, and 34 compile errors stood between it and any newer toolkit.

Why that blockage now costs something

go-widgets/window v0.44.0 wires in the Android back-end: Open dials the go-widgets/android host inside an APK, and falls through to X11/Wayland under Termux. reader gets Android by upgrading — once it can upgrade.

It builds for android/arm64 as of this commit, and the cross-build matrix gains that target so the capability is CI-guarded rather than proven once by hand.

The port

Four APIs moved; each call site follows to its accessor.

API was now
SearchEntry.Text field Text() *Observable[string]
TreeView.ScrollRow field ScrollRow() *Observable[int]
TreeView.Selected field Selected() *Observable[*TreeNode]
Spinner.Active field Active() *Observable[bool]

.Text is not a safe blanket rename — non-converted widgets still have a Text field — so the sweep is by identifier, not by symbol.

app/bind.go is the one non-mechanical change

An MVVM-only widget has no field to seed and no callback to compose, so BindField cannot express it. What it has is a property that must agree with the ViewModel's — which is mvvm.BindTwoWay, added in mvvm v0.8.0 for exactly this shape:

mvvm.BindTwoWay(vm.Search, s.SearchEntry().Text(), s.InvalidateSearch)

The reasoning about which thread may Set these is unchanged and still documented at the call site.

TestSearchEntryWidget stood in for the binder by filling the OnChange slot; it now subscribes to the widget's own Observable, which is what the binder actually does.

Gate

gofmt clean · go vet clean · 100.0% coverage · -race clean · window boundary green · every cross-build target including android/arm64.

js/wasm still fails on modernc.org/sqlite exactly as it does on main (verified against origin/main as a control) — pre-existing, and not in the matrix.

🤖 Generated with Claude Code

window v0.44.0 wires in the Android back-end: Open dials the go-widgets/android
host inside an APK — a thin Java host owning the Activity and surface, with the
Go side owning layout, widgets and hit-testing over a shared memfd — and falls
through to X11/Wayland under Termux, chosen by whether $GW_ANDROID_SOCKET is
exported. Nothing in reader has to know which: the upgrade is the whole port.

#222 having already recabled the widgets to their MVVM-only APIs, that upgrade
is all that stands between this repo and android/arm64, which it now builds for.

The cross-build matrix gains that target, so the capability is guarded rather
than proven once by hand. arm64 is the only Android arch Go links CGO-free, so
it is the only one worth adding.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@tannevaled
tannevaled force-pushed the fix/toolkit-mvvm-only branch from 8094f35 to 56e6f5d Compare August 18, 2026 20:35
@tannevaled
tannevaled merged commit d5ecf16 into main Aug 18, 2026
13 checks passed
@tannevaled
tannevaled deleted the fix/toolkit-mvvm-only branch August 18, 2026 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant