|
| 1 | +import 'dart:async'; |
| 2 | + |
1 | 3 | import 'package:clerk_flutter/src/utils/clerk_auth_config.dart';
|
2 |
| -import 'package:clerk_flutter/src/widgets/ui/common.dart'; |
| 4 | +import 'package:clerk_flutter/src/widgets/ui/clerk_overlay_host.dart'; |
3 | 5 | import 'package:flutter/widgets.dart';
|
4 | 6 |
|
5 | 7 | /// Clerk Loading Overlay
|
6 | 8 | class ClerkLoadingOverlay {
|
7 | 9 | /// Constructs a [ClerkLoadingOverlay]
|
8 |
| - ClerkLoadingOverlay(ClerkAuthConfig config) |
9 |
| - : _overlayEntry = OverlayEntry( |
10 |
| - builder: (context) => config.loading ?? defaultLoadingWidget, |
11 |
| - ); |
| 10 | + ClerkLoadingOverlay(ClerkAuthConfig config) : _loadingWidget = config.loading; |
| 11 | + |
| 12 | + /// The delay between an [insertInto] call and the loading overlay |
| 13 | + /// being displayed |
| 14 | + static const startupDuration = Duration(milliseconds: 300); |
| 15 | + |
| 16 | + /// The minimum amount of time the loading overlay should remain |
| 17 | + /// on screen for |
| 18 | + static const minimumOnScreenDuration = Duration(milliseconds: 800); |
| 19 | + |
| 20 | + /// The number of [ClerkLoadingOverlay] requests that are currently |
| 21 | + /// pending |
| 22 | + int count = 0; |
| 23 | + |
| 24 | + Timer? _displayTimer; |
| 25 | + Timer? _hideTimer; |
| 26 | + DateTime _hideAfter = DateTime(0); |
12 | 27 |
|
13 |
| - final OverlayEntry _overlayEntry; |
| 28 | + final Widget? _loadingWidget; |
14 | 29 |
|
15 | 30 | /// Shows the loading overlay
|
16 |
| - void show(BuildContext context) { |
17 |
| - final overlay = Overlay.of(context); |
18 |
| - if (overlay.context.mounted && _overlayEntry.mounted == false) { |
19 |
| - overlay.insert(_overlayEntry); |
| 31 | + void insertInto(ClerkOverlay overlay) { |
| 32 | + // no overlay widget was supplied so we dont try and display it |
| 33 | + if (_loadingWidget == null) { |
| 34 | + return; |
| 35 | + } |
| 36 | + // make the display of loading indicator reentrant |
| 37 | + if (++count == 1) { |
| 38 | + _hideTimer?.cancel(); |
| 39 | + _hideTimer = null; |
| 40 | + _displayTimer ??= Timer( |
| 41 | + startupDuration, |
| 42 | + () { |
| 43 | + if (!overlay.isDisplaying(_loadingWidget!)) { |
| 44 | + _hideAfter = DateTime.timestamp().add(minimumOnScreenDuration); |
| 45 | + overlay.insert(_loadingWidget!); |
| 46 | + } |
| 47 | + }, |
| 48 | + ); |
20 | 49 | }
|
21 | 50 | }
|
22 | 51 |
|
23 | 52 | /// Hides the loading overlay
|
24 |
| - void hide() { |
25 |
| - _overlayEntry.remove(); |
| 53 | + void removeFrom(ClerkOverlay overlay) { |
| 54 | + // no overlay widget was supplied so we dont try and remove it |
| 55 | + if (_loadingWidget == null) { |
| 56 | + return; |
| 57 | + } |
| 58 | + // make the display of loading indicator reentrant |
| 59 | + if (count > 0 && --count == 0) { |
| 60 | + _displayTimer?.cancel(); |
| 61 | + _displayTimer = null; |
| 62 | + |
| 63 | + if (_hideTimer == null && overlay.isDisplaying(_loadingWidget!)) { |
| 64 | + final now = DateTime.timestamp(); |
| 65 | + if (_hideAfter.isBefore(now)) { |
| 66 | + overlay.remove(_loadingWidget!); |
| 67 | + } else { |
| 68 | + _hideTimer = Timer( |
| 69 | + _hideAfter.difference(now), |
| 70 | + () { |
| 71 | + _hideTimer = null; |
| 72 | + overlay.remove(_loadingWidget!); |
| 73 | + }, |
| 74 | + ); |
| 75 | + } |
| 76 | + } |
| 77 | + } |
26 | 78 | }
|
27 | 79 | }
|
0 commit comments