feat(app): the topics' foot the same with or without topics
Without sub-studysets, the side bar and the drawer showed New sub-studyset in the invitation at the top and the bibliography alone at the foot. Now New sub-studyset always sits at the foot's start, across from the bibliography, once the topics are read (not while reordering); the invitation keeps its words, without a button of its own (decided 2026-10-08). 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:
parent
fc2f55046b
commit
b4fe6814ef
2 changed files with 32 additions and 19 deletions
|
|
@ -23,7 +23,9 @@ import 'package:material_ui/material_ui.dart';
|
||||||
/// topics are rearranged. Below, the topics in their order, each opening its
|
/// topics are rearranged. Below, the topics in their order, each opening its
|
||||||
/// own screen on top of this one, with the study it invites and its options;
|
/// own screen on top of this one, with the study it invites and its options;
|
||||||
/// a switch rearranges them by dragging. New sub-studyset stays at the foot,
|
/// a switch rearranges them by dragging. New sub-studyset stays at the foot,
|
||||||
/// across from [footEnd]. Without topics, an invitation to create the first.
|
/// across from [footEnd], with or without topics, so the foot looks the same
|
||||||
|
/// in every studyset (decided 2026-10-08). Without topics, a word on what
|
||||||
|
/// they are for in their place.
|
||||||
class const StudysetRail({
|
class const StudysetRail({
|
||||||
/// The studyset whose topics these are.
|
/// The studyset whose topics these are.
|
||||||
required final Studyset parent,
|
required final Studyset parent,
|
||||||
|
|
@ -113,10 +115,7 @@ class _StudysetRailState() extends State<StudysetRail> {
|
||||||
_ => const <String, StudyProgress>{},
|
_ => const <String, StudyProgress>{},
|
||||||
};
|
};
|
||||||
final addMaterial = widget.onAddMaterial;
|
final addMaterial = widget.onAddMaterial;
|
||||||
final newSubStudyset =
|
final newSubStudyset = state is StudysetListStateLoaded && !_reordering;
|
||||||
state is StudysetListStateLoaded &&
|
|
||||||
topics.isNotEmpty &&
|
|
||||||
!_reordering;
|
|
||||||
final footEnd = widget.footEnd;
|
final footEnd = widget.footEnd;
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
|
@ -174,9 +173,7 @@ class _StudysetRailState() extends State<StudysetRail> {
|
||||||
StudysetListStateFailed() => Center(
|
StudysetListStateFailed() => Center(
|
||||||
child: Text(l10n.libraryUnreadable),
|
child: Text(l10n.libraryUnreadable),
|
||||||
),
|
),
|
||||||
StudysetListStateLoaded(studysets: []) => _NoTopics(
|
StudysetListStateLoaded(studysets: []) => const _NoTopics(),
|
||||||
onCreate: _create,
|
|
||||||
),
|
|
||||||
StudysetListStateLoaded() when _reordering => Scrollbar(
|
StudysetListStateLoaded() when _reordering => Scrollbar(
|
||||||
controller: _scroll,
|
controller: _scroll,
|
||||||
thumbVisibility: true,
|
thumbVisibility: true,
|
||||||
|
|
@ -248,8 +245,8 @@ class _StudysetRailState() extends State<StudysetRail> {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// At the foot, below a line, however long the list: New
|
// At the foot, below a line, however long the list: New
|
||||||
// sub-studyset while topics are listed (without, the invitation
|
// sub-studyset once the topics are read, and what the rail is
|
||||||
// in their place has it), and what the rail is given to end on.
|
// given to end on.
|
||||||
if (newSubStudyset || footEnd != null)
|
if (newSubStudyset || footEnd != null)
|
||||||
DecoratedBox(
|
DecoratedBox(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|
@ -582,9 +579,9 @@ class const StudyActionIcon({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// No topics yet: an invitation to create the first.
|
/// No topics yet, and what they are for; New sub-studyset at the foot
|
||||||
class const _NoTopics({required final VoidCallback onCreate})
|
/// creates the first.
|
||||||
extends StatelessWidget {
|
class const _NoTopics() extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final l10n = AppLocalizations.of(context);
|
final l10n = AppLocalizations.of(context);
|
||||||
|
|
@ -606,12 +603,6 @@ class const _NoTopics({required final VoidCallback onCreate})
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
|
||||||
FilledButton.tonalIcon(
|
|
||||||
onPressed: onCreate,
|
|
||||||
icon: const Icon(LucideIcons.plus),
|
|
||||||
label: Text(l10n.studysetNewSubStudyset),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -442,6 +442,28 @@ void main() {
|
||||||
expect(bibliography.right, moreOrLessEquals(rail.right - 16));
|
expect(bibliography.right, moreOrLessEquals(rail.right - 16));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('without topics, the foot is the same: one New sub-studyset '
|
||||||
|
'at its start, the bibliography at its end', (tester) async {
|
||||||
|
stored('japanese', 'Japanese');
|
||||||
|
await showApp(tester, location: RoutePaths.studyset('japanese'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(find.text('No sub-studysets yet.'), findsOneWidget);
|
||||||
|
|
||||||
|
expect(find.text('New sub-studyset'), findsOneWidget);
|
||||||
|
final create = tester.getRect(
|
||||||
|
find.ancestor(
|
||||||
|
of: find.text('New sub-studyset'),
|
||||||
|
matching: find.byWidgetPredicate((widget) => widget is FilledButton),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final bibliography = tester.getRect(find.byTooltip('Bibliography'));
|
||||||
|
expect(bibliography.center.dy, moreOrLessEquals(create.center.dy));
|
||||||
|
expect(
|
||||||
|
create.top,
|
||||||
|
greaterThan(tester.getRect(find.text('No sub-studysets yet.')).bottom),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('on a phone, the bibliography shares the foot of the topics '
|
testWidgets('on a phone, the bibliography shares the foot of the topics '
|
||||||
'with New sub-studyset: that at the start, the bibliography at the '
|
'with New sub-studyset: that at the start, the bibliography at the '
|
||||||
'end', (tester) async {
|
'end', (tester) async {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue