Skip to content

feat(ui): refs #517 — un-stub MapView on tvOS / GTK4 / Android / watchOS - #558

Merged
proggeramlug merged 1 commit into
mainfrom
worktree-issue-517-map-widget
May 7, 2026
Merged

proggeramlug merged 1 commit into
mainfrom
worktree-issue-517-map-widget

Conversation

@proggeramlug

@proggeramlug proggeramlug commented May 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Un-stubs the MapView widget on tvOS, GTK4, Android, and watchOS, complementing v0.5.636's macOS / iOS / visionOS impls. Windows remains stubbed pending WinUI MapControl XAML Islands work — tracked as a separate follow-up issue.

This PR was originally a parallel Map(lat, lng, zoom) API, but main shipped a different MapView(w, h) API in v0.5.636 first. This rewrites everything onto main's MapView API so the four newly-supported platforms speak the same surface as the Apple platforms.

What it un-stubs

Platform Backend Notes
tvOS MKMapView Source-equivalent to iOS; Siri Remote drives focus-engine pan/zoom inside the view. Adds -framework MapKit to tvOS link arm.
GTK4 libshumate GNOME's GTK4 vector-tile widget. OSM-mapnik tile source by default. No API key. set_region converts lat/lon span to libshumate's tile zoom via log2(360 / span).
Android Google Maps SDK 5 new PerryBridge.kt helpers + activity lifecycle forwarding (forwardMapsLifecycle). Per-MapView pending-ops queue replays calls until getMapAsync fires. set_map_type explicitly translates 0/1/2 → MAP_TYPE_NORMAL / _SATELLITE / _HYBRID.
watchOS SwiftUI Map Data-driven tree model extension: NodeKind::MapView + 6 fields + 9 FFI getters; Map(coordinateRegion:annotationItems:) with MapMarker pins (watchOS 7+ API).

Required user action

  • Android: replace __YOUR_GOOGLE_MAPS_API_KEY__ in AndroidManifest.xml with a real key from Google Cloud Console (Maps SDK for Android enabled).
  • GTK4 (Linux): install libshumate-dev (Debian/Ubuntu) or libshumate-devel (Fedora/RHEL).

Test plan

  • Workspace builds clean on macOS host (libshumate 0.6 resolves against gtk4-rs 0.9, no gtk-4 links collision)
  • cargo check -p perry-ui-watchos clean
  • Minimal MapView + setRegion + addPin + clearPins + setMapType(1) smoke test compiles, binary launches into a real MKMapView
  • Cross-compile verification (NDK / GTK4-on-Linux / WatchKit) — deferred to maintainer's host environments at merge time
  • Parallel android-build/ template at repo root needs same Kotlin / Manifest / Gradle changes — synced at merge time per v0.5.632 convention

