From 5fe2a1a66f21d09686cb3d0a87d590ff7f659cf2 Mon Sep 17 00:00:00 2001 From: ume-kun1015 Date: Wed, 11 Dec 2024 00:16:54 +0900 Subject: [PATCH 1/5] feat: add useOverlayPortalController --- packages/flutter_hooks/lib/src/hooks.dart | 1 + .../lib/src/overlay_portal_controller.dart | 30 +++++++ .../use_overlay_portal_controller_test.dart | 84 +++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 packages/flutter_hooks/lib/src/overlay_portal_controller.dart create mode 100644 packages/flutter_hooks/test/use_overlay_portal_controller_test.dart diff --git a/packages/flutter_hooks/lib/src/hooks.dart b/packages/flutter_hooks/lib/src/hooks.dart index 023868d..1d840b2 100644 --- a/packages/flutter_hooks/lib/src/hooks.dart +++ b/packages/flutter_hooks/lib/src/hooks.dart @@ -26,6 +26,7 @@ part 'keep_alive.dart'; part 'listenable.dart'; part 'listenable_selector.dart'; part 'misc.dart'; +part 'overlay_portal_controller.dart'; part 'page_controller.dart'; part 'platform_brightness.dart'; part 'primitives.dart'; diff --git a/packages/flutter_hooks/lib/src/overlay_portal_controller.dart b/packages/flutter_hooks/lib/src/overlay_portal_controller.dart new file mode 100644 index 0000000..087ef1c --- /dev/null +++ b/packages/flutter_hooks/lib/src/overlay_portal_controller.dart @@ -0,0 +1,30 @@ +part of 'hooks.dart'; + +/// Creates a [OverlayPortalController] that will be disposed automatically. +/// +/// See also: +/// - [OverlayPortalController] +OverlayPortalController useOverlayPortalController({ + List? keys, +}) { + return use(_OverlayPortalControllerHook(keys: keys)); +} + +class _OverlayPortalControllerHook extends Hook { + const _OverlayPortalControllerHook({List? keys}) : super(keys: keys); + + @override + HookState> + createState() => _OverlayPortalControllerHookState(); +} + +class _OverlayPortalControllerHookState + extends HookState { + final controller = OverlayPortalController(); + + @override + OverlayPortalController build(BuildContext context) => controller; + + @override + String get debugLabel => 'useOverlayPortalController'; +} diff --git a/packages/flutter_hooks/test/use_overlay_portal_controller_test.dart b/packages/flutter_hooks/test/use_overlay_portal_controller_test.dart new file mode 100644 index 0000000..30011c4 --- /dev/null +++ b/packages/flutter_hooks/test/use_overlay_portal_controller_test.dart @@ -0,0 +1,84 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/src/framework.dart'; +import 'package:flutter_hooks/src/hooks.dart'; + +import 'mock.dart'; + +void main() { + testWidgets('debugFillProperties', (tester) async { + await tester.pumpWidget( + HookBuilder(builder: (context) { + useOverlayPortalController(); + return const SizedBox(); + }), + ); + + await tester.pump(); + + final element = tester.element(find.byType(HookBuilder)); + + expect( + element + .toDiagnosticsNode(style: DiagnosticsTreeStyle.offstage) + .toStringDeep(), + equalsIgnoringHashCodes( + 'HookBuilder\n' + ' │ useOverlayPortalController: OverlayPortalController DETACHED\n' + ' └SizedBox(renderObject: RenderConstrainedBox#00000)\n', + ), + ); + }); + + group('useOverlayPortalController', () { + testWidgets('initial values matches with real constructor', (tester) async { + late OverlayPortalController controller; + final controller2 = OverlayPortalController(); + + await tester.pumpWidget(MaterialApp( + home: Scaffold( + body: HookBuilder(builder: (context) { + controller = useOverlayPortalController(); + return Column( + children: [ + OverlayPortal( + controller: controller, + overlayChildBuilder: (context) => + const Text('Expansion Tile'), + ), + OverlayPortal( + controller: controller2, + overlayChildBuilder: (context) => + const Text('Expansion Tile 2'), + ), + ], + ); + }), + ), + )); + expect(controller, isA()); + expect(controller.isShowing, controller2.isShowing); + }); + + testWidgets('check show/hide of overlay portal', (tester) async { + late OverlayPortalController controller; + await tester.pumpWidget(MaterialApp( + home: Scaffold( + body: HookBuilder(builder: (context) { + controller = useOverlayPortalController(); + return OverlayPortal( + controller: controller, + overlayChildBuilder: (context) => const Text('Expansion Tile 2'), + ); + }), + ), + )); + + expect(controller.isShowing, false); + controller.show(); + expect(controller.isShowing, true); + controller.hide(); + expect(controller.isShowing, false); + }); + }); +} From 96820070844bc775d29931c400231d57037da677 Mon Sep 17 00:00:00 2001 From: ume-kun1015 Date: Wed, 11 Dec 2024 00:17:30 +0900 Subject: [PATCH 2/5] docs: updated README and CHANGELOG --- README.md | 1 + packages/flutter_hooks/CHANGELOG.md | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/README.md b/README.md index 99aff23..9106a24 100644 --- a/README.md +++ b/README.md @@ -358,6 +358,7 @@ A series of hooks with no particular theme. | [useExpansionTileController](https://api.flutter.dev/flutter/material/ExpansionTileController-class.html) | Creates a `ExpansionTileController`. | | [useDebounced](https://pub.dev/documentation/flutter_hooks/latest/flutter_hooks/useDebounced.html) | Returns a debounced version of the provided value, triggering widget updates accordingly after a specified timeout duration | | [useDraggableScrollableController](https://api.flutter.dev/flutter/widgets/DraggableScrollableController-class.html) | Creates a `DraggableScrollableController`. | +| [useOverlayPortalController](https://api.flutter.dev/flutter/widgets/OverlayPortalController-class.html) | Creates a `useOverlayPortalController`. | ## Contributions diff --git a/packages/flutter_hooks/CHANGELOG.md b/packages/flutter_hooks/CHANGELOG.md index 952422b..a0b28a4 100644 --- a/packages/flutter_hooks/CHANGELOG.md +++ b/packages/flutter_hooks/CHANGELOG.md @@ -1,3 +1,7 @@ +## Unreleased build + +- Added `useOverlayPortalController` (thanks to @offich) + ## 0.21.1-pre.4 - 2024-08-01 - Added `useFixedExtentScrollController` (thanks to @whynotmake-it) From 51e3c56ed937ba88c9d1a20983b85672f5efac2d Mon Sep 17 00:00:00 2001 From: ume-kun1015 Date: Wed, 11 Dec 2024 00:29:14 +0900 Subject: [PATCH 3/5] test: fix texts --- .../test/use_overlay_portal_controller_test.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/flutter_hooks/test/use_overlay_portal_controller_test.dart b/packages/flutter_hooks/test/use_overlay_portal_controller_test.dart index 30011c4..bbc33e0 100644 --- a/packages/flutter_hooks/test/use_overlay_portal_controller_test.dart +++ b/packages/flutter_hooks/test/use_overlay_portal_controller_test.dart @@ -44,12 +44,12 @@ void main() { OverlayPortal( controller: controller, overlayChildBuilder: (context) => - const Text('Expansion Tile'), + const Text('Overlay Portal'), ), OverlayPortal( controller: controller2, overlayChildBuilder: (context) => - const Text('Expansion Tile 2'), + const Text('Overlay Portal 2'), ), ], ); @@ -68,7 +68,7 @@ void main() { controller = useOverlayPortalController(); return OverlayPortal( controller: controller, - overlayChildBuilder: (context) => const Text('Expansion Tile 2'), + overlayChildBuilder: (context) => const Text('Overlay Portal 2'), ); }), ), From db9a63f468a174a5b30f8e6c1463394aecc5ade5 Mon Sep 17 00:00:00 2001 From: ume-kun1015 Date: Wed, 11 Dec 2024 00:56:48 +0900 Subject: [PATCH 4/5] test: improve test --- .../test/use_overlay_portal_controller_test.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/flutter_hooks/test/use_overlay_portal_controller_test.dart b/packages/flutter_hooks/test/use_overlay_portal_controller_test.dart index bbc33e0..c922645 100644 --- a/packages/flutter_hooks/test/use_overlay_portal_controller_test.dart +++ b/packages/flutter_hooks/test/use_overlay_portal_controller_test.dart @@ -68,17 +68,24 @@ void main() { controller = useOverlayPortalController(); return OverlayPortal( controller: controller, - overlayChildBuilder: (context) => const Text('Overlay Portal 2'), + overlayChildBuilder: (context) => const Text('Overlay Content'), ); }), ), )); expect(controller.isShowing, false); + expect(find.text('Overlay Content'), findsNothing); + controller.show(); + await tester.pump(); expect(controller.isShowing, true); + expect(find.text('Overlay Content'), findsOneWidget); + controller.hide(); + await tester.pump(); expect(controller.isShowing, false); + expect(find.text('Overlay Content'), findsNothing); }); }); } From f0faeff458d59fe0cf388dc57cfb33e7f122c5be Mon Sep 17 00:00:00 2001 From: offich Date: Sun, 15 Dec 2024 14:10:02 +0900 Subject: [PATCH 5/5] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9106a24..8525390 100644 --- a/README.md +++ b/README.md @@ -358,7 +358,7 @@ A series of hooks with no particular theme. | [useExpansionTileController](https://api.flutter.dev/flutter/material/ExpansionTileController-class.html) | Creates a `ExpansionTileController`. | | [useDebounced](https://pub.dev/documentation/flutter_hooks/latest/flutter_hooks/useDebounced.html) | Returns a debounced version of the provided value, triggering widget updates accordingly after a specified timeout duration | | [useDraggableScrollableController](https://api.flutter.dev/flutter/widgets/DraggableScrollableController-class.html) | Creates a `DraggableScrollableController`. | -| [useOverlayPortalController](https://api.flutter.dev/flutter/widgets/OverlayPortalController-class.html) | Creates a `useOverlayPortalController`. | +| [useOverlayPortalController](https://api.flutter.dev/flutter/widgets/OverlayPortalController-class.html) | Creates and manages an `OverlayPortalController` for controlling the visibility of overlay content. The controller will be automatically disposed when no longer needed. | ## Contributions