29 changed files with 180 additions and 97 deletions
			
			
		@ -0,0 +1,103 @@
					 | 
				
			||||
import 'package:flutter/widgets.dart'; | 
				
			||||
import 'package:neon/src/models/disposable.dart'; | 
				
			||||
import 'package:provider/provider.dart'; | 
				
			||||
import 'package:provider/single_child_widget.dart'; | 
				
			||||
 | 
				
			||||
/// A [Provider] that manages the lifecycle of a [Disposable] value it provides | 
				
			||||
/// by delegating [Create] and calling [Disposable.dispose]. | 
				
			||||
class NeonProvider<T extends Disposable> extends SingleChildStatelessWidget { | 
				
			||||
  /// Creates a value, stores it, and exposes it to its descendants. | 
				
			||||
  const NeonProvider({ | 
				
			||||
    required final Create<T> create, | 
				
			||||
    super.key, | 
				
			||||
    this.child, | 
				
			||||
    this.lazy = true, | 
				
			||||
  })  : _create = create, | 
				
			||||
        _value = null, | 
				
			||||
        super(child: child); | 
				
			||||
 | 
				
			||||
  /// Expose an existing value without disposing it. | 
				
			||||
  /// | 
				
			||||
  /// {@macro provider.updateshouldnotify} | 
				
			||||
  const NeonProvider.value({ | 
				
			||||
    required final T value, | 
				
			||||
    super.key, | 
				
			||||
    this.child, | 
				
			||||
  })  : _value = value, | 
				
			||||
        _create = null, | 
				
			||||
        lazy = true, | 
				
			||||
        super(child: child); | 
				
			||||
 | 
				
			||||
  /// Optional widget below this widget in the tree having access to the value. | 
				
			||||
  /// | 
				
			||||
  /// {@macro flutter.widgets.ProxyWidget.child} | 
				
			||||
  final Widget? child; | 
				
			||||
 | 
				
			||||
  /// Whether the value should be created lazily. | 
				
			||||
  /// Defaults to `true`. | 
				
			||||
  final bool lazy; | 
				
			||||
 | 
				
			||||
  final Create<T>? _create; | 
				
			||||
 | 
				
			||||
  final T? _value; | 
				
			||||
 | 
				
			||||
  /// Method that allows widgets to access the value as long as their | 
				
			||||
  /// `BuildContext` contains a [NeonProvider] or [Provider] instance of the | 
				
			||||
  /// specified type. | 
				
			||||
  /// | 
				
			||||
  /// Calling this method is equivalent to calling: | 
				
			||||
  /// | 
				
			||||
  /// ```dart | 
				
			||||
  /// Provider.of(context, listen: false); | 
				
			||||
  /// ``` | 
				
			||||
  /// | 
				
			||||
  /// If we want to access an instance of `DisposableA` which was provided higher up | 
				
			||||
  /// in the widget tree we can do so via: | 
				
			||||
  /// | 
				
			||||
  /// ```dart | 
				
			||||
  /// NeonProvider.of<DisposableA>(context); | 
				
			||||
  /// ``` | 
				
			||||
  static T of<T>( | 
				
			||||
    final BuildContext context, { | 
				
			||||
    final bool listen = false, | 
				
			||||
  }) { | 
				
			||||
    try { | 
				
			||||
      return Provider.of<T>(context, listen: listen); | 
				
			||||
    } on ProviderNotFoundException catch (e) { | 
				
			||||
      if (e.valueType != T) { | 
				
			||||
        rethrow; | 
				
			||||
      } | 
				
			||||
      throw FlutterError( | 
				
			||||
        ''' | 
				
			||||
        NeonProvider.of() called with a context that does not contain a $T. | 
				
			||||
        No ancestor could be found starting from the context that was passed to NeonProvider.of<$T>(). | 
				
			||||
 | 
				
			||||
        This can happen if the context you used comes from a widget above the NeonProvider. | 
				
			||||
 | 
				
			||||
        The context used was: $context | 
				
			||||
        ''', | 
				
			||||
      ); | 
				
			||||
    } | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  @override | 
				
			||||
  Widget buildWithChild(final BuildContext context, final Widget? child) { | 
				
			||||
    assert( | 
				
			||||
      child != null, | 
				
			||||
      '$runtimeType used outside of MultiBlocProvider must specify a child', | 
				
			||||
    ); | 
				
			||||
    final value = _value; | 
				
			||||
    return value != null | 
				
			||||
        ? InheritedProvider<T>.value( | 
				
			||||
            value: value, | 
				
			||||
            lazy: lazy, | 
				
			||||
            child: child, | 
				
			||||
          ) | 
				
			||||
        : InheritedProvider<T>( | 
				
			||||
            create: _create, | 
				
			||||
            dispose: (final _, final value) => value.dispose(), | 
				
			||||
            lazy: lazy, | 
				
			||||
            child: child, | 
				
			||||
          ); | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue