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

MD: fix page controller updates #468

Merged
merged 1 commit into from
Jan 7, 2023
Merged
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
1 change: 1 addition & 0 deletions lib/src/layouts/yaru_landscape_layout.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class _YaruLandscapeLayoutState extends State<YaruLandscapeLayout> {
if (widget.controller != oldWidget.controller) {
oldWidget.controller.removeListener(_controllerCallback);
widget.controller.addListener(_controllerCallback);
_selectedIndex = max(widget.controller.index, 0);
}
}

Expand Down
12 changes: 7 additions & 5 deletions lib/src/layouts/yaru_master_detail_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,14 @@ class YaruMasterDetailPage extends StatefulWidget {

class _YaruMasterDetailPageState extends State<YaruMasterDetailPage> {
double? _previousPaneWidth;
late final YaruPageController _controller;
late YaruPageController _controller;

void _updateController() => _controller = widget.controller ??
YaruPageController(
length: _length,
length: widget.length ?? widget.controller!.length,
initialIndex: widget.initialIndex ?? -1,
);

int get _length => widget.length ?? widget.controller!.length;

@override
void initState() {
super.initState();
Expand All @@ -128,7 +126,11 @@ class _YaruMasterDetailPageState extends State<YaruMasterDetailPage> {
@override
void didUpdateWidget(covariant YaruMasterDetailPage oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.controller != oldWidget.controller) _updateController();
if (widget.controller != oldWidget.controller ||
widget.length != oldWidget.length ||
widget.initialIndex != oldWidget.initialIndex) {
_updateController();
}
}

@override
Expand Down
1 change: 1 addition & 0 deletions lib/src/layouts/yaru_portrait_layout.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class _YaruPortraitLayoutState extends State<YaruPortraitLayout> {
if (widget.controller != oldWidget.controller) {
oldWidget.controller.removeListener(_controllerCallback);
widget.controller.addListener(_controllerCallback);
_selectedIndex = widget.controller.index;
}
}

Expand Down
103 changes: 70 additions & 33 deletions test/pages/yaru_master_detail_page_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void main() {
),
),
themeMode: variant.themeMode,
size: Size(variant.value!, 480),
size: Size(variant.value!.width, 480),
);
await tester.pumpAndSettle();

Expand All @@ -48,47 +48,84 @@ void main() {
testWidgets(
'controller',
(tester) async {
final variant = goldenVariant.currentValue!;
final variant = orientationVariant.currentValue!;
final controller = YaruPageController(length: 8);
await tester.pumpScaffold(
YaruMasterDetailPage(
controller: controller,
layoutDelegate: const YaruMasterFixedPaneDelegate(
paneWidth: kYaruMasterDetailBreakpoint / 3,
),
appBar: AppBar(title: const Text('Master')),
tileBuilder: (context, index, selected) => YaruMasterTile(
leading: const Icon(YaruIcons.menu),
title: Text('Tile $index'),
),
pageBuilder: (context, index) => YaruDetailPage(
appBar: AppBar(
title: Text('Detail title $index'),

Future<void> buildMasterDetailPage({
int? length,
int? initialIndex,
YaruPageController? controller,
}) {
return tester.pumpScaffold(
YaruMasterDetailPage(
length: length,
initialIndex: initialIndex,
controller: controller,
layoutDelegate: const YaruMasterFixedPaneDelegate(
paneWidth: kYaruMasterDetailBreakpoint / 3,
),
appBar: AppBar(title: const Text('Master')),
tileBuilder: (context, index, selected) => YaruMasterTile(
leading: const Icon(YaruIcons.menu),
title: Text('Tile $index'),
),
pageBuilder: (context, index) => YaruDetailPage(
appBar: AppBar(
title: Text('Detail title $index'),
),
body: Center(child: Text('Detail body $index')),
),
body: Center(child: Text('Detail body $index')),
),
),
themeMode: variant.themeMode,
size: Size(variant.value!, 480),
);
size: Size(variant.width, 480),
);
}

controller.index = 3;
void expectDetailPage(int index) {
for (var i = 0; i < 8; i++) {
final matcher = i == index ? findsOneWidget : findsNothing;
expect(find.text('Detail title $i'), matcher);
expect(find.text('Detail body $i'), matcher);
}
}

await buildMasterDetailPage(controller: controller);
await tester.pumpAndSettle();
if (variant.label.startsWith('portrait')) {
expect(find.text('Master'), findsNothing);
expect(find.text('Tile 3'), findsNothing);
} else if (variant.label.startsWith('landscape')) {
expect(find.text('Master'), findsOneWidget);
expect(find.text('Tile 3'), findsOneWidget);
if (variant == Orientation.portrait) {
expectDetailPage(-1);
} else {
expectDetailPage(0);
}
expect(find.text('Detail title 3'), findsOneWidget);
expect(find.text('Detail body 3'), findsOneWidget);

controller.index = 0;
await tester.pumpAndSettle();
expectDetailPage(0);

controller.index = 5;
await tester.pumpAndSettle();
expectDetailPage(5);

await buildMasterDetailPage(length: 3, initialIndex: 1);
await tester.pumpAndSettle();
expectDetailPage(1);
},
variant: goldenVariant,
variant: orientationVariant,
);
}

final goldenVariant = ValueVariant({
...goldenThemeVariants('portrait', kYaruMasterDetailBreakpoint / 2),
...goldenThemeVariants('landscape', kYaruMasterDetailBreakpoint),
...goldenThemeVariants('portrait', Orientation.portrait),
...goldenThemeVariants('landscape', Orientation.landscape),
});

final orientationVariant = ValueVariant(Orientation.values.toSet());

extension OrientationX on Orientation {
double get width {
switch (this) {
case Orientation.portrait:
return kYaruMasterDetailBreakpoint / 2;
case Orientation.landscape:
return kYaruMasterDetailBreakpoint;
}
}
}