feat(learn,app): explanations wait behind a question mark beside their title

What explains a setting or a section, rather than what is the person's
own, moves behind halkyon_ui's HelpButton, beside its title through the
new ExplainedTitle (the developer's review of 3 Nov 2026): in Learn's
settings (citations, the Pomodoro timer, grammar, the web search,
Jellyfin, the device's dictionaries, counting one's learning), the study
settings, export's progress, the Jellyfin tags and the study button's
back first; in halkyon_app, setting up a password, adding SimpleLogin,
own keys not allowed, the profile page's link back and the operator's
grant sheet.

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-03 22:24:39 +01:00
commit 830aea10fe
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
2 changed files with 279 additions and 115 deletions

View file

@ -419,6 +419,14 @@ void main() {
expect(copied, 'https://halkyon.eu/@raisondetredev');
expect(find.text('Address copied.'), findsOneWidget);
// What linking back does, behind its question mark (decided 3 Nov
// 2026).
final checkmark = find.textContaining('gets a checkmark');
expect(checkmark, findsNothing);
await tester.tap(find.byTooltip("What's this?").last);
await tester.pumpAndSettle();
expect(checkmark, findsOneWidget);
});
testWidgets('a link saved is checked by itself, and gets a checkmark once '

View file

@ -206,6 +206,38 @@ void main() {
expect(brightnessAt(tester, find.text('Appearance')), Brightness.light);
});
testWidgets("every setting's explanation waits behind the question mark "
"beside its title, its values in view (the developer's review of 3 Nov "
'2026)', (tester) async {
await pumpApp(tester, testDependencies(), location: RoutePaths.settings);
for (final (title, explanation) in [
('Citations', 'How sources and studysets'),
('Show the Pomodoro timer while studying', 'Show the focus / break'),
('Check grammar while writing', 'Underline possible spelling'),
('Search the web from the app', 'Off unless you turn it on.'),
('Jellyfin', 'Watch shows and films'),
('Count my learning in Explore', 'Explore shows how many people'),
]) {
final titled = find.widgetWithText(ExplainedTitle, title);
await tester.scrollUntilVisible(
titled,
200,
scrollable: find.byType(Scrollable).first,
);
await tester.pumpAndSettle();
expect(find.textContaining(explanation), findsNothing, reason: title);
await tester.tap(
find.descendant(of: titled, matching: find.byType(HelpButton)),
);
await tester.pumpAndSettle();
expect(find.textContaining(explanation), findsOneWidget, reason: title);
await tester.tap(find.text('OK'));
await tester.pumpAndSettle();
}
expect(find.text('APA (7th edition)'), findsOneWidget, reason: 'a value');
});
testWidgets('the citation style chosen shows on a sample at once and is '
'kept', (tester) async {
final store = MemoryDeviceSettingsStore();