onTextLocatorChanged property
Fires whenever the Reader's current Locator changes.
The underlying event channel opts in to native-side buffering so the first
event is never dropped even if it fires before the Dart onListen
handshake completes (a race that can happen when the EPUB platform view
initialises faster than the asynchronous channel setup).
Undecodable events are logged and dropped rather than raised on the stream. Both platforms guard against emitting one, so this is defence against a native regression — and against a Locator that decodes but fails validation.
Implementation
@override
Stream<Locator> get onTextLocatorChanged {
_onTextLocatorChanged ??= textLocatorChannel
.receiveBroadcastStream()
.map(Locator.fromJsonDynamic)
.where((locator) => locator != null)
.cast<Locator>()
.asBroadcastStream();
return _onTextLocatorChanged!;
}