Skip to content
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

add param to keep showing from widget after flight #7

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 29 additions & 21 deletions lib/src/widgets/sidekick.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class Sidekick extends StatefulWidget {
this.flightShuttleBuilder,
this.placeholderBuilder,
SidekickAnimationBuilder animationBuilder,
this.keepShowingWidget,
@required this.child,
}) : assert(tag != null),
assert(child != null),
Expand Down Expand Up @@ -137,6 +138,9 @@ class Sidekick extends StatefulWidget {
/// Optional override to specified the animation used while flying.
final SidekickAnimationBuilder animationBuilder;

/// Keep showing the source "from" widget after it has flown
final bool keepShowingWidget;

// Returns a map of all of the sidekicks in context, indexed by sidekick tag.
static Map<Object, _SidekickState> _allSidekicksFor(BuildContext context) {
assert(context != null);
Expand Down Expand Up @@ -221,16 +225,17 @@ class _SidekickState extends State<Sidekick> with TickerProviderStateMixin {

/// Everything known about a sidekick flight that's to be started or diverted.
class _SidekickFlightManifest {
_SidekickFlightManifest({
@required this.type,
@required this.overlay,
@required this.rect,
@required this.fromSidekick,
@required this.toSidekick,
@required this.createRectTween,
@required this.shuttleBuilder,
@required this.animationController,
}) : assert((type == SidekickFlightDirection.toTarget &&
_SidekickFlightManifest(
{@required this.type,
@required this.overlay,
@required this.rect,
@required this.fromSidekick,
@required this.toSidekick,
@required this.createRectTween,
@required this.shuttleBuilder,
@required this.animationController,
@required this.keepShowingFromWidget})
: assert((type == SidekickFlightDirection.toTarget &&
fromSidekick.widget.targetTag == toSidekick.widget.tag) ||
(type == SidekickFlightDirection.toSource &&
toSidekick.widget.targetTag == fromSidekick.widget.tag));
Expand All @@ -243,6 +248,7 @@ class _SidekickFlightManifest {
final CreateRectTween createRectTween;
final SidekickFlightShuttleBuilder shuttleBuilder;
final Animation<double> animationController;
final bool keepShowingFromWidget;

Object get tag => fromSidekick.widget.tag;

Expand Down Expand Up @@ -357,6 +363,7 @@ class _SidekickFlight {
overlayEntry.remove();
overlayEntry = null;

manifest.keepShowingFromWidget ? manifest.fromSidekick.endFlight() : null;
manifest.toSidekick.endFlight();
onFlightEnded(this);
}
Expand Down Expand Up @@ -612,19 +619,20 @@ class SidekickController extends Animation<double> {
fromSidekick.flightShuttleBuilder;
final SidekickFlightShuttleBuilder toShuttleBuilder =
toSidekick.flightShuttleBuilder;
final bool keepShowingFromWidget = fromSidekick?.keepShowingWidget;

final _SidekickFlightManifest manifest = _SidekickFlightManifest(
type: flightType,
overlay: Overlay.of(context),
rect: rect,
fromSidekick: sidekicks[tag],
toSidekick: sidekicks[targetTag],
createRectTween: createRectTween,
shuttleBuilder: toShuttleBuilder ??
fromShuttleBuilder ??
_defaultSidekickFlightShuttleBuilder,
animationController: _controller.view,
);
type: flightType,
overlay: Overlay.of(context),
rect: rect,
fromSidekick: sidekicks[tag],
toSidekick: sidekicks[targetTag],
createRectTween: createRectTween,
shuttleBuilder: toShuttleBuilder ??
fromShuttleBuilder ??
_defaultSidekickFlightShuttleBuilder,
animationController: _controller.view,
keepShowingFromWidget: keepShowingFromWidget ?? false);

if (_flights[tag] != null) {
_flights[tag].divert(manifest);
Expand Down
36 changes: 36 additions & 0 deletions test/flutter_sidekick_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ class SimpleExample extends StatefulWidget {
SimpleExample([
this.sourceTag = 'source',
this.targetTag = 'target',
this.keepShowingSource = false,
]);
final String sourceTag;
final String targetTag;
final bool keepShowingSource;

@override
_SimpleExampleState createState() => _SimpleExampleState();
Expand Down Expand Up @@ -51,6 +53,7 @@ class _SimpleExampleState extends State<SimpleExample>
child: Sidekick(
tag: widget.sourceTag,
targetTag: widget.targetTag,
keepShowingWidget: widget.keepShowingSource,
child: Container(
key: simpleSource,
color: Colors.blue,
Expand Down Expand Up @@ -249,6 +252,39 @@ void main() {
expect(find.byKey(simpleTarget), isInCard);
});

testWidgets('Animate to target with keepShowing source',
(WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(home: SimpleExample('source', 'target', true)));

// the initial setup.
expect(find.byKey(simpleSource), isInCard);
expect(find.byKey(simpleTarget), isInCard);

await tester.tap(find.byKey(simpleSource));
await tester.pump(); // the animation will start at the next frame.
await tester.pump(frameDuration);

// at this stage, the sidekick just gone on its journey, we are
// seeing them at t=16ms.

expect(find.byKey(simpleSource), findsNothing);
expect(find.byKey(simpleTarget), isNotInCard);

await tester.pump(frameDuration);

// t=32ms for the journey. Surely they are still at it.
expect(find.byKey(simpleSource), findsNothing);
expect(find.byKey(simpleTarget), isNotInCard);

await tester.pump(const Duration(seconds: 1));

// t=1.033s for the journey. The journey has ended (it ends this frame, in
// fact). The sidekicks should be back now.
expect(find.byKey(simpleSource), isInCard);
expect(find.byKey(simpleTarget), isInCard);
});

testWidgets('Animate to source', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(home: SimpleExample()));

Expand Down