Skip to content

Commit

Permalink
fix resize (#25)
Browse files Browse the repository at this point in the history
* fix: only reizing needed axis

* feat: only retry resizing in a limit count

* fix: calculate initiala extendedSize

* fix: find scrollable instead of scrollView

* feat: update error message

* fix: also check resize too large

* fix: try catch controller position
  • Loading branch information
lcdsmao authored Oct 15, 2021
1 parent 1b73144 commit a99060d
Showing 1 changed file with 85 additions and 22 deletions.
107 changes: 85 additions & 22 deletions playbook_snapshot/lib/src/snapshot_support.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import 'package:playbook/playbook.dart';
import 'snapshot_device.dart';

class SnapshotSupport {
static const _maxTryResizeCount = 10;
static const _maxSnapshotSize = 50000;

static Future<void> startDevice(
Widget target,
WidgetTester tester,
Expand Down Expand Up @@ -38,25 +41,43 @@ class SnapshotSupport {
// We use scrollController.maxScrollExtent to calculate the snapshot size.
// However, maxScrollExtent may report incorrectly.
// To solve this, we repeatedly calculate size and update size until we can get a stable value.
var lastExtendedSize = device.size;
var lastExtendedSize = Size(
scenario.layout.compressedResizingTarget.needResizingWidth
? device.size.width
: absoluteSize.width,
scenario.layout.compressedResizingTarget.needResizingHeight
? device.size.height
: absoluteSize.height,
);
var resize = 0;
while (true) {
final scrollViews = find
.byWidgetPredicate((widget) => widget is ScrollView)
final scrollables = find
.byWidgetPredicate((widget) => widget is Scrollable)
.evaluate()
.map((e) => e.widget as ScrollView);
if (scrollViews.isEmpty) break;
.map((e) => e.widget as Scrollable);
if (scrollables.isEmpty) break;

var extendedSize = device.size;
for (final scrollView in scrollViews) {
for (final scrollable in scrollables) {
extendedSize = _extendScrollableSnapshotSize(
scrollView: scrollView,
extendedSize: extendedSize,
scrollable: scrollable,
currentExtendedSize: extendedSize,
originSize: lastExtendedSize,
resizingTarget: scenario.layout.compressedResizingTarget,
);
}
if (extendedSize <= lastExtendedSize) break;
lastExtendedSize = extendedSize;
await _setSnapshotSize(tester, lastExtendedSize);
resize++;
if (resize >= _maxTryResizeCount) {
throw StateError(
'Try resizing too many times. Please try to set your scenario to have a fixed size.');
}
if (extendedSize.width >= _maxSnapshotSize || extendedSize.height >= _maxSnapshotSize) {
throw StateError(
'Try resizing too large size ${extendedSize}. Please try to set your scenario to have a fixed size.');
}
}
snapshotSize = lastExtendedSize;
} else {
Expand Down Expand Up @@ -86,31 +107,47 @@ class SnapshotSupport {
}

static Size _extendScrollableSnapshotSize({
required ScrollView scrollView,
required Size extendedSize,
required Scrollable scrollable,
required Size currentExtendedSize,
required Size originSize,
required _CompressedResizingTarget resizingTarget,
}) {
final controller = scrollView.controller;
if (controller == null) {
final controller = scrollable.controller;
ScrollPosition? position;
try {
position = controller?.position;
} catch (_) {}
if (position == null) {
return Size(
max(extendedSize.width, originSize.width),
max(extendedSize.height, originSize.height),
resizingTarget.needResizingWidth
? max(currentExtendedSize.width, originSize.width)
: originSize.width,
resizingTarget.needResizingHeight
? max(currentExtendedSize.height, originSize.height)
: originSize.height,
);
}

final scrollAxis = controller.position.axis;
final maxScrollExtent = controller.position.maxScrollExtent;
final scrollAxis = position.axis;
final maxScrollExtent = position.maxScrollExtent;

final Size newExtendedSize;
switch (scrollAxis) {
case Axis.horizontal:
final height = max(originSize.height, extendedSize.height);
final width = max(maxScrollExtent + originSize.width, extendedSize.width);
return Size(width, height);
final height = max(originSize.height, currentExtendedSize.height);
final width = max(maxScrollExtent + originSize.width, currentExtendedSize.width);
newExtendedSize = Size(width, height);
break;
case Axis.vertical:
final height = max(maxScrollExtent + originSize.height, extendedSize.height);
final width = max(originSize.width, extendedSize.width);
return Size(width, height);
final height = max(maxScrollExtent + originSize.height, currentExtendedSize.height);
final width = max(originSize.width, currentExtendedSize.width);
newExtendedSize = Size(width, height);
break;
}
return Size(
resizingTarget.needResizingWidth ? newExtendedSize.width : originSize.width,
resizingTarget.needResizingHeight ? newExtendedSize.height : originSize.height,
);
}
}

Expand All @@ -123,6 +160,18 @@ extension on ScenarioLayout {
return v is ScenarioLayoutCompressed || h is ScenarioLayoutCompressed;
}

_CompressedResizingTarget get compressedResizingTarget {
if (v is ScenarioLayoutCompressed && h is ScenarioLayoutCompressed) {
return _CompressedResizingTarget.both;
} else if (v is ScenarioLayoutCompressed) {
return _CompressedResizingTarget.vertical;
} else if (h is ScenarioLayoutCompressed) {
return _CompressedResizingTarget.horizontal;
} else {
throw StateError('No need compressed resizing.');
}
}

double absoluteWidth(SnapshotDevice device) {
switch (h.runtimeType) {
case ScenarioLayoutFixed:
Expand All @@ -147,3 +196,17 @@ extension on ScenarioLayout {
return device.size.height;
}
}

enum _CompressedResizingTarget {
horizontal,
vertical,
both,
}

extension on _CompressedResizingTarget {
bool get needResizingWidth =>
this == _CompressedResizingTarget.both || this == _CompressedResizingTarget.horizontal;

bool get needResizingHeight =>
this == _CompressedResizingTarget.both || this == _CompressedResizingTarget.vertical;
}

0 comments on commit a99060d

Please sign in to comment.