Skip to content

Commit 349b88b

Browse files
authored
Merge pull request #13 from Notalib/chor/clean-await-native-ready-fn
refactor: _awaitNativeViewReady is no longer recursive
2 parents d9573bc + 1e5bc07 commit 349b88b

File tree

1 file changed

+53
-30
lines changed

1 file changed

+53
-30
lines changed

flutter_readium/lib/reader_widget.dart

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,16 @@ class ReadiumReaderWidget extends StatefulWidget {
3939
State<StatefulWidget> createState() => _ReadiumReaderWidgetState();
4040
}
4141

42-
class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget> implements ReadiumReaderWidgetInterface {
42+
class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget>
43+
implements ReadiumReaderWidgetInterface {
4344
static const _wakelockTimerDuration = Duration(minutes: 30);
44-
static const _maxRetryAwaitNativeViewReady = 100;
45+
46+
/// Duration per retry to wait for native view to be ready.
47+
static const _awaitNativeViewReadyDuration = Duration(milliseconds: 20);
48+
49+
/// Maximum number of retries to check, if native view is ready.
50+
static const _maxRetryAwaitNativeViewReady = 500;
51+
4552
Timer? _wakelockTimer;
4653
ReadiumReaderChannel? _channel;
4754

@@ -176,7 +183,8 @@ class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget> implements Re
176183
Future<void> goLeft({final bool animated = true}) async => _channel?.goLeft();
177184

178185
@override
179-
Future<void> goRight({final bool animated = true}) async => _channel?.goRight();
186+
Future<void> goRight({final bool animated = true}) async =>
187+
_channel?.goRight();
180188

181189
@override
182190
Future<void> skipToNext({final bool animated = true}) async {
@@ -199,7 +207,8 @@ class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget> implements Re
199207
final newIndex = (curIndex + 1).clamp(0, toc.length - 1);
200208
Locator? nextChapter = widget.publication.locatorFromLink(toc[newIndex]);
201209
if (nextChapter != null) {
202-
await _channel?.go(nextChapter, isAudioBookWithText: false, animated: true);
210+
await _channel?.go(nextChapter,
211+
isAudioBookWithText: false, animated: true);
203212
}
204213
}
205214
}
@@ -214,9 +223,11 @@ class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget> implements Re
214223
int? curIndex = toc.indexWhere((l) => l.href == currentHref);
215224
if (curIndex > -1) {
216225
final newIndex = (curIndex - 1).clamp(0, toc.length - 1);
217-
Locator? previousChapter = widget.publication.locatorFromLink(toc[newIndex]);
226+
Locator? previousChapter =
227+
widget.publication.locatorFromLink(toc[newIndex]);
218228
if (previousChapter != null) {
219-
await _channel?.go(previousChapter, isAudioBookWithText: false, animated: true);
229+
await _channel?.go(previousChapter,
230+
isAudioBookWithText: false, animated: true);
220231
}
221232
}
222233
}
@@ -242,7 +253,8 @@ class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget> implements Re
242253
}
243254

