Skip to content

Commit cf06c67

Browse files
committed
feat: add Hook for managing SnapshotController instances
1 parent ca0b17f commit cf06c67

File tree

3 files changed

+137
-0
lines changed

3 files changed

+137
-0
lines changed

packages/flutter_hooks/lib/src/hooks.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,4 @@ part 'transformation_controller.dart';
4141
part 'tree_sliver_controller.dart';
4242
part 'widget_states_controller.dart';
4343
part 'widgets_binding_observer.dart';
44+
part 'snapshot_controller.dart';
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
part of 'hooks.dart';
2+
3+
/// Creates and disposes a [SnapshotController].
4+
///
5+
/// Note that [allowSnapshotting] must be set to `true`
6+
/// in order for this controller to actually do anything.
7+
/// This is consistent with [SnapshotController.new].
8+
///
9+
/// If [allowSnapshotting] changes on subsequent calls to [useSnapshotController],
10+
/// [SnapshotController.allowSnapshotting] will be called to update accordingly.
11+
///
12+
/// ```dart
13+
/// final controller = useSnapshotController(allowSnapshotting: true);
14+
/// // is equivalent to
15+
/// final controller = useSnapshotController();
16+
/// controller.allowSnapshotting = true;
17+
/// ```
18+
///
19+
/// See also:
20+
/// - [SnapshotController]
21+
SnapshotController useSnapshotController({
22+
bool allowSnapshotting = false,
23+
}) {
24+
return use(
25+
_SnapshotControllerHook(
26+
allowSnapshotting: allowSnapshotting,
27+
),
28+
);
29+
}
30+
31+
class _SnapshotControllerHook extends Hook<SnapshotController> {
32+
const _SnapshotControllerHook({
33+
required this.allowSnapshotting,
34+
});
35+
36+
final bool allowSnapshotting;
37+
38+
@override
39+
HookState<SnapshotController, Hook<SnapshotController>>
40+
createState() => _SnapshotControllerHookState();
41+
}
42+
43+
class _SnapshotControllerHookState
44+
extends HookState<SnapshotController, _SnapshotControllerHook> {
45+
late final controller = SnapshotController(allowSnapshotting: hook.allowSnapshotting);
46+
47+
@override
48+
void didUpdateHook(_SnapshotControllerHook oldHook) {
49+
super.didUpdateHook(oldHook);
50+
controller.allowSnapshotting = hook.allowSnapshotting;
51+
}
52+
53+
@override
54+
SnapshotController build(BuildContext context) => controller;
55+
56+
@override
57+
void dispose() => controller.dispose();
58+
59+
@override
60+
String get debugLabel => 'useSnapshotController';
61+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import 'package:flutter/foundation.dart';
2+
import 'package:flutter/widgets.dart';
3+
import 'package:flutter_hooks/src/framework.dart';
4+
import 'package:flutter_hooks/src/hooks.dart';
5+
6+
import 'mock.dart';
7+
8+
void main() {
9+
testWidgets('debugFillProperties', (tester) async {
10+
await tester.pumpWidget(
11+
HookBuilder(builder: (context) {
12+
useSnapshotController();
13+
return const SizedBox();
14+
}),
15+
);
16+
17+
await tester.pump();
18+
19+
final element = tester.element(find.byType(HookBuilder));
20+
21+
expect(
22+
element
23+
.toDiagnosticsNode(style: DiagnosticsTreeStyle.offstage)
24+
.toStringDeep(),
25+
equalsIgnoringHashCodes(
26+
'HookBuilder\n'
27+
" │ useSnapshotController: Instance of 'SnapshotController'\n"
28+
' └SizedBox(renderObject: RenderConstrainedBox#00000)\n',
29+
),
30+
);
31+
});
32+
33+
group('useSnapshotController', () {
34+
testWidgets('initial values matches with real constructor', (tester) async {
35+
late SnapshotController controller;
36+
late SnapshotController controller2;
37+
38+
await tester.pumpWidget(
39+
HookBuilder(builder: (context) {
40+
controller2 = SnapshotController();
41+
controller = useSnapshotController();
42+
return Container();
43+
}),
44+
);
45+
46+
expect(controller.allowSnapshotting, controller2.allowSnapshotting);
47+
});
48+
49+
testWidgets('passes hook parameters to the SnapshotController',
50+
(tester) async {
51+
late SnapshotController controller;
52+
53+
await tester.pumpWidget(
54+
HookBuilder(builder: (context) {
55+
controller = useSnapshotController(allowSnapshotting: true);
56+
return const SizedBox();
57+
}),
58+
);
59+
60+
expect(controller.allowSnapshotting, true);
61+
62+
late SnapshotController retrievedController;
63+
await tester.pumpWidget(
64+
HookBuilder(builder: (context) {
65+
// ignore: avoid_redundant_argument_values
66+
retrievedController = useSnapshotController(allowSnapshotting: false);
67+
return const SizedBox();
68+
}),
69+
);
70+
71+
expect(retrievedController, same(controller));
72+
expect(retrievedController.allowSnapshotting, false);
73+
});
74+
});
75+
}

0 commit comments

Comments
 (0)