feat(tag): one switch hides the tags from Jellyfin while studying

Every tag the app makes for where words were met on Jellyfin (the show
and the episode, the artist and the song) now says so (`origin` in tag
schema 2, written only for such a tag), in place of a tag hidden one by
one. Manage tags, where there are such tags, has one switch, Hide tags
from Jellyfin while studying (`hideJellyfinTags`, settings schema 9,
following the person): with it on, cards being studied leave them out of
their row at once, and Tags and Manage tags list them faint. They still
filter and narrow a session. The per-tag eye button is gone.

A word added while watching no longer takes the line it was met in as
its first hint: its hints are the dictionary's examples alone. Tatoeba's
sentences are checked, a subtitle line may be wrong or mistyped, a word
met again in a better line wouldn't get it, and every episode's line
would pile up on a common word.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-13 20:52:22 +02:00
commit c6e7a53dd6
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -145,8 +145,9 @@ void main() {
});
testWidgets('a word tapped pauses the video and shows what it is a form '
'of; added, it is a flashcard with its line and translation as its '
'first hint, tagged with the show, and is marked from then on', (
"of; added, it is a flashcard with the dictionary's checked examples "
'(never its line, which may be wrong), tagged with the show and the '
'episode as tags from Jellyfin, and is marked from then on', (
tester,
) async {
await watch(tester);
@ -161,25 +162,19 @@ void main() {
await tester.tap(find.text('Add'));
await tester.pumpAndSettle();
expect(find.text('会う added, with this line'), findsOneWidget);
expect(find.text('会う added'), findsOneWidget);
final card = (await cards.cardsOf('japanese')).single;
expect(card.content.type, CardType.vocabulary);
expect(card.content.entry, (source: 'jmdict', id: '6'));
expect(
card.content.hints.first.plainText,
allOf(
contains('昨日、駅で友達に会いました。'),
contains('Yesterday I met a friend at the station.'),
),
);
expect(card.content.hints, hasLength(1));
expect(card.content.hints.single.plainText, contains('また会いましょう。'));
final tagging = await tags.read();
expect(
[for (final tag in tagging.of(card.id)) tag.name],
containsAll(['Sample Journey', 'Sample Journey S1 E1', 'JLPT-N5']),
);
// The episode's own tag is hidden on cards; the show's is not.
expect(tagging.named('Sample Journey S1 E1')?.hidden, isTrue);
expect(tagging.named('Sample Journey')?.hidden, isFalse);
expect(tagging.named('Sample Journey S1 E1')?.fromJellyfin, isTrue);
expect(tagging.named('Sample Journey')?.fromJellyfin, isTrue);
// How far it is learnt: not yet.
expect(find.text('New'), findsOneWidget);
});
@ -654,7 +649,10 @@ void main() {
[for (final tag in tagging.of(card.id)) tag.name],
containsAll(['Sample Artist', 'Sample Artist · Sample Song']),
);
expect(tagging.named('Sample Artist · Sample Song')?.hidden, isTrue);
expect(
tagging.named('Sample Artist · Sample Song')?.fromJellyfin,
isTrue,
);
});
testWidgets('on a phone the words are below the video', (tester) async {