2025-05-02 11:42:32 +03:00
|
|
|
import 'package:cherrypick/cherrypick.dart';
|
|
|
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
|
|
2025-05-02 11:53:03 +03:00
|
|
|
///
|
2025-05-16 13:06:46 +03:00
|
|
|
/// Copyright 2021 Sergey Penkovsky (sergey.penkovsky@gmail.com)
|
2025-05-02 11:53:03 +03:00
|
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
/// you may not use this file except in compliance with the License.
|
|
|
|
|
/// You may obtain a copy of the License at
|
2025-08-08 23:24:05 +03:00
|
|
|
/// https://www.apache.org/licenses/LICENSE-2.0
|
2025-05-02 11:53:03 +03:00
|
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
/// See the License for the specific language governing permissions and
|
|
|
|
|
/// limitations under the License.
|
|
|
|
|
///
|
|
|
|
|
|
2025-08-12 15:46:14 +03:00
|
|
|
/// {@template cherrypick_flutter_provider}
|
|
|
|
|
/// An [InheritedWidget] that provides convenient integration of CherryPick
|
|
|
|
|
/// dependency injection scopes into the Flutter widget tree.
|
|
|
|
|
///
|
|
|
|
|
/// Place `CherryPickProvider` at the top of your widget subtree to make a
|
|
|
|
|
/// [Scope] (or its descendants) available via `CherryPickProvider.of(context)`.
|
|
|
|
|
///
|
|
|
|
|
/// This is the recommended entry point for connecting CherryPick DI to your
|
|
|
|
|
/// Flutter app or feature area, enabling context-based scope management and
|
|
|
|
|
/// DI resolution in child widgets.
|
|
|
|
|
///
|
|
|
|
|
/// ### Example: Root Integration
|
|
|
|
|
/// ```dart
|
|
|
|
|
/// void main() {
|
|
|
|
|
/// final rootScope = CherryPick.openRootScope()
|
|
|
|
|
/// ..installModules([AppModule()]);
|
|
|
|
|
/// runApp(
|
|
|
|
|
/// CherryPickProvider(
|
|
|
|
|
/// child: MyApp(),
|
|
|
|
|
/// ),
|
|
|
|
|
/// );
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// // In any widget:
|
|
|
|
|
/// final provider = CherryPickProvider.of(context);
|
|
|
|
|
/// final scope = provider.openRootScope();
|
|
|
|
|
/// final myService = scope.resolve<MyService>();
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// ### Example: Subscope for a Feature/Screen
|
|
|
|
|
/// ```dart
|
|
|
|
|
/// Widget build(BuildContext context) {
|
|
|
|
|
/// final provider = CherryPickProvider.of(context);
|
|
|
|
|
/// final featureScope = provider.openSubScope(scopeName: 'featureA');
|
|
|
|
|
/// return MyFeatureScreen(scope: featureScope);
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// You can use [openRootScope] and [openSubScope] as helpers to get/create scopes.
|
|
|
|
|
/// {@endtemplate}
|
2025-05-03 17:02:13 +03:00
|
|
|
final class CherryPickProvider extends InheritedWidget {
|
2025-08-12 15:46:14 +03:00
|
|
|
/// Opens (or returns) the application-wide root [Scope].
|
|
|
|
|
///
|
|
|
|
|
/// Use to make all dependencies available at the top of your widget tree.
|
2025-05-03 17:02:13 +03:00
|
|
|
Scope openRootScope() => CherryPick.openRootScope();
|
|
|
|
|
|
2025-08-12 15:46:14 +03:00
|
|
|
/// Opens a subscope (child [Scope]) with the given [scopeName].
|
|
|
|
|
///
|
|
|
|
|
/// Useful to create isolated feature/module scopes in widget subtrees.
|
|
|
|
|
/// If [scopeName] is empty, an unnamed scope is created.
|
2025-05-03 17:02:13 +03:00
|
|
|
Scope openSubScope({String scopeName = '', String separator = '.'}) =>
|
|
|
|
|
CherryPick.openScope(scopeName: scopeName, separator: separator);
|
2025-05-02 11:42:32 +03:00
|
|
|
|
2025-08-12 15:46:14 +03:00
|
|
|
/// Creates a [CherryPickProvider] and exposes it to the widget subtree.
|
|
|
|
|
///
|
|
|
|
|
/// Place near the root of your widget tree. Use [child] to provide the subtree.
|
2025-05-02 11:42:32 +03:00
|
|
|
const CherryPickProvider({
|
|
|
|
|
super.key,
|
|
|
|
|
required super.child,
|
|
|
|
|
});
|
|
|
|
|
|
2025-08-12 15:46:14 +03:00
|
|
|
/// Locates the nearest [CherryPickProvider] up the widget tree from [context].
|
|
|
|
|
///
|
|
|
|
|
/// Throws if not found. Use this to access DI [Scope] controls anywhere below the provider.
|
|
|
|
|
///
|
|
|
|
|
/// Example:
|
|
|
|
|
/// ```dart
|
|
|
|
|
/// final provider = CherryPickProvider.of(context);
|
|
|
|
|
/// final scope = provider.openRootScope();
|
|
|
|
|
/// ```
|
2025-05-02 11:42:32 +03:00
|
|
|
static CherryPickProvider of(BuildContext context) {
|
|
|
|
|
final CherryPickProvider? result =
|
|
|
|
|
context.dependOnInheritedWidgetOfExactType<CherryPickProvider>();
|
|
|
|
|
assert(result != null, 'No CherryPickProvider found in context');
|
|
|
|
|
return result!;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-12 15:46:14 +03:00
|
|
|
/// Controls update notifications for dependent widgets.
|
|
|
|
|
///
|
|
|
|
|
/// Always returns false because the provider itself is stateless:
|
|
|
|
|
/// changes are to the underlying scopes, not the widget.
|
2025-05-02 11:42:32 +03:00
|
|
|
@override
|
|
|
|
|
bool updateShouldNotify(CherryPickProvider oldWidget) {
|
2025-05-03 17:02:13 +03:00
|
|
|
return false;
|
2025-05-02 11:42:32 +03:00
|
|
|
}
|
|
|
|
|
}
|