Skip to content

Add Hook for managing SnapshotController instances #464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/flutter_hooks/lib/src/hooks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ part 'transformation_controller.dart';
part 'tree_sliver_controller.dart';
part 'widget_states_controller.dart';
part 'widgets_binding_observer.dart';
part 'snapshot_controller.dart';
62 changes: 62 additions & 0 deletions packages/flutter_hooks/lib/src/snapshot_controller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
part of 'hooks.dart';

/// Creates and disposes a [SnapshotController].
///
/// Note that [allowSnapshotting] must be set to `true`
/// in order for this controller to actually do anything.
/// This is consistent with [SnapshotController.new].
///
/// If [allowSnapshotting] changes on subsequent calls to [useSnapshotController],
/// [SnapshotController.allowSnapshotting] will be called to update accordingly.
///
/// ```dart
/// final controller = useSnapshotController(allowSnapshotting: true);
/// // is equivalent to
/// final controller = useSnapshotController();
/// controller.allowSnapshotting = true;
/// ```
///
/// See also:
/// - [SnapshotController]
SnapshotController useSnapshotController({
bool allowSnapshotting = false,
}) {
return use(
_SnapshotControllerHook(
allowSnapshotting: allowSnapshotting,
),
);
}

class _SnapshotControllerHook extends Hook<SnapshotController> {
const _SnapshotControllerHook({
required this.allowSnapshotting,
});

final bool allowSnapshotting;

@override
HookState<SnapshotController, Hook<SnapshotController>> createState() =>
_SnapshotControllerHookState();
}

class _SnapshotControllerHookState
extends HookState<SnapshotController, _SnapshotControllerHook> {
late final controller =
SnapshotController(allowSnapshotting: hook.allowSnapshotting);

@override
void didUpdateHook(_SnapshotControllerHook oldHook) {
super.didUpdateHook(oldHook);
controller.allowSnapshotting = hook.allowSnapshotting;
}

@override
SnapshotController build(BuildContext context) => controller;

@override
void dispose() => controller.dispose();

@override
String get debugLabel => 'useSnapshotController';
}
75 changes: 75 additions & 0 deletions packages/flutter_hooks/test/use_snapshot_controller_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.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) {
useSnapshotController();
return const SizedBox();
}),
);

await tester.pump();

final element = tester.element(find.byType(HookBuilder));

expect(
element
.toDiagnosticsNode(style: DiagnosticsTreeStyle.offstage)
.toStringDeep(),
equalsIgnoringHashCodes(
'HookBuilder\n'
" │ useSnapshotController: Instance of 'SnapshotController'\n"
' └SizedBox(renderObject: RenderConstrainedBox#00000)\n',
),
);
});

group('useSnapshotController', () {
testWidgets('initial values matches with real constructor', (tester) async {
late SnapshotController controller;
late SnapshotController controller2;

await tester.pumpWidget(
HookBuilder(builder: (context) {
controller2 = SnapshotController();
controller = useSnapshotController();
return Container();
}),
);

expect(controller.allowSnapshotting, controller2.allowSnapshotting);
});

testWidgets('passes hook parameters to the SnapshotController',
(tester) async {
late SnapshotController controller;

await tester.pumpWidget(
HookBuilder(builder: (context) {
controller = useSnapshotController(allowSnapshotting: true);
return const SizedBox();
}),
);

expect(controller.allowSnapshotting, true);

late SnapshotController retrievedController;
await tester.pumpWidget(
HookBuilder(builder: (context) {
// ignore: avoid_redundant_argument_values
retrievedController = useSnapshotController(allowSnapshotting: false);
return const SizedBox();
}),
);

expect(retrievedController, same(controller));
expect(retrievedController.allowSnapshotting, false);
});
});
}
Loading