downloadOfflineRegion function

Future<OfflineRegion> downloadOfflineRegion(
  1. OfflineRegionDefinition definition, {
  2. Map<String, dynamic> metadata = const {},
  3. dynamic onEvent(
    1. DownloadRegionStatus event
    )?,
})

Implementation

Future<OfflineRegion> downloadOfflineRegion(
  OfflineRegionDefinition definition, {
  Map<String, dynamic> metadata = const {},
  Function(DownloadRegionStatus event)? onEvent,
}) async {
  final channelName =
      'downloadOfflineRegion_${DateTime.now().microsecondsSinceEpoch}';

  await _globalChannel.invokeMethod(
    'downloadOfflineRegion#setup',
    <String, dynamic>{
      'channelName': channelName,
    },
  );

  if (onEvent != null) {
    void cleanup() {
      final sub = _offlineDownloadSubscriptions.remove(channelName);
      if (sub != null) unawaited(sub.cancel());
    }

    // Subscription is retained in _offlineDownloadSubscriptions and cancelled
    // in cleanup() on the terminal Success/Error event.
    // ignore: cancel_subscriptions
    final subscription = EventChannel(channelName)
        .receiveBroadcastStream()
        .handleError((error) {
          if (error is PlatformException) {
            onEvent(Error(error));
            cleanup();
            return Error(error);
          }
          final unknownError = Error(
            PlatformException(
              code: 'UnknowException',
              message:
                  'This error is unhandled by plugin. Please contact us if needed.',
              details: error,
            ),
          );
          onEvent(unknownError);
          cleanup();
          return unknownError;
        })
        .listen((data) {
          final Map<String, Object?> jsonData = json.decode(data);
          final status = switch (jsonData['status']) {
            'start' => InProgress(0.0),
            'progress' => InProgress(
              (jsonData['progress']! as num).toDouble(),
              completedResourceCount:
                  (jsonData['completedResourceCount'] as num?)?.toInt() ?? 0,
              requiredResourceCount:
                  (jsonData['requiredResourceCount'] as num?)?.toInt() ?? 0,
              completedResourceSize:
                  (jsonData['completedResourceSize'] as num?)?.toInt() ?? 0,
            ),
            'success' => Success(),
            _ => throw Exception('Invalid event status ${jsonData['status']}'),
          };
          onEvent(status);
          if (status is Success) cleanup();
        });

    _offlineDownloadSubscriptions[channelName] = subscription;
  }

  final result = await _globalChannel.invokeMethod(
    'downloadOfflineRegion',
    <String, dynamic>{
      'definition': definition.toMap(),
      'metadata': metadata,
    },
  );

  return OfflineRegion.fromMap(json.decode(result));
}