fix(learn): a tab whose material is in its topics says so in the middle, as an empty tab does

The tab saying that its material is in the studyset's topics stood at the
top of the room below the tabs, while an empty tab's message stands in
its middle (SliverCentered), so switching between them moved the message
up and down (the developer's review, 9 Nov 2026). It stands in the middle
too now.

Whats-New: A studyset's tab whose material is in its topics now says so in the middle, as empty tabs do.
Whats-New-De: Ein Tab eines Lernsets, dessen Material in seinen Themen liegt, sagt das jetzt in der Mitte, wie leere Tabs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-09 23:25:34 +01:00
commit f47f6b23b5
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -645,6 +645,8 @@ class const _SliverSectionLoading() extends StatelessWidget {
/// tabs): that it is in them, each topic holding some with how much,
/// everything inside it counted, opening it; with [onBrowse] (flashcards)
/// all of them in one list; and, quieter, how to add some here after all.
/// In the middle of the room left, as an empty tab says it (the
/// developer's review, 9 Nov 2026).
class const _SliverInTopics({
required final String parentId,
required final List<({Studyset topic, int count})> topics,
@ -665,69 +667,67 @@ class const _SliverInTopics({
}
}
return SliverToBoxAdapter(
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 480),
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 24, 16, 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Icon(icon, size: 40, color: muted),
const SizedBox(height: 12),
Text(
title,
textAlign: TextAlign.center,
style: theme.textTheme.titleMedium,
),
const SizedBox(height: 16),
for (final (index, (:topic, :count)) in topics.indexed) ...[
if (index > 0) const Divider(height: 1),
ListTile(
title: Text(
topic.content.title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'$count',
style: theme.textTheme.bodyMedium?.copyWith(
color: muted,
),
),
const SizedBox(width: 8),
Icon(LucideIcons.chevronRight, size: 18, color: muted),
],
),
onTap: () => unawaited(open(topic)),
return SliverCentered(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 480),
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 24, 16, 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Icon(icon, size: 40, color: muted),
const SizedBox(height: 12),
Text(
title,
textAlign: TextAlign.center,
style: theme.textTheme.titleMedium,
),
const SizedBox(height: 16),
for (final (index, (:topic, :count)) in topics.indexed) ...[
if (index > 0) const Divider(height: 1),
ListTile(
title: Text(
topic.content.title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
if (onBrowse case final browse?) ...[
const SizedBox(height: 16),
Center(
child: FilledButton.tonalIcon(
onPressed: browse,
icon: const Icon(LucideIcons.layoutGrid, size: 18),
label: Text(
l10n.studysetBrowseAllFlashcards(
topics.fold(0, (sum, held) => sum + held.count),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'$count',
style: theme.textTheme.bodyMedium?.copyWith(
color: muted,
),
),
const SizedBox(width: 8),
Icon(LucideIcons.chevronRight, size: 18, color: muted),
],
),
onTap: () => unawaited(open(topic)),
),
],
if (onBrowse case final browse?) ...[
const SizedBox(height: 16),
Center(
child: FilledButton.tonalIcon(
onPressed: browse,
icon: const Icon(LucideIcons.layoutGrid, size: 18),
label: Text(
l10n.studysetBrowseAllFlashcards(
topics.fold(0, (sum, held) => sum + held.count),
),
),
),
],
const SizedBox(height: 16),
Text(
hint,
textAlign: TextAlign.center,
style: theme.textTheme.bodySmall?.copyWith(color: muted),
),
],
),
const SizedBox(height: 16),
Text(
hint,
textAlign: TextAlign.center,
style: theme.textTheme.bodySmall?.copyWith(color: muted),
),
],
),
),
),