1
import 'dart:async';
2

3
import 'package:connectivity/connectivity.dart';
4
import 'package:flutter/widgets.dart';
5
import 'package:flutter_offline/src/utils.dart';
6

7 17
const kOfflineDebounceDuration = const Duration(seconds: 3);
8

9
typedef Widget ConnectivityBuilder(
10
    BuildContext context, ConnectivityResult connectivity, Widget child);
11

12
class OfflineBuilder extends StatefulWidget {
13 17
  factory OfflineBuilder({
14
    Key key,
15
    @required ConnectivityBuilder connectivityBuilder,
16
    Duration debounceDuration = kOfflineDebounceDuration,
17
    WidgetBuilder builder,
18
    Widget child,
19
    WidgetBuilder errorBuilder,
20
  }) {
21 17
    return OfflineBuilder.initialize(
22
      key: key,
23
      connectivityBuilder: connectivityBuilder,
24 17
      connectivityService: Connectivity(),
25
      debounceDuration: debounceDuration,
26
      builder: builder,
27
      child: child,
28
      errorBuilder: errorBuilder,
29
    );
30
  }
31

32 17
  @visibleForTesting
33
  OfflineBuilder.initialize({
34
    Key key,
35
    @required this.connectivityBuilder,
36
    @required this.connectivityService,
37
    this.debounceDuration = kOfflineDebounceDuration,
38
    this.builder,
39
    this.child,
40
    this.errorBuilder,
41
  })  : assert(
42 17
            connectivityBuilder != null, 'connectivityBuilder cannot be null'),
43 17
        assert(debounceDuration != null, 'debounceDuration cannot be null'),
44
        assert(
45 17
            connectivityService != null, 'connectivityService cannot be null'),
46
        assert(
47 17
            !(builder is WidgetBuilder && child is Widget) &&
48
                !(builder == null && child == null),
49
            'You should specify either a builder or a child'),
50 17
        super(key: key);
51

52
  /// Override connectivity service used for testing
53
  final Connectivity connectivityService;
54

55
  /// Debounce duration from epileptic network situations
56
  final Duration debounceDuration;
57

58
  /// Used for building the Offline and/or Online UI
59
  final ConnectivityBuilder connectivityBuilder;
60

61
  /// Used for building the child widget
62
  final WidgetBuilder builder;
63

64
  /// The widget below this widget in the tree.
65
  final Widget child;
66

67
  /// Used for building the error widget incase of any platform errors
68
  final WidgetBuilder errorBuilder;
69

70 17
  @override
71 17
  OfflineBuilderState createState() => OfflineBuilderState();
72
}
73

74
class OfflineBuilderState extends State<OfflineBuilder> {
75
  Stream<ConnectivityResult> _connectivityStream;
76

77 17
  @override
78
  void initState() {
79 17
    super.initState();
80

81 17
    _connectivityStream = Stream.fromFuture(
82 17
      widget.connectivityService.checkConnectivity(),
83 17
    ).asyncExpand(
84 17
      (ConnectivityResult data) {
85 17
        return widget.connectivityService.onConnectivityChanged.transform(
86 17
          startsWith(data),
87
        );
88
      },
89 17
    ).transform(
90 17
      debounce(widget.debounceDuration),
91
    );
92
  }
93

94 17
  @override
95
  Widget build(BuildContext context) {
96 17
    return StreamBuilder<ConnectivityResult>(
97 17
      stream: _connectivityStream,
98 17
      builder: (
99
        BuildContext context,
100
        AsyncSnapshot<ConnectivityResult> snapshot,
101
      ) {
102 17
        final child = widget.child ?? widget.builder(context);
103 17
        if (!snapshot.hasData && !snapshot.hasError) {
104
          return const SizedBox();
105 17
        } else if (snapshot.hasError) {
106 17
          if (widget.errorBuilder != null) {
107 17
            return widget.errorBuilder(context);
108
          }
109 17
          throw OfflineBuilderError(snapshot.error);
110
        }
111 17
        return widget.connectivityBuilder(context, snapshot.data, child);
112
      },
113
    );
114
  }
115
}
116

117
class OfflineBuilderError extends Error {
118 17
  OfflineBuilderError(this.error);
119

120
  final Object error;
121

122 17
  @override
123 17
  String toString() => error.toString();
124
}

Read our documentation on viewing source code .

Loading