Commit graph halkyon/halkyon_learn_flutter/test/feature/jellyfin/watch_screen_test.dart
Author SHA1 Message Date
6737a42ff7
fix(dictionary): words held in topics, a chosen destination, faster adds
A word counted as held only in the studyset itself, so adding from a
studyset whose topics held it (Vocabulary, its words in N3) made a
second card, and watching from a top-level studyset put every new word
into it. Now a word is held anywhere in the studyset and its topics,
archived ones too, and its progress shows from that card; new words go
where the person chose for the studyset ("Adds to N3" in the dictionary
and the Watch screen, the studyset and its topics but archived ones,
kept in their settings, schema 10), the studyset itself until then.

Adding a word took about two seconds on 17,000 card tags: each of its
four tags read every card's tags twice. They are now written with one
read, the Watch screen shows the word added at once and takes it back
should writing fail, and it no longer reads the studyset's progress
again after each word. On a copy of a real database an Add takes 0.3 to
0.4 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-17 19:46:32 +02:00
1d2011a676
feat(dictionary): Japanese cut into words and looked up on the device
Once the person agrees, the device holds MeCab's IPADIC and the
instance's JMdict and cuts lines as Jisho.org does, so their text never
leaves it (ADR 0012). MeCab comes through mecab_for_dart, whose build
hook compiles it; its tokens are grouped by Ve's rules, written anew in
Dart, with に kept a word of its own. Each word is found as it stands or
as a form of a word, else by its dictionary form, else as the longest
words it holds from token to token; longer words over token boundaries
are offered as before.

The curator packs Ubuntu's compiled IPADIC beside the dictionary files
(curate ipadic, and every update run). The server exports its JMdict
from its tables, so the device finds the same keys and keeps the same
versions, and serves both at /device-dictionaries/, named in
dictionary.deviceFiles('ja') with their hashes; Caddy forwards the path.

The app checks each file against its hash, unpacks IPADIC, builds a
SQLite database from the export on an isolate, and asks the instance
for newer files every 30 days, downloading only what changed. The Watch
screen offers the download once per device with its size (34 MB, some
150 MB once set up); Settings downloads and removes them. Without them,
or should cutting on the device fail, lines go to the instance as
before. MeCab's, IPADIC's and Ve's licences join the licence list.

