fix(studyset): the parts' switch centred above the material, a section's buttons at its edge

From expanded windows on, the switch between Material, Progress and Study
plan stands centred above the column it switches, rather than at the end
of the path's line; where that column is narrower than the switch, it
ends the line as before. The path takes what is left of the line and
folds before it.

A section's title was Flexible beside a Spacer, which share the free room
between them, so Browse, Reorder and Show all ended halfway across a wide
section. The title now takes what the buttons leave. The study plan's
paths and Explore's licence row had the same row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-12 15:55:56 +02:00
commit 51ddd5a5e6
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -12,9 +12,11 @@ import 'package:halkyon_learn_flutter/src/core/theme/palette_color.dart';
import 'package:halkyon_learn_flutter/src/core/widget/adaptive_sheet.dart';
import 'package:halkyon_learn_flutter/src/core/widget/empty_list_message.dart';
import 'package:halkyon_learn_flutter/src/core/widget/palette_color_picker.dart';
import 'package:halkyon_learn_flutter/src/core/widget/section_card.dart';
import 'package:halkyon_learn_flutter/src/core/widget/top_gradient.dart';
import 'package:halkyon_learn_flutter/src/feature/card/data/card_repository.dart';
import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
import 'package:halkyon_learn_flutter/src/feature/card/widget/card_list.dart';
import 'package:halkyon_learn_flutter/src/feature/learning_path/data/learning_path_repository.dart';
import 'package:halkyon_learn_flutter/src/feature/learning_path/model/exercise.dart';
import 'package:halkyon_learn_flutter/src/feature/learning_path/model/learning_path.dart';
@ -141,8 +143,12 @@ void main() {
/// Opens the studyset titled [title] from the library, so its screen has
/// the library below it.
Future<void> openFromLibrary(WidgetTester tester, String title) async {
await showApp(tester);
Future<void> openFromLibrary(
WidgetTester tester,
String title, {
double width = 1200,
}) async {
await showApp(tester, width: width);
await tester.tap(find.text(title));
await tester.pumpAndSettle();
}
@ -1390,8 +1396,8 @@ void main() {
expect(targetOf('…'), const Size.square(StudysetBreadcrumb.minTarget));
// Wide enough for the whole path.
await openFromLibrary(tester, 'Japanese');
// Wide enough for the whole path beside the parts' switch.
await openFromLibrary(tester, 'Japanese', width: 1600);
expect(targetOf('Library').height, StudysetBreadcrumb.minTarget);
});
@ -1600,9 +1606,8 @@ void main() {
];
testWidgets('the parts are switched in the header: on a phone under the '
"title, above the path; on a desktop at the end of the path's line", (
tester,
) async {
"title, above the path; on a desktop in the path's line, centred above "
'the material, where it fits', (tester) async {
stored('japanese', 'Japanese');
await showApp(
tester,
@ -1626,7 +1631,62 @@ void main() {
);
// The path's line stays as high as its steps.
expect(pathRect().height, StudysetBreadcrumb.minTarget);
Rect materialRect() => tester.getRect(
find
.ancestor(
of: find.byType(MaterialPart),
matching: find.byType(SectionCard),
)
.first,
);
expect(
switchRect().center.dx,
moreOrLessEquals(materialRect().center.dx, epsilon: 1),
);
// Where the material is narrower than the switch, all three parts
// once a card was studied, it ends the line.
final id = await card('japanese', '猫');
await PersonScope.of(
tester.element(find.byType(StudysetScreen)),
).reviews.record(
cardId: id,
rating: Rating.good,
reviewedAt: clock.now(),
duration: const Duration(minutes: 2),
);
await showApp(
tester,
location: RoutePaths.studyset('japanese'),
width: 860,
);
await tester.pumpAndSettle();
expect(parts(tester), hasLength(3));
expect(materialRect().width, lessThan(switchRect().width));
expect(switchRect().right, greaterThan(pathRect().right - 16));
expect(switchRect().right, lessThanOrEqualTo(pathRect().right));
});
testWidgets("a section's buttons end at the material's edge, however "
'short its title', (tester) async {
stored('japanese', 'Japanese');
await card('japanese', '猫');
await showApp(tester, location: RoutePaths.studyset('japanese'));
await tester.pumpAndSettle();
final material = tester.getRect(
find
.ancestor(
of: find.byType(MaterialPart),
matching: find.byType(SectionCard),
)
.first,
);
// Browse, then the filter and the menu, the last at the edge.
expect(
tester.getRect(find.byType(CardListToolbar)).right,
greaterThan(material.right - 16),
);
});
testWidgets('Progress shows once a card in the studyset was studied: how '