Why this PR (timeline)

  1. v0.5.634 (this PR's first commit) — a competing Map(lat,lng,zoom) API on Apple platforms
  2. v0.5.635 (this PR's second commit) — extended to GTK4 / Android / watchOS / Windows
  3. main shipped v0.5.636 with a richer MapView(w,h) API on macOS/iOS/visionOS while this PR was open — superseded the Apple-side work
  4. v0.5.637 (this commit) — reset onto main, kept the non-Apple platform impls, rewrote them to use main's MapView API. Strictly additive vs main now.

…hOS (v0.5.637)

Builds on v0.5.636's MapView API (`MapView(w,h)` + `mapViewSetRegion` /
`mapViewAddPin` / `mapViewClearPins` / `mapViewSetMapType`) by replacing
the silent-zero-handle stubs on four platforms. Windows remains stubbed
pending WinUI MapControl XAML Islands work — separate follow-up.

tvOS — source-equivalent UIKit copy of the iOS MKMapView impl. Adds
`-framework MapKit` to the tvOS arm of link.rs.

GTK4 — wraps `libshumate` (GNOME's GTK4 vector-tile widget). Default
OSM-mapnik tile source, no API key. Markers go into a lazy MarkerLayer
overlay; clear_pins drops the layer. set_region converts MapKit's
lat/lon span to libshumate's tile zoom via log2(360 / span). Cargo dep
`libshumate = "0.6"` (matches gtk4-rs 0.9). New pkg-config /
hardcoded-fallback link block in link.rs for shumate-1.0.

Android — Google Maps SDK MapView via 5 new PerryBridge.kt static
helpers + lifecycle forwarding (forwardMapsLifecycle event hook) in
PerryActivity.kt. Pending-ops queue replays calls once getMapAsync
fires. set_map_type translates 0/1/2 → MAP_TYPE_NORMAL/SATELLITE/HYBRID
explicitly (Google's enum is 1/2/3/4 with TERRAIN=3). Gradle dep
play-services-maps:18.2.0; AndroidManifest meta-data placeholder for
the Google Maps API key.

watchOS — extends the data-driven SwiftUI tree model with
NodeKind::MapView + map_lat/lon/lat_span/lon_span/type/pins fields, 9
new FFI getters, and a `mapView` SwiftUI subview rendering
Map(coordinateRegion:annotationItems:) with MapMarker pins (the
deprecated-but-watchOS-7-compatible API; newer Marker shape requires
watchOS 10). Adds `import MapKit` to PerryWatchApp.swift.

Verified
- Workspace builds clean on macOS host (libshumate 0.6 resolves
  against gtk4-rs 0.9, no gtk-4 links collision)
- perry-ui-watchos cargo check clean
- Minimal MapView smoke test (MapView/setRegion/addPin/clearPins/
  setMapType) compiles + binary launches into a real MKMapView
- Cross-compile verification (NDK / GTK4 on Linux / WatchKit) deferred
  to maintainer's host environments at merge time
- Parallel android-build/ template at repo root needs the same
  Kotlin / Manifest / Gradle changes — synced at merge time per the
  v0.5.632 convention
@proggeramlug
proggeramlug force-pushed the worktree-issue-517-map-widget branch from a70baea to f42da21 Compare May 7, 2026 13:08
@proggeramlug proggeramlug changed the title feat(ui): native Map widget via MapKit (refs #517) feat(ui): refs #517 — un-stub MapView on tvOS / GTK4 / Android / watchOS May 7, 2026
@proggeramlug
proggeramlug merged commit c3bc684 into main May 7, 2026
4 of 10 checks passed
proggeramlug added a commit that referenced this pull request May 7, 2026
…metadata for non-exported classes (v0.5.638)

Lib3 exports class C with populate() { this.children['a'] = new Inner(); },
where Inner is a sibling class declared in the same module BUT not exported.
The HIR-level inliner harvested populate as cross-module-inlinable (the
is_cross_module_safe filter only rejects FuncRef / ExternFuncRef / GlobalGet
/ Closure — NOT Expr::New { class_name } against an unexported local class).
Body got copied verbatim; consumer's lower_new("Inner") fell into the
no-class-metadata fallback and emitted js_object_alloc(0, 0); subsequent
inst.method() dispatch found class_id=0 and fell through to NULL.

Fix adds collect_nonexported_class_names + body_references_class_in_set
helpers to crates/perry-transform/src/inline.rs. Methods whose body
references any local non-exported class via Expr::New / ClassRef /
StaticFieldGet / StaticFieldSet / ClassStaticSymbolSet / StaticMethodCall
are excluded from the cross-module inline candidates. Such methods stay as
real cross-module method calls (bl perry_method_<src>__C__populate), where
the source module's codegen — which DOES have the class metadata — emits
the correct inline-alloc with the right class_id.

__AnonShape_* content-addressed shapes are deliberately KEPT inlinable
because they're already propagated via extra_anon_classes so the
destination module synthesizes the same definition.

End-to-end: minimal repro (new Inner() inside populate()) prints
'result: hello-inner' matching Node byte-for-byte (was '[object Object]').
Sanity tests test_inheritance / test_gap_class_advanced / test_gap_closures
/ test_edge_promises all match Node. Hono canonical
app.get('/', c => c.text('hello')) still passes.

Version bumped from the original 0.5.637 to 0.5.638 because v0.5.637 was
already taken by the parallel MapView un-stub merge (c3bc684, PR #558)
that landed first.
@proggeramlug
proggeramlug deleted the worktree-issue-517-map-widget branch May 7, 2026 13:35
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