244255
@override
245-
Future<void> applyDecorations(String id, List<ReaderDecoration> decorations) async {
256+
Future<void> applyDecorations(
257+
String id, List<ReaderDecoration> decorations) async {
246258
await _channel?.applyDecorations(id, decorations);
247259
}
248260

@@ -273,7 +285,9 @@ class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget> implements Re
273285
final creationParams = <String, dynamic>{
274286
'pubIdentifier': publication.identifier,
275287
'preferences': defaultPreferences,
276-
'initialLocator': widget.initialLocator == null ? null : json.encode(widget.initialLocator),
288+
'initialLocator': widget.initialLocator == null
289+
? null
290+
: json.encode(widget.initialLocator),
277291
};
278292

279293
R2Log.d('creationParams=$creationParams');
@@ -286,16 +300,17 @@ class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget> implements Re
286300
gestureRecognizers: const {},
287301
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
288302
),
289-
onCreatePlatformView: (final params) => PlatformViewsService.initSurfaceAndroidView(
303+
onCreatePlatformView: (final params) =>
304+
PlatformViewsService.initSurfaceAndroidView(
290305
id: params.id,
291306
viewType: _viewType,
292307
layoutDirection: TextDirection.ltr,
293308
creationParams: creationParams,
294309
creationParamsCodec: const StandardMessageCodec(),
295310
)
296-
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
297-
..addOnPlatformViewCreatedListener(_onPlatformViewCreated)
298-
..create(),
311+
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
312+
..addOnPlatformViewCreatedListener(_onPlatformViewCreated)
313+
..create(),
299314
);
300315
} else if (Platform.isIOS) {
301316
return UiKitView(
@@ -356,29 +371,32 @@ class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget> implements Re
356371

357372
_awaitNativeViewReady().then((final _) {
358373
// TODO: This is just to demo how to use and debounce the Stream, remove when appropriate.
359-
final nativeLocatorStream =
360-
_readium.onTextLocatorChanged.debounceTime(const Duration(milliseconds: 50)).asBroadcastStream().distinct();
374+
final nativeLocatorStream = _readium.onTextLocatorChanged
375+
.debounceTime(const Duration(milliseconds: 50))
376+
.asBroadcastStream()
377+
.distinct();
361378

362379
nativeLocatorStream.listen((locator) {
363380
R2Log.d('LocatorChanged - $locator');
364381
});
365382
});
366383
}
367384

368-
Future<void> _awaitNativeViewReady([int retry = 0]) async {
369-
R2Log.d('attempt: $retry');
385+
Future<void> _awaitNativeViewReady() async {
386+
final nativeViewStartTime = DateTime.now();
387+
for (int retry = 0; retry < _maxRetryAwaitNativeViewReady; retry++) {
388+
if (await _channel?.isReaderReady() == true) {
389+
R2Log.d(
390+
'Native view is ready! Time spent: ${DateTime.now().difference(nativeViewStartTime).inMilliseconds} ms');
391+
return;
392+
}
370393

371-
if (retry >= _maxRetryAwaitNativeViewReady) {
372-
R2Log.d('Max retry reached!');
373-
return;
394+
R2Log.d('Native reader not ready - retry:$retry');
395+
await Future.delayed(_awaitNativeViewReadyDuration);
374396
}
375397

376-
if (await _channel?.isReaderReady() != true) {
377-
R2Log.d(() => 'Native reader not ready - retry');
378-
379-
await Future.delayed(const Duration(milliseconds: 100));
380-
return _awaitNativeViewReady(++retry);
381-
}
398+
R2Log.d(
399+
'Max retry reached! After ${DateTime.now().difference(nativeViewStartTime).inMilliseconds} ms');
382400
}
383401

384402
/// Gets a Locator's href with toc fragment appended as identifier
@@ -388,14 +406,16 @@ class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget> implements Re
388406
}
389407

390408
final txtLoc = locator.toTextLocator();
391-
final tocFragment = locator.locations?.fragments?.firstWhereOrNull((f) => f.startsWith("toc="));
409+
final tocFragment = locator.locations?.fragments
410+
?.firstWhereOrNull((f) => f.startsWith("toc="));
392411
if (tocFragment == null) {
393412
return null;
394413
}
395414
return '${txtLoc.toTextLocator().hrefPath.substring(1)}#${tocFragment.substring(4)}';
396415
}
397416

398-
Future<void> _setLocation(final Locator locator, final bool isAudioBookWithText) async {
417+
Future<void> _setLocation(
418+
final Locator locator, final bool isAudioBookWithText) async {
399419
R2Log.d('Set highlight');
400420

401421
// final playbackRate = FlutterReadium.state.playbackRate;
@@ -413,7 +433,8 @@ class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget> implements Re
413433
}
414434

415435
// Make sure to copy fragment durations onto locators before sending over native channel.
416-
final fragmentDurationInSec = (locations?.xFragmentDuration?.inSeconds ?? 0);
436+
final fragmentDurationInSec =
437+
(locations?.xFragmentDuration?.inSeconds ?? 0);
417438

418439
_channel?.setLocation(
419440
locator.mapLocations(
@@ -442,12 +463,14 @@ class _ReadiumReaderWidgetState extends State<ReadiumReaderWidget> implements Re
442463
// trigger scrolling to the nearest page.
443464
if (_lastOrientation != null && _currentLocator != null) {
444465
Future.delayed(const Duration(milliseconds: 500)).then((final value) {
445-
R2Log.d('Orientation changed. Re-navigating to current locator to re-align page.');
466+
R2Log.d(
467+
'Orientation changed. Re-navigating to current locator to re-align page.');
446468
R2Log.d('locator = $_currentLocator');
447469
_channel?.go(
448470
_currentLocator!,
449471
animated: false,
450-
isAudioBookWithText: false, // TODO: isAudioBookWithText - we don't know atm.
472+
isAudioBookWithText:
473+
false, // TODO: isAudioBookWithText - we don't know atm.
451474
);
452475
});
453476
}

0 commit comments

Comments
 (0)