Every build now needs a C++ compiler; mecab_for_dart holds code_assets
at 1.x.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-17 19:46:30 +02:00
48ac84d92c
feat(jellyfin): any stretch of a line's characters chosen by hand
The cut takes the longest word and knows no grammar, so 今日は reads as
こんにちは where it is 今日 and は. Any stretch of a line's characters can
now be chosen by hand: dragged across with a mouse, Shift+clicked from
the word or stretch chosen, or on a touch screen held on a character and
dragged on. It is looked up as one word, as it stands or as a form of
one, in one small request (the instance has the line's text already);
while it is chosen the line reads it as that word (きょう over 今日), and
what the dictionary lacks as one word is offered as a search on Jisho.

The line's words move into line_words.dart, out of the Watch screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-14 00:33:51 +02:00
d552f8bea0
feat(jellyfin): From Jellyfin once signed in, the panel in the glow's colour, adding the words listed
All checks were successful
CI / check (push) Successful in 16m0s
CI / deploy (push) Successful in 1m13s
Add material's entry is now From Jellyfin (Aus Jellyfin), with a play
icon rather than a TV, as it plays music too, and shows only once the
device is signed in to a server in Settings, as the assistant shows only
once switched on; Settings says where it then is. The screen it opens is
called Jellyfin, and its search finds music too.

The words' panel takes the glow's colour as the scene changes: each copy
the glow takes (every 3 s) gives its average, no lighter than 35 % so the
text stays readable, as strong as the glow and fading into the next as
it does. In the light theme, which has no glow, the panel is tinted from
it while the pointer is over it. What lights up in the panel takes a
scheme made from the same colour; the episode's thumbnail is no longer
used.

While the studyset holds none of the video's words, the study button
adds the words listed (Add 11 words, as the filter shows them), tagged
as a word added alone is; afterwards it studies them, and its menu adds
the new ones listed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-13 21:21:50 +02:00
c6e7a53dd6
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>
2026-10-13 21:21:50 +02:00
22f5a4fcd1
feat(jellyfin): songs and their lyrics, read as subtitles are
A music library's artists and albums open as shows and seasons do, and
can be tied to a studyset. A song plays as sound alone (`/Audio/{id}/
stream`, as stored) with its lyrics as Jellyfin keeps them (`/Audio/{id}/
Lyrics`: an LRC file beside it, or its tags), cut into the dictionary's
words as a video's subtitles are, with no translation. Timed lyrics
follow the song: the line sung large and bright among the others faded,
scrolled to as it comes, a line tapped played from its start; untimed
ones show whole. A song without lyrics shows greyed and doesn't open
(`HasLyrics`), as there is nothing in it to read. Its cover stands where
the picture would, glowing as a video does, and its words are tagged
with the artist, shown, and "artist · title", hidden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-13 21:21:50 +02:00
436dc884b6
feat(jellyfin): an episode's own tag, and studying an episode's words
A word added from an episode gets the show's tag and the episode's own ("あかね噺 S1 E1"), hidden on cards. The words panel's Study button studies the studyset's cards of the video's words, on their schedules or crammed (each once): it pauses the video and first gives the episode's tag to the cards of its words the studyset held before, then opens the session on that tag. A study focus can now ask for cramming.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-13 21:21:49 +02:00
747d73b867
fix(jellyfin): Add and Jisho on the word's own line, entries unfold after 0.6 s
The Watch screen's entries carry Jisho's link and Add at the end of the headword's line, aligned right, rather than beside the senses; and an entry unfolds over the list once the pointer has rested on it for 0.6 s, as 0.3 s opened entries the pointer only passed over.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-13 21:21:49 +02:00
8fb5e105c9
fix(dictionary): a long kana word stands, and a word offers the longer ones
Cutting a line into words, kana that is no common word gave way to a
shorter common one whatever its length, so もうろく (耄碌, senility) was
taken as もう and ろく. The rule now holds only for kana of up to three
characters (が and まだ still win over がま, a cattail, and だ); a longer
kana word stands even when uncommon, as ichi.moe's segmenter weighs long
kana words by their length. And as no cut is always right, each word now
knows the longer words running over it into its neighbours, worked out
from the same lookup, which the Watch screen's panel offers beneath its
entries ("Longer words here"), each to add with the line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-13 21:21:49 +02:00
fbe53c3441
feat(jellyfin): the words' panel unfolds senses, shows progress, filters
The panel beside the video lists each entry's senses one to a line, as
Jisho does (and as every dictionary list in the app now does), folded
to two lines; an entry unfolds over the list, not in it, after a moment
under the pointer or on a tap, in the video's colour, so nothing moves
under the pointer and words of many senses (上げる has 25) crowd out
nothing. Each entry links to the word on Jisho.org, opened only when
tapped. A word the studyset holds shows how far its card is learnt:
New, Learning, Due, or Learned with when it comes again. The video's
words go through a filter in place of New only: new to the studyset,
held or all, JLPT levels, and word classes. The dictionary's sources
stay in the panel's lower right corner, and the player's controls hide
after 2 seconds rather than 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-13 21:21:49 +02:00
48a9564231
feat(jellyfin): the player as players are, with the settings under a cog
The Watch screen's player takes the shape people know from players,
YouTube's first: the picture set in from every side with rounded
corners, so the glow of its colours shows all around it, and over it
play or pause in the middle with 10 seconds back and on beside it, and
along its foot where the video is (0:05 ──── 23:47) and a cog. The
controls fade out while it plays and the pointer rests, and come back as
it moves, on a tap with a finger, on a jump and while paused. The cog
opens a panel inside the picture, so nothing runs off the window: Pause
after each line, the subtitles, the translation and the sound, each
track named by its language in the app's words, and the keyboard
shortcuts. The buttons for the line before, again and the next sit
beside the subtitles they act on, no longer looking like a player's
skip to the next video. Keys are YouTube's (Space or K, J and L, the
arrows, 0 to 9, Home, End) with Shift and the arrows for lines, R, P and
Esc; ? lists them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-13 21:21:48 +02:00
96cbd912de
fix(ui): a window resized across 600 dp keeps every screen as it was
Crossing from compact to medium windows or back built screens anew,
losing what they held: a study session started over, a card being
written lost its text, a video began again. The frame around a screen
over the tabs (FramedScreen) was added above it only from medium windows
on, and the snack bars' width (FittedSnackBars) put a Theme above the
app's navigator only there, so the screens below sat at another depth
after the change. The snack bars now always keep their Theme, changing
only the width in it, and the framed screen keeps its screen under a
global key, which moves it whole between the two places.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-13 21:21:48 +02:00
da51ef73cb
feat(jellyfin): watch from one's own Jellyfin server and learn the words of its subtitles
Animelon's way of learning from video, from the person's own Jellyfin
server: connected per device (Settings, or a studyset's Add material ›
Watch from Jellyfin) with a name and password or a Quick Connect code,
over HTTPS only (plain HTTP only to a server on the same machine); the
token stays in the system's keyring. Shows, films and videos tied to a
studyset follow the person in their settings as the server's and the
item's ids alone (settings schema 9), named by the server when shown.

The Watch screen plays the video (video_player on Android, media_kit's
libmpv on Linux and Windows) with the line in the studyset's front
language cut into the dictionary's words with furigana, and the back
language's line beneath; a word tapped pauses the video and becomes a
card with the line and its translation as its first hint, tagged with
the show. The video's words are listed, most frequent first. The sound is
the track in the studyset's language, whichever the file marks default,
and the menu switches it; the subtitles read are a whole track, never a
forced one (which only covers what the sound doesn't say), and captions
for the hard of hearing only without plain ones. The line and its
translation take the video's width in a box of a fixed height, so the
video keeps its size; in the dark theme the video's colours glow around
it, as YouTube's ambient mode, and the words' panel takes the colour of
the episode's picture under the pointer.

A line is cut into words with one request: DictionaryEndpoint.withKeys
looks up every stretch of it that may be a word, as it stands and as
every word it may be a conjugation of, in the new dictionary_key table
(one row per key, indexed; migration dictionary-keys adds the table and
its index, nothing else), which the loader fills beside the entries.
The instance gets the text of each line looked up and keeps none of it,
as the Watch screen says.

Linux builds need libmpv-dev, and the app links libmpv: the snap stages
Ubuntu's libmpv2, makes the update-alternatives links for BLAS and LAPACK
that ffmpeg's speech recognition needs (staging never runs install
scripts), and removes what the GNOME runtime and core24 already hold, as
older copies of cairo, pango and librsvg hid the runtime's from its GTK.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-13 21:21:48 +